diff options
author | msmith <msmith@FreeBSD.org> | 2000-10-28 06:59:48 +0000 |
---|---|---|
committer | msmith <msmith@FreeBSD.org> | 2000-10-28 06:59:48 +0000 |
commit | a69e8faa90e4070a65302cf076ac04b9186fa622 (patch) | |
tree | a28f70dd99f84e0e7c0aeb156ae5ff36e60bd789 /sys/dev/acpica/acpi_resource.c | |
parent | 64e150eaa441bc8b9ecc4f649c022b7d522e487f (diff) | |
download | FreeBSD-src-a69e8faa90e4070a65302cf076ac04b9186fa622.zip FreeBSD-src-a69e8faa90e4070a65302cf076ac04b9186fa622.tar.gz |
Initial FreeBSD OSPM (operating system power management) modules for
ACPICA. Most of these are still works in progress. Support exists for:
- Fixed feature and control method power, lid and sleep buttons.
- Detection of ISA PnP devices using ACPI namespace.
- Detection of PCI root busses using ACPI namespace.
- CPU throttling and sleep states (incomplete)
- Thermal monitoring and cooling control (incomplete)
- Interface to platform embedded controllers (mostly complete)
- ACPI timer (incomplete)
- Simple userland control of sleep states.
- Shutdown and poweroff.
Diffstat (limited to 'sys/dev/acpica/acpi_resource.c')
-rw-r--r-- | sys/dev/acpica/acpi_resource.c | 343 |
1 files changed, 343 insertions, 0 deletions
diff --git a/sys/dev/acpica/acpi_resource.c b/sys/dev/acpica/acpi_resource.c new file mode 100644 index 0000000..3581ff7 --- /dev/null +++ b/sys/dev/acpica/acpi_resource.c @@ -0,0 +1,343 @@ +/*- + * 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$ + */ + +#include "opt_acpi.h" +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/bus.h> +#include <machine/bus.h> +#include <machine/resource.h> + +#include "acpi.h" + +#include <dev/acpica/acpivar.h> + +/* + * Fetch a device's resources and associate them with the device. + * + * Note that it might be nice to also locate ACPI-specific resource items, such + * as GPE bits. + */ +ACPI_STATUS +acpi_parse_resources(device_t dev, ACPI_HANDLE handle, struct acpi_parse_resource_set *set) +{ + ACPI_BUFFER buf; + RESOURCE *res; + char *curr, *last; + ACPI_STATUS status; + int i; + void *context; + + /* + * Fetch the device resources + */ + if (((status = acpi_GetIntoBuffer(handle, AcpiGetPossibleResources, &buf)) != AE_OK) && + ((status = acpi_GetIntoBuffer(handle, AcpiGetCurrentResources, &buf)) != AE_OK)) { + device_printf(dev, "can't fetch ACPI resources - %s\n", acpi_strerror(status)); + return(status); + } + +#ifdef ACPI_RES_DEBUG + device_printf(dev, "got %d bytes of resources\n", buf.Length); +#endif + set->set_init(dev, &context); + + /* + * Iterate through the resources + */ + curr = buf.Pointer; + last = (char *)buf.Pointer + buf.Length; + while (curr < last) { + res = (RESOURCE *)curr; + curr += res->Length; + + /* + * Handle the individual resource types + */ + switch(res->Id) { + case EndTag: +#ifdef ACPI_RES_DEBUG + device_printf(dev, "EndTag\n"); +#endif + curr = last; + break; + + case FixedIo: +#ifdef ACPI_RES_DEBUG + device_printf(dev, "FixedIo 0x%x/%d\n", res->Data.FixedIo.BaseAddress, res->Data.FixedIo.RangeLength); +#endif + set->set_ioport(dev, context, res->Data.FixedIo.BaseAddress, res->Data.FixedIo.RangeLength); + break; + + case Io: + if (res->Data.Io.MinBaseAddress == res->Data.Io.MaxBaseAddress) { +#ifdef ACPI_RES_DEBUG + device_printf(dev, "Io 0x%x/%d\n", res->Data.Io.MinBaseAddress, res->Data.Io.RangeLength); +#endif + set->set_ioport(dev, context, res->Data.Io.MinBaseAddress, res->Data.Io.RangeLength); + } else { +#ifdef ACPI_RES_DEBUG + device_printf(dev, "Io 0x%x-0x%x/%d\n", res->Data.Io.MinBaseAddress, res->Data.Io.MaxBaseAddress, + res->Data.Io.RangeLength); +#endif + set->set_iorange(dev, context, res->Data.Io.MinBaseAddress, res->Data.Io.MaxBaseAddress, + res->Data.Io.RangeLength, res->Data.Io.Alignment); + } + break; + + case FixedMemory32: +#ifdef ACPI_RES_DEBUG + device_printf(dev, "FixedMemory32 0x%x/%d\n", res->Data.FixedMemory32.RangeBaseAddress, + res->Data.FixedMemory32.RangeLength); +#endif + set->set_memory(dev, context, res->Data.FixedMemory32.RangeBaseAddress, + res->Data.FixedMemory32.RangeLength); + break; + + case Memory32: + if (res->Data.Memory32.MinBaseAddress == res->Data.Memory32.MaxBaseAddress) { +#ifdef ACPI_RES_DEBUG + device_printf(dev, "Memory32 0x%x/%d\n", res->Data.Memory32.MinBaseAddress, + res->Data.Memory32.RangeLength); +#endif + set->set_memory(dev, context, res->Data.Memory32.MinBaseAddress, res->Data.Memory32.RangeLength); + } else { +#ifdef ACPI_RES_DEBUG + device_printf(dev, "Memory32 0x%x-0x%x/%d\n", res->Data.Memory32.MinBaseAddress, + res->Data.Memory32.MaxBaseAddress, res->Data.Memory32.RangeLength); +#endif + set->set_memoryrange(dev, context, res->Data.Memory32.MinBaseAddress, res->Data.Memory32.MaxBaseAddress, + res->Data.Memory32.RangeLength, res->Data.Memory32.Alignment); + } + break; + + case Memory24: + if (res->Data.Memory24.MinBaseAddress == res->Data.Memory24.MaxBaseAddress) { +#ifdef ACPI_RES_DEBUG + device_printf(dev, "Memory24 0x%x/%d\n", res->Data.Memory24.MinBaseAddress, + res->Data.Memory24.RangeLength); +#endif + set->set_memory(dev, context, res->Data.Memory24.MinBaseAddress, res->Data.Memory24.RangeLength); + } else { +#ifdef ACPI_RES_DEBUG + device_printf(dev, "Memory24 0x%x-0x%x/%d\n", res->Data.Memory24.MinBaseAddress, + res->Data.Memory24.MaxBaseAddress, res->Data.Memory24.RangeLength); +#endif + set->set_memoryrange(dev, context, res->Data.Memory24.MinBaseAddress, res->Data.Memory24.MaxBaseAddress, + res->Data.Memory24.RangeLength, res->Data.Memory24.Alignment); + } + break; + + case Irq: + for (i = 0; i < res->Data.Irq.NumberOfInterrupts; i++) { +#ifdef ACPI_RES_DEBUG + device_printf(dev, "Irq %d\n", res->Data.Irq.Interrupts[i]); +#endif + set->set_irq(dev, context, res->Data.Irq.Interrupts[i]); + } + break; + + case Dma: + for (i = 0; i < res->Data.Dma.NumberOfChannels; i++) { +#ifdef ACPI_RES_DEBUG + device_printf(dev, "Drq %d\n", res->Data.Dma.Channels[i]); +#endif + set->set_drq(dev, context, res->Data.Dma.Channels[i]); + } + break; + + case StartDependentFunctions: +#ifdef ACPI_RES_DEBUG + device_printf(dev, "start dependant functions"); +#endif + set->set_start_dependant(dev, context, res->Data.StartDependentFunctions.CompatibilityPriority); + break; + + case EndDependentFunctions: +#ifdef ACPI_RES_DEBUG + device_printf(dev, "end dependant functions"); +#endif + set->set_end_dependant(dev, context); + break; + + case Address32: + device_printf(dev, "unimplemented Address32 resource\n"); + break; + + case Address16: + device_printf(dev, "unimplemented Address16 resource\n"); + break; + + case ExtendedIrq: + device_printf(dev, "unimplemented ExtendedIrq resource\n"); + break; + + case VendorSpecific: + device_printf(dev, "unimplemented VendorSpecific resource\n"); + break; + default: + break; + } + } + AcpiOsFree(buf.Pointer); + set->set_done(dev, context); + return(AE_OK); +} + +static void acpi_res_set_init(device_t dev, void **context); +static void acpi_res_set_done(device_t dev, void *context); +static void acpi_res_set_ioport(device_t dev, void *context, u_int32_t base, u_int32_t length); +static void acpi_res_set_iorange(device_t dev, void *context, u_int32_t low, u_int32_t high, + u_int32_t length, u_int32_t align); +static void acpi_res_set_memory(device_t dev, void *context, u_int32_t base, u_int32_t length); +static void acpi_res_set_memoryrange(device_t dev, void *context, u_int32_t low, u_int32_t high, + u_int32_t length, u_int32_t align); +static void acpi_res_set_irq(device_t dev, void *context, u_int32_t irq); +static void acpi_res_set_drq(device_t dev, void *context, u_int32_t drq); +static void acpi_res_set_start_dependant(device_t dev, void *context, int preference); +static void acpi_res_set_end_dependant(device_t dev, void *context); + +struct acpi_parse_resource_set acpi_res_parse_set = { + acpi_res_set_init, + acpi_res_set_done, + acpi_res_set_ioport, + acpi_res_set_iorange, + acpi_res_set_memory, + acpi_res_set_memoryrange, + acpi_res_set_irq, + acpi_res_set_drq, + acpi_res_set_start_dependant, + acpi_res_set_end_dependant +}; + +struct acpi_res_context { + int ar_nio; + int ar_nmem; + int ar_nirq; +}; + +static void +acpi_res_set_init(device_t dev, void **context) +{ + struct acpi_res_context *cp; + + if ((cp = AcpiOsAllocate(sizeof(*cp))) != NULL) { + bzero(cp, sizeof(*cp)); + *context = cp; + } +} + +static void +acpi_res_set_done(device_t dev, void *context) +{ + struct acpi_res_context *cp = (struct acpi_res_context *)context; + + if (cp == NULL) + return; + AcpiOsFree(cp); +} + +static void +acpi_res_set_ioport(device_t dev, void *context, u_int32_t base, u_int32_t length) +{ + struct acpi_res_context *cp = (struct acpi_res_context *)context; + + if (cp == NULL) + return; + bus_set_resource(dev, SYS_RES_IOPORT, cp->ar_nio++, base, length); +} + +static void +acpi_res_set_iorange(device_t dev, void *context, u_int32_t low, u_int32_t high, u_int32_t length, u_int32_t align) +{ + struct acpi_res_context *cp = (struct acpi_res_context *)context; + + if (cp == NULL) + return; + device_printf(dev, "I/O range not supported\n"); +} + +static void +acpi_res_set_memory(device_t dev, void *context, u_int32_t base, u_int32_t length) +{ + struct acpi_res_context *cp = (struct acpi_res_context *)context; + + if (cp == NULL) + return; + bus_set_resource(dev, SYS_RES_MEMORY, cp->ar_nmem++, base, length); +} + +static void +acpi_res_set_memoryrange(device_t dev, void *context, u_int32_t low, u_int32_t high, u_int32_t length, u_int32_t align) +{ + struct acpi_res_context *cp = (struct acpi_res_context *)context; + + if (cp == NULL) + return; + device_printf(dev, "memory range not supported\n"); +} + +static void +acpi_res_set_irq(device_t dev, void *context, u_int32_t irq) +{ + struct acpi_res_context *cp = (struct acpi_res_context *)context; + + if (cp == NULL) + return; + bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, irq, 1); +} + +static void +acpi_res_set_drq(device_t dev, void *context, u_int32_t drq) +{ + struct acpi_res_context *cp = (struct acpi_res_context *)context; + + if (cp == NULL) + return; + device_printf(dev, "DRQ not supported\n"); +} + +static void +acpi_res_set_start_dependant(device_t dev, void *context, int preference) +{ + struct acpi_res_context *cp = (struct acpi_res_context *)context; + + if (cp == NULL) + return; + device_printf(dev, "dependant functions not supported"); +} + +static void +acpi_res_set_end_dependant(device_t dev, void *context) +{ + struct acpi_res_context *cp = (struct acpi_res_context *)context; + + if (cp == NULL) + return; +} |