sync with trunk r46493
[reactos.git] / drivers / bus / acpi / busmgr / bus.c
index 8858902..ae04c2c 100644 (file)
@@ -34,7 +34,7 @@
 #include <acpi_drivers.h>
 #include <glue.h>
 
-//#define NDEBUG
+#define NDEBUG
 #include <debug.h>
 
 #define _COMPONENT             ACPI_BUS_COMPONENT
@@ -48,7 +48,7 @@ ACPI_MODULE_NAME              ("acpi_bus")
 #define HAS_SIBLINGS(d)                (((d)->parent) && ((d)->node.next != &(d)->parent->children))
 #define NODE_TO_DEVICE(n)      (list_entry(n, struct acpi_device, node))
 
-extern int                     event_is_open;
+int                    event_is_open;
 extern void acpi_pic_sci_set_trigger(unsigned int irq, UINT16 trigger);
 
 typedef int (*acpi_bus_walk_callback)(struct acpi_device*, int, void*);
@@ -57,6 +57,8 @@ struct acpi_device            *acpi_root;
 KSPIN_LOCK     acpi_bus_event_lock;
 LIST_HEAD(acpi_bus_event_list);
 //DECLARE_WAIT_QUEUE_HEAD(acpi_bus_event_queue);
+KEVENT AcpiEventQueue;
+KDPC event_dpc;
 
 
 static int
@@ -454,6 +456,21 @@ acpi_bus_get_perf_flags (
                                 Event Management
    -------------------------------------------------------------------------- */
 
+void
+acpi_bus_generate_event_dpc(PKDPC Dpc,
+                            PVOID DeferredContext,
+                            PVOID SystemArgument1,
+                            PVOID SystemArgument2)
+{
+       struct acpi_bus_event *event = SystemArgument1;
+       KIRQL OldIrql;
+
+       KeAcquireSpinLock(&acpi_bus_event_lock, &OldIrql);
+       list_add_tail(&event->node, &acpi_bus_event_list);
+       KeReleaseSpinLock(&acpi_bus_event_lock, OldIrql);
+
+       KeSetEvent(&AcpiEventQueue, IO_NO_INCREMENT, FALSE);
+}
 
 int
 acpi_bus_generate_event (
@@ -462,16 +479,15 @@ acpi_bus_generate_event (
        int                     data)
 {
        struct acpi_bus_event   *event = NULL;
-       //unsigned long         flags = 0;
 
-       DPRINT1("acpi_bus_generate_event");
+       DPRINT("acpi_bus_generate_event");
 
        if (!device)
                return_VALUE(AE_BAD_PARAMETER);
 
        /* drop event on the floor if no one's listening */
-       //if (!event_is_open)
-       //      return_VALUE(0);
+       if (!event_is_open)
+               return_VALUE(0);
 
        event = ExAllocatePool(NonPagedPool,sizeof(struct acpi_bus_event));
        if (!event)
@@ -482,11 +498,8 @@ acpi_bus_generate_event (
        event->type = type;
        event->data = data;
 
-       //spin_lock_irqsave(&acpi_bus_event_lock, flags);
-       list_add_tail(&event->node, &acpi_bus_event_list);
-       //spin_unlock_irqrestore(&acpi_bus_event_lock, flags);
-
-       //wake_up_interruptible(&acpi_bus_event_queue);
+       if (!KeInsertQueueDpc(&event_dpc, event, NULL))
+           ExFreePool(event);
 
        return_VALUE(0);
 }
@@ -495,44 +508,43 @@ int
 acpi_bus_receive_event (
        struct acpi_bus_event   *event)
 {
-       //unsigned long         flags = 0;
-       //struct acpi_bus_event *entry = NULL;
+//     unsigned long           flags = 0;
+       struct acpi_bus_event   *entry = NULL;
+       KIRQL OldIrql;
 
        //DECLARE_WAITQUEUE(wait, current);
 
-       DPRINT1("acpi_bus_receive_event");
-
-       //if (!event)
-       //      return AE_BAD_PARAMETER;
-
-       //if (list_empty(&acpi_bus_event_list)) {
-
-       //      set_current_state(TASK_INTERRUPTIBLE);
-       //      add_wait_queue(&acpi_bus_event_queue, &wait);
+       DPRINT("acpi_bus_receive_event");
 
-       //      if (list_empty(&acpi_bus_event_list))
-       //              schedule();
+       if (!event)
+               return AE_BAD_PARAMETER;
 
-       //      remove_wait_queue(&acpi_bus_event_queue, &wait);
-       //      set_current_state(TASK_RUNNING);
+       event_is_open++;
+       KeWaitForSingleObject(&AcpiEventQueue,
+                             Executive,
+                             KernelMode,
+                             FALSE,
+                             NULL);
+       event_is_open--;
+       KeClearEvent(&AcpiEventQueue);
 
-       //      if (signal_pending(current))
-       //              return_VALUE(-ERESTARTSYS);
-       //}
+       if (list_empty(&acpi_bus_event_list))
+               return_VALUE(AE_NOT_FOUND);
 
-       //spin_lock_irqsave(&acpi_bus_event_lock, flags);
-       //entry = list_entry(acpi_bus_event_list.next, struct acpi_bus_event, node);
-       //if (entry)
-       //      list_del(&entry->node);
-       //spin_unlock_irqrestore(&acpi_bus_event_lock, flags);
+//     spin_lock_irqsave(&acpi_bus_event_lock, flags);
+       KeAcquireSpinLock(&acpi_bus_event_lock, &OldIrql);
+       entry = list_entry(acpi_bus_event_list.next, struct acpi_bus_event, node);
+       if (entry)
+               list_del(&entry->node);
+       KeReleaseSpinLock(&acpi_bus_event_lock, OldIrql);
+//     spin_unlock_irqrestore(&acpi_bus_event_lock, flags);
 
-       //if (!entry)
-       //      return_VALUE(AE_NOT_FOUND);
+       if (!entry)
+               return_VALUE(AE_NOT_FOUND);
 
-       //memcpy(event, entry, sizeof(struct acpi_bus_event));
+       memcpy(event, entry, sizeof(struct acpi_bus_event));
 
-       //kfree(entry);
-       UNIMPLEMENTED;
+       ExFreePool(entry);
        return_VALUE(0);
 }
 
@@ -789,6 +801,7 @@ acpi_bus_notify (
 
 static LIST_HEAD(acpi_bus_drivers);
 //static DECLARE_MUTEX(acpi_bus_drivers_lock);
+static FAST_MUTEX acpi_bus_drivers_lock;
 
 
 /**
@@ -914,9 +927,9 @@ acpi_bus_attach (
        if (result)
                return_VALUE(result);
 
-       //down(&acpi_bus_drivers_lock);
+       down(&acpi_bus_drivers_lock);
        ++driver->references;
-       //up(&acpi_bus_drivers_lock);
+       up(&acpi_bus_drivers_lock);
 
        return_VALUE(0);
 }
@@ -953,9 +966,9 @@ acpi_bus_unattach (
        device->driver = NULL;
        acpi_driver_data(device) = NULL;
 
-       //down(&acpi_bus_drivers_lock);
+       down(&acpi_bus_drivers_lock);
        driver->references--;
-       //up(&acpi_bus_drivers_lock);
+       up(&acpi_bus_drivers_lock);
 
        return_VALUE(0);
 }
@@ -978,7 +991,7 @@ acpi_bus_find_driver (
        if (!device || device->driver)
                return_VALUE(AE_BAD_PARAMETER);
 
-       //down(&acpi_bus_drivers_lock);
+       down(&acpi_bus_drivers_lock);
 
        list_for_each(entry, &acpi_bus_drivers) {
 
@@ -994,7 +1007,7 @@ acpi_bus_find_driver (
                break;
        }
 
-       //up(&acpi_bus_drivers_lock);
+       up(&acpi_bus_drivers_lock);
 
        return_VALUE(result);
 }
@@ -1016,9 +1029,9 @@ acpi_bus_register_driver (
        //if (acpi_disabled)
        //      return_VALUE(AE_NOT_FOUND);
 
-       //down(&acpi_bus_drivers_lock);
+       down(&acpi_bus_drivers_lock);
        list_add_tail(&driver->node, &acpi_bus_drivers);
-       //up(&acpi_bus_drivers_lock);
+       up(&acpi_bus_drivers_lock);
 
        acpi_bus_walk(acpi_root, acpi_bus_attach, 
                WALK_DOWN, driver);
@@ -1045,9 +1058,9 @@ acpi_bus_unregister_driver (
        if (driver->references)
                return;
 
-       //down(&acpi_bus_drivers_lock);
+       down(&acpi_bus_drivers_lock);
        list_del(&driver->node);
-       //up(&acpi_bus_drivers_lock);
+       up(&acpi_bus_drivers_lock);
 
        return;
 }
@@ -1148,9 +1161,11 @@ acpi_bus_add (
        case ACPI_BUS_TYPE_SYSTEM:
                sprintf(device->pnp.bus_id, "%s", "ACPI");
                break;
+       case ACPI_BUS_TYPE_POWER_BUTTONF:
        case ACPI_BUS_TYPE_POWER_BUTTON:
                sprintf(device->pnp.bus_id, "%s", "PWRF");
                break;
+       case ACPI_BUS_TYPE_SLEEP_BUTTONF:
        case ACPI_BUS_TYPE_SLEEP_BUTTON:
                sprintf(device->pnp.bus_id, "%s", "SLPF");
                break;
@@ -1257,9 +1272,15 @@ acpi_bus_add (
                hid = ACPI_THERMAL_HID;
                break;
        case ACPI_BUS_TYPE_POWER_BUTTON:
+               hid = ACPI_BUTTON_HID_POWER;
+               break;
+       case ACPI_BUS_TYPE_POWER_BUTTONF:
                hid = ACPI_BUTTON_HID_POWERF;
                break;
        case ACPI_BUS_TYPE_SLEEP_BUTTON:
+               hid = ACPI_BUTTON_HID_SLEEP;
+               break;
+       case ACPI_BUS_TYPE_SLEEP_BUTTONF:
                hid = ACPI_BUTTON_HID_SLEEPF;
                break;
        }
@@ -1321,7 +1342,9 @@ acpi_bus_add (
         */
        switch (type) {
        case ACPI_BUS_TYPE_POWER_BUTTON:
+       case ACPI_BUS_TYPE_POWER_BUTTONF:
        case ACPI_BUS_TYPE_SLEEP_BUTTON:
+       case ACPI_BUS_TYPE_SLEEP_BUTTONF:
                break;
        default:
                status = AcpiAttachData(device->handle,
@@ -1525,16 +1548,40 @@ acpi_bus_scan_fixed (
        if (!root)
                return_VALUE(AE_NOT_FOUND);
 
-       /*
-        * Enumerate all fixed-feature devices.
+       /* If ACPI_FADT_POWER_BUTTON is set, then a control
+        * method power button is present. Otherwise, a fixed
+        * power button is present.
         */
        if (AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON)
                result = acpi_bus_add(&device, acpi_root, 
                        NULL, ACPI_BUS_TYPE_POWER_BUTTON);
+       else
+       {
+               /* Enable the fixed power button so we get notified if it is pressed */
+               AcpiWriteBitRegister(ACPI_BITREG_POWER_BUTTON_ENABLE, 1);
 
+               result = acpi_bus_add(&device, acpi_root,
+                       NULL, ACPI_BUS_TYPE_POWER_BUTTONF);
+       }
+
+       /* This one is a bit more complicated and we do it wrong
+        * right now. If ACPI_FADT_SLEEP_BUTTON is set but no
+        * device object is present then no sleep button is present, but
+        * if the flags is clear and there is no device object then it is
+        * a fixed sleep button. If the flag is set and there is a device object
+        * the we have a control method button just like above.
+        */
        if (AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON)
                result = acpi_bus_add(&device, acpi_root, 
                        NULL, ACPI_BUS_TYPE_SLEEP_BUTTON);
+       else
+       {
+               /* Enable the fixed sleep button so we get notified if it is pressed */
+               AcpiWriteBitRegister(ACPI_BITREG_SLEEP_BUTTON_ENABLE, 1);
+
+               result = acpi_bus_add(&device, acpi_root,
+                       NULL, ACPI_BUS_TYPE_SLEEP_BUTTONF);
+       }
 
        return_VALUE(result);
 }
@@ -1544,120 +1591,6 @@ acpi_bus_scan_fixed (
                              Initialization/Cleanup
    -------------------------------------------------------------------------- */
 
-static int
-acpi_bus_init_irq (void)
-{
-       ACPI_STATUS             status = AE_OK;
-       ACPI_OBJECT     arg = {ACPI_TYPE_INTEGER};
-       ACPI_OBJECT_LIST        arg_list = {1, &arg};
-       //char                  *message = NULL;
-
-       DPRINT("acpi_bus_init_irq");
-
-       /* 
-        * Let the system know what interrupt model we are using by
-        * evaluating the \_PIC object, if exists.
-        */
-
-       //switch (acpi_irq_model) {
-       //case ACPI_IRQ_MODEL_PIC:
-       //      message = "PIC";
-       //      break;
-       //case ACPI_IRQ_MODEL_IOAPIC:
-       //      message = "IOAPIC";
-       //      break;
-       //case ACPI_IRQ_MODEL_IOSAPIC:
-       //      message = "IOSAPIC";
-       //      break;
-       //default:
-       //      DPRINT1("Unknown interrupt routing model\n");
-       //      return_VALUE(AE_NOT_FOUND);
-       //}
-
-       //DPRINT("Using %s for interrupt routing\n", message);
-
-       //arg.Integer.Value = acpi_irq_model;
-
-       //status = AcpiEvaluateObject(NULL, "\\_PIC", &arg_list, NULL);
-       //if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
-       //      ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PIC\n"));
-       //      return_VALUE(AE_NOT_FOUND);
-       //}
-
-       return_VALUE(0);
-}
-
-
-//void
-//acpi_early_init (void)
-//{
-//     ACPI_STATUS             status = AE_OK;
-//
-//     DPRINT("acpi_early_init");
-//
-//     if (acpi_disabled)
-//             return_VOID;
-//
-       /* enable workarounds, unless strict ACPI spec. compliance */
-//     if (!acpi_strict)
-//             acpi_gbl_enable_interpreter_slack = TRUE;
-//
-//     status = acpi_reallocate_root_table();
-//     if (ACPI_FAILURE(status)) {
-//             printk(KERN_ERR PREFIX
-//                    "Unable to reallocate ACPI tables\n");
-//             goto error0;
-//     }
-//
-//     status = acpi_initialize_subsystem();
-//     if (ACPI_FAILURE(status)) {
-//             printk(KERN_ERR PREFIX
-//                    "Unable to initialize the ACPI Interpreter\n");
-//             goto error0;
-//     }
-//
-//     status = acpi_load_tables();
-//     if (ACPI_FAILURE(status)) {
-//             printk(KERN_ERR PREFIX
-//                    "Unable to load the System Description Tables\n");
-//             goto error0;
-//     }
-//
-//#ifdef CONFIG_X86
-//     if (!acpi_ioapic) {
-//             /* compatible (0) means level (3) */
-//             if (!(acpi_sci_flags & ACPI_MADT_TRIGGER_MASK)) {
-//                     acpi_sci_flags &= ~ACPI_MADT_TRIGGER_MASK;
-//                     acpi_sci_flags |= ACPI_MADT_TRIGGER_LEVEL;
-//             }
-//             /* Set PIC-mode SCI trigger type */
-//             acpi_pic_sci_set_trigger(acpi_gbl_FADT.sci_interrupt,
-//                                      (acpi_sci_flags & ACPI_MADT_TRIGGER_MASK) >> 2);
-//     } else {
-//             /*
-//              * now that acpi_gbl_FADT is initialized,
-//              * update it with result from INT_SRC_OVR parsing
-//              */
-//             acpi_gbl_FADT.sci_interrupt = acpi_sci_override_gsi;
-//     }
-//#endif
-//
-//     status =
-//         acpi_enable_subsystem(~
-//                               (ACPI_NO_HARDWARE_INIT |
-//                                ACPI_NO_ACPI_ENABLE));
-//     if (ACPI_FAILURE(status)) {
-//             printk(KERN_ERR PREFIX "Unable to enable ACPI\n");
-//             goto error0;
-//     }
-//
-//     return;
-//
-//      error0:
-//     disable_acpi();
-//     return;
-//}
-
 int
 acpi_bus_init (void)
 {
@@ -1666,6 +1599,8 @@ acpi_bus_init (void)
 
        DPRINT("acpi_bus_init");
 
+        KeInitializeDpc(&event_dpc, acpi_bus_generate_event_dpc, NULL);
+
        status = AcpiEnableSubsystem(ACPI_FULL_INITIALIZATION);
        if (ACPI_FAILURE(status)) {
                DPRINT1("Unable to start the ACPI Interpreter\n");
@@ -1696,13 +1631,6 @@ acpi_bus_init (void)
        /* Initialize sleep structures */
        //acpi_sleep_init();
 
-       /*
-        * Get the system interrupt model and evaluate \_PIC.
-        */
-       result = acpi_bus_init_irq();
-       if (result)
-               goto error1;
-
        /*
         * Register the for all standard device notifications.
         */
@@ -1721,6 +1649,7 @@ acpi_bus_init (void)
        if (result)
                goto error2;
 
+
        /*
         * Enumerate devices in the ACPI namespace.
         */
@@ -1731,7 +1660,6 @@ acpi_bus_init (void)
        if (result)
                DPRINT1("acpi_bus_scan failed\n");
 
-       //acpi_motherboard_init();
        return_VALUE(0);
 
        /* Mimic structured exception handling */
@@ -1786,6 +1714,10 @@ acpi_init (void)
 
        DPRINT("Subsystem revision %08x\n",ACPI_CA_VERSION);
 
+        KeInitializeSpinLock(&acpi_bus_event_lock);
+       KeInitializeEvent(&AcpiEventQueue, NotificationEvent, FALSE);
+       ExInitializeFastMutex(&acpi_bus_drivers_lock);
+
        result = acpi_bus_init();
 
        //if (!result) {