Subversion Repositories Kolibri OS

Rev

Rev 1627 | Rev 1633 | Go to most recent revision | 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. #define PREFIX "ACPI: "
  12.  
  13. #define ACPI_BUS_CLASS          "system_bus"
  14. #define ACPI_BUS_HID            "KLBSYBUS"
  15. #define ACPI_BUS_DEVICE_NAME    "System Bus"
  16.  
  17.  
  18. #define ACPI_IS_ROOT_DEVICE(device)    (!(device)->parent)
  19.  
  20. static LIST_HEAD(acpi_device_list);
  21. static LIST_HEAD(acpi_bus_id_list);
  22.  
  23.  
  24. struct acpi_device_bus_id
  25. {
  26.     char bus_id[15];
  27.     unsigned int instance_no;
  28.     struct list_head node;
  29. };
  30.  
  31.  
  32. #define ACPI_NS_ROOT_PATH       "\\"
  33. #define ACPI_NS_SYSTEM_BUS      "_SB_"
  34.  
  35. enum acpi_irq_model_id {
  36.         ACPI_IRQ_MODEL_PIC = 0,
  37.         ACPI_IRQ_MODEL_IOAPIC,
  38.         ACPI_IRQ_MODEL_IOSAPIC,
  39.         ACPI_IRQ_MODEL_PLATFORM,
  40.         ACPI_IRQ_MODEL_COUNT
  41. };
  42.  
  43. enum acpi_bus_removal_type {
  44.     ACPI_BUS_REMOVAL_NORMAL = 0,
  45.     ACPI_BUS_REMOVAL_EJECT,
  46.     ACPI_BUS_REMOVAL_SUPRISE,
  47.     ACPI_BUS_REMOVAL_TYPE_COUNT
  48. };
  49.  
  50.  
  51. #define PCI_MAX_DEVICES 32
  52. #define PCI_MAX_PINS    4
  53.  
  54. #define IRQ_TABLE_ENTRIES   (PCI_MAX_DEVICES * PCI_MAX_PINS)
  55.  
  56. static int irqtable[IRQ_TABLE_ENTRIES];
  57. static ACPI_HANDLE pci_root_handle;
  58.  
  59.  
  60. #define  addr_offset(addr, off) \
  61.     (addr_t)((addr_t)(addr) + (addr_t)(off))
  62.  
  63. //#define acpi_remap( addr ) \
  64. //    (addr_t)((addr_t)(addr) + OS_BASE)
  65.  
  66. #define acpi_remap( addr ) MapIoMem((void*)(addr),4096, 0x01)
  67.  
  68.  
  69. struct acpi_device *acpi_root;
  70.  
  71. extern struct resource iomem_resource;
  72. extern struct resource ioport_resource;
  73.  
  74. enum pic_mode
  75. {
  76.     IO_PIC  = 0,
  77.     IO_APIC
  78. };
  79.  
  80. static void set_pic_mode(enum pic_mode mode)
  81. {
  82.     ACPI_OBJECT arg1;
  83.     ACPI_OBJECT_LIST args;
  84.     ACPI_STATUS as;
  85.  
  86.     arg1.Type = ACPI_TYPE_INTEGER;
  87.     arg1.Integer.Value = mode;
  88.     args.Count = 1;
  89.     args.Pointer = &arg1;
  90.  
  91.     as = AcpiEvaluateObject(ACPI_ROOT_OBJECT, "_PIC", &args, NULL);
  92.     /*
  93.      * We can silently ignore failure as it may not be implemented, ACPI should
  94.      * provide us with correct information anyway
  95.      */
  96.     if (ACPI_SUCCESS(as))
  97.         dbgprintf(PREFIX "machine set to %s mode\n", mode ? "APIC" : "PIC");
  98. }
  99.  
  100. void print_device_tree(struct acpi_device *device)
  101. {
  102.     struct acpi_device *child;
  103.  
  104.     dbgprintf("%s\n", device->pnp.bus_id);
  105.  
  106.     list_for_each_entry(child, &device->children, node)
  107.     {
  108.         print_device_tree(child);
  109.     };
  110. };
  111.  
  112.  
  113.  
  114.  
  115. static bool pci_use_crs = false;
  116.  
  117. #define IORESOURCE_BUS      0x00001000
  118.  
  119.  
  120. static LIST_HEAD(acpi_pci_roots);
  121.  
  122. #define ACPI_PCI_ROOT_CLASS     "pci_bridge"
  123. #define ACPI_PCI_ROOT_DEVICE_NAME   "PCI Root Bridge"
  124.  
  125. static ACPI_STATUS
  126. get_root_bridge_busnr_callback(ACPI_RESOURCE *resource, void *data)
  127. {
  128.     struct resource *res = data;
  129.     ACPI_RESOURCE_ADDRESS64 address;
  130.  
  131.     if (resource->Type != ACPI_RESOURCE_TYPE_ADDRESS16 &&
  132.         resource->Type != ACPI_RESOURCE_TYPE_ADDRESS32 &&
  133.         resource->Type != ACPI_RESOURCE_TYPE_ADDRESS64)
  134.         return AE_OK;
  135.  
  136.     AcpiResourceToAddress64(resource, &address);
  137.     if ((address.AddressLength > 0) &&
  138.         (address.ResourceType == ACPI_BUS_NUMBER_RANGE)) {
  139.         res->start = address.Minimum;
  140.         res->end = address.Minimum + address.AddressLength - 1;
  141.     }
  142.  
  143.     return AE_OK;
  144. }
  145.  
  146.  
  147.  
  148. static ACPI_STATUS try_get_root_bridge_busnr(ACPI_HANDLE handle,
  149.                          struct resource *res)
  150. {
  151.     ACPI_STATUS status;
  152.  
  153.     res->start = -1;
  154.     status =
  155.         AcpiWalkResources(handle, METHOD_NAME__CRS,
  156.                 get_root_bridge_busnr_callback, res);
  157.     if (ACPI_FAILURE(status))
  158.         return status;
  159.     if (res->start == -1)
  160.         return AE_ERROR;
  161.     return AE_OK;
  162. }
  163.  
  164.  
  165. static void acpi_pci_bridge_scan(struct acpi_device *device)
  166. {
  167.     int status;
  168.     struct acpi_device *child = NULL;
  169.  
  170.     if (device->flags.bus_address)
  171.         if (device->parent && device->parent->ops.bind) {
  172.             status = device->parent->ops.bind(device);
  173.             if (!status) {
  174.                 list_for_each_entry(child, &device->children, node)
  175.                     acpi_pci_bridge_scan(child);
  176.             }
  177.         }
  178. }
  179.  
  180.  
  181.  
  182. struct pci_root_info
  183. {
  184.     struct acpi_device *bridge;
  185.     char *name;
  186.     unsigned int res_num;
  187.     struct resource *res;
  188.     struct pci_bus *bus;
  189.     int busnum;
  190. };
  191.  
  192.  
  193. static ACPI_STATUS
  194. resource_to_addr(ACPI_RESOURCE *resource, ACPI_RESOURCE_ADDRESS64 *addr)
  195. {
  196.     ACPI_STATUS status;
  197.     struct acpi_resource_memory24 *memory24;
  198.     struct acpi_resource_memory32 *memory32;
  199.     struct acpi_resource_fixed_memory32 *fixed_memory32;
  200.  
  201.     memset(addr, 0, sizeof(*addr));
  202.     switch (resource->Type) {
  203.     case ACPI_RESOURCE_TYPE_MEMORY24:
  204.         memory24 = &resource->Data.Memory24;
  205.         addr->ResourceType = ACPI_MEMORY_RANGE;
  206.         addr->Minimum = memory24->Minimum;
  207.         addr->AddressLength = memory24->AddressLength;
  208.         addr->Maximum = addr->Minimum + addr->AddressLength - 1;
  209.         return AE_OK;
  210.     case ACPI_RESOURCE_TYPE_MEMORY32:
  211.         memory32 = &resource->Data.Memory32;
  212.         addr->ResourceType = ACPI_MEMORY_RANGE;
  213.         addr->Minimum = memory32->Minimum;
  214.         addr->AddressLength = memory32->AddressLength;
  215.         addr->Maximum = addr->Minimum + addr->AddressLength - 1;
  216.         return AE_OK;
  217.     case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
  218.         fixed_memory32 = &resource->Data.FixedMemory32;
  219.         addr->ResourceType = ACPI_MEMORY_RANGE;
  220.         addr->Minimum = fixed_memory32->Address;
  221.         addr->AddressLength = fixed_memory32->AddressLength;
  222.         addr->Maximum = addr->Minimum + addr->AddressLength - 1;
  223.         return AE_OK;
  224.     case ACPI_RESOURCE_TYPE_ADDRESS16:
  225.     case ACPI_RESOURCE_TYPE_ADDRESS32:
  226.     case ACPI_RESOURCE_TYPE_ADDRESS64:
  227.         status = AcpiResourceToAddress64(resource, addr);
  228.         if (ACPI_SUCCESS(status) &&
  229.             (addr->ResourceType == ACPI_MEMORY_RANGE ||
  230.             addr->ResourceType == ACPI_IO_RANGE) &&
  231.             addr->AddressLength > 0) {
  232.             return AE_OK;
  233.         }
  234.         break;
  235.     }
  236.     return AE_ERROR;
  237. }
  238.  
  239.  
  240. static ACPI_STATUS
  241. count_resource(ACPI_RESOURCE *acpi_res, void *data)
  242. {
  243.     struct pci_root_info *info = data;
  244.     ACPI_RESOURCE_ADDRESS64 addr;
  245.     ACPI_STATUS status;
  246.  
  247.     status = resource_to_addr(acpi_res, &addr);
  248.     if (ACPI_SUCCESS(status))
  249.         info->res_num++;
  250.     return AE_OK;
  251. }
  252.  
  253.  
  254. static ACPI_STATUS setup_resource(ACPI_RESOURCE *acpi_res, void *data)
  255. {
  256.     struct pci_root_info *info = data;
  257.     struct resource *res;
  258.     struct acpi_resource_address64 addr;
  259.     ACPI_STATUS status;
  260.     unsigned long flags;
  261.     struct resource *root, *conflict;
  262.     u64 start, end;
  263.  
  264.     status = resource_to_addr(acpi_res, &addr);
  265.     if (!ACPI_SUCCESS(status))
  266.         return AE_OK;
  267.  
  268.     if (addr.ResourceType == ACPI_MEMORY_RANGE)
  269.     {
  270.         root = &iomem_resource;
  271.         flags = IORESOURCE_MEM;
  272.         if (addr.Info.Mem.Caching == ACPI_PREFETCHABLE_MEMORY)
  273.             flags |= IORESOURCE_PREFETCH;
  274.     }
  275.     else if (addr.ResourceType == ACPI_IO_RANGE)
  276.     {
  277.         root = &ioport_resource;
  278.         flags = IORESOURCE_IO;
  279.     } else
  280.         return AE_OK;
  281.  
  282.     start = addr.Minimum + addr.TranslationOffset;
  283.     end = addr.Maximum + addr.TranslationOffset;
  284.  
  285.     res = &info->res[info->res_num];
  286.     res->name = info->name;
  287.     res->flags = flags;
  288.     res->start = start;
  289.     res->end = end;
  290.     res->child = NULL;
  291.  
  292.     if (!pci_use_crs) {
  293.         printk("host bridge window %pR (ignored)\n", res);
  294.         return AE_OK;
  295.     }
  296.  
  297. #if 0
  298.     conflict = insert_resource_conflict(root, res);
  299.     if (conflict) {
  300.         dev_err(&info->bridge->dev,
  301.             "address space collision: host bridge window %pR "
  302.             "conflicts with %s %pR\n",
  303.             res, conflict->name, conflict);
  304.     } else {
  305.         pci_bus_add_resource(info->bus, res, 0);
  306.         info->res_num++;
  307.         if (addr.translation_offset)
  308.             dev_info(&info->bridge->dev, "host bridge window %pR "
  309.                  "(PCI address [%#llx-%#llx])\n",
  310.                  res, res->start - addr.translation_offset,
  311.                  res->end - addr.translation_offset);
  312.         else
  313.             dev_info(&info->bridge->dev,
  314.                  "host bridge window %pR\n", res);
  315.     }
  316.     return AE_OK;
  317. #endif
  318. }
  319.  
  320.  
  321.  
  322. static void
  323. get_current_resources(struct acpi_device *device, int busnum,
  324.             int domain, struct pci_bus *bus)
  325. {
  326.     struct pci_root_info info;
  327.     size_t size;
  328.  
  329.     char buf[64];
  330.  
  331. //    if (pci_use_crs)
  332. //        pci_bus_remove_resources(bus);
  333.  
  334.     info.bridge = device;
  335.     info.bus = bus;
  336.     info.res_num = 0;
  337.     AcpiWalkResources(device->handle, METHOD_NAME__CRS, count_resource,
  338.                 &info);
  339.     if (!info.res_num)
  340.         return;
  341.  
  342.     size = sizeof(*info.res) * info.res_num;
  343.     info.res = kmalloc(size, GFP_KERNEL);
  344.     if (!info.res)
  345.         goto res_alloc_fail;
  346.  
  347.     vsprintf(buf,"PCI Bus %04x:%02x", domain, busnum);
  348.     info.name = strdup(buf);
  349.  
  350.     if (!info.name)
  351.         goto name_alloc_fail;
  352.  
  353.     info.res_num = 0;
  354.     AcpiWalkResources(device->handle, METHOD_NAME__CRS, setup_resource,
  355.                 &info);
  356.  
  357.     return;
  358.  
  359. name_alloc_fail:
  360.     kfree(info.res);
  361. res_alloc_fail:
  362.     return;
  363. }
  364.  
  365.  
  366.  
  367.  
  368. struct pci_ops pci_root_ops = {
  369.     .read = NULL,
  370.     .write = NULL,
  371. };
  372.  
  373.  
  374. struct pci_bus*  pci_acpi_scan_root(struct acpi_pci_root *root)
  375. {
  376.     struct acpi_device *device = root->device;
  377.     int domain = root->segment;
  378.     int busnum = root->secondary.start;
  379.     struct pci_bus *bus;
  380.     struct pci_sysdata *sd;
  381.     int node = 0;
  382.  
  383.     if (domain ) {
  384.         printk(KERN_WARNING "pci_bus %04x:%02x: "
  385.                "ignored (multiple domains not supported)\n",
  386.                domain, busnum);
  387.         return NULL;
  388.     }
  389.  
  390.     /* Allocate per-root-bus (not per bus) arch-specific data.
  391.      * TODO: leak; this memory is never freed.
  392.      * It's arguable whether it's worth the trouble to care.
  393.      */
  394.     sd = kzalloc(sizeof(*sd), GFP_KERNEL);
  395.     if (!sd) {
  396.         printk(KERN_WARNING "pci_bus %04x:%02x: "
  397.                "ignored (out of memory)\n", domain, busnum);
  398.         return NULL;
  399.     }
  400.  
  401.     sd->domain = domain;
  402.     sd->node = node;
  403.     /*
  404.      * Maybe the desired pci bus has been already scanned. In such case
  405.      * it is unnecessary to scan the pci bus with the given domain,busnum.
  406.      */
  407.     bus = pci_find_bus(domain, busnum);
  408.     if (bus) {
  409.         /*
  410.          * If the desired bus exits, the content of bus->sysdata will
  411.          * be replaced by sd.
  412.          */
  413.         memcpy(bus->sysdata, sd, sizeof(*sd));
  414.         kfree(sd);
  415.     } else {
  416.         bus = pci_create_bus(busnum, &pci_root_ops, sd);
  417.         if (bus) {
  418.             get_current_resources(device, busnum, domain, bus);
  419.             bus->subordinate = pci_scan_child_bus(bus);
  420.         }
  421.     }
  422.  
  423.     if (!bus)
  424.         kfree(sd);
  425.  
  426.     if (bus && node != -1) {
  427.         printk("on NUMA node %d\n", node);
  428.     }
  429.  
  430.     return bus;
  431. }
  432.  
  433.  
  434.  
  435. static int acpi_pci_root_add(struct acpi_device *device)
  436. {
  437.     unsigned long long segment, bus;
  438.     ACPI_STATUS status;
  439.     int result;
  440.     struct acpi_pci_root *root;
  441.     ACPI_HANDLE handle;
  442.     struct acpi_device *child;
  443.     u32 flags, base_flags;
  444.  
  445.     root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
  446.     if (!root)
  447.         return -ENOMEM;
  448.  
  449.     segment = 0;
  450.     status = acpi_evaluate_integer(device->handle, METHOD_NAME__SEG, NULL,
  451.                        &segment);
  452.     if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
  453.         printk(KERN_ERR PREFIX "can't evaluate _SEG\n");
  454.         result = -ENODEV;
  455.         goto end;
  456.     }
  457.  
  458.     /* Check _CRS first, then _BBN.  If no _BBN, default to zero. */
  459.     root->secondary.flags = IORESOURCE_BUS;
  460.     status = try_get_root_bridge_busnr(device->handle, &root->secondary);
  461.     if (ACPI_FAILURE(status))
  462.     {
  463.         /*
  464.          * We need both the start and end of the downstream bus range
  465.          * to interpret _CBA (MMCONFIG base address), so it really is
  466.          * supposed to be in _CRS.  If we don't find it there, all we
  467.          * can do is assume [_BBN-0xFF] or [0-0xFF].
  468.          */
  469.         root->secondary.end = 0xFF;
  470.         printk(KERN_WARNING PREFIX
  471.                "no secondary bus range in _CRS\n");
  472.         status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN,                           NULL, &bus);
  473.         if (ACPI_SUCCESS(status))
  474.             root->secondary.start = bus;
  475.         else if (status == AE_NOT_FOUND)
  476.             root->secondary.start = 0;
  477.         else {
  478.             printk(KERN_ERR PREFIX "can't evaluate _BBN\n");
  479.             result = -ENODEV;
  480.             goto end;
  481.         }
  482.     }
  483.  
  484.     INIT_LIST_HEAD(&root->node);
  485.     root->device = device;
  486.     root->segment = segment & 0xFFFF;
  487.     strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME);
  488.     strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
  489.     device->driver_data = root;
  490.  
  491.     /*
  492.      * All supported architectures that use ACPI have support for
  493.      * PCI domains, so we indicate this in _OSC support capabilities.
  494.      */
  495. //    flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT;
  496. //    acpi_pci_osc_support(root, flags);
  497.  
  498.     /*
  499.      * TBD: Need PCI interface for enumeration/configuration of roots.
  500.      */
  501.  
  502.     /* TBD: Locking */
  503.     list_add_tail(&root->node, &acpi_pci_roots);
  504.  
  505.     printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n",
  506.            acpi_device_name(device), acpi_device_bid(device),
  507.            root->segment, &root->secondary);
  508.  
  509.     /*
  510.      * Scan the Root Bridge
  511.      * --------------------
  512.      * Must do this prior to any attempt to bind the root device, as the
  513.      * PCI namespace does not get created until this call is made (and
  514.      * thus the root bridge's pci_dev does not exist).
  515.      */
  516.  
  517.     root->bus = pci_acpi_scan_root(root);
  518.     if (!root->bus) {
  519.         printk(KERN_ERR PREFIX
  520.                 "Bus %04x:%02x not present in PCI namespace\n",
  521.                 root->segment, (unsigned int)root->secondary.start);
  522.         result = -ENODEV;
  523.         goto end;
  524.     }
  525.  
  526.     /*
  527.      * Attach ACPI-PCI Context
  528.      * -----------------------
  529.      * Thus binding the ACPI and PCI devices.
  530.      */
  531.     result = acpi_pci_bind_root(device);
  532.     if (result)
  533.         goto end;
  534.  
  535.     /*
  536.      * PCI Routing Table
  537.      * -----------------
  538.      * Evaluate and parse _PRT, if exists.
  539.      */
  540.     status = AcpiGetHandle(device->handle, METHOD_NAME__PRT, &handle);
  541.     if (ACPI_SUCCESS(status))
  542.         result = acpi_pci_irq_add_prt(device->handle, root->bus);
  543.  
  544.     /*
  545.      * Scan and bind all _ADR-Based Devices
  546.      */
  547.     list_for_each_entry(child, &device->children, node)
  548.         acpi_pci_bridge_scan(child);
  549.  
  550.     return 0;
  551.  
  552. end:
  553.     if (!list_empty(&root->node))
  554.         list_del(&root->node);
  555.     kfree(root);
  556.     return result;
  557. }
  558.  
  559.  
  560. static const struct acpi_device_ids root_device_ids[] =
  561. {
  562.     {"PNP0A03", 0},
  563.     {"",        0},
  564. };
  565.  
  566. void acpi_init_pci(struct acpi_device *device)
  567. {
  568.     struct acpi_device *child;
  569.  
  570.     if ( !acpi_match_device_ids(device, root_device_ids) )
  571.     {
  572.         dbgprintf(PREFIX "PCI root %s\n", device->pnp.bus_id);
  573.         acpi_pci_root_add(device);
  574.     };
  575.  
  576.     list_for_each_entry(child, &device->children, node)
  577.     {
  578.         acpi_init_pci(child);
  579.     };
  580.  
  581. };
  582.  
  583.  
  584. u32_t drvEntry(int action, char *cmdline)
  585. {
  586.     u32_t retval;
  587.  
  588.     ACPI_STATUS status;
  589.  
  590.     int i;
  591.  
  592.     if(action != 1)
  593.         return 0;
  594.  
  595.     if( !dbg_open("/rd/1/drivers/acpi.log") )
  596.     {
  597.         printf("Can't open /rd/1/drivers/acpi.log\nExit\n");
  598.         return 0;
  599.     }
  600.  
  601.     status = AcpiReallocateRootTable();
  602.     if (ACPI_FAILURE(status)) {
  603.         dbgprintf("Unable to reallocate ACPI tables\n");
  604.         goto err;
  605.     }
  606.  
  607.     status = AcpiInitializeSubsystem();
  608.     if (status != AE_OK) {
  609.           dbgprintf("AcpiInitializeSubsystem failed (%s)\n",
  610.                      AcpiFormatException(status));
  611.           goto err;
  612.     }
  613.  
  614.     status = AcpiInitializeTables(NULL, 0, TRUE);
  615.     if (status != AE_OK) {
  616.           dbgprintf("AcpiInitializeTables failed (%s)\n",
  617.                      AcpiFormatException(status));
  618.           goto err;
  619.     }
  620.  
  621.     status = AcpiLoadTables();
  622.     if (status != AE_OK) {
  623.           dbgprintf("AcpiLoadTables failed (%s)\n",
  624.                      AcpiFormatException(status));
  625.           goto err;
  626.     }
  627.  
  628. //    u32_t mode = ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE;
  629.  
  630.     status = AcpiEnableSubsystem(0);
  631.     if (status != AE_OK) {
  632.         dbgprintf("AcpiEnableSubsystem failed (%s)\n",
  633.             AcpiFormatException(status));
  634.         goto err;
  635.     }
  636.  
  637.     status = AcpiInitializeObjects (0);
  638.     if (ACPI_FAILURE (status))
  639.     {
  640.         dbgprintf("AcpiInitializeObjects failed (%s)\n",
  641.             AcpiFormatException(status));
  642.         goto err;
  643.     }
  644.  
  645.  
  646.     set_pic_mode(IO_APIC);
  647.  
  648.     acpi_scan();
  649.  
  650. //    print_device_tree(acpi_root);
  651.  
  652.     acpi_init_pci(acpi_root);
  653.  
  654. /*
  655.     ACPI_HANDLE bus_handle;
  656.     ACPI_HANDLE pci_root;
  657.  
  658.     status = AcpiGetHandle(0, "\\_SB_", &bus_handle);
  659.     dbgprintf("system bus handle %x\n", bus_handle);
  660.  
  661.     status = AcpiGetHandle(bus_handle, "PCI0", &pci_root);
  662.     if (status != AE_OK) {
  663.           dbgprintf("AcpiGetHandle failed (%s)\n",
  664.                      AcpiFormatException(status));
  665.           goto err;
  666.     }
  667.  
  668.     AcpiWalkNamespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, 100,
  669.                       get_device_by_hid_callback, NULL, NULL, NULL);
  670. */
  671.  
  672. #if 0
  673.  
  674.     AcpiWalkNamespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 4,
  675.                       get_device_by_hid_callback, NULL, NULL, NULL);
  676.  
  677.     ACPI_OBJECT obj;
  678.     ACPI_HANDLE bus_handle;
  679.     ACPI_HANDLE pci_root;
  680.  
  681.     status = AcpiGetHandle(0, "\\_SB_", &bus_handle);
  682.     dbgprintf("system bus handle %x\n", bus_handle);
  683.  
  684.     status = AcpiGetHandle(bus_handle, "PCI0", &pci_root);
  685.  
  686.     if (status != AE_OK) {
  687.         dbgprintf("AcpiGetHandle failed (%s)\n",
  688.             AcpiFormatException(status));
  689.         goto err;
  690.     }
  691.  
  692.     dbgprintf("pci root handle %x\n\n", pci_root);
  693.  
  694.     ACPI_BUFFER prt_buffer;
  695.  
  696.     prt_buffer.Length = ACPI_ALLOCATE_BUFFER;
  697.     prt_buffer.Pointer = NULL;
  698.  
  699.     status = AcpiGetIrqRoutingTable(pci_root, &prt_buffer);
  700.  
  701.     if (status != AE_OK) {
  702.         dbgprintf("AcpiGetIrqRoutingTable failed (%s)\n",
  703.             AcpiFormatException(status));
  704.         goto err;
  705.     }
  706.  
  707.     prt_walk_table(&prt_buffer);
  708.  
  709.  
  710.     ACPI_OBJECT arg = { ACPI_TYPE_INTEGER };
  711.     ACPI_OBJECT_LIST arg_list = { 1, &arg };
  712.  
  713.     arg.Integer.Value = ACPI_IRQ_MODEL_IOAPIC;
  714.  
  715.     dbgprintf("\nset ioapic mode\n\n");
  716.  
  717.     status = AcpiEvaluateObject(NULL, "\\_PIC", &arg_list, NULL);
  718.  
  719.     if (ACPI_FAILURE(status)) {
  720.         dbgprintf("AcpiEvaluateObject failed (%s)\n",
  721.             AcpiFormatException(status));
  722.  //       goto err;
  723.     }
  724.  
  725.  
  726.     status = AcpiGetIrqRoutingTable(pci_root, &prt_buffer);
  727.  
  728.     if (status != AE_OK) {
  729.         dbgprintf("AcpiGetIrqRoutingTable failed (%s)\n",
  730.             AcpiFormatException(status));
  731.         goto err;
  732.     }
  733.  
  734.     prt_walk_table(&prt_buffer);
  735.  
  736.     u8_t pin = PciRead8 (0, (31<<3) | 1, 0x3D);
  737.     dbgprintf("bus 0 device 31 function 1 pin %d\n", pin-1);
  738.  
  739.     pin = PciRead8 (0, (31<<3) | 2, 0x3D);
  740.     dbgprintf("bus 0 device 31 function 2 pin %d\n", pin-1);
  741.  
  742.     pin = PciRead8 (0, (31<<3) | 3, 0x3D);
  743.     dbgprintf("bus 0 device 31 function 3 pin %d\n", pin-1);
  744.  
  745.     pin = PciRead8 (0, (31<<3) | 4, 0x3D);
  746.     dbgprintf("bus 0 device 31 function 4 pin %d\n", pin-1);
  747.  
  748.     pin = PciRead8 (0, (31<<3) | 5, 0x3D);
  749.     dbgprintf("bus 0 device 31 function 5 pin %d\n", pin-1);
  750.  
  751.     pin = PciRead8 (0, (31<<3) | 6, 0x3D);
  752.     dbgprintf("bus 0 device 31 function 6 pin %d\n", pin-1);
  753.  
  754.     pin = PciRead8 (0, (31<<3) | 7, 0x3D);
  755.     dbgprintf("bus 0 device 31 function 7 pin %d\n", pin-1);
  756. #endif
  757.  
  758. err:
  759.  
  760.     return 0;
  761.  
  762. };
  763.  
  764. #if 0
  765.  
  766. ACPI_STATUS
  767. get_device_by_hid_callback(ACPI_HANDLE obj, u32_t depth, void* context,
  768.     void** retval)
  769. {
  770.     static u32_t counter = 0;
  771.     static char buff[256];
  772.  
  773.     ACPI_STATUS status;
  774.  
  775.     ACPI_BUFFER buffer;
  776.  
  777.     ACPI_DEVICE_INFO *info;
  778.  
  779.    // *retval = NULL;
  780.  
  781.     buffer.Length = 255;
  782.     buffer.Pointer = buff;
  783.  
  784.     status = AcpiGetName(obj, ACPI_FULL_PATHNAME, &buffer);
  785.     if (status != AE_OK) {
  786.         return AE_CTRL_TERMINATE;
  787.     }
  788.  
  789.     buff[buffer.Length] = '\0';
  790.  
  791.     dbgprintf("device %d %s ", counter, buff);
  792.  
  793.     status = AcpiGetObjectInfo(obj, &info);
  794.  
  795.     if (ACPI_SUCCESS (status))
  796.     {
  797.         if (info->Valid & ACPI_VALID_HID)
  798.             dbgprintf (" HID: %s", info->HardwareId.String);
  799.  
  800.     };
  801.  
  802.     dbgprintf("\n");
  803.     counter++;
  804.  
  805.     return AE_OK;
  806. }
  807.  
  808. prt_walk_table(ACPI_BUFFER *prt)
  809. {
  810.     ACPI_PCI_ROUTING_TABLE *entry;
  811.     char *prtptr;
  812.  
  813.     /* First check to see if there is a table to walk. */
  814.     if (prt == NULL || prt->Pointer == NULL)
  815.         return;
  816.  
  817.     /* Walk the table executing the handler function for each entry. */
  818.     prtptr = prt->Pointer;
  819.     entry = (ACPI_PCI_ROUTING_TABLE *)prtptr;
  820.     while (entry->Length != 0)
  821.     {
  822.  
  823.         dbgprintf("adress: %x %x  ", (u32_t)(entry->Address>>32),
  824.                   (u32_t)entry->Address);
  825.         dbgprintf("pin: %d  index: %d  source: %s\n",
  826.                    entry->Pin,
  827.                    entry->SourceIndex,
  828.                    entry->Source);
  829.  
  830. //      handler(entry, arg);
  831.         prtptr += entry->Length;
  832.         entry = (ACPI_PCI_ROUTING_TABLE *)prtptr;
  833.     }
  834. }
  835.  
  836.  
  837. static void add_irq(unsigned dev, unsigned pin, u8_t irq)
  838. {
  839. //    assert(dev < PCI_MAX_DEVICES && pin < PCI_MAX_PINS);
  840.  
  841.     irqtable[dev * PCI_MAX_PINS + pin] = irq;
  842. }
  843.  
  844. static ACPI_STATUS get_irq_resource(ACPI_RESOURCE *res, void *context)
  845. {
  846.     ACPI_PCI_ROUTING_TABLE *tbl = (ACPI_PCI_ROUTING_TABLE *) context;
  847.  
  848.     if (res->Type == ACPI_RESOURCE_TYPE_IRQ)
  849.     {
  850.         ACPI_RESOURCE_IRQ *irq;
  851.  
  852.         irq = &res->Data.Irq;
  853.         add_irq(tbl->Address >> 16, tbl->Pin,
  854.                 irq->Interrupts[tbl->SourceIndex]);
  855.     } else if (res->Type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ)
  856.     {
  857.         ACPI_RESOURCE_EXTENDED_IRQ *irq;
  858.  
  859.         add_irq(tbl->Address >> 16, tbl->Pin,
  860.                 irq->Interrupts[tbl->SourceIndex]);
  861.     }
  862.  
  863.     return AE_OK;
  864. }
  865.  
  866. char buff[4096];
  867.  
  868. static ACPI_STATUS get_pci_irq_routing(ACPI_HANDLE handle)
  869. {
  870.     ACPI_STATUS status;
  871.     ACPI_BUFFER abuff;
  872.     ACPI_PCI_ROUTING_TABLE *tbl;
  873.  
  874.     abuff.Length = sizeof(buff);
  875.     abuff.Pointer = buff;
  876.  
  877.     status = AcpiGetIrqRoutingTable(handle, &abuff);
  878.     if (ACPI_FAILURE(status)) {
  879.         return AE_OK;
  880.     }
  881.  
  882.     for (tbl = (ACPI_PCI_ROUTING_TABLE *)abuff.Pointer; tbl->Length;
  883.             tbl = (ACPI_PCI_ROUTING_TABLE *)
  884.             ((char *)tbl + tbl->Length))
  885.     {
  886.         ACPI_HANDLE src_handle;
  887.  
  888.         if (*(char*)tbl->Source == '\0') {
  889.             add_irq(tbl->Address >> 16, tbl->Pin, tbl->SourceIndex);
  890.             continue;
  891.         }
  892.  
  893.         status = AcpiGetHandle(handle, tbl->Source, &src_handle);
  894.         if (ACPI_FAILURE(status)) {
  895.             printf("Failed AcpiGetHandle\n");
  896.             continue;
  897.         }
  898.         status = AcpiWalkResources(src_handle, METHOD_NAME__CRS,
  899.                 get_irq_resource, tbl);
  900.         if (ACPI_FAILURE(status)) {
  901.             printf("Failed IRQ resource\n");
  902.             continue;
  903.         }
  904.     }
  905.  
  906.     return AE_OK;
  907. }
  908.  
  909. static ACPI_STATUS add_pci_root_dev(ACPI_HANDLE handle,
  910.                 UINT32 level,
  911.                 void *context,
  912.                 void **retval)
  913. {
  914.     int i;
  915.     static unsigned called;
  916.  
  917.     if (++called > 1) {
  918.         dbgprintf("ACPI: Warning! Multi rooted PCI is not supported!\n");
  919.         return AE_OK;
  920.     }
  921.  
  922.     for (i = 0; i < IRQ_TABLE_ENTRIES; i++)
  923.         irqtable[i] = -1;
  924.  
  925.     return get_pci_irq_routing(handle);
  926. }
  927.  
  928. static ACPI_STATUS add_pci_dev(ACPI_HANDLE handle,
  929.                 UINT32 level,
  930.                 void *context,
  931.                 void **retval)
  932. {
  933.     /* skip pci root when we get to it again */
  934.     if (handle == pci_root_handle)
  935.         return AE_OK;
  936.  
  937.     return get_pci_irq_routing(handle);
  938. }
  939.  
  940. static void scan_devices(void)
  941. {
  942.     ACPI_STATUS status;
  943.  
  944.     /* get the root first */
  945.     status = AcpiGetDevices("PNP0A03", add_pci_root_dev, NULL, NULL);
  946.     if (status != AE_OK) {
  947.         dbgprintf("scan_devices failed (%s)\n",
  948.                    AcpiFormatException(status));
  949.           return;
  950.     }
  951.  
  952. //    assert(ACPI_SUCCESS(status));
  953.  
  954.     /* get the rest of the devices that implement _PRT */
  955.     status = AcpiGetDevices(NULL, add_pci_dev, NULL, NULL);
  956. //    assert(ACPI_SUCCESS(status));
  957. }
  958.  
  959. #endif
  960.  
  961. char* strdup(const char *str)
  962. {
  963.     size_t len = strlen (str) + 1;
  964.     char *copy = malloc(len);
  965.     if (copy)
  966.     {
  967.         memcpy (copy, str, len);
  968.     }
  969.     return copy;
  970. }
  971.  
  972.