- 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
This commit is contained in:
Cameron Gutman 2010-03-25 14:19:54 +00:00
parent 497c878f97
commit da0c010307
5 changed files with 85 additions and 143 deletions

View 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 */

View 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)

View 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
};

View file

@ -18,6 +18,9 @@
#endif
extern struct acpi_device *sleep_button;
extern struct acpi_device *power_button;
NTSTATUS
NTAPI
Bus_AddDevice(
@ -215,23 +218,38 @@ ACPIDispatchDeviceControl(
break;
}
if (wcsstr(((PPDO_DEVICE_DATA)commonData)->HardwareIDs, L"PNP0C0C") ||
wcsstr(((PPDO_DEVICE_DATA)commonData)->HardwareIDs, L"ACPI_FPB"))
{
DPRINT1("Power button reported to power manager\n");
Caps |= SYS_BUTTON_POWER;
}
else if (wcsstr(((PPDO_DEVICE_DATA)commonData)->HardwareIDs, L"PNP0C0E") ||
wcsstr(((PPDO_DEVICE_DATA)commonData)->HardwareIDs, L"ACPI_FSB"))
{
DPRINT1("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"PNP0C0D"))
{
DPRINT1("Lid button reported to power manager\n");
Caps |= SYS_BUTTON_LID;
}
else if (((PPDO_DEVICE_DATA)commonData)->AcpiHandle == NULL)
{
/* 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;
}
}
if (wcsstr(((PPDO_DEVICE_DATA)commonData)->HardwareIDs, L"PNP0C0C"))
{
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
{
DPRINT1("IOCTL_GET_SYS_BUTTON_CAPS sent to a non-button device\n");

View 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;
}