diff options
Diffstat (limited to 'sys/dev/acpica/Osd')
-rw-r--r-- | sys/dev/acpica/Osd/OsdDebug.c | 119 | ||||
-rw-r--r-- | sys/dev/acpica/Osd/OsdHardware.c | 263 | ||||
-rw-r--r-- | sys/dev/acpica/Osd/OsdInterrupt.c | 157 | ||||
-rw-r--r-- | sys/dev/acpica/Osd/OsdMemory.c | 162 | ||||
-rw-r--r-- | sys/dev/acpica/Osd/OsdSchedule.c | 289 | ||||
-rw-r--r-- | sys/dev/acpica/Osd/OsdStream.c | 51 | ||||
-rw-r--r-- | sys/dev/acpica/Osd/OsdSynch.c | 392 | ||||
-rw-r--r-- | sys/dev/acpica/Osd/OsdTable.c | 96 |
8 files changed, 1529 insertions, 0 deletions
diff --git a/sys/dev/acpica/Osd/OsdDebug.c b/sys/dev/acpica/Osd/OsdDebug.c new file mode 100644 index 0000000..3df9e45 --- /dev/null +++ b/sys/dev/acpica/Osd/OsdDebug.c @@ -0,0 +1,119 @@ +/*- + * Copyright (c) 2000 Michael Smith + * Copyright (c) 2000 BSDi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * 6.8 : Debugging support + */ + +#include "opt_ddb.h" +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/cons.h> +#include <sys/kernel.h> + +#include <sys/bus.h> +#include <machine/resource.h> +#include <machine/bus.h> +#include <sys/rman.h> + +#include <ddb/ddb.h> +#include <ddb/db_output.h> + +#include "acpi.h" +#include "acdebug.h" +#include <dev/acpica/acpivar.h> + +UINT32 +AcpiOsGetLine(char *Buffer) +{ +#ifdef DDB + char *cp; + + db_readline(Buffer, 80); + for (cp = Buffer; *cp != 0; cp++) + if (*cp == '\n') + *cp = 0; + return(AE_OK); +#else + printf("AcpiOsGetLine called but no input support"); + return(AE_NOT_EXIST); +#endif +} + +void +AcpiOsDbgAssert(void *FailedAssertion, void *FileName, UINT32 LineNumber, char *Message) +{ + printf("ACPI: %s:%d - %s\n", (char *)FileName, LineNumber, Message); + printf("ACPI: assertion %s\n", (char *)FailedAssertion); +} + +ACPI_STATUS +AcpiOsSignal ( + UINT32 Function, + void *Info) +{ + ACPI_SIGNAL_FATAL_INFO *fatal; + char *message; + + switch(Function) { + case ACPI_SIGNAL_FATAL: + fatal = (ACPI_SIGNAL_FATAL_INFO *)Info; + printf("ACPI fatal signal, type 0x%x code 0x%x argument 0x%x", + fatal->Type, fatal->Code, fatal->Argument); + Debugger("AcpiOsSignal"); + break; + + case ACPI_SIGNAL_BREAKPOINT: + message = (char *)Info; + Debugger(message); + break; + + default: + return(AE_BAD_PARAMETER); + } + return(AE_OK); +} + +#ifdef ACPI_DEBUGGER +void +acpi_EnterDebugger(void) +{ + ACPI_PARSE_OBJECT obj; + static int initted = 0; + + if (!initted) { + printf("Initialising ACPICA debugger...\n"); + AcpiDbInitialize(); + initted = 1; + } + + printf("Entering ACPICA debugger...\n"); + AcpiDbUserCommands('A', &obj); +} +#endif diff --git a/sys/dev/acpica/Osd/OsdHardware.c b/sys/dev/acpica/Osd/OsdHardware.c new file mode 100644 index 0000000..90d2385 --- /dev/null +++ b/sys/dev/acpica/Osd/OsdHardware.c @@ -0,0 +1,263 @@ +/*- + * Copyright (c) 2000, 2001 Michael Smith + * Copyright (c) 2000 BSDi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * 6.7 : Hardware Abstraction + */ + +#include "acpi.h" + +#include <machine/bus_pio.h> +#include <machine/bus.h> +#include <machine/pci_cfgreg.h> +#if __FreeBSD_version >= 500000 +#include <dev/pci/pcireg.h> +#else +#include <pci/pcireg.h> +#endif + +/* + * ACPICA's rather gung-ho approach to hardware resource ownership is a little + * troublesome insofar as there is no easy way for us to know in advance + * exactly which I/O resources it's going to want to use. + * + * In order to deal with this, we ignore resource ownership entirely, and simply + * use the native I/O space accessor functionality. This is Evil, but it works. + * + * XXX use an intermediate #define for the tag/handle + */ + +#ifdef __i386__ +#define ACPI_BUS_SPACE_IO I386_BUS_SPACE_IO +#define ACPI_BUS_HANDLE 0 +#endif +#ifdef __ia64__ +#define ACPI_BUS_SPACE_IO IA64_BUS_SPACE_IO +#define ACPI_BUS_HANDLE 0 +#endif +#ifdef __amd64__ +#define ACPI_BUS_SPACE_IO AMD64_BUS_SPACE_IO +#define ACPI_BUS_HANDLE 0 +#endif + +ACPI_STATUS +AcpiOsReadPort ( + ACPI_IO_ADDRESS InPort, + UINT32 *Value, + UINT32 Width) +{ + switch (Width) { + case 8: + *(u_int8_t *)Value = bus_space_read_1(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, InPort); + break; + case 16: + *(u_int16_t *)Value = bus_space_read_2(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, InPort); + break; + case 32: + *(u_int32_t *)Value = bus_space_read_4(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, InPort); + break; + default: + /* debug trap goes here */ + break; + } + + return(AE_OK); +} + +ACPI_STATUS +AcpiOsWritePort ( + ACPI_IO_ADDRESS OutPort, + UINT32 Value, + UINT32 Width) +{ + switch (Width) { + case 8: + bus_space_write_1(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, OutPort, Value); + break; + case 16: + bus_space_write_2(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, OutPort, Value); + break; + case 32: + bus_space_write_4(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, OutPort, Value); + break; + default: + /* debug trap goes here */ + break; + } + + return(AE_OK); +} + +ACPI_STATUS +AcpiOsReadPciConfiguration ( + ACPI_PCI_ID *PciId, + UINT32 Register, + void *Value, + UINT32 Width) +{ + u_int32_t byte_width = Width / 8; + u_int32_t val; + + if (!pci_cfgregopen()) + return(AE_NOT_EXIST); + + val = pci_cfgregread(PciId->Bus, PciId->Device, PciId->Function, Register, byte_width); + switch (Width) { + case 8: + *(u_int8_t *)Value = val & 0xff; + break; + case 16: + *(u_int16_t *)Value = val & 0xffff; + break; + case 32: + *(u_int32_t *)Value = val; + break; + default: + /* debug trap goes here */ + break; + } + + + return(AE_OK); +} + + +ACPI_STATUS +AcpiOsWritePciConfiguration ( + ACPI_PCI_ID *PciId, + UINT32 Register, + ACPI_INTEGER Value, + UINT32 Width) +{ + u_int32_t byte_width = Width / 8; + + if (!pci_cfgregopen()) + return(AE_NOT_EXIST); + + pci_cfgregwrite(PciId->Bus, PciId->Device, PciId->Function, Register, Value, byte_width); + + return(AE_OK); +} + +/* XXX should use acpivar.h but too many include dependencies */ +extern ACPI_STATUS acpi_EvaluateInteger(ACPI_HANDLE handle, char *path, int + *number); + +/* + * Depth-first recursive case for finding the bus, given the slot/function. + */ +static int +acpi_bus_number(ACPI_HANDLE root, ACPI_HANDLE curr, ACPI_PCI_ID *PciId) +{ + ACPI_HANDLE parent; + ACPI_OBJECT_TYPE type; + UINT32 adr; + int bus, slot, func, class, subclass, header; + + /* Try to get the _BBN object of the root, otherwise assume it is 0 */ + bus = 0; + if (root == curr) { + if (ACPI_FAILURE(acpi_EvaluateInteger(root, "_BBN", &bus)) && + bootverbose) + printf("acpi_bus_number: root bus has no _BBN, assuming 0\n"); + return (bus); + } + if (ACPI_FAILURE(AcpiGetParent(curr, &parent))) + return (bus); + + /* First, recurse up the tree until we find the host bus */ + bus = acpi_bus_number(root, parent, PciId); + + /* Validate parent bus device type */ + if (ACPI_FAILURE(AcpiGetType(parent, &type)) || type != ACPI_TYPE_DEVICE) { + printf("acpi_bus_number: not a device, type %d\n", type); + return (bus); + } + /* Get the parent's slot and function */ + if (ACPI_FAILURE(acpi_EvaluateInteger(parent, "_ADR", &adr))) { + printf("acpi_bus_number: can't get _ADR\n"); + return (bus); + } + slot = ACPI_HIWORD(adr); + func = ACPI_LOWORD(adr); + + /* Is this a PCI-PCI or Cardbus-PCI bridge? */ + class = pci_cfgregread(bus, slot, func, PCIR_CLASS, 1); + if (class != PCIC_BRIDGE) + return (bus); + subclass = pci_cfgregread(bus, slot, func, PCIR_SUBCLASS, 1); + /* Find the header type, masking off the multifunction bit */ + header = pci_cfgregread(bus, slot, func, PCIR_HDRTYPE, 1) & PCIM_HDRTYPE; + if (header == PCIM_HDRTYPE_BRIDGE && subclass == PCIS_BRIDGE_PCI) + bus = pci_cfgregread(bus, slot, func, PCIR_SECBUS_1, 1); + if (header == PCIM_HDRTYPE_CARDBUS && subclass == PCIS_BRIDGE_CARDBUS) + bus = pci_cfgregread(bus, slot, func, PCIR_SECBUS_2, 1); + return (bus); +} + +/* + * Find the bus number for a device + * + * rhandle: handle for the root bus + * chandle: handle for the device + * PciId: pointer to device slot and function, we fill out bus + */ +void +AcpiOsDerivePciId ( + ACPI_HANDLE rhandle, + ACPI_HANDLE chandle, + ACPI_PCI_ID **PciId) +{ + ACPI_HANDLE parent; + int bus; + + if (pci_cfgregopen() == 0) + panic("AcpiOsDerivePciId unable to initialize pci bus"); + + /* Try to read _BBN for bus number if we're at the root */ + bus = 0; + if (rhandle == chandle) { + if (ACPI_FAILURE(acpi_EvaluateInteger(rhandle, "_BBN", &bus)) && + bootverbose) + printf("AcpiOsDerivePciId: root bus has no _BBN, assuming 0\n"); + } + /* + * Get the parent handle and call the recursive case. It is not + * clear why we seem to be getting a chandle that points to a child + * of the desired slot/function but passing in the parent handle + * here works. + */ + if (ACPI_SUCCESS(AcpiGetParent(chandle, &parent))) + bus = acpi_bus_number(rhandle, parent, *PciId); + (*PciId)->Bus = bus; + if (bootverbose) { + printf("AcpiOsDerivePciId: bus %d dev %d func %d\n", + (*PciId)->Bus, (*PciId)->Device, (*PciId)->Function); + } +} diff --git a/sys/dev/acpica/Osd/OsdInterrupt.c b/sys/dev/acpica/Osd/OsdInterrupt.c new file mode 100644 index 0000000..e95ee80 --- /dev/null +++ b/sys/dev/acpica/Osd/OsdInterrupt.c @@ -0,0 +1,157 @@ +/*- + * Copyright (c) 2000 Michael Smith + * Copyright (c) 2000 BSDi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * 6.5 : Interrupt handling + */ + +#include "acpi.h" + +#include <sys/bus.h> +#include <machine/resource.h> +#include <machine/bus.h> +#include <sys/rman.h> + +#include <dev/acpica/acpivar.h> + +#define _COMPONENT ACPI_OS_SERVICES +ACPI_MODULE_NAME("INTERRUPT") + +static void InterruptWrapper(void *arg); +static OSD_HANDLER InterruptHandler; + +static UINT32 InterruptOverride = 0; + +/* + * XXX this does not correctly free resources in the case of partically successful + * attachment. + */ +ACPI_STATUS +AcpiOsInstallInterruptHandler(UINT32 InterruptNumber, OSD_HANDLER ServiceRoutine, void *Context) +{ + struct acpi_softc *sc; + + ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); + + if ((sc = devclass_get_softc(devclass_find("acpi"), 0)) == NULL) + panic("can't find ACPI device to register interrupt"); + if (sc->acpi_dev == NULL) + panic("acpi softc has invalid device"); + + if ((InterruptNumber < 0) || (InterruptNumber > 255)) + return_ACPI_STATUS(AE_BAD_PARAMETER); + if (ServiceRoutine == NULL) + return_ACPI_STATUS(AE_BAD_PARAMETER); + if (InterruptHandler != NULL && InterruptHandler != ServiceRoutine) { + device_printf(sc->acpi_dev, "can't register more than one ACPI interrupt\n"); + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + InterruptHandler = ServiceRoutine; + + /* + * This isn't strictly true, as we ought to be able to handle > 1 interrupt. The ACPI + * spec doesn't call for this though. + */ + if (sc->acpi_irq != NULL) { + device_printf(sc->acpi_dev, "attempt to register more than one interrupt handler\n"); + return_ACPI_STATUS(AE_ALREADY_EXISTS); + } + sc->acpi_irq_rid = 0; + if (InterruptOverride != 0) { + device_printf(sc->acpi_dev, + "Overriding SCI Interrupt from IRQ %u to IRQ %u\n", + InterruptNumber, InterruptOverride); + InterruptNumber = InterruptOverride; + } + bus_set_resource(sc->acpi_dev, SYS_RES_IRQ, 0, InterruptNumber, 1); + if ((sc->acpi_irq = bus_alloc_resource(sc->acpi_dev, SYS_RES_IRQ, &sc->acpi_irq_rid, 0, ~0, 1, + RF_SHAREABLE | RF_ACTIVE)) == NULL) { + device_printf(sc->acpi_dev, "could not allocate SCI interrupt\n"); + return_ACPI_STATUS(AE_ALREADY_EXISTS); + } + if (bus_setup_intr(sc->acpi_dev, sc->acpi_irq, INTR_TYPE_MISC, (driver_intr_t *)InterruptWrapper, + Context, &sc->acpi_irq_handle)) { + device_printf(sc->acpi_dev, "could not set up SCI interrupt\n"); + return_ACPI_STATUS(AE_ALREADY_EXISTS); + } + + return_ACPI_STATUS(AE_OK); +} + +ACPI_STATUS +AcpiOsRemoveInterruptHandler (UINT32 InterruptNumber, OSD_HANDLER ServiceRoutine) +{ + struct acpi_softc *sc; + + ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); + + if ((InterruptNumber < 0) || (InterruptNumber > 255)) + return_ACPI_STATUS(AE_BAD_PARAMETER); + if (ServiceRoutine == NULL) + return_ACPI_STATUS(AE_BAD_PARAMETER); + + if ((sc = devclass_get_softc(devclass_find("acpi"), 0)) == NULL) + panic("can't find ACPI device to deregister interrupt"); + + if (sc->acpi_irq == NULL) + return_ACPI_STATUS(AE_NOT_EXIST); + + bus_teardown_intr(sc->acpi_dev, sc->acpi_irq, sc->acpi_irq_handle); + bus_release_resource(sc->acpi_dev, SYS_RES_IRQ, 0, sc->acpi_irq); + bus_delete_resource(sc->acpi_dev, SYS_RES_IRQ, 0); + + sc->acpi_irq = NULL; + + return_ACPI_STATUS(AE_OK); +} + +ACPI_STATUS +acpi_OverrideInterruptLevel(UINT32 InterruptNumber) +{ + + ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); + + if (InterruptOverride != 0) + return_ACPI_STATUS(AE_ALREADY_EXISTS); + InterruptOverride = InterruptNumber; + return_ACPI_STATUS(AE_OK); +} + +/* + * Interrupt handler wrapper. + */ +static void +InterruptWrapper(void *arg) +{ + ACPI_LOCK_DECL; + + ACPI_LOCK; + InterruptHandler(arg); + ACPI_UNLOCK; +} diff --git a/sys/dev/acpica/Osd/OsdMemory.c b/sys/dev/acpica/Osd/OsdMemory.c new file mode 100644 index 0000000..8fe1a44 --- /dev/null +++ b/sys/dev/acpica/Osd/OsdMemory.c @@ -0,0 +1,162 @@ +/*- + * Copyright (c) 2000 Mitsaru Iwasaki + * Copyright (c) 2000 Michael Smith + * Copyright (c) 2000 BSDi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * 6.2 : Memory Management + */ + +#include "acpi.h" + +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <vm/vm.h> +#include <vm/pmap.h> + +static MALLOC_DEFINE(M_ACPICA, "acpica", "ACPI CA memory pool"); + +void * +AcpiOsAllocate(ACPI_SIZE Size) +{ + return(malloc(Size, M_ACPICA, M_NOWAIT)); +} + +void +AcpiOsFree (void *Memory) +{ + free(Memory, M_ACPICA); +} + +ACPI_STATUS +AcpiOsMapMemory (ACPI_PHYSICAL_ADDRESS PhysicalAddress, ACPI_SIZE Length, void **LogicalAddress) +{ + *LogicalAddress = pmap_mapdev((vm_offset_t)PhysicalAddress, Length); + if (*LogicalAddress == NULL) + return(AE_BAD_ADDRESS); + return(AE_OK); +} + +void +AcpiOsUnmapMemory (void *LogicalAddress, ACPI_SIZE Length) +{ + pmap_unmapdev((vm_offset_t)LogicalAddress, Length); +} + +ACPI_STATUS +AcpiOsGetPhysicalAddress(void *LogicalAddress, ACPI_PHYSICAL_ADDRESS *PhysicalAddress) +{ + /* we can't necessarily do this, so cop out */ + return(AE_BAD_ADDRESS); +} + +/* + * There is no clean way to do this. We make the charitable assumption + * that callers will not pass garbage to us. + */ +BOOLEAN +AcpiOsReadable (void *Pointer, ACPI_SIZE Length) +{ + return(TRUE); +} + +BOOLEAN +AcpiOsWritable (void *Pointer, ACPI_SIZE Length) +{ + return(TRUE); +} + +ACPI_STATUS +AcpiOsReadMemory ( + ACPI_PHYSICAL_ADDRESS Address, + UINT32 *Value, + UINT32 Width) +{ + void *LogicalAddress; + + if (AcpiOsMapMemory(Address, Width / 8, &LogicalAddress) != AE_OK) { + return(AE_NOT_EXIST); + } + + switch (Width) { + case 8: + *(u_int8_t *)Value = (*(volatile u_int8_t *)LogicalAddress); + break; + case 16: + *(u_int16_t *)Value = (*(volatile u_int16_t *)LogicalAddress); + break; + case 32: + *(u_int32_t *)Value = (*(volatile u_int32_t *)LogicalAddress); + break; + case 64: + *(u_int64_t *)Value = (*(volatile u_int64_t *)LogicalAddress); + break; + default: + /* debug trap goes here */ + break; + } + + AcpiOsUnmapMemory(LogicalAddress, Width / 8); + + return(AE_OK); +} + +ACPI_STATUS +AcpiOsWriteMemory ( + ACPI_PHYSICAL_ADDRESS Address, + UINT32 Value, + UINT32 Width) +{ + void *LogicalAddress; + + if (AcpiOsMapMemory(Address, Width / 8, &LogicalAddress) != AE_OK) { + return(AE_NOT_EXIST); + } + + switch (Width) { + case 8: + (*(volatile u_int8_t *)LogicalAddress) = Value & 0xff; + break; + case 16: + (*(volatile u_int16_t *)LogicalAddress) = Value & 0xffff; + break; + case 32: + (*(volatile u_int32_t *)LogicalAddress) = Value & 0xffffffff; + break; + case 64: + (*(volatile u_int64_t *)LogicalAddress) = Value; + break; + default: + /* debug trap goes here */ + break; + } + + AcpiOsUnmapMemory(LogicalAddress, Width / 8); + + return(AE_OK); +} diff --git a/sys/dev/acpica/Osd/OsdSchedule.c b/sys/dev/acpica/Osd/OsdSchedule.c new file mode 100644 index 0000000..4ba1dee --- /dev/null +++ b/sys/dev/acpica/Osd/OsdSchedule.c @@ -0,0 +1,289 @@ +/*- + * Copyright (c) 2000 Michael Smith + * Copyright (c) 2000 BSDi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * 6.3 : Scheduling services + */ + +#include "acpi.h" + +#include "opt_acpi.h" +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/interrupt.h> +#include <sys/kernel.h> +#include <sys/kthread.h> +#include <sys/malloc.h> +#include <sys/proc.h> +#include <sys/taskqueue.h> +#include <machine/clock.h> + +#include <sys/bus.h> + +#include <dev/acpica/acpivar.h> + +#define _COMPONENT ACPI_OS_SERVICES +ACPI_MODULE_NAME("SCHEDULE") + +/* + * This is a little complicated due to the fact that we need to build and then + * free a 'struct task' for each task we enqueue. + */ + +MALLOC_DEFINE(M_ACPITASK, "acpitask", "ACPI deferred task"); + +static void AcpiOsExecuteQueue(void *arg, int pending); + +struct acpi_task { + struct task at_task; + OSD_EXECUTION_CALLBACK at_function; + void *at_context; +}; + +struct acpi_task_queue { + STAILQ_ENTRY(acpi_task_queue) at_q; + struct acpi_task *at; +}; + +#if __FreeBSD_version >= 500000 +/* + * Private task queue definition for ACPI + */ +TASKQUEUE_DECLARE(acpi); +static void *taskqueue_acpi_ih; + +static void +taskqueue_acpi_enqueue(void *context) +{ + swi_sched(taskqueue_acpi_ih, 0); +} + +static void +taskqueue_acpi_run(void *dummy) +{ + taskqueue_run(taskqueue_acpi); +} + +TASKQUEUE_DEFINE(acpi, taskqueue_acpi_enqueue, 0, + swi_add(NULL, "acpitaskq", taskqueue_acpi_run, NULL, + SWI_TQ, 0, &taskqueue_acpi_ih)); + +#ifdef ACPI_USE_THREADS +STAILQ_HEAD(, acpi_task_queue) acpi_task_queue; +static struct mtx acpi_task_mtx; + +static void +acpi_task_thread(void *arg) +{ + struct acpi_task_queue *atq; + OSD_EXECUTION_CALLBACK Function; + void *Context; + + for (;;) { + mtx_lock(&acpi_task_mtx); + if ((atq = STAILQ_FIRST(&acpi_task_queue)) == NULL) { + msleep(&acpi_task_queue, &acpi_task_mtx, PCATCH, "actask", 0); + mtx_unlock(&acpi_task_mtx); + continue; + } + + STAILQ_REMOVE_HEAD(&acpi_task_queue, at_q); + mtx_unlock(&acpi_task_mtx); + + Function = (OSD_EXECUTION_CALLBACK)atq->at->at_function; + Context = atq->at->at_context; + + mtx_lock(&Giant); + Function(Context); + + free(atq->at, M_ACPITASK); + free(atq, M_ACPITASK); + mtx_unlock(&Giant); + } + + kthread_exit(0); +} + +int +acpi_task_thread_init(void) +{ + int i, err; + struct proc *acpi_kthread_proc; + + err = 0; + STAILQ_INIT(&acpi_task_queue); + mtx_init(&acpi_task_mtx, "ACPI task", NULL, MTX_DEF); + + for (i = 0; i < ACPI_MAX_THREADS; i++) { + err = kthread_create(acpi_task_thread, NULL, &acpi_kthread_proc, + 0, 0, "acpi_task%d", i); + if (err != 0) { + printf("%s: kthread_create failed(%d)\n", __func__, err); + break; + } + } + return (err); +} +#endif +#endif + +ACPI_STATUS +AcpiOsQueueForExecution(UINT32 Priority, OSD_EXECUTION_CALLBACK Function, void *Context) +{ + struct acpi_task *at; + int pri; + + ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); + + if (Function == NULL) + return_ACPI_STATUS(AE_BAD_PARAMETER); + + at = malloc(sizeof(*at), M_ACPITASK, M_NOWAIT); /* Interrupt Context */ + if (at == NULL) + return_ACPI_STATUS(AE_NO_MEMORY); + bzero(at, sizeof(*at)); + + at->at_function = Function; + at->at_context = Context; + switch (Priority) { + case OSD_PRIORITY_GPE: + pri = 4; + break; + case OSD_PRIORITY_HIGH: + pri = 3; + break; + case OSD_PRIORITY_MED: + pri = 2; + break; + case OSD_PRIORITY_LO: + pri = 1; + break; + default: + free(at, M_ACPITASK); + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + TASK_INIT(&at->at_task, pri, AcpiOsExecuteQueue, at); + +#if __FreeBSD_version < 500000 + taskqueue_enqueue(taskqueue_swi, (struct task *)at); +#else + taskqueue_enqueue(taskqueue_acpi, (struct task *)at); +#endif + return_ACPI_STATUS(AE_OK); +} + +static void +AcpiOsExecuteQueue(void *arg, int pending) +{ + struct acpi_task *at; + struct acpi_task_queue *atq; + OSD_EXECUTION_CALLBACK Function; + void *Context; + + ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); + + at = (struct acpi_task *)arg; + atq = NULL; + Function = NULL; + Context = NULL; + +#ifdef ACPI_USE_THREADS + atq = malloc(sizeof(*atq), M_ACPITASK, M_NOWAIT); + if (atq == NULL) { + printf("%s: no memory\n", __func__); + return; + } + + atq->at = at; + + mtx_lock(&acpi_task_mtx); + STAILQ_INSERT_TAIL(&acpi_task_queue, atq, at_q); + mtx_unlock(&acpi_task_mtx); + wakeup_one(&acpi_task_queue); +#else + Function = (OSD_EXECUTION_CALLBACK)at->at_function; + Context = at->at_context; + + Function(Context); + free(at, M_ACPITASK); +#endif + + return_VOID; +} + +/* + * We don't have any sleep granularity better than hz, so + * make do with that. + */ +void +AcpiOsSleep(UINT32 Seconds, UINT32 Milliseconds) +{ + int timo; + static int dummy; + + ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); + + timo = (Seconds * hz) + Milliseconds * hz / 1000; + + /* + * If requested sleep time is less than our hz resolution, use + * DELAY instead for better granularity. + */ + if (timo > 0) + tsleep(&dummy, 0, "acpislp", timo); + else + DELAY(Milliseconds * 1000); + + return_VOID; +} + +void +AcpiOsStall(UINT32 Microseconds) +{ + ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); + + DELAY(Microseconds); + return_VOID; +} + +UINT32 +AcpiOsGetThreadId(void) +{ + struct proc *p; + /* XXX do not add FUNCTION_TRACE here, results in recursive call */ + + p = curproc; +#if __FreeBSD_version < 500000 + if (p == NULL) + p = &proc0; +#endif + KASSERT(p != NULL, ("%s: curproc is NULL!", __func__)); + return(p->p_pid + 1); /* can't return 0 */ +} diff --git a/sys/dev/acpica/Osd/OsdStream.c b/sys/dev/acpica/Osd/OsdStream.c new file mode 100644 index 0000000..7c9acde --- /dev/null +++ b/sys/dev/acpica/Osd/OsdStream.c @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 2000 Michael Smith + * Copyright (c) 2000 BSDi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * 6.6 : Stream I/O + */ + +#include "acpi.h" + +void +AcpiOsPrintf (const char *Format, ...) +{ + va_list ap; + + va_start(ap, Format); + vprintf(Format, ap); + va_end(ap); +} + +void +AcpiOsVprintf (const char *Format, va_list Args) +{ + vprintf(Format, Args); +} + diff --git a/sys/dev/acpica/Osd/OsdSynch.c b/sys/dev/acpica/Osd/OsdSynch.c new file mode 100644 index 0000000..f22b67e --- /dev/null +++ b/sys/dev/acpica/Osd/OsdSynch.c @@ -0,0 +1,392 @@ +/*- + * Copyright (c) 2000 Michael Smith + * Copyright (c) 2000 BSDi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * 6.1 : Mutual Exclusion and Synchronisation + */ + +#include "acpi.h" + +#include "opt_acpi.h" +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/sysctl.h> +#if __FreeBSD_version >= 500000 +#include <sys/lock.h> +#include <sys/mutex.h> +#endif + +#define _COMPONENT ACPI_OS_SERVICES +ACPI_MODULE_NAME("SYNCH") + +static MALLOC_DEFINE(M_ACPISEM, "acpisem", "ACPI semaphore"); + +#if __FreeBSD_version < 500000 +# define AS_LOCK(as) s = splhigh() +# define AS_UNLOCK(as) splx(s) +# define AS_LOCK_DECL int s +# define msleep(a, b, c, d, e) tsleep(a, c, d, e) +#else +# define AS_LOCK(as) mtx_lock(&(as)->as_mtx) +# define AS_UNLOCK(as) mtx_unlock(&(as)->as_mtx) +# define AS_LOCK_DECL +#endif + +/* + * Simple counting semaphore implemented using a mutex. (Subsequently used + * in the OSI code to implement a mutex. Go figure.) + */ +struct acpi_semaphore { +#if __FreeBSD_version >= 500000 + struct mtx as_mtx; +#endif + UINT32 as_units; + UINT32 as_maxunits; + UINT32 as_pendings; + UINT32 as_resetting; + UINT32 as_timeouts; +}; + +#ifndef ACPI_NO_SEMAPHORES +#ifndef ACPI_SEMAPHORES_MAX_PENDING +#define ACPI_SEMAPHORES_MAX_PENDING 4 +#endif +static int acpi_semaphore_debug = 0; +TUNABLE_INT("debug.acpi_semaphore_debug", &acpi_semaphore_debug); +SYSCTL_DECL(_debug_acpi); +SYSCTL_INT(_debug_acpi, OID_AUTO, semaphore_debug, CTLFLAG_RW, + &acpi_semaphore_debug, 0, "Enable ACPI semaphore debug messages"); +#endif + +ACPI_STATUS +AcpiOsCreateSemaphore(UINT32 MaxUnits, UINT32 InitialUnits, ACPI_HANDLE *OutHandle) +{ +#ifndef ACPI_NO_SEMAPHORES + struct acpi_semaphore *as; + + ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); + + if (OutHandle == NULL) + return(AE_BAD_PARAMETER); + if (InitialUnits > MaxUnits) + return_ACPI_STATUS(AE_BAD_PARAMETER); + + if ((as = malloc(sizeof(*as), M_ACPISEM, M_NOWAIT)) == NULL) + return_ACPI_STATUS(AE_NO_MEMORY); + + bzero(as, sizeof(*as)); +#if __FreeBSD_version >= 500000 + mtx_init(&as->as_mtx, "ACPI semaphore", NULL, MTX_DEF); +#endif + as->as_units = InitialUnits; + as->as_maxunits = MaxUnits; + as->as_pendings = as->as_resetting = as->as_timeouts = 0; + + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, + "created semaphore %p max %d, initial %d\n", + as, InitialUnits, MaxUnits)); + + *OutHandle = (ACPI_HANDLE)as; + return_ACPI_STATUS(AE_OK); +#else + *OutHandle = (ACPI_HANDLE)OutHandle; + return(AE_OK); +#endif +} + +ACPI_STATUS +AcpiOsDeleteSemaphore (ACPI_HANDLE Handle) +{ +#ifndef ACPI_NO_SEMAPHORES + struct acpi_semaphore *as = (struct acpi_semaphore *)Handle; + + ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); + + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "destroyed semaphore %p\n", as)); +#if __FreeBSD_version >= 500000 + mtx_destroy(&as->as_mtx); +#endif + free(Handle, M_ACPISEM); + return_ACPI_STATUS(AE_OK); +#else + return(AE_OK); +#endif +} + +/* + * This implementation has a bug, in that it has to stall for the entire + * timeout before it will return AE_TIME. A better implementation would + * use getmicrotime() to correctly adjust the timeout after being woken up. + */ +ACPI_STATUS +AcpiOsWaitSemaphore(ACPI_HANDLE Handle, UINT32 Units, UINT16 Timeout) +{ +#ifndef ACPI_NO_SEMAPHORES + struct acpi_semaphore *as = (struct acpi_semaphore *)Handle; + ACPI_STATUS result; + int rv, tmo; + struct timeval timeouttv, currenttv, timelefttv; + AS_LOCK_DECL; + + ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); + + if (as == NULL) + return_ACPI_STATUS(AE_BAD_PARAMETER); + + if (cold) + return_ACPI_STATUS(AE_OK); + +#if 0 + if (as->as_units < Units && as->as_timeouts > 10) { + printf("%s: semaphore %p too many timeouts, resetting\n", __func__, as); + AS_LOCK(as); + as->as_units = as->as_maxunits; + if (as->as_pendings) + as->as_resetting = 1; + as->as_timeouts = 0; + wakeup(as); + AS_UNLOCK(as); + return_ACPI_STATUS(AE_TIME); + } + + if (as->as_resetting) { + return_ACPI_STATUS(AE_TIME); + } +#endif + + /* a timeout of ACPI_WAIT_FOREVER means "forever" */ + if (Timeout == ACPI_WAIT_FOREVER) { + tmo = 0; + timeouttv.tv_sec = ((0xffff/1000) + 1); /* cf. ACPI spec */ + timeouttv.tv_usec = 0; + } else { + /* compute timeout using microseconds per tick */ + tmo = (Timeout * 1000) / (1000000 / hz); + if (tmo <= 0) + tmo = 1; + timeouttv.tv_sec = Timeout / 1000; + timeouttv.tv_usec = (Timeout % 1000) * 1000; + } + + /* calculate timeout value in timeval */ + getmicrotime(¤ttv); + timevaladd(&timeouttv, ¤ttv); + + AS_LOCK(as); + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, + "get %d units from semaphore %p (has %d), timeout %d\n", + Units, as, as->as_units, Timeout)); + for (;;) { + if (as->as_maxunits == ACPI_NO_UNIT_LIMIT) { + result = AE_OK; + break; + } + if (as->as_units >= Units) { + as->as_units -= Units; + result = AE_OK; + break; + } + + /* limit number of pending treads */ + if (as->as_pendings >= ACPI_SEMAPHORES_MAX_PENDING) { + result = AE_TIME; + break; + } + + /* if timeout values of zero is specified, return immediately */ + if (Timeout == 0) { + result = AE_TIME; + break; + } + +#if __FreeBSD_version >= 500000 + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, + "semaphore blocked, calling msleep(%p, %p, %d, \"acsem\", %d)\n", + as, &as->as_mtx, PCATCH, tmo)); +#endif + + as->as_pendings++; + + if (acpi_semaphore_debug) { + printf("%s: Sleep %d, pending %d, semaphore %p, thread %d\n", + __func__, Timeout, as->as_pendings, as, AcpiOsGetThreadId()); + } + + rv = msleep(as, &as->as_mtx, PCATCH, "acsem", tmo); + + as->as_pendings--; + +#if 0 + if (as->as_resetting) { + /* semaphore reset, return immediately */ + if (as->as_pendings == 0) { + as->as_resetting = 0; + } + result = AE_TIME; + break; + } +#endif + + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "msleep(%d) returned %d\n", tmo, rv)); + if (rv == EWOULDBLOCK) { + result = AE_TIME; + break; + } + + /* check if we already awaited enough */ + timelefttv = timeouttv; + getmicrotime(¤ttv); + timevalsub(&timelefttv, ¤ttv); + if (timelefttv.tv_sec < 0) { + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "await semaphore %p timeout\n", as)); + result = AE_TIME; + break; + } + + /* adjust timeout for the next sleep */ + tmo = (timelefttv.tv_sec * 1000000 + timelefttv.tv_usec) / (1000000 / hz); + if (tmo <= 0) + tmo = 1; + + if (acpi_semaphore_debug) { + printf("%s: Wakeup timeleft(%lu, %lu), tmo %u, semaphore %p, thread %d\n", + __func__, timelefttv.tv_sec, timelefttv.tv_usec, tmo, as, AcpiOsGetThreadId()); + } + } + + if (acpi_semaphore_debug) { + if (result == AE_TIME && Timeout > 0) { + printf("%s: Timeout %d, pending %d, semaphore %p\n", + __func__, Timeout, as->as_pendings, as); + } + if (result == AE_OK && (as->as_timeouts > 0 || as->as_pendings > 0)) { + printf("%s: Acquire %d, units %d, pending %d, semaphore %p, thread %d\n", + __func__, Units, as->as_units, as->as_pendings, as, AcpiOsGetThreadId()); + } + } + + if (result == AE_TIME) { + as->as_timeouts++; + } else { + as->as_timeouts = 0; + } + + AS_UNLOCK(as); + + return_ACPI_STATUS(result); +#else + return(AE_OK); +#endif +} + +ACPI_STATUS +AcpiOsSignalSemaphore(ACPI_HANDLE Handle, UINT32 Units) +{ +#ifndef ACPI_NO_SEMAPHORES + struct acpi_semaphore *as = (struct acpi_semaphore *)Handle; + AS_LOCK_DECL; + + ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); + + if (as == NULL) + return_ACPI_STATUS(AE_BAD_PARAMETER); + + AS_LOCK(as); + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, + "return %d units to semaphore %p (has %d)\n", + Units, as, as->as_units)); + if (as->as_maxunits != ACPI_NO_UNIT_LIMIT) { + as->as_units += Units; + if (as->as_units > as->as_maxunits) + as->as_units = as->as_maxunits; + } + + if (acpi_semaphore_debug && (as->as_timeouts > 0 || as->as_pendings > 0)) { + printf("%s: Release %d, units %d, pending %d, semaphore %p, thread %d\n", + __func__, Units, as->as_units, as->as_pendings, as, AcpiOsGetThreadId()); + } + + wakeup(as); + AS_UNLOCK(as); + return_ACPI_STATUS(AE_OK); +#else + return(AE_OK); +#endif +} + +ACPI_STATUS +AcpiOsCreateLock (ACPI_HANDLE *OutHandle) +{ + struct mtx *m; + + if (OutHandle == NULL) + return (AE_BAD_PARAMETER); + MALLOC(m, struct mtx *, sizeof(*m), M_ACPISEM, M_NOWAIT | M_ZERO); + if (m == NULL) + return (AE_NO_MEMORY); + + mtx_init(m, "acpica subsystem lock", NULL, MTX_DEF); + *OutHandle = (ACPI_HANDLE)m; + return (AE_OK); +} + +void +AcpiOsDeleteLock (ACPI_HANDLE Handle) +{ + struct mtx *m = (struct mtx *)Handle; + + if (Handle == NULL) + return; + mtx_destroy(m); +} + +/* + * The Flags parameter seems to state whether or not caller is an ISR + * (and thus can't block) but since we have ithreads, we don't worry + * about potentially blocking. + */ +void +AcpiOsAcquireLock (ACPI_HANDLE Handle, UINT32 Flags) +{ + struct mtx *m = (struct mtx *)Handle; + + if (Handle == NULL) + return; + mtx_lock(m); +} + +void +AcpiOsReleaseLock (ACPI_HANDLE Handle, UINT32 Flags) +{ + struct mtx *m = (struct mtx *)Handle; + + if (Handle == NULL) + return; + mtx_unlock(m); +} diff --git a/sys/dev/acpica/Osd/OsdTable.c b/sys/dev/acpica/Osd/OsdTable.c new file mode 100644 index 0000000..f24c5ea --- /dev/null +++ b/sys/dev/acpica/Osd/OsdTable.c @@ -0,0 +1,96 @@ +/*- + * Copyright (c) 2002 Mitsaru Iwasaki + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * ACPI Table interfaces + */ + +#include "acpi.h" + +#include <sys/kernel.h> +#include <sys/linker.h> + +#undef _COMPONENT +#define _COMPONENT ACPI_TABLES + +static char acpi_os_name[128]; + +ACPI_STATUS +AcpiOsPredefinedOverride ( + const ACPI_PREDEFINED_NAMES *InitVal, + ACPI_STRING *NewVal) +{ + if (InitVal == NULL || NewVal == NULL) + return(AE_BAD_PARAMETER); + + *NewVal = NULL; + if (strncmp(InitVal->Name, "_OS_", 4) == 0 && + getenv_string("hw.acpi.os_name", acpi_os_name, sizeof(acpi_os_name))) { + printf("ACPI: Overriding _OS definition with \"%s\"\n", acpi_os_name); + *NewVal = acpi_os_name; + } + + return(AE_OK); +} + +ACPI_STATUS +AcpiOsTableOverride ( + ACPI_TABLE_HEADER *ExistingTable, + ACPI_TABLE_HEADER **NewTable) +{ + caddr_t acpi_dsdt, p; + + if (ExistingTable == NULL || NewTable == NULL) + { + return(AE_BAD_PARAMETER); + } + + (*NewTable) = NULL; + + if (strncmp(ExistingTable->Signature, "DSDT", 4) != 0) + { + return(AE_OK); + } + + if ((acpi_dsdt = preload_search_by_type("acpi_dsdt")) == NULL) + { + return(AE_OK); + } + + if ((p = preload_search_info(acpi_dsdt, MODINFO_ADDR)) == NULL) + { + return(AE_OK); + } + + (*NewTable) = *(void **)p; + + printf("ACPI: DSDT was overridden.\n"); + + return(AE_OK); +} + |