Subversion Repositories Kolibri OS

Rev

Rev 4104 | Rev 5060 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /* drm_pci.h -- PCI DMA memory management wrappers for DRM -*- linux-c -*- */
  2. /**
  3.  * \file drm_pci.c
  4.  * \brief Functions and ioctls to manage PCI memory
  5.  *
  6.  * \warning These interfaces aren't stable yet.
  7.  *
  8.  * \todo Implement the remaining ioctl's for the PCI pools.
  9.  * \todo The wrappers here are so thin that they would be better off inlined..
  10.  *
  11.  * \author José Fonseca <jrfonseca@tungstengraphics.com>
  12.  * \author Leif Delgass <ldelgass@retinalburn.net>
  13.  */
  14.  
  15. /*
  16.  * Copyright 2003 José Fonseca.
  17.  * Copyright 2003 Leif Delgass.
  18.  * All Rights Reserved.
  19.  *
  20.  * Permission is hereby granted, free of charge, to any person obtaining a
  21.  * copy of this software and associated documentation files (the "Software"),
  22.  * to deal in the Software without restriction, including without limitation
  23.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  24.  * and/or sell copies of the Software, and to permit persons to whom the
  25.  * Software is furnished to do so, subject to the following conditions:
  26.  *
  27.  * The above copyright notice and this permission notice (including the next
  28.  * paragraph) shall be included in all copies or substantial portions of the
  29.  * Software.
  30.  *
  31.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  32.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  33.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
  34.  * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  35.  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  36.  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  37.  */
  38.  
  39. //#include <linux/pci.h>
  40. //#include <linux/slab.h>
  41. //#include <linux/dma-mapping.h>
  42. #include <linux/export.h>
  43. #include <drm/drmP.h>
  44.  
  45. #include <syscall.h>
  46.  
  47. /**********************************************************************/
  48. /** \name PCI memory */
  49. /*@{*/
  50.  
  51. /**
  52.  * \brief Allocate a PCI consistent memory block, for DMA.
  53.  */
  54. drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t align)
  55. {
  56.         drm_dma_handle_t *dmah;
  57. #if 1
  58.         unsigned long addr;
  59.         size_t sz;
  60. #endif
  61.  
  62.         /* pci_alloc_consistent only guarantees alignment to the smallest
  63.          * PAGE_SIZE order which is greater than or equal to the requested size.
  64.          * Return NULL here for now to make sure nobody tries for larger alignment
  65.          */
  66.         if (align > size)
  67.                 return NULL;
  68.  
  69.         dmah = kmalloc(sizeof(drm_dma_handle_t), GFP_KERNEL);
  70.         if (!dmah)
  71.                 return NULL;
  72.  
  73.         dmah->size = size;
  74.     dmah->vaddr = (void*)KernelAlloc(size);
  75.     dmah->busaddr = GetPgAddr(dmah->vaddr);
  76.  
  77.         if (dmah->vaddr == NULL) {
  78.                 kfree(dmah);
  79.                 return NULL;
  80.         }
  81.  
  82.         memset(dmah->vaddr, 0, size);
  83.  
  84.         return dmah;
  85. }
  86.  
  87. EXPORT_SYMBOL(drm_pci_alloc);
  88.  
  89. #if 0
  90. /**
  91.  * \brief Free a PCI consistent memory block without freeing its descriptor.
  92.  *
  93.  * This function is for internal use in the Linux-specific DRM core code.
  94.  */
  95. void __drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah)
  96. {
  97.         unsigned long addr;
  98.         size_t sz;
  99.  
  100.         if (dmah->vaddr) {
  101.                 /* XXX - Is virt_to_page() legal for consistent mem? */
  102.                 /* Unreserve */
  103.                 for (addr = (unsigned long)dmah->vaddr, sz = dmah->size;
  104.                      sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
  105.                         ClearPageReserved(virt_to_page((void *)addr));
  106.                 }
  107.                 dma_free_coherent(&dev->pdev->dev, dmah->size, dmah->vaddr,
  108.                                   dmah->busaddr);
  109.         }
  110. }
  111.  
  112. /**
  113.  * \brief Free a PCI consistent memory block
  114.  */
  115. void drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah)
  116. {
  117.         __drm_pci_free(dev, dmah);
  118.         kfree(dmah);
  119. }
  120.  
  121. EXPORT_SYMBOL(drm_pci_free);
  122.  
  123.  
  124. static int drm_get_pci_domain(struct drm_device *dev)
  125. {
  126. #ifndef __alpha__
  127.         /* For historical reasons, drm_get_pci_domain() is busticated
  128.          * on most archs and has to remain so for userspace interface
  129.          * < 1.4, except on alpha which was right from the beginning
  130.          */
  131.         if (dev->if_version < 0x10004)
  132.                 return 0;
  133. #endif /* __alpha__ */
  134.  
  135.         return pci_domain_nr(dev->pdev->bus);
  136. }
  137.  
  138. static int drm_pci_get_irq(struct drm_device *dev)
  139. {
  140.         return dev->pdev->irq;
  141. }
  142.  
  143. static const char *drm_pci_get_name(struct drm_device *dev)
  144. {
  145.         struct pci_driver *pdriver = dev->driver->kdriver.pci;
  146.         return pdriver->name;
  147. }
  148.  
  149. static int drm_pci_set_busid(struct drm_device *dev, struct drm_master *master)
  150. {
  151.         int len, ret;
  152.         struct pci_driver *pdriver = dev->driver->kdriver.pci;
  153.         master->unique_len = 40;
  154.         master->unique_size = master->unique_len;
  155.         master->unique = kmalloc(master->unique_size, GFP_KERNEL);
  156.         if (master->unique == NULL)
  157.                 return -ENOMEM;
  158.  
  159.  
  160.         len = snprintf(master->unique, master->unique_len,
  161.                        "pci:%04x:%02x:%02x.%d",
  162.                        drm_get_pci_domain(dev),
  163.                        dev->pdev->bus->number,
  164.                        PCI_SLOT(dev->pdev->devfn),
  165.                        PCI_FUNC(dev->pdev->devfn));
  166.  
  167.         if (len >= master->unique_len) {
  168.                 DRM_ERROR("buffer overflow");
  169.                 ret = -EINVAL;
  170.                 goto err;
  171.         } else
  172.                 master->unique_len = len;
  173.  
  174.         dev->devname =
  175.                 kmalloc(strlen(pdriver->name) +
  176.                         master->unique_len + 2, GFP_KERNEL);
  177.  
  178.         if (dev->devname == NULL) {
  179.                 ret = -ENOMEM;
  180.                 goto err;
  181.         }
  182.  
  183.         sprintf(dev->devname, "%s@%s", pdriver->name,
  184.                 master->unique);
  185.  
  186.         return 0;
  187. err:
  188.         return ret;
  189. }
  190.  
  191. static int drm_pci_set_unique(struct drm_device *dev,
  192.                               struct drm_master *master,
  193.                               struct drm_unique *u)
  194. {
  195.         int domain, bus, slot, func, ret;
  196.         const char *bus_name;
  197.  
  198.         master->unique_len = u->unique_len;
  199.         master->unique_size = u->unique_len + 1;
  200.         master->unique = kmalloc(master->unique_size, GFP_KERNEL);
  201.         if (!master->unique) {
  202.                 ret = -ENOMEM;
  203.                 goto err;
  204.         }
  205.  
  206.         if (copy_from_user(master->unique, u->unique, master->unique_len)) {
  207.                 ret = -EFAULT;
  208.                 goto err;
  209.         }
  210.  
  211.         master->unique[master->unique_len] = '\0';
  212.  
  213.         bus_name = dev->driver->bus->get_name(dev);
  214.         dev->devname = kmalloc(strlen(bus_name) +
  215.                                strlen(master->unique) + 2, GFP_KERNEL);
  216.         if (!dev->devname) {
  217.                 ret = -ENOMEM;
  218.                 goto err;
  219.         }
  220.  
  221.         sprintf(dev->devname, "%s@%s", bus_name,
  222.                 master->unique);
  223.  
  224.         /* Return error if the busid submitted doesn't match the device's actual
  225.          * busid.
  226.          */
  227.         ret = sscanf(master->unique, "PCI:%d:%d:%d", &bus, &slot, &func);
  228.         if (ret != 3) {
  229.                 ret = -EINVAL;
  230.                 goto err;
  231.         }
  232.  
  233.         domain = bus >> 8;
  234.         bus &= 0xff;
  235.  
  236.         if ((domain != drm_get_pci_domain(dev)) ||
  237.             (bus != dev->pdev->bus->number) ||
  238.             (slot != PCI_SLOT(dev->pdev->devfn)) ||
  239.             (func != PCI_FUNC(dev->pdev->devfn))) {
  240.                 ret = -EINVAL;
  241.                 goto err;
  242.         }
  243.         return 0;
  244. err:
  245.         return ret;
  246. }
  247.  
  248.  
  249. static int drm_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p)
  250. {
  251.         if ((p->busnum >> 8) != drm_get_pci_domain(dev) ||
  252.             (p->busnum & 0xff) != dev->pdev->bus->number ||
  253.             p->devnum != PCI_SLOT(dev->pdev->devfn) || p->funcnum != PCI_FUNC(dev->pdev->devfn))
  254.                 return -EINVAL;
  255.  
  256.         p->irq = dev->pdev->irq;
  257.  
  258.         DRM_DEBUG("%d:%d:%d => IRQ %d\n", p->busnum, p->devnum, p->funcnum,
  259.                   p->irq);
  260.         return 0;
  261. }
  262.  
  263. static void drm_pci_agp_init(struct drm_device *dev)
  264. {
  265.         if (drm_core_check_feature(dev, DRIVER_USE_AGP)) {
  266.                 if (drm_pci_device_is_agp(dev))
  267.                         dev->agp = drm_agp_init(dev);
  268.                 if (dev->agp) {
  269.                         dev->agp->agp_mtrr = arch_phys_wc_add(
  270.                                 dev->agp->agp_info.aper_base,
  271.                                 dev->agp->agp_info.aper_size *
  272.                                 1024 * 1024);
  273.                 }
  274.         }
  275. }
  276.  
  277. void drm_pci_agp_destroy(struct drm_device *dev)
  278. {
  279.         if (dev->agp) {
  280.                 arch_phys_wc_del(dev->agp->agp_mtrr);
  281.                 drm_agp_clear(dev);
  282.                 kfree(dev->agp);
  283.                 dev->agp = NULL;
  284.         }
  285. }
  286.  
  287. static struct drm_bus drm_pci_bus = {
  288.         .bus_type = DRIVER_BUS_PCI,
  289.         .get_irq = drm_pci_get_irq,
  290.         .get_name = drm_pci_get_name,
  291.         .set_busid = drm_pci_set_busid,
  292.         .set_unique = drm_pci_set_unique,
  293.         .irq_by_busid = drm_pci_irq_by_busid,
  294. };
  295. #endif
  296.  
  297. /**
  298.  * Register.
  299.  *
  300.  * \param pdev - PCI device structure
  301.  * \param ent entry from the PCI ID table with device type flags
  302.  * \return zero on success or a negative number on failure.
  303.  *
  304.  * Attempt to gets inter module "drm" information. If we are first
  305.  * then register the character device and inter module information.
  306.  * Try and register, if we fail to register, backout previous work.
  307.  */
  308. int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
  309.                     struct drm_driver *driver)
  310. {
  311.     static struct drm_device drm_dev;
  312.     static struct drm_file   drm_file;
  313.  
  314.         struct drm_device *dev;
  315.     struct drm_file   *priv;
  316.  
  317.         int ret;
  318.  
  319.     dev  = &drm_dev;
  320.     priv = &drm_file;
  321.  
  322.     drm_file_handlers[0] = priv;
  323.  
  324.  //   ret = pci_enable_device(pdev);
  325.  //   if (ret)
  326.  //       goto err_g1;
  327.  
  328.     pci_set_master(pdev);
  329.  
  330.     if ((ret = drm_fill_in_dev(dev, ent, driver))) {
  331.         printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
  332.         goto err_g2;
  333.     }
  334.  
  335.         DRM_DEBUG("\n");
  336.  
  337.  
  338.         dev->pdev = pdev;
  339.         dev->pci_device = pdev->device;
  340.         dev->pci_vendor = pdev->vendor;
  341.  
  342. #ifdef __alpha__
  343.         dev->hose = pdev->sysdata;
  344. #endif
  345.  
  346. //   mutex_lock(&drm_global_mutex);
  347.  
  348.         if ((ret = drm_fill_in_dev(dev, ent, driver))) {
  349.                 printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
  350.                 goto err_g2;
  351.         }
  352.  
  353. #if 0
  354.         if (drm_core_check_feature(dev, DRIVER_MODESET)) {
  355.                 pci_set_drvdata(pdev, dev);
  356.                 ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL);
  357.                 if (ret)
  358.                         goto err_g2;
  359.         }
  360.  
  361.         if (drm_core_check_feature(dev, DRIVER_RENDER) && drm_rnodes) {
  362.                 ret = drm_get_minor(dev, &dev->render, DRM_MINOR_RENDER);
  363.                 if (ret)
  364.                         goto err_g21;
  365.         }
  366.  
  367.         if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY)))
  368.                 goto err_g3;
  369. #endif
  370.  
  371.         if (dev->driver->load) {
  372.                 ret = dev->driver->load(dev, ent->driver_data);
  373.                 if (ret)
  374.                         goto err_g4;
  375.         }
  376.  
  377.     if (dev->driver->open) {
  378.         ret = dev->driver->open(dev, priv);
  379.         if (ret < 0)
  380.             goto err_g4;
  381.     }
  382.  
  383.  
  384. //   mutex_unlock(&drm_global_mutex);
  385.         return 0;
  386.  
  387. err_g4:
  388. //   drm_put_minor(&dev->primary);
  389. err_g3:
  390. //   if (dev->render)
  391. //       drm_put_minor(&dev->render);
  392. err_g21:
  393. //   if (drm_core_check_feature(dev, DRIVER_MODESET))
  394. //       drm_put_minor(&dev->control);
  395. err_g2:
  396. //   pci_disable_device(pdev);
  397. err_g1:
  398. //   kfree(dev);
  399. //   mutex_unlock(&drm_global_mutex);
  400.         return ret;
  401. }
  402. EXPORT_SYMBOL(drm_get_pci_dev);
  403.  
  404. int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *mask)
  405. {
  406.         struct pci_dev *root;
  407.         u32 lnkcap, lnkcap2;
  408.  
  409.         *mask = 0;
  410.         if (!dev->pdev)
  411.                 return -EINVAL;
  412.  
  413.  
  414.     return -EINVAL;
  415.  
  416. #if 0
  417.         root = dev->pdev->bus->self;
  418.  
  419.         /* we've been informed via and serverworks don't make the cut */
  420.         if (root->vendor == PCI_VENDOR_ID_VIA ||
  421.             root->vendor == PCI_VENDOR_ID_SERVERWORKS)
  422.                 return -EINVAL;
  423.  
  424.         pcie_capability_read_dword(root, PCI_EXP_LNKCAP, &lnkcap);
  425.         pcie_capability_read_dword(root, PCI_EXP_LNKCAP2, &lnkcap2);
  426.  
  427.         if (lnkcap2) {  /* PCIe r3.0-compliant */
  428.                 if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_2_5GB)
  429.                         *mask |= DRM_PCIE_SPEED_25;
  430.                 if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_5_0GB)
  431.                         *mask |= DRM_PCIE_SPEED_50;
  432.                 if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_8_0GB)
  433.                         *mask |= DRM_PCIE_SPEED_80;
  434.         } else {        /* pre-r3.0 */
  435.                 if (lnkcap & PCI_EXP_LNKCAP_SLS_2_5GB)
  436.                         *mask |= DRM_PCIE_SPEED_25;
  437.                 if (lnkcap & PCI_EXP_LNKCAP_SLS_5_0GB)
  438.                         *mask |= (DRM_PCIE_SPEED_25 | DRM_PCIE_SPEED_50);
  439.         }
  440.  
  441.         DRM_INFO("probing gen 2 caps for device %x:%x = %x/%x\n", root->vendor, root->device, lnkcap, lnkcap2);
  442.         return 0;
  443. #endif
  444.  
  445. }
  446. EXPORT_SYMBOL(drm_pcie_get_speed_cap_mask);
  447.