[ACPI]
authorCameron Gutman <aicommander@gmail.com>
Thu, 25 Mar 2010 14:19:54 +0000 (14:19 +0000)
committerCameron Gutman <aicommander@gmail.com>
Thu, 25 Mar 2010 14:19:54 +0000 (14:19 +0000)
- Add support for fixed power buttons
- Cleanup some extra junk
- Add a hack to prevent acquiring the mutex while in an ISR or DPC
- Button events are received now and "acpi_bus_generate_event" will appear in the debug log when a power/sleep button is pressed
- TODO: Implement IOCTL_GET_SYS_BUTTON_EVENT support so the power manager can recognize our button presses

svn path=/trunk/; revision=46442

reactos/drivers/bus/acpi/busmgr/bus.c
reactos/drivers/bus/acpi/busmgr/button.c
reactos/drivers/bus/acpi/include/acpi_bus.h
reactos/drivers/bus/acpi/main.c
reactos/drivers/bus/acpi/osl.c

index 34aa076..6309f20 100644 (file)
@@ -1262,9 +1262,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;
        }
@@ -1326,7 +1332,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,
@@ -1530,16 +1538,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);
 }
@@ -1549,120 +1581,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)
 {
@@ -1701,13 +1619,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.
         */
@@ -1726,6 +1637,7 @@ acpi_bus_init (void)
        if (result)
                goto error2;
 
+
        /*
         * Enumerate devices in the ACPI namespace.
         */
@@ -1736,7 +1648,6 @@ acpi_bus_init (void)
        if (result)
                DPRINT1("acpi_bus_scan failed\n");
 
-       //acpi_motherboard_init();
        return_VALUE(0);
 
        /* Mimic structured exception handling */
index 5e3eb2b..9344a5f 100644 (file)
@@ -57,6 +57,11 @@ struct acpi_button {
        UINT8                   type;
        unsigned long           pushed;
 };
+
+struct acpi_device *power_button;
+struct acpi_device *sleep_button;
+struct acpi_device *lid_button;
+
 /* --------------------------------------------------------------------------
                                 Driver Interface
    -------------------------------------------------------------------------- */
@@ -113,10 +118,6 @@ acpi_button_add (
        ACPI_STATUS             status = AE_OK;
        struct acpi_button      *button = NULL;
 
-       static struct acpi_device *power_button;
-       static struct acpi_device *sleep_button;
-       static struct acpi_device *lid_button;
-
        ACPI_FUNCTION_TRACE("acpi_button_add");
 
        if (!device)
index d5fe9ef..d2dc22d 100644 (file)
@@ -73,6 +73,8 @@ enum acpi_bus_device_type {
        ACPI_BUS_TYPE_SYSTEM,
        ACPI_BUS_TYPE_POWER_BUTTON,
        ACPI_BUS_TYPE_SLEEP_BUTTON,
+       ACPI_BUS_TYPE_POWER_BUTTONF,
+       ACPI_BUS_TYPE_SLEEP_BUTTONF,
        ACPI_BUS_DEVICE_TYPE_COUNT
 };
 
index 22946cd..4cbdfda 100644 (file)
@@ -18,6 +18,9 @@
 
 #endif
 
+extern struct acpi_device *sleep_button;
+extern struct acpi_device *power_button;
+
 NTSTATUS
 NTAPI
 Bus_AddDevice(
@@ -215,22 +218,37 @@ ACPIDispatchDeviceControl(
                   break;
               }
 
-              if (wcsstr(((PPDO_DEVICE_DATA)commonData)->HardwareIDs, L"PNP0C0C") ||
-                  wcsstr(((PPDO_DEVICE_DATA)commonData)->HardwareIDs, L"ACPI_FPB"))
+              if (wcsstr(((PPDO_DEVICE_DATA)commonData)->HardwareIDs, L"PNP0C0D"))
               {
-                  DPRINT1("Power button reported to power manager\n");
-                  Caps |= SYS_BUTTON_POWER;
+                  DPRINT1("Lid button reported to power manager\n");
+                  Caps |= SYS_BUTTON_LID;
               }
-              else if (wcsstr(((PPDO_DEVICE_DATA)commonData)->HardwareIDs, L"PNP0C0E") ||
-                       wcsstr(((PPDO_DEVICE_DATA)commonData)->HardwareIDs, L"ACPI_FSB"))
+              else if (((PPDO_DEVICE_DATA)commonData)->AcpiHandle == NULL)
               {
-                  DPRINT1("Sleep button reported to power manager\n");
-                  Caps |= SYS_BUTTON_SLEEP;
+                  /* We have to return both at the same time because since we
+                   * have a NULL handle we are the fixed feature DO and we will
+                   * only be called once (not once per device)
+                   */
+                  if (power_button)
+                  {
+                      DPRINT1("Fixed power button reported to power manager\n");
+                      Caps |= SYS_BUTTON_POWER;
+                  }
+                  if (sleep_button)
+                  {
+                      DPRINT1("Fixed sleep button reported to power manager\n");
+                      Caps |= SYS_BUTTON_SLEEP;
+                  }
               }
-              else if (wcsstr(((PPDO_DEVICE_DATA)commonData)->HardwareIDs, L"PNP0C0D"))
+              if (wcsstr(((PPDO_DEVICE_DATA)commonData)->HardwareIDs, L"PNP0C0C"))
               {
-                  DPRINT1("Lid button reported to power manager\n");
-                  Caps |= SYS_BUTTON_LID;
+                  DPRINT1("Control method power button reported to power manager\n");
+                  Caps |= SYS_BUTTON_POWER;
+              }
+              else if (wcsstr(((PPDO_DEVICE_DATA)commonData)->HardwareIDs, L"PNP0C0E"))
+              {
+                  DPRINT1("Control method sleep reported to power manager\n");
+                  Caps |= SYS_BUTTON_SLEEP;
               }
               else
               {
index f254995..a5df0c0 100644 (file)
@@ -576,7 +576,12 @@ AcpiOsWaitSemaphore(
     DPRINT("Waiting for semaphore %p\n", Handle);
     ASSERT(Mutex);
 
-    ExAcquireFastMutex(Mutex);
+    /* HACK: We enter here at a high IRQL sometimes
+     * because we get called from DPCs and ISRs and
+     * we can't use a fast mutex at that IRQL */
+    if (KeGetCurrentIrql() <= APC_LEVEL)
+        ExAcquireFastMutex(Mutex);
+
     return AE_OK;
 }
 
@@ -590,7 +595,12 @@ AcpiOsSignalSemaphore (
     DPRINT("AcpiOsSignalSemaphore %p\n",Handle);
     ASSERT(Mutex);
 
-    ExReleaseFastMutex(Mutex);
+    /* HACK: We enter here at a high IRQL sometimes
+     * because we get called from DPCs and ISRs and
+     * we can't use a fast mutex at that IRQL */
+    if (KeGetCurrentIrql() <= APC_LEVEL)
+        ExReleaseFastMutex(Mutex);
+
     return AE_OK;
 }