static ACPI_STATUS acpi_dock_insert_child(ACPI_HANDLE handle, UINT32 level, void *context, void **status) { device_t dock_dev, dev; ACPI_HANDLE dock_handle; dock_dev = (device_t)context; dock_handle = acpi_get_handle(dock_dev); if (!acpi_dock_is_ejd_device(dock_handle, handle)) goto out; ACPI_VPRINT(dock_dev, acpi_device_get_parent_softc(dock_dev), "inserting device for %s\n", acpi_name(handle)); #if 0 /* * If the system boot up w/o Docking, the devices under the dock * still un-initialized, also control methods such as _INI, _STA * are not executed. * Normal devices are initialized at booting by calling * AcpiInitializeObjects(), however the devices under the dock * need to be initialized here on the scheme of ACPICA. */ ACPI_INIT_WALK_INFO Info; AcpiNsWalkNamespace(ACPI_TYPE_ANY, handle, 100, TRUE, AcpiNsInitOneDevice, NULL, &Info, NULL); #endif dev = acpi_get_device(handle); if (dev == NULL) { device_printf(dock_dev, "error: %s has no associated device\n", acpi_name(handle)); goto out; } AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_dock_attach_later, dev); out: return (AE_OK); }
static void acpi_fujitsu_notify_handler(ACPI_HANDLE h, uint32_t notify, void *context) { struct acpi_fujitsu_softc *sc; ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, notify); sc = (struct acpi_fujitsu_softc *)context; switch (notify) { case ACPI_NOTIFY_STATUS_CHANGED: AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_fujitsu_notify_status_changed, sc); break; default: /* unknown notification value */ break; } }
static void acpi_lid_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context) { struct acpi_lid_softc *sc; ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, notify); sc = (struct acpi_lid_softc *)context; switch (notify) { case ACPI_NOTIFY_STATUS_CHANGED: AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_lid_notify_status_changed, sc); break; default: device_printf(sc->lid_dev, "unknown notify %#x\n", notify); break; } return_VOID; }
static int acpi_acad_attach(device_t dev) { struct acpi_acad_softc *sc; struct acpi_softc *acpi_sc; ACPI_HANDLE handle; int error; sc = device_get_softc(dev); handle = acpi_get_handle(dev); error = acpi_register_ioctl(ACPIIO_ACAD_GET_STATUS, acpi_acad_ioctl, dev); if (error != 0) return (error); ACPI_SERIAL_INIT(acad); if (device_get_unit(dev) == 0) { acpi_sc = acpi_device_get_parent_softc(dev); SYSCTL_ADD_PROC(&acpi_sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree), OID_AUTO, "acline", CTLTYPE_INT | CTLFLAG_RD, &sc->status, 0, acpi_acad_sysctl, "I", ""); } /* Get initial status after whole system is up. */ sc->status = -1; /* * Install both system and device notify handlers since the Casio * FIVA needs them. */ AcpiInstallNotifyHandler(handle, ACPI_ALL_NOTIFY, acpi_acad_notify_handler, dev); AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_acad_init_acline, dev); return (0); }
static void acpitz_notify_handler(ACPI_HANDLE hdl, uint32_t notify, void *opaque) { ACPI_OSD_EXEC_CALLBACK func = NULL; device_t dv = opaque; switch (notify) { case ACPI_NOTIFY_TZ_ZONE: func = acpitz_get_status; break; case ACPI_NOTIFY_TZ_TRIP: case ACPI_NOTIFY_TZ_DEVLIST: func = acpitz_get_zone_quiet; break; default: aprint_debug_dev(dv, "unknown notify 0x%02X\n", notify); return; } (void)AcpiOsExecute(OSL_NOTIFY_HANDLER, func, dv); }
void AcpiDbCreateExecutionThreads ( char *NumThreadsArg, char *NumLoopsArg, char *MethodNameArg) { ACPI_STATUS Status; UINT32 NumThreads; UINT32 NumLoops; UINT32 i; UINT32 Size; ACPI_MUTEX MainThreadGate; ACPI_MUTEX ThreadCompleteGate; ACPI_MUTEX InfoGate; /* Get the arguments */ NumThreads = ACPI_STRTOUL (NumThreadsArg, NULL, 0); NumLoops = ACPI_STRTOUL (NumLoopsArg, NULL, 0); if (!NumThreads || !NumLoops) { AcpiOsPrintf ("Bad argument: Threads %X, Loops %X\n", NumThreads, NumLoops); return; } /* * Create the semaphore for synchronization of * the created threads with the main thread. */ Status = AcpiOsCreateSemaphore (1, 0, &MainThreadGate); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("Could not create semaphore for synchronization with the main thread, %s\n", AcpiFormatException (Status)); return; } /* * Create the semaphore for synchronization * between the created threads. */ Status = AcpiOsCreateSemaphore (1, 1, &ThreadCompleteGate); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("Could not create semaphore for synchronization between the created threads, %s\n", AcpiFormatException (Status)); (void) AcpiOsDeleteSemaphore (MainThreadGate); return; } Status = AcpiOsCreateSemaphore (1, 1, &InfoGate); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("Could not create semaphore for synchronization of AcpiGbl_DbMethodInfo, %s\n", AcpiFormatException (Status)); (void) AcpiOsDeleteSemaphore (ThreadCompleteGate); (void) AcpiOsDeleteSemaphore (MainThreadGate); return; } ACPI_MEMSET (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO)); /* Array to store IDs of threads */ AcpiGbl_DbMethodInfo.NumThreads = NumThreads; Size = sizeof (ACPI_THREAD_ID) * AcpiGbl_DbMethodInfo.NumThreads; AcpiGbl_DbMethodInfo.Threads = AcpiOsAllocate (Size); if (AcpiGbl_DbMethodInfo.Threads == NULL) { AcpiOsPrintf ("No memory for thread IDs array\n"); (void) AcpiOsDeleteSemaphore (MainThreadGate); (void) AcpiOsDeleteSemaphore (ThreadCompleteGate); (void) AcpiOsDeleteSemaphore (InfoGate); return; } ACPI_MEMSET (AcpiGbl_DbMethodInfo.Threads, 0, Size); /* Setup the context to be passed to each thread */ AcpiGbl_DbMethodInfo.Name = MethodNameArg; AcpiGbl_DbMethodInfo.Flags = 0; AcpiGbl_DbMethodInfo.NumLoops = NumLoops; AcpiGbl_DbMethodInfo.MainThreadGate = MainThreadGate; AcpiGbl_DbMethodInfo.ThreadCompleteGate = ThreadCompleteGate; AcpiGbl_DbMethodInfo.InfoGate = InfoGate; /* Init arguments to be passed to method */ AcpiGbl_DbMethodInfo.InitArgs = 1; AcpiGbl_DbMethodInfo.Args = AcpiGbl_DbMethodInfo.Arguments; AcpiGbl_DbMethodInfo.Arguments[0] = AcpiGbl_DbMethodInfo.NumThreadsStr; AcpiGbl_DbMethodInfo.Arguments[1] = AcpiGbl_DbMethodInfo.IdOfThreadStr; AcpiGbl_DbMethodInfo.Arguments[2] = AcpiGbl_DbMethodInfo.IndexOfThreadStr; AcpiGbl_DbMethodInfo.Arguments[3] = NULL; AcpiGbl_DbMethodInfo.Types = AcpiGbl_DbMethodInfo.ArgTypes; AcpiGbl_DbMethodInfo.ArgTypes[0] = ACPI_TYPE_INTEGER; AcpiGbl_DbMethodInfo.ArgTypes[1] = ACPI_TYPE_INTEGER; AcpiGbl_DbMethodInfo.ArgTypes[2] = ACPI_TYPE_INTEGER; AcpiDbUint32ToHexString (NumThreads, AcpiGbl_DbMethodInfo.NumThreadsStr); Status = AcpiDbExecuteSetup (&AcpiGbl_DbMethodInfo); if (ACPI_FAILURE (Status)) { goto CleanupAndExit; } /* Get the NS node, determines existence also */ Status = AcpiGetHandle (NULL, AcpiGbl_DbMethodInfo.Pathname, &AcpiGbl_DbMethodInfo.Method); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("%s Could not get handle for %s\n", AcpiFormatException (Status), AcpiGbl_DbMethodInfo.Pathname); goto CleanupAndExit; } /* Create the threads */ AcpiOsPrintf ("Creating %X threads to execute %X times each\n", NumThreads, NumLoops); for (i = 0; i < (NumThreads); i++) { Status = AcpiOsExecute (OSL_DEBUGGER_THREAD, AcpiDbMethodThread, &AcpiGbl_DbMethodInfo); if (ACPI_FAILURE (Status)) { break; } } /* Wait for all threads to complete */ (void) AcpiOsWaitSemaphore (MainThreadGate, 1, ACPI_WAIT_FOREVER); AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); AcpiOsPrintf ("All threads (%X) have completed\n", NumThreads); AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); CleanupAndExit: /* Cleanup and exit */ (void) AcpiOsDeleteSemaphore (MainThreadGate); (void) AcpiOsDeleteSemaphore (ThreadCompleteGate); (void) AcpiOsDeleteSemaphore (InfoGate); AcpiOsFree (AcpiGbl_DbMethodInfo.Threads); AcpiGbl_DbMethodInfo.Threads = NULL; }
ACPI_STATUS AcpiEvQueueNotifyRequest ( ACPI_NAMESPACE_NODE *Node, UINT32 NotifyValue) { ACPI_OPERAND_OBJECT *ObjDesc; ACPI_OPERAND_OBJECT *HandlerListHead = NULL; ACPI_GENERIC_STATE *Info; UINT8 HandlerListId = 0; ACPI_STATUS Status = AE_OK; ACPI_FUNCTION_NAME (EvQueueNotifyRequest); /* Are Notifies allowed on this object? */ if (!AcpiEvIsNotifyObject (Node)) { return (AE_TYPE); } /* Get the correct notify list type (System or Device) */ if (NotifyValue <= ACPI_MAX_SYS_NOTIFY) { HandlerListId = ACPI_SYSTEM_HANDLER_LIST; } else { HandlerListId = ACPI_DEVICE_HANDLER_LIST; } /* Get the notify object attached to the namespace Node */ ObjDesc = AcpiNsGetAttachedObject (Node); if (ObjDesc) { /* We have an attached object, Get the correct handler list */ HandlerListHead = ObjDesc->CommonNotify.NotifyList[HandlerListId]; } /* * If there is no notify handler (Global or Local) * for this object, just ignore the notify */ if (!AcpiGbl_GlobalNotify[HandlerListId].Handler && !HandlerListHead) { ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "No notify handler for Notify, ignoring (%4.4s, %X) node %p\n", AcpiUtGetNodeName (Node), NotifyValue, Node)); return (AE_OK); } /* Setup notify info and schedule the notify dispatcher */ Info = AcpiUtCreateGenericState (); if (!Info) { return (AE_NO_MEMORY); } Info->Common.DescriptorType = ACPI_DESC_TYPE_STATE_NOTIFY; Info->Notify.Node = Node; Info->Notify.Value = (UINT16) NotifyValue; Info->Notify.HandlerListId = HandlerListId; Info->Notify.HandlerListHead = HandlerListHead; Info->Notify.Global = &AcpiGbl_GlobalNotify[HandlerListId]; ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Dispatching Notify on [%4.4s] (%s) Value 0x%2.2X (%s) Node %p\n", AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type), NotifyValue, AcpiUtGetNotifyName (NotifyValue, ACPI_TYPE_ANY), Node)); Status = AcpiOsExecute (OSL_NOTIFY_HANDLER, AcpiEvNotifyDispatch, Info); if (ACPI_FAILURE (Status)) { AcpiUtDeleteGenericState (Info); } return (Status); }
UINT32 AcpiEvGpeDispatch ( ACPI_NAMESPACE_NODE *GpeDevice, ACPI_GPE_EVENT_INFO *GpeEventInfo, UINT32 GpeNumber) { ACPI_STATUS Status; UINT32 ReturnValue; ACPI_FUNCTION_TRACE (EvGpeDispatch); /* * Always disable the GPE so that it does not keep firing before * any asynchronous activity completes (either from the execution * of a GPE method or an asynchronous GPE handler.) * * If there is no handler or method to run, just disable the * GPE and leave it disabled permanently to prevent further such * pointless events from firing. */ Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "Unable to disable GPE %02X", GpeNumber)); return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); } /* * If edge-triggered, clear the GPE status bit now. Note that * level-triggered events are cleared after the GPE is serviced. */ if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) == ACPI_GPE_EDGE_TRIGGERED) { Status = AcpiHwClearGpe (GpeEventInfo); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "Unable to clear GPE %02X", GpeNumber)); (void) AcpiHwLowSetGpe ( GpeEventInfo, ACPI_GPE_CONDITIONAL_ENABLE); return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); } } /* * Dispatch the GPE to either an installed handler or the control * method associated with this GPE (_Lxx or _Exx). If a handler * exists, we invoke it and do not attempt to run the method. * If there is neither a handler nor a method, leave the GPE * disabled. */ switch (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags)) { case ACPI_GPE_DISPATCH_HANDLER: /* Invoke the installed handler (at interrupt level) */ ReturnValue = GpeEventInfo->Dispatch.Handler->Address ( GpeDevice, GpeNumber, GpeEventInfo->Dispatch.Handler->Context); /* If requested, clear (if level-triggered) and reenable the GPE */ if (ReturnValue & ACPI_REENABLE_GPE) { (void) AcpiEvFinishGpe (GpeEventInfo); } break; case ACPI_GPE_DISPATCH_METHOD: case ACPI_GPE_DISPATCH_NOTIFY: /* * Execute the method associated with the GPE * NOTE: Level-triggered GPEs are cleared after the method completes. */ Status = AcpiOsExecute (OSL_GPE_HANDLER, AcpiEvAsynchExecuteGpeMethod, GpeEventInfo); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "Unable to queue handler for GPE %02X - event disabled", GpeNumber)); } break; default: /* * No handler or method to run! * 03/2010: This case should no longer be possible. We will not allow * a GPE to be enabled if it has no handler or method. */ ACPI_ERROR ((AE_INFO, "No handler or method for GPE %02X, disabling event", GpeNumber)); break; } return_UINT32 (ACPI_INTERRUPT_HANDLED); }
static void ACPI_SYSTEM_XFACE AcpiEvAsynchExecuteGpeMethod ( void *Context) { ACPI_GPE_EVENT_INFO *GpeEventInfo = Context; ACPI_STATUS Status = AE_OK; ACPI_EVALUATE_INFO *Info; ACPI_GPE_NOTIFY_INFO *Notify; ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod); /* Do the correct dispatch - normal method or implicit notify */ switch (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags)) { case ACPI_GPE_DISPATCH_NOTIFY: /* * Implicit notify. * Dispatch a DEVICE_WAKE notify to the appropriate handler. * NOTE: the request is queued for execution after this method * completes. The notify handlers are NOT invoked synchronously * from this thread -- because handlers may in turn run other * control methods. * * June 2012: Expand implicit notify mechanism to support * notifies on multiple device objects. */ Notify = GpeEventInfo->Dispatch.NotifyList; while (ACPI_SUCCESS (Status) && Notify) { Status = AcpiEvQueueNotifyRequest ( Notify->DeviceNode, ACPI_NOTIFY_DEVICE_WAKE); Notify = Notify->Next; } break; case ACPI_GPE_DISPATCH_METHOD: /* Allocate the evaluation information block */ Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); if (!Info) { Status = AE_NO_MEMORY; } else { /* * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the * _Lxx/_Exx control method that corresponds to this GPE */ Info->PrefixNode = GpeEventInfo->Dispatch.MethodNode; Info->Flags = ACPI_IGNORE_RETURN_VALUE; Status = AcpiNsEvaluate (Info); ACPI_FREE (Info); } if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "while evaluating GPE method [%4.4s]", AcpiUtGetNodeName (GpeEventInfo->Dispatch.MethodNode))); } break; default: goto ErrorExit; /* Should never happen */ } /* Defer enabling of GPE until all notify handlers are done */ Status = AcpiOsExecute (OSL_NOTIFY_HANDLER, AcpiEvAsynchEnableGpe, GpeEventInfo); if (ACPI_SUCCESS (Status)) { return_VOID; } ErrorExit: AcpiEvAsynchEnableGpe (GpeEventInfo); return_VOID; }
static int acpi_cpu_attach(device_t dev) { ACPI_BUFFER buf; ACPI_OBJECT arg[4], *obj; ACPI_OBJECT_LIST arglist; struct pcpu *pcpu_data; struct acpi_cpu_softc *sc; struct acpi_softc *acpi_sc; ACPI_STATUS status; u_int features; int cpu_id, drv_count, i; driver_t **drivers; uint32_t cap_set[3]; /* UUID needed by _OSC evaluation */ static uint8_t cpu_oscuuid[16] = { 0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29, 0xBE, 0x47, 0x9E, 0xBD, 0xD8, 0x70, 0x58, 0x71, 0x39, 0x53 }; ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); sc = device_get_softc(dev); sc->cpu_dev = dev; sc->cpu_handle = acpi_get_handle(dev); cpu_id = (int)(intptr_t)acpi_get_private(dev); cpu_softc[cpu_id] = sc; pcpu_data = pcpu_find(cpu_id); pcpu_data->pc_device = dev; sc->cpu_pcpu = pcpu_data; cpu_smi_cmd = AcpiGbl_FADT.SmiCommand; cpu_cst_cnt = AcpiGbl_FADT.CstControl; buf.Pointer = NULL; buf.Length = ACPI_ALLOCATE_BUFFER; status = AcpiEvaluateObject(sc->cpu_handle, NULL, NULL, &buf); if (ACPI_FAILURE(status)) { device_printf(dev, "attach failed to get Processor obj - %s\n", AcpiFormatException(status)); return (ENXIO); } obj = (ACPI_OBJECT *)buf.Pointer; sc->cpu_p_blk = obj->Processor.PblkAddress; sc->cpu_p_blk_len = obj->Processor.PblkLength; sc->cpu_acpi_id = obj->Processor.ProcId; AcpiOsFree(obj); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "acpi_cpu%d: P_BLK at %#x/%d\n", device_get_unit(dev), sc->cpu_p_blk, sc->cpu_p_blk_len)); /* * If this is the first cpu we attach, create and initialize the generic * resources that will be used by all acpi cpu devices. */ if (device_get_unit(dev) == 0) { /* Assume we won't be using generic Cx mode by default */ cpu_cx_generic = FALSE; /* Install hw.acpi.cpu sysctl tree */ acpi_sc = acpi_device_get_parent_softc(dev); sysctl_ctx_init(&cpu_sysctl_ctx); cpu_sysctl_tree = SYSCTL_ADD_NODE(&cpu_sysctl_ctx, SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree), OID_AUTO, "cpu", CTLFLAG_RD, 0, "node for CPU children"); /* Queue post cpu-probing task handler */ AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_cpu_startup, NULL); } /* * Before calling any CPU methods, collect child driver feature hints * and notify ACPI of them. We support unified SMP power control * so advertise this ourselves. Note this is not the same as independent * SMP control where each CPU can have different settings. */ sc->cpu_features = ACPI_CAP_SMP_SAME | ACPI_CAP_SMP_SAME_C3; if (devclass_get_drivers(acpi_cpu_devclass, &drivers, &drv_count) == 0) { for (i = 0; i < drv_count; i++) { if (ACPI_GET_FEATURES(drivers[i], &features) == 0) sc->cpu_features |= features; } free(drivers, M_TEMP); } /* * CPU capabilities are specified in * Intel Processor Vendor-Specific ACPI Interface Specification. */ if (sc->cpu_features) { arglist.Pointer = arg; arglist.Count = 4; arg[0].Type = ACPI_TYPE_BUFFER; arg[0].Buffer.Length = sizeof(cpu_oscuuid); arg[0].Buffer.Pointer = cpu_oscuuid; /* UUID */ arg[1].Type = ACPI_TYPE_INTEGER; arg[1].Integer.Value = 1; /* revision */ arg[2].Type = ACPI_TYPE_INTEGER; arg[2].Integer.Value = 1; /* count */ arg[3].Type = ACPI_TYPE_BUFFER; arg[3].Buffer.Length = sizeof(cap_set); /* Capabilities buffer */ arg[3].Buffer.Pointer = (uint8_t *)cap_set; cap_set[0] = 0; /* status */ cap_set[1] = sc->cpu_features; status = AcpiEvaluateObject(sc->cpu_handle, "_OSC", &arglist, NULL); if (ACPI_SUCCESS(status)) { if (cap_set[0] != 0) device_printf(dev, "_OSC returned status %#x\n", cap_set[0]); } else { arglist.Pointer = arg; arglist.Count = 1; arg[0].Type = ACPI_TYPE_BUFFER; arg[0].Buffer.Length = sizeof(cap_set); arg[0].Buffer.Pointer = (uint8_t *)cap_set; cap_set[0] = 1; /* revision */ cap_set[1] = 1; /* number of capabilities integers */ cap_set[2] = sc->cpu_features; AcpiEvaluateObject(sc->cpu_handle, "_PDC", &arglist, NULL); } } /* Probe for Cx state support. */ acpi_cpu_cx_probe(sc); return (0); }
ACPI_STATUS AcpiDbInitialize ( void) { ACPI_STATUS Status; /* Init globals */ AcpiGbl_DbBuffer = NULL; AcpiGbl_DbFilename = NULL; AcpiGbl_DbOutputToFile = FALSE; AcpiGbl_DbDebugLevel = ACPI_LV_VERBOSITY2; AcpiGbl_DbConsoleDebugLevel = ACPI_NORMAL_DEFAULT | ACPI_LV_TABLES; AcpiGbl_DbOutputFlags = ACPI_DB_CONSOLE_OUTPUT; AcpiGbl_DbOpt_tables = FALSE; AcpiGbl_DbOpt_stats = FALSE; #ifdef ACPI_DISASSEMBLER AcpiGbl_DbOpt_disasm = FALSE; AcpiGbl_DbOpt_verbose = TRUE; #endif AcpiGbl_DbOpt_ini_methods = TRUE; AcpiGbl_DbBuffer = AcpiOsAllocate (ACPI_DEBUG_BUFFER_SIZE); if (!AcpiGbl_DbBuffer) { return (AE_NO_MEMORY); } ACPI_MEMSET (AcpiGbl_DbBuffer, 0, ACPI_DEBUG_BUFFER_SIZE); /* Initial scope is the root */ AcpiGbl_DbScopeBuf [0] = '\\'; AcpiGbl_DbScopeBuf [1] = 0; AcpiGbl_DbScopeNode = AcpiGbl_RootNode; /* * If configured for multi-thread support, the debug executor runs in * a separate thread so that the front end can be in another address * space, environment, or even another machine. */ if (AcpiGbl_DebuggerConfiguration & DEBUGGER_MULTI_THREADED) { /* These were created with one unit, grab it */ Status = AcpiUtAcquireMutex (ACPI_MTX_DEBUG_CMD_COMPLETE); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("Could not get debugger mutex\n"); return (Status); } Status = AcpiUtAcquireMutex (ACPI_MTX_DEBUG_CMD_READY); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("Could not get debugger mutex\n"); return (Status); } /* Create the debug execution thread to execute commands */ Status = AcpiOsExecute (OSL_DEBUGGER_THREAD, AcpiDbExecuteThread, NULL); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("Could not start debugger thread\n"); return (Status); } } #ifdef ACPI_DISASSEMBLER if (!AcpiGbl_DbOpt_verbose) { AcpiGbl_DbOpt_disasm = TRUE; AcpiGbl_DbOpt_stats = FALSE; } #endif return (AE_OK); }
static void wmi_hp_notify_handler(ACPI_HANDLE hdl, uint32_t evt, void *aux) { static const int handler = OSL_NOTIFY_HANDLER; struct wmi_hp_softc *sc; device_t self = aux; ACPI_OBJECT *obj; ACPI_BUFFER buf; ACPI_STATUS rv; uint32_t val; buf.Pointer = NULL; sc = device_private(self); rv = acpi_wmi_event_get(sc->sc_parent, evt, &buf); if (ACPI_FAILURE(rv)) goto out; obj = buf.Pointer; if (obj->Type != ACPI_TYPE_BUFFER) { rv = AE_TYPE; goto out; } if (obj->Buffer.Length != 8) { rv = AE_LIMIT; goto out; } val = *((uint8_t *)obj->Buffer.Pointer); if (val == 0x00) { rv = AE_BAD_DATA; goto out; } switch (val) { case WMI_HP_EVENT_SWITCH: rv = AcpiOsExecute(handler, wmi_hp_sensor_switch_update, self); break; case WMI_HP_EVENT_HOTKEY: rv = AcpiOsExecute(handler, wmi_hp_hotkey, self); break; case WMI_HP_EVENT_DOCK: /* FALLTHROUGH */ default: aprint_debug_dev(sc->sc_dev, "unknown event 0x%02X\n", evt); break; } out: if (buf.Pointer != NULL) ACPI_FREE(buf.Pointer); if (ACPI_FAILURE(rv)) aprint_error_dev(sc->sc_dev, "failed to get data for " "event 0x%02X: %s\n", evt, AcpiFormatException(rv)); }
ACPI_STATUS AcpiEvQueueNotifyRequest ( ACPI_NAMESPACE_NODE *Node, UINT32 NotifyValue) { ACPI_OPERAND_OBJECT *ObjDesc; ACPI_OPERAND_OBJECT *HandlerObj = NULL; ACPI_GENERIC_STATE *NotifyInfo; ACPI_STATUS Status = AE_OK; ACPI_FUNCTION_NAME (EvQueueNotifyRequest); /* * For value 3 (Ejection Request), some device method may need to be run. * For value 2 (Device Wake) if _PRW exists, the _PS0 method may need * to be run. * For value 0x80 (Status Change) on the power button or sleep button, * initiate soft-off or sleep operation? */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Dispatching Notify on [%4.4s] Node %p Value 0x%2.2X (%s)\n", AcpiUtGetNodeName (Node), Node, NotifyValue, AcpiUtGetNotifyName (NotifyValue))); /* Get the notify object attached to the NS Node */ ObjDesc = AcpiNsGetAttachedObject (Node); if (ObjDesc) { /* We have the notify object, Get the right handler */ switch (Node->Type) { /* Notify allowed only on these types */ case ACPI_TYPE_DEVICE: case ACPI_TYPE_THERMAL: case ACPI_TYPE_PROCESSOR: if (NotifyValue <= ACPI_MAX_SYS_NOTIFY) { HandlerObj = ObjDesc->CommonNotify.SystemNotify; } else { HandlerObj = ObjDesc->CommonNotify.DeviceNotify; } break; default: /* All other types are not supported */ return (AE_TYPE); } } /* * If there is any handler to run, schedule the dispatcher. * Check for: * 1) Global system notify handler * 2) Global device notify handler * 3) Per-device notify handler */ if ((AcpiGbl_SystemNotify.Handler && (NotifyValue <= ACPI_MAX_SYS_NOTIFY)) || (AcpiGbl_DeviceNotify.Handler && (NotifyValue > ACPI_MAX_SYS_NOTIFY)) || HandlerObj) { NotifyInfo = AcpiUtCreateGenericState (); if (!NotifyInfo) { return (AE_NO_MEMORY); } if (!HandlerObj) { ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Executing system notify handler for Notify (%4.4s, %X) " "node %p\n", AcpiUtGetNodeName (Node), NotifyValue, Node)); } NotifyInfo->Common.DescriptorType = ACPI_DESC_TYPE_STATE_NOTIFY; NotifyInfo->Notify.Node = Node; NotifyInfo->Notify.Value = (UINT16) NotifyValue; NotifyInfo->Notify.HandlerObj = HandlerObj; Status = AcpiOsExecute ( OSL_NOTIFY_HANDLER, AcpiEvNotifyDispatch, NotifyInfo); if (ACPI_FAILURE (Status)) { AcpiUtDeleteGenericState (NotifyInfo); } } else { /* There is no notify handler (per-device or system) for this device */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "No notify handler for Notify (%4.4s, %X) node %p\n", AcpiUtGetNodeName (Node), NotifyValue, Node)); } return (Status); }
void AcpiDbCreateExecutionThreads ( char *NumThreadsArg, char *NumLoopsArg, char *MethodNameArg) { ACPI_STATUS Status; UINT32 NumThreads; UINT32 NumLoops; UINT32 i; ACPI_MUTEX ThreadGate; /* Get the arguments */ NumThreads = ACPI_STRTOUL (NumThreadsArg, NULL, 0); NumLoops = ACPI_STRTOUL (NumLoopsArg, NULL, 0); if (!NumThreads || !NumLoops) { AcpiOsPrintf ("Bad argument: Threads %X, Loops %X\n", NumThreads, NumLoops); return; } /* Create the synchronization semaphore */ Status = AcpiOsCreateSemaphore (1, 0, &ThreadGate); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("Could not create semaphore, %s\n", AcpiFormatException (Status)); return; } /* Setup the context to be passed to each thread */ AcpiGbl_DbMethodInfo.Name = MethodNameArg; AcpiGbl_DbMethodInfo.Args = NULL; AcpiGbl_DbMethodInfo.Flags = 0; AcpiGbl_DbMethodInfo.NumLoops = NumLoops; AcpiGbl_DbMethodInfo.ThreadGate = ThreadGate; AcpiDbExecuteSetup (&AcpiGbl_DbMethodInfo); /* Create the threads */ AcpiOsPrintf ("Creating %X threads to execute %X times each\n", NumThreads, NumLoops); for (i = 0; i < (NumThreads); i++) { Status = AcpiOsExecute (OSL_DEBUGGER_THREAD, AcpiDbMethodThread, &AcpiGbl_DbMethodInfo); if (ACPI_FAILURE (Status)) { break; } } /* Wait for all threads to complete */ i = NumThreads; while (i) /* Brain damage for host OSs that only support wait of 1 unit */ { Status = AcpiOsWaitSemaphore (ThreadGate, 1, ACPI_WAIT_FOREVER); i--; } /* Cleanup and exit */ (void) AcpiOsDeleteSemaphore (ThreadGate); AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); AcpiOsPrintf ("All threads (%X) have completed\n", NumThreads); AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); }
ACPI_STATUS AcpiInitializeDebugger ( void) { ACPI_STATUS Status; ACPI_FUNCTION_TRACE (AcpiInitializeDebugger); /* Init globals */ AcpiGbl_DbBuffer = NULL; AcpiGbl_DbFilename = NULL; AcpiGbl_DbOutputToFile = FALSE; AcpiGbl_DbDebugLevel = ACPI_LV_VERBOSITY2; AcpiGbl_DbConsoleDebugLevel = ACPI_NORMAL_DEFAULT | ACPI_LV_TABLES; AcpiGbl_DbOutputFlags = ACPI_DB_CONSOLE_OUTPUT; AcpiGbl_DbOpt_NoIniMethods = FALSE; AcpiGbl_DbBuffer = AcpiOsAllocate (ACPI_DEBUG_BUFFER_SIZE); if (!AcpiGbl_DbBuffer) { return_ACPI_STATUS (AE_NO_MEMORY); } memset (AcpiGbl_DbBuffer, 0, ACPI_DEBUG_BUFFER_SIZE); /* Initial scope is the root */ AcpiGbl_DbScopeBuf [0] = AML_ROOT_PREFIX; AcpiGbl_DbScopeBuf [1] = 0; AcpiGbl_DbScopeNode = AcpiGbl_RootNode; /* Initialize user commands loop */ AcpiGbl_DbTerminateLoop = FALSE; /* * If configured for multi-thread support, the debug executor runs in * a separate thread so that the front end can be in another address * space, environment, or even another machine. */ if (AcpiGbl_DebuggerConfiguration & DEBUGGER_MULTI_THREADED) { /* These were created with one unit, grab it */ Status = AcpiOsAcquireMutex (AcpiGbl_DbCommandComplete, ACPI_WAIT_FOREVER); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("Could not get debugger mutex\n"); return_ACPI_STATUS (Status); } Status = AcpiOsAcquireMutex (AcpiGbl_DbCommandReady, ACPI_WAIT_FOREVER); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("Could not get debugger mutex\n"); return_ACPI_STATUS (Status); } /* Create the debug execution thread to execute commands */ AcpiGbl_DbThreadsTerminated = FALSE; Status = AcpiOsExecute (OSL_DEBUGGER_MAIN_THREAD, AcpiDbExecuteThread, NULL); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "Could not start debugger thread")); AcpiGbl_DbThreadsTerminated = TRUE; return_ACPI_STATUS (Status); } } else { AcpiGbl_DbThreadId = AcpiOsGetThreadId (); } return_ACPI_STATUS (AE_OK); }
static void ACPI_SYSTEM_XFACE AcpiEvAsynchExecuteGpeMethod ( void *Context) { ACPI_GPE_EVENT_INFO *GpeEventInfo = Context; ACPI_STATUS Status; ACPI_GPE_EVENT_INFO *LocalGpeEventInfo; ACPI_EVALUATE_INFO *Info; ACPI_GPE_NOTIFY_INFO *Notify; ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod); /* Allocate a local GPE block */ LocalGpeEventInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_EVENT_INFO)); if (!LocalGpeEventInfo) { ACPI_EXCEPTION ((AE_INFO, AE_NO_MEMORY, "while handling a GPE")); return_VOID; } Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); if (ACPI_FAILURE (Status)) { ACPI_FREE (LocalGpeEventInfo); return_VOID; } /* Must revalidate the GpeNumber/GpeBlock */ if (!AcpiEvValidGpeEvent (GpeEventInfo)) { Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS); ACPI_FREE (LocalGpeEventInfo); return_VOID; } /* * Take a snapshot of the GPE info for this level - we copy the info to * prevent a race condition with RemoveHandler/RemoveBlock. */ ACPI_MEMCPY (LocalGpeEventInfo, GpeEventInfo, sizeof (ACPI_GPE_EVENT_INFO)); Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS); if (ACPI_FAILURE (Status)) { ACPI_FREE (LocalGpeEventInfo); return_VOID; } /* Do the correct dispatch - normal method or implicit notify */ switch (LocalGpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) { case ACPI_GPE_DISPATCH_NOTIFY: /* * Implicit notify. * Dispatch a DEVICE_WAKE notify to the appropriate handler. * NOTE: the request is queued for execution after this method * completes. The notify handlers are NOT invoked synchronously * from this thread -- because handlers may in turn run other * control methods. * * June 2012: Expand implicit notify mechanism to support * notifies on multiple device objects. */ Notify = LocalGpeEventInfo->Dispatch.NotifyList; while (ACPI_SUCCESS (Status) && Notify) { Status = AcpiEvQueueNotifyRequest (Notify->DeviceNode, ACPI_NOTIFY_DEVICE_WAKE); Notify = Notify->Next; } break; case ACPI_GPE_DISPATCH_METHOD: /* Allocate the evaluation information block */ Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); if (!Info) { Status = AE_NO_MEMORY; } else { /* * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the * _Lxx/_Exx control method that corresponds to this GPE */ Info->PrefixNode = LocalGpeEventInfo->Dispatch.MethodNode; Info->Flags = ACPI_IGNORE_RETURN_VALUE; Status = AcpiNsEvaluate (Info); ACPI_FREE (Info); } if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "while evaluating GPE method [%4.4s]", AcpiUtGetNodeName (LocalGpeEventInfo->Dispatch.MethodNode))); } break; default: return_VOID; /* Should never happen */ } /* Defer enabling of GPE until all notify handlers are done */ Status = AcpiOsExecute (OSL_NOTIFY_HANDLER, AcpiEvAsynchEnableGpe, LocalGpeEventInfo); if (ACPI_FAILURE (Status)) { ACPI_FREE (LocalGpeEventInfo); } return_VOID; }