#include <acpi_drivers.h>
#include <glue.h>
-//#define NDEBUG
+#define NDEBUG
#include <debug.h>
#define _COMPONENT ACPI_BUS_COMPONENT
#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*);
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
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 (
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)
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);
}
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);
}
static LIST_HEAD(acpi_bus_drivers);
//static DECLARE_MUTEX(acpi_bus_drivers_lock);
+static FAST_MUTEX acpi_bus_drivers_lock;
/**
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);
}
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);
}
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) {
break;
}
- //up(&acpi_bus_drivers_lock);
+ up(&acpi_bus_drivers_lock);
return_VALUE(result);
}
//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);
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;
}
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;
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;
}
*/
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,
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);
}
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)
{
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");
/* 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.
*/
if (result)
goto error2;
+
/*
* Enumerate devices in the ACPI namespace.
*/
if (result)
DPRINT1("acpi_bus_scan failed\n");
- //acpi_motherboard_init();
return_VALUE(0);
/* Mimic structured exception handling */
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) {