Subversion Repositories Kolibri OS

Rev

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

  1.  
  2.  
  3. #include <ddk.h>
  4. #include <linux/errno.h>
  5. #include <mutex.h>
  6. #include <pci.h>
  7. #include <syscall.h>
  8.  
  9. #include "acpi.h"
  10. #include "acpi_bus.h"
  11.  
  12.  
  13. #define PREFIX "ACPI: "
  14.  
  15. #define ACPI_BUS_CLASS          "system_bus"
  16. #define ACPI_BUS_HID            "KLBSYBUS"
  17. #define ACPI_BUS_DEVICE_NAME    "System Bus"
  18.  
  19.  
  20. #define ACPI_IS_ROOT_DEVICE(device)    (!(device)->parent)
  21.  
  22. #define STRUCT_TO_INT(s)        (*((int*)&s))
  23.  
  24.  
  25. extern struct acpi_device *acpi_root;
  26.  
  27. extern struct list_head acpi_device_list;
  28. extern struct list_head acpi_bus_id_list;
  29.  
  30. DEFINE_MUTEX(acpi_device_lock);
  31.  
  32.  
  33. struct acpi_device_bus_id{
  34.         char bus_id[15];
  35.         unsigned int instance_no;
  36.         struct list_head node;
  37. };
  38.  
  39.  
  40. struct acpi_hardware_id {
  41.     struct list_head list;
  42.     char *id;
  43. };
  44.  
  45. #define acpi_device_name(d) ((d)->pnp.device_name)
  46. #define acpi_device_class(d)    ((d)->pnp.device_class)
  47.  
  48.  
  49. static void
  50. acpi_util_eval_error(ACPI_HANDLE h, ACPI_STRING p, ACPI_STATUS s)
  51. {
  52. #ifdef ACPI_DEBUG_OUTPUT
  53.     char prefix[80] = {'\0'};
  54.     ACPI_BUFFER buffer = {sizeof(prefix), prefix};
  55.     AcpiGetName(h, ACPI_FULL_PATHNAME, &buffer);
  56.     ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluate [%s.%s]: %s\n",
  57.         (char *) prefix, p, AcpiFormatException(s)));
  58. #else
  59.     return;
  60. #endif
  61. }
  62.  
  63. ACPI_STATUS
  64. acpi_evaluate_integer(ACPI_HANDLE handle, ACPI_STRING pathname,
  65.               ACPI_OBJECT_LIST *arguments, unsigned long long *data)
  66. {
  67.     ACPI_STATUS status = AE_OK;
  68.     ACPI_OBJECT element;
  69.     ACPI_BUFFER buffer = { 0, NULL };
  70.  
  71.     if (!data)
  72.         return AE_BAD_PARAMETER;
  73.  
  74.     buffer.Length = sizeof(ACPI_OBJECT);
  75.     buffer.Pointer = &element;
  76.     status = AcpiEvaluateObject(handle, pathname, arguments, &buffer);
  77.     if (ACPI_FAILURE(status)) {
  78.         acpi_util_eval_error(handle, pathname, status);
  79.         return status;
  80.     }
  81.  
  82.     if (element.Type != ACPI_TYPE_INTEGER) {
  83.         acpi_util_eval_error(handle, pathname, AE_BAD_DATA);
  84.         return AE_BAD_DATA;
  85.     }
  86.  
  87.     *data = element.Integer.Value;
  88.  
  89.     ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%llu]\n", *data));
  90.  
  91.     return AE_OK;
  92. }
  93.  
  94.  
  95. void acpi_bus_data_handler(ACPI_HANDLE handle, void *context)
  96. {
  97.  
  98.     /* TBD */
  99.  
  100.     return;
  101. }
  102.  
  103. int acpi_bus_get_device(ACPI_HANDLE handle, struct acpi_device **device)
  104. {
  105.     ACPI_STATUS status = AE_OK;
  106.  
  107.     if (!device)
  108.     {
  109.         return -EINVAL;
  110.     };
  111.  
  112.     /* TBD: Support fixed-feature devices */
  113.  
  114.     status = AcpiGetData(handle, acpi_bus_data_handler, (void **)device);
  115.     if (ACPI_FAILURE(status) || !*device) {
  116.         ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n",
  117.                   handle));
  118.         return -ENODEV;
  119.     }
  120.     return 0;
  121. }
  122.  
  123.  
  124. ACPI_STATUS acpi_bus_get_status_handle(ACPI_HANDLE handle,
  125.                        unsigned long long *sta)
  126. {
  127.     ACPI_STATUS status;
  128.  
  129.     status = acpi_evaluate_integer(handle, "_STA", NULL, sta);
  130.     if (ACPI_SUCCESS(status))
  131.     {
  132.         return AE_OK;
  133.     };
  134.  
  135.     if (status == AE_NOT_FOUND)
  136.     {
  137.         *sta = ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED |
  138.                ACPI_STA_DEVICE_UI      | ACPI_STA_DEVICE_FUNCTIONING;
  139.         return AE_OK;
  140.     }
  141.     return status;
  142. }
  143.  
  144.  
  145.  
  146. /* --------------------------------------------------------------------------
  147.                         ACPI Bus operations
  148.    -------------------------------------------------------------------------- */
  149.  
  150. int acpi_match_device_ids(struct acpi_device *device,
  151.               const struct acpi_device_ids *ids)
  152. {
  153.     const struct acpi_device_ids *id;
  154.     struct acpi_hardware_id *hwid;
  155.  
  156.     /*
  157.      * If the device is not present, it is unnecessary to load device
  158.      * driver for it.
  159.      */
  160. //    if (!device->status.present)
  161. //        return -ENODEV;
  162.  
  163.     for (id = ids; id->id[0]; id++)
  164.         list_for_each_entry(hwid, &device->pnp.ids, list)
  165.             if (!strcmp((char *) id->id, hwid->id))
  166.                 return 0;
  167.  
  168.     return -ENOENT;
  169. }
  170.  
  171.  
  172. static int acpi_device_register(struct acpi_device *device)
  173. {
  174.     int result;
  175.     struct acpi_device_bus_id *acpi_device_bus_id, *new_bus_id;
  176.     int found = 0;
  177.  
  178.     /*
  179.      * Linkage
  180.      * -------
  181.      * Link this device to its parent and siblings.
  182.      */
  183.     INIT_LIST_HEAD(&device->children);
  184.     INIT_LIST_HEAD(&device->node);
  185.  
  186.     new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL);
  187.     if (!new_bus_id) {
  188.                 printk(KERN_ERR PREFIX "Memory allocation error\n");
  189.         return -ENOMEM;
  190.     }
  191.  
  192.     mutex_lock(&acpi_device_lock);
  193.     /*
  194.      * Find suitable bus_id and instance number in acpi_bus_id_list
  195.      * If failed, create one and link it into acpi_bus_id_list
  196.      */
  197.     list_for_each_entry(acpi_device_bus_id, &acpi_bus_id_list, node)
  198.     {
  199.                 if (!strcmp(acpi_device_bus_id->bus_id,
  200.                 acpi_device_hid(device)))
  201.         {
  202.             acpi_device_bus_id->instance_no++;
  203.             found = 1;
  204.             kfree(new_bus_id);
  205.             break;
  206.         }
  207.     };
  208.  
  209.     if (!found)
  210.     {
  211.         acpi_device_bus_id = new_bus_id;
  212.         strcpy(acpi_device_bus_id->bus_id, acpi_device_hid(device));
  213.         acpi_device_bus_id->instance_no = 0;
  214.         list_add_tail(&acpi_device_bus_id->node, &acpi_bus_id_list);
  215.     }
  216.  
  217. //    dev_set_name(&device->dev, "%s:%02x", acpi_device_bus_id->bus_id, acpi_device_bus_id->instance_no);
  218.  
  219.     if (device->parent)
  220.         list_add_tail(&device->node, &device->parent->children);
  221.  
  222.     mutex_unlock(&acpi_device_lock);
  223.  
  224. //    device->dev.bus = &acpi_bus_type;
  225. //    device->dev.release = &acpi_device_release;
  226. //    result = device_register(&device->dev);
  227. //    if (result) {
  228. //        dev_err(&device->dev, "Error registering device\n");
  229. //        goto end;
  230. //    }
  231.  
  232.  
  233. //    device->removal_type = ACPI_BUS_REMOVAL_NORMAL;
  234.     return 0;
  235. end:
  236.     mutex_lock(&acpi_device_lock);
  237.     if (device->parent)
  238.         list_del(&device->node);
  239.     mutex_unlock(&acpi_device_lock);
  240.     return result;
  241. }
  242.  
  243.  
  244. static struct acpi_device *acpi_bus_get_parent(ACPI_HANDLE handle)
  245. {
  246.     ACPI_STATUS status;
  247.     struct      acpi_device *device;
  248.     int         ret;
  249.  
  250.     /*
  251.      * Fixed hardware devices do not appear in the namespace and do not
  252.      * have handles, but we fabricate acpi_devices for them, so we have
  253.      * to deal with them specially.
  254.      */
  255.     if (handle == NULL)
  256.         return acpi_root;
  257.  
  258.         do {
  259.         status = AcpiGetParent(handle, &handle);
  260.         if (status == AE_NULL_ENTRY)
  261.             return NULL;
  262.         if (ACPI_FAILURE(status))
  263.             return acpi_root;
  264.  
  265.         ret = acpi_bus_get_device(handle, &device);
  266.         if (ret == 0)
  267.             return device;
  268.     } while (1);
  269. }
  270.  
  271.  
  272. static int acpi_bus_get_flags(struct acpi_device *device)
  273. {
  274.     ACPI_STATUS status = AE_OK;
  275.     ACPI_HANDLE temp   = NULL;
  276.  
  277.     /* Presence of _STA indicates 'dynamic_status' */
  278.     status = AcpiGetHandle(device->handle, "_STA", &temp);
  279.     if (ACPI_SUCCESS(status))
  280.         device->flags.dynamic_status = 1;
  281.  
  282.     /* Presence of _RMV indicates 'removable' */
  283.     status = AcpiGetHandle(device->handle, "_RMV", &temp);
  284.     if (ACPI_SUCCESS(status))
  285.         device->flags.removable = 1;
  286.  
  287.     /* Presence of _EJD|_EJ0 indicates 'ejectable' */
  288.     status = AcpiGetHandle(device->handle, "_EJD", &temp);
  289.     if (ACPI_SUCCESS(status))
  290.         device->flags.ejectable = 1;
  291.     else {
  292.         status = AcpiGetHandle(device->handle, "_EJ0", &temp);
  293.         if (ACPI_SUCCESS(status))
  294.             device->flags.ejectable = 1;
  295.     }
  296.  
  297.     /* Presence of _LCK indicates 'lockable' */
  298.     status = AcpiGetHandle(device->handle, "_LCK", &temp);
  299.     if (ACPI_SUCCESS(status))
  300.         device->flags.lockable = 1;
  301.  
  302.     /* Presence of _PS0|_PR0 indicates 'power manageable' */
  303.     status = AcpiGetHandle(device->handle, "_PS0", &temp);
  304.     if (ACPI_FAILURE(status))
  305.         status = AcpiGetHandle(device->handle, "_PR0", &temp);
  306.     if (ACPI_SUCCESS(status))
  307.         device->flags.power_manageable = 1;
  308.  
  309.     /* Presence of _PRW indicates wake capable */
  310.     status = AcpiGetHandle(device->handle, "_PRW", &temp);
  311.     if (ACPI_SUCCESS(status))
  312.         device->flags.wake_capable = 1;
  313.  
  314.     /* TBD: Performance management */
  315.  
  316.     return 0;
  317. }
  318.  
  319. static void acpi_device_get_busid(struct acpi_device *device)
  320. {
  321.     char bus_id[5] = { '?', 0 };
  322.     struct acpi_buffer buffer = { sizeof(bus_id), bus_id };
  323.     int i = 0;
  324.  
  325.     /*
  326.      * Bus ID
  327.      * ------
  328.      * The device's Bus ID is simply the object name.
  329.      * TBD: Shouldn't this value be unique (within the ACPI namespace)?
  330.      */
  331.     if (ACPI_IS_ROOT_DEVICE(device)) {
  332.         strcpy(device->pnp.bus_id, "ACPI");
  333.         return;
  334.     }
  335.  
  336.     switch (device->device_type)
  337.     {
  338.         case ACPI_BUS_TYPE_POWER_BUTTON:
  339.             strcpy(device->pnp.bus_id, "PWRF");
  340.             break;
  341.         case ACPI_BUS_TYPE_SLEEP_BUTTON:
  342.             strcpy(device->pnp.bus_id, "SLPF");
  343.             break;
  344.         default:
  345.             AcpiGetName(device->handle, ACPI_SINGLE_NAME, &buffer);
  346.         /* Clean up trailing underscores (if any) */
  347.                 for (i = 3; i > 1; i--) {
  348.                 if (bus_id[i] == '_')
  349.                     bus_id[i] = '\0';
  350.                 else
  351.                     break;
  352.             }
  353.             strcpy(device->pnp.bus_id, bus_id);
  354.             break;
  355.     }
  356. }
  357.  
  358.  
  359. #define ACPI_VIDEO_OUTPUT_SWITCHING         0x0001
  360. #define ACPI_VIDEO_DEVICE_POSTING           0x0002
  361. #define ACPI_VIDEO_ROM_AVAILABLE            0x0004
  362. #define ACPI_VIDEO_BACKLIGHT                0x0008
  363. #define ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR       0x0010
  364. #define ACPI_VIDEO_BACKLIGHT_FORCE_VIDEO        0x0020
  365. #define ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VENDOR    0x0040
  366. #define ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO     0x0080
  367. #define ACPI_VIDEO_BACKLIGHT_DMI_VENDOR         0x0100
  368. #define ACPI_VIDEO_BACKLIGHT_DMI_VIDEO          0x0200
  369. #define ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VENDOR      0x0400
  370. #define ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VIDEO       0x0800
  371.  
  372.  
  373. long acpi_is_video_device(struct acpi_device *device)
  374. {
  375.     ACPI_HANDLE h_dummy;
  376.     long video_caps = 0;
  377.  
  378.     if (!device)
  379.         return 0;
  380.  
  381.     /* Is this device able to support video switching ? */
  382.     if (ACPI_SUCCESS(AcpiGetHandle(device->handle, "_DOD", &h_dummy)) ||
  383.         ACPI_SUCCESS(AcpiGetHandle(device->handle, "_DOS", &h_dummy)))
  384.         video_caps |= ACPI_VIDEO_OUTPUT_SWITCHING;
  385.  
  386.     /* Is this device able to retrieve a video ROM ? */
  387.     if (ACPI_SUCCESS(AcpiGetHandle(device->handle, "_ROM", &h_dummy)))
  388.         video_caps |= ACPI_VIDEO_ROM_AVAILABLE;
  389.  
  390.     /* Is this device able to configure which video head to be POSTed ? */
  391.     if (ACPI_SUCCESS(AcpiGetHandle(device->handle, "_VPO", &h_dummy)) &&
  392.         ACPI_SUCCESS(AcpiGetHandle(device->handle, "_GPD", &h_dummy)) &&
  393.         ACPI_SUCCESS(AcpiGetHandle(device->handle, "_SPD", &h_dummy)))
  394.         video_caps |= ACPI_VIDEO_DEVICE_POSTING;
  395.  
  396.      return video_caps;
  397. }
  398.  
  399. /*
  400.  * acpi_bay_match - see if a device is an ejectable driver bay
  401.  *
  402.  * If an acpi object is ejectable and has one of the ACPI ATA methods defined,
  403.  * then we can safely call it an ejectable drive bay
  404.  */
  405. static int acpi_bay_match(struct acpi_device *device){
  406.     ACPI_STATUS status;
  407.     ACPI_HANDLE handle;
  408.     ACPI_HANDLE tmp;
  409.     ACPI_HANDLE phandle;
  410.  
  411.     handle = device->handle;
  412.  
  413.     status = AcpiGetHandle(handle, "_EJ0", &tmp);
  414.     if (ACPI_FAILURE(status))
  415.         return -ENODEV;
  416.  
  417.     if ((ACPI_SUCCESS(AcpiGetHandle(handle, "_GTF", &tmp))) ||
  418.         (ACPI_SUCCESS(AcpiGetHandle(handle, "_GTM", &tmp))) ||
  419.         (ACPI_SUCCESS(AcpiGetHandle(handle, "_STM", &tmp))) ||
  420.         (ACPI_SUCCESS(AcpiGetHandle(handle, "_SDD", &tmp))))
  421.         return 0;
  422.  
  423.     if (AcpiGetParent(handle, &phandle))
  424.         return -ENODEV;
  425.  
  426.     if ((ACPI_SUCCESS(AcpiGetHandle(phandle, "_GTF", &tmp))) ||
  427.         (ACPI_SUCCESS(AcpiGetHandle(phandle, "_GTM", &tmp))) ||
  428.         (ACPI_SUCCESS(AcpiGetHandle(phandle, "_STM", &tmp))) ||
  429.         (ACPI_SUCCESS(AcpiGetHandle(phandle, "_SDD", &tmp))))
  430.         return 0;
  431.  
  432.     return -ENODEV;
  433. }
  434.  
  435. /*
  436.  * acpi_dock_match - see if a device has a _DCK method
  437.  */
  438. static int acpi_dock_match(struct acpi_device *device)
  439. {
  440.     ACPI_HANDLE tmp;
  441.     return AcpiGetHandle(device->handle, "_DCK", &tmp);
  442. }
  443.  
  444. char *acpi_device_hid(struct acpi_device *device)
  445. {
  446.     struct acpi_hardware_id *hid;
  447.  
  448.     hid = list_first_entry(&device->pnp.ids, struct acpi_hardware_id, list);
  449.     return hid->id;
  450. }
  451.  
  452. static void acpi_add_id(struct acpi_device *device, const char *dev_id)
  453. {
  454.     struct acpi_hardware_id *id;
  455.  
  456.     id = kmalloc(sizeof(*id), GFP_KERNEL);
  457.     if (!id)
  458.         return;
  459.  
  460.     INIT_LIST_HEAD(&id->list);
  461.  
  462.     id->id = kmalloc(strlen(dev_id) + 1, GFP_KERNEL);
  463.     if (!id->id) {
  464.         kfree(id);
  465.         return;
  466.     }
  467.  
  468.     strcpy(id->id, dev_id);
  469.     list_add_tail(&id->list, &device->pnp.ids);
  470. }
  471.  
  472.  
  473.  
  474. static void acpi_device_set_id(struct acpi_device *device)
  475. {
  476.     ACPI_STATUS status;
  477.     ACPI_DEVICE_INFO *info;
  478.     ACPI_DEVICE_ID_LIST *cid_list;
  479.     int i;
  480.  
  481.     switch (device->device_type)
  482.     {
  483.         case ACPI_BUS_TYPE_DEVICE:
  484.                 if (ACPI_IS_ROOT_DEVICE(device)) {
  485.                 acpi_add_id(device, ACPI_SYSTEM_HID);
  486.                 break;
  487.             }
  488.  
  489.             status = AcpiGetObjectInfo(device->handle, &info);
  490.             if (ACPI_FAILURE(status)) {
  491.                 printk(KERN_ERR PREFIX "%s: Error reading device info\n", __func__);
  492.                 return;
  493.             }
  494.  
  495.             if (info->Valid & ACPI_VALID_HID)
  496.                 acpi_add_id(device, info->HardwareId.String);
  497.             if (info->Valid & ACPI_VALID_CID)
  498.             {
  499.                 cid_list = &info->CompatibleIdList;
  500.                 for (i = 0; i < cid_list->Count; i++)
  501.                     acpi_add_id(device, cid_list->Ids[i].String);
  502.             }
  503.             if (info->Valid & ACPI_VALID_ADR) {
  504.                 device->pnp.bus_address = info->Address;
  505.                 device->flags.bus_address = 1;
  506.             }
  507.  
  508.             kfree(info);
  509.  
  510.         /*
  511.          * Some devices don't reliably have _HIDs & _CIDs, so add
  512.          * synthetic HIDs to make sure drivers can find them.
  513.          */
  514.         if (acpi_is_video_device(device))
  515.             acpi_add_id(device, ACPI_VIDEO_HID);
  516.         else if (ACPI_SUCCESS(acpi_bay_match(device)))
  517.             acpi_add_id(device, ACPI_BAY_HID);
  518.         else if (ACPI_SUCCESS(acpi_dock_match(device)))
  519.             acpi_add_id(device, ACPI_DOCK_HID);
  520.         else if (!acpi_device_hid(device) &&
  521.              ACPI_IS_ROOT_DEVICE(device->parent)) {
  522.             acpi_add_id(device, ACPI_BUS_HID); /* \_SB, LNXSYBUS */
  523.             strcpy(device->pnp.device_name, ACPI_BUS_DEVICE_NAME);
  524.             strcpy(device->pnp.device_class, ACPI_BUS_CLASS);
  525.         }
  526.  
  527.         break;
  528.     case ACPI_BUS_TYPE_POWER:
  529.         acpi_add_id(device, ACPI_POWER_HID);
  530.         break;
  531.     case ACPI_BUS_TYPE_PROCESSOR:
  532.         acpi_add_id(device, ACPI_PROCESSOR_OBJECT_HID);
  533.         break;
  534.     case ACPI_BUS_TYPE_THERMAL:
  535.         acpi_add_id(device, ACPI_THERMAL_HID);
  536.         break;
  537.     case ACPI_BUS_TYPE_POWER_BUTTON:
  538.         acpi_add_id(device, ACPI_BUTTON_HID_POWERF);
  539.         break;
  540.     case ACPI_BUS_TYPE_SLEEP_BUTTON:
  541.         acpi_add_id(device, ACPI_BUTTON_HID_SLEEPF);
  542.         break;
  543.     }
  544.  
  545.     /*
  546.      * We build acpi_devices for some objects that don't have _HID or _CID,
  547.      * e.g., PCI bridges and slots.  Drivers can't bind to these objects,
  548.      * but we do use them indirectly by traversing the acpi_device tree.
  549.      * This generic ID isn't useful for driver binding, but it provides
  550.      * the useful property that "every acpi_device has an ID."
  551.      */
  552.     if (list_empty(&device->pnp.ids))
  553.         acpi_add_id(device, "device");
  554. }
  555.  
  556. static int acpi_device_set_context(struct acpi_device *device)
  557. {
  558.     ACPI_STATUS status;
  559.  
  560.     /*
  561.      * Context
  562.      * -------
  563.      * Attach this 'struct acpi_device' to the ACPI object.  This makes
  564.      * resolutions from handle->device very efficient.  Fixed hardware
  565.      * devices have no handles, so we skip them.
  566.      */
  567.     if (!device->handle)
  568.         return 0;
  569.  
  570.     status = AcpiAttachData(device->handle,
  571.                   acpi_bus_data_handler, device);
  572.     if (ACPI_SUCCESS(status))
  573.         return 0;
  574.  
  575.         printk(KERN_ERR PREFIX "Error attaching device data\n");
  576.     return -ENODEV;
  577. }
  578.  
  579.  
  580. static int acpi_add_single_object(struct acpi_device **child,
  581.                   ACPI_HANDLE handle, int type,
  582.                   unsigned long long sta,
  583.                   struct acpi_bus_ops *ops)
  584. {
  585.     int result;
  586.     struct acpi_device *device;
  587.     ACPI_BUFFER buffer = { ACPI_ALLOCATE_BUFFER, NULL };
  588.     ACPI_DEVICE_INFO *info = NULL;
  589.     ACPI_DEVICE_ID_LIST *cid_list;
  590.     int i;
  591.  
  592.  
  593.     device = kzalloc(sizeof(struct acpi_device), GFP_KERNEL);
  594.     if (!device) {
  595.                 printk(KERN_ERR PREFIX "Memory allocation error\n");
  596.         return -ENOMEM;
  597.     }
  598.  
  599.     INIT_LIST_HEAD(&device->pnp.ids);
  600.     device->device_type = type;
  601.     device->handle = handle;
  602.     device->parent = acpi_bus_get_parent(handle);
  603.     device->bus_ops = *ops; /* workround for not call .start */
  604.     STRUCT_TO_INT(device->status) = sta;
  605.  
  606.     acpi_device_get_busid(device);
  607.  
  608.     /*
  609.      * Flags
  610.      * -----
  611.      * Note that we only look for object handles -- cannot evaluate objects
  612.      * until we know the device is present and properly initialized.
  613.      */
  614.     result = acpi_bus_get_flags(device);
  615.     if (result)
  616.         goto end;
  617.  
  618.     /*
  619.      * Initialize Device
  620.      * -----------------
  621.      * TBD: Synch with Core's enumeration/initialization process.
  622.      */
  623.     acpi_device_set_id(device);
  624.  
  625.  
  626.     if ((result = acpi_device_set_context(device)))
  627.         goto end;
  628.  
  629.     result = acpi_device_register(device);
  630.  
  631.     /*
  632.      * Bind _ADR-Based Devices when hot add
  633.      */
  634.     if (device->flags.bus_address) {
  635.         if (device->parent && device->parent->ops.bind)
  636.             device->parent->ops.bind(device);
  637.     }
  638.  
  639. end:
  640.  
  641.     AcpiGetName(handle, ACPI_FULL_PATHNAME, &buffer);
  642.     dbgprintf(PREFIX "Adding [%s]", (char *)buffer.Pointer);
  643.     kfree(buffer.Pointer);
  644.  
  645.     AcpiGetObjectInfo(handle, &info);
  646.     if (info->Valid & ACPI_VALID_HID)
  647.       dbgprintf (" HID: %s", info->HardwareId.String);
  648.  
  649.     if (info->Valid & ACPI_VALID_CID)
  650.     {
  651.         cid_list = &info->CompatibleIdList;
  652.         for (i = 0; i < cid_list->Count; i++)
  653.             dbgprintf("  CID: %s\n", cid_list->Ids[i].String);
  654.     }
  655.     dbgprintf("\n");
  656.  
  657.     kfree(info);
  658.  
  659.     if (!result) {
  660.         *child = device;
  661.     };
  662.     return result;
  663. }
  664.  
  665. #define ACPI_STA_DEFAULT (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | \
  666.                           ACPI_STA_DEVICE_UI      | ACPI_STA_DEVICE_FUNCTIONING)
  667.  
  668. static int acpi_bus_type_and_status(ACPI_HANDLE handle, int *type,
  669.                     unsigned long long *sta)
  670. {
  671.     ACPI_STATUS status;
  672.     ACPI_OBJECT_TYPE acpi_type;
  673.  
  674.     status = AcpiGetType(handle, &acpi_type);
  675.     if (ACPI_FAILURE(status))
  676.         return -ENODEV;
  677.  
  678.     switch (acpi_type)
  679.     {
  680.         case ACPI_TYPE_ANY:     /* for ACPI_ROOT_OBJECT */
  681.         case ACPI_TYPE_DEVICE:
  682.             *type = ACPI_BUS_TYPE_DEVICE;
  683.             status = acpi_bus_get_status_handle(handle, sta);
  684.             if (ACPI_FAILURE(status))
  685.                 return -ENODEV;
  686.             break;
  687.         case ACPI_TYPE_PROCESSOR:
  688.             *type = ACPI_BUS_TYPE_PROCESSOR;
  689.             status = acpi_bus_get_status_handle(handle, sta);
  690.             if (ACPI_FAILURE(status))
  691.                 return -ENODEV;
  692.             break;
  693.         case ACPI_TYPE_THERMAL:
  694.             *type = ACPI_BUS_TYPE_THERMAL;
  695.             *sta = ACPI_STA_DEFAULT;
  696.             break;
  697.         case ACPI_TYPE_POWER:
  698.             *type = ACPI_BUS_TYPE_POWER;
  699.             *sta = ACPI_STA_DEFAULT;
  700.             break;
  701.         default:
  702.             return -ENODEV;
  703.     }
  704.  
  705.     return 0;
  706. }
  707.  
  708.  
  709. static ACPI_STATUS acpi_bus_check_add(ACPI_HANDLE handle, u32 lvl,
  710.                       void *context, void **return_value)
  711. {
  712.     struct acpi_bus_ops *ops = context;
  713.     int type;
  714.     unsigned long long sta;
  715.     struct acpi_device *device;
  716.     ACPI_STATUS status;
  717.     int result;
  718.  
  719.     result = acpi_bus_type_and_status(handle, &type, &sta);
  720.     if (result)
  721.         return AE_OK;
  722.  
  723.     if (!(sta & ACPI_STA_DEVICE_PRESENT) &&
  724.         !(sta & ACPI_STA_DEVICE_FUNCTIONING))
  725.         return AE_CTRL_DEPTH;
  726.  
  727.     /*
  728.      * We may already have an acpi_device from a previous enumeration.  If
  729.      * so, we needn't add it again, but we may still have to start it.
  730.      */
  731.     device = NULL;
  732.     acpi_bus_get_device(handle, &device);
  733.     if (ops->acpi_op_add && !device)
  734.         acpi_add_single_object(&device, handle, type, sta, ops);
  735.  
  736.     if (!device)
  737.         return AE_CTRL_DEPTH;
  738.  
  739. /*
  740.     if (ops->acpi_op_start && !(ops->acpi_op_add)) {
  741.         status = acpi_start_single_object(device);
  742.         if (ACPI_FAILURE(status))
  743.             return AE_CTRL_DEPTH;
  744.     }
  745. */
  746.  
  747.     if (!*return_value)
  748.         *return_value = device;
  749.     return AE_OK;
  750. }
  751.  
  752.  
  753. static int acpi_bus_scan(ACPI_HANDLE handle, struct acpi_bus_ops *ops,
  754.              struct acpi_device **child)
  755. {
  756.     ACPI_STATUS status;
  757.     void *device = NULL;
  758.  
  759.     status = acpi_bus_check_add(handle, 0, ops, &device);
  760.     if (ACPI_SUCCESS(status))
  761.         AcpiWalkNamespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
  762.                     acpi_bus_check_add, NULL, ops, &device);
  763.  
  764.     if (child)
  765.         *child = device;
  766.  
  767.     if (device)
  768.         return 0;
  769.     else
  770.         return -ENODEV;
  771. }
  772.  
  773.  
  774. int acpi_scan()
  775. {
  776.     int err;
  777.     struct acpi_bus_ops ops;
  778.  
  779.     memset(&ops, 0, sizeof(ops));
  780.     ops.acpi_op_add = 1;
  781.     ops.acpi_op_start = 1;
  782.  
  783.     err = acpi_bus_scan(ACPI_ROOT_OBJECT, &ops, &acpi_root);
  784.  
  785.     return err;
  786. };
  787.  
  788.