Subversion Repositories Kolibri OS

Rev

Rev 1633 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1.  
  2. #include <ddk.h>
  3. #include <linux/errno.h>
  4. #include <mutex.h>
  5. #include <pci.h>
  6. #include <syscall.h>
  7.  
  8. #include "acpi.h"
  9. #include "acpi_bus.h"
  10.  
  11.  
  12. #define PREFIX "ACPI: "
  13.  
  14.  
  15. struct acpi_handle_node {
  16.     struct list_head node;
  17.     ACPI_HANDLE handle;
  18. };
  19.  
  20. static const struct acpi_device_ids root_device_ids[] = {
  21.     {"PNP0A03", 0},
  22.     {"", 0},
  23. };
  24.  
  25. LIST_HEAD(acpi_pci_roots);
  26.  
  27.  
  28. /**
  29.  * acpi_is_root_bridge - determine whether an ACPI CA node is a PCI root bridge
  30.  * @handle - the ACPI CA node in question.
  31.  *
  32.  * Note: we could make this API take a struct acpi_device * instead, but
  33.  * for now, it's more convenient to operate on an acpi_handle.
  34.  */
  35. int acpi_is_root_bridge(ACPI_HANDLE handle)
  36. {
  37.     int ret;
  38.     struct acpi_device *device;
  39.  
  40.     ret = acpi_bus_get_device(handle, &device);
  41.     if (ret)
  42.         return 0;
  43.  
  44.     ret = acpi_match_device_ids(device, root_device_ids);
  45.     if (ret)
  46.         return 0;
  47.     else
  48.         return 1;
  49. }
  50.  
  51.  
  52. struct acpi_pci_root *acpi_pci_find_root(ACPI_HANDLE handle)
  53. {
  54.     struct acpi_pci_root *root;
  55.  
  56.     list_for_each_entry(root, &acpi_pci_roots, node) {
  57.         if (root->device->handle == handle)
  58.             return root;
  59.     }
  60.     return NULL;
  61. }
  62.  
  63.  
  64. /**
  65.  * acpi_get_pci_dev - convert ACPI CA handle to struct pci_dev
  66.  * @handle: the handle in question
  67.  *
  68.  * Given an ACPI CA handle, the desired PCI device is located in the
  69.  * list of PCI devices.
  70.  *
  71.  * If the device is found, its reference count is increased and this
  72.  * function returns a pointer to its data structure.  The caller must
  73.  * decrement the reference count by calling pci_dev_put().
  74.  * If no device is found, %NULL is returned.
  75.  */
  76. struct pci_dev *acpi_get_pci_dev(ACPI_HANDLE handle)
  77. {
  78.     int dev, fn;
  79.     unsigned long long adr;
  80.     ACPI_STATUS status;
  81.     ACPI_HANDLE phandle;
  82.     struct pci_bus *pbus;
  83.     struct pci_dev *pdev = NULL;
  84.     struct acpi_handle_node *node, *tmp;
  85.     struct acpi_pci_root *root;
  86.     LIST_HEAD(device_list);
  87.  
  88.     /*
  89.      * Walk up the ACPI CA namespace until we reach a PCI root bridge.
  90.      */
  91.     phandle = handle;
  92.     while (!acpi_is_root_bridge(phandle)) {
  93.         node = kzalloc(sizeof(struct acpi_handle_node), GFP_KERNEL);
  94.         if (!node)
  95.             goto out;
  96.  
  97.         INIT_LIST_HEAD(&node->node);
  98.         node->handle = phandle;
  99.         list_add(&node->node, &device_list);
  100.  
  101.         status = AcpiGetParent(phandle, &phandle);
  102.         if (ACPI_FAILURE(status))
  103.             goto out;
  104.     }
  105.  
  106.     root = acpi_pci_find_root(phandle);
  107.     if (!root)
  108.         goto out;
  109.  
  110.     pbus = root->bus;
  111.  
  112.     /*
  113.      * Now, walk back down the PCI device tree until we return to our
  114.      * original handle. Assumes that everything between the PCI root
  115.      * bridge and the device we're looking for must be a P2P bridge.
  116.      */
  117.     list_for_each_entry(node, &device_list, node) {
  118.         ACPI_HANDLE hnd = node->handle;
  119.         status = acpi_evaluate_integer(hnd, "_ADR", NULL, &adr);
  120.         if (ACPI_FAILURE(status))
  121.             goto out;
  122.         dev = (adr >> 16) & 0xffff;
  123.         fn  = adr & 0xffff;
  124.  
  125.         pdev = pci_get_slot(pbus, PCI_DEVFN(dev, fn));
  126.         if (!pdev || hnd == handle)
  127.             break;
  128.  
  129.         pbus = pdev->subordinate;
  130. //        pci_dev_put(pdev);
  131.  
  132.         /*
  133.          * This function may be called for a non-PCI device that has a
  134.          * PCI parent (eg. a disk under a PCI SATA controller).  In that
  135.          * case pdev->subordinate will be NULL for the parent.
  136.          */
  137.         if (!pbus) {
  138.             dbgprintf("Not a PCI-to-PCI bridge\n");
  139.             pdev = NULL;
  140.             break;
  141.         }
  142.     }
  143. out:
  144.     list_for_each_entry_safe(node, tmp, &device_list, node)
  145.         kfree(node);
  146.  
  147.     return pdev;
  148. }
  149.  
  150.  
  151. static void print_bus_irqs(struct pci_bus *bus)
  152. {
  153.     struct pci_dev *dev;
  154.  
  155.     list_for_each_entry(dev, &bus->devices, bus_list)
  156.     {
  157.         if(dev->pin)
  158.         {
  159.             dbgprintf("PCI_%x_%x bus:%d devfn: %x pin %d bios irq: %d acpi irq: %d\n",
  160.                        dev->vendor, dev->device, dev->busnr, dev->devfn,
  161.                        dev->pin, dev->irq, acpi_get_irq(dev));
  162.         };
  163.     };
  164. }
  165.  
  166. void print_pci_irqs()
  167. {
  168.     struct acpi_pci_root *root;
  169.  
  170.     list_for_each_entry(root, &acpi_pci_roots, node)
  171.     {
  172.         struct pci_bus *pbus, *tbus;
  173.         struct pci_dev *dev;
  174.  
  175.         pbus = root->bus;
  176.  
  177.         list_for_each_entry(dev, &pbus->devices, bus_list)
  178.         {
  179.             if(dev->pin)
  180.                 dbgprintf("PCI_%x_%x bus:%d devfn: %x pin %d bios irq: %d acpi irq: %d\n",
  181.                           dev->vendor, dev->device, dev->busnr, dev->devfn,
  182.                           dev->pin, dev->irq, acpi_get_irq(dev));
  183.         };
  184.  
  185.         list_for_each_entry(tbus, &pbus->children, node)
  186.         {
  187.             print_bus_irqs(tbus);
  188.         };
  189.     }
  190. };
  191.  
  192.  
  193.