Subversion Repositories Kolibri OS

Rev

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