summaryrefslogtreecommitdiffstats
path: root/sys/dev/acpica/acpi_resource.c
diff options
context:
space:
mode:
authormsmith <msmith@FreeBSD.org>2000-10-28 06:59:48 +0000
committermsmith <msmith@FreeBSD.org>2000-10-28 06:59:48 +0000
commita69e8faa90e4070a65302cf076ac04b9186fa622 (patch)
treea28f70dd99f84e0e7c0aeb156ae5ff36e60bd789 /sys/dev/acpica/acpi_resource.c
parent64e150eaa441bc8b9ecc4f649c022b7d522e487f (diff)
downloadFreeBSD-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.c343
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;
+}
OpenPOWER on IntegriCloud