summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authormsmith <msmith@FreeBSD.org>2001-07-30 08:59:43 +0000
committermsmith <msmith@FreeBSD.org>2001-07-30 08:59:43 +0000
commitf3637b944d3ff9ce2560aca5c4ebfb9546237ab3 (patch)
tree4565ade0f1c229c587d2a413b5006f1c6133c8f7 /sys
parent19f490118823e7ffc57548dc393848d40cdfce0c (diff)
downloadFreeBSD-src-f3637b944d3ff9ce2560aca5c4ebfb9546237ab3.zip
FreeBSD-src-f3637b944d3ff9ce2560aca5c4ebfb9546237ab3.tar.gz
- Prevent the ACPI code from being loaded as a module other than at
boot time. Loading as a module once the system is up and running doesn't make any sense. - Fix acpi_FindIndexedResource (it would only check the first resource), changes the calling interface. - Add a new helper function (acpi_AppendBufferResource) to help building buffers containing resources.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/acpica/acpi.c129
-rw-r--r--sys/dev/acpica/acpivar.h5
2 files changed, 123 insertions, 11 deletions
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index 8eaaeb2..f319a91 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -93,6 +93,7 @@ static int acpi_off_state = ACPI_STATE_S5;
struct mtx acpi_mutex;
+static int acpi_modevent(struct module *mod, int event, void *junk);
static void acpi_identify(driver_t *driver, device_t parent);
static int acpi_probe(device_t dev);
static int acpi_attach(device_t dev);
@@ -156,12 +157,33 @@ static driver_t acpi_driver = {
};
devclass_t acpi_devclass;
-DRIVER_MODULE(acpi, nexus, acpi_driver, acpi_devclass, 0, 0);
+DRIVER_MODULE(acpi, nexus, acpi_driver, acpi_devclass, acpi_modevent, 0);
SYSCTL_INT(_debug, OID_AUTO, acpi_debug_layer, CTLFLAG_RW, &AcpiDbgLayer, 0, "");
SYSCTL_INT(_debug, OID_AUTO, acpi_debug_level, CTLFLAG_RW, &AcpiDbgLevel, 0, "");
/*
+ * ACPI can only be loaded as a module by the loader; activating it after
+ * system bootstrap time is not useful, and can be fatal to the system.
+ * It also cannot be unloaded, since the entire system bus heirarchy hangs off it.
+ */
+static int
+acpi_modevent(struct module *mod, int event, void *junk)
+{
+ switch(event) {
+ case MOD_LOAD:
+ if (!cold)
+ return(EPERM);
+ break;
+ case MOD_UNLOAD:
+ return(EBUSY);
+ default:
+ break;
+ }
+ return(0);
+}
+
+/*
* Detect ACPI, perform early initialisation
*/
static void
@@ -937,22 +959,109 @@ acpi_ForeachPackageObject(ACPI_OBJECT *pkg, void (* func)(ACPI_OBJECT *comp, voi
* Find the (index)th resource object in a set.
*/
ACPI_STATUS
-acpi_FindIndexedResource(ACPI_RESOURCE *resbuf, int index, ACPI_RESOURCE **resp)
+acpi_FindIndexedResource(ACPI_BUFFER *buf, int index, ACPI_RESOURCE **resp)
{
- u_int8_t *p;
+ ACPI_RESOURCE *rp;
int i;
- p = (u_int8_t *)resbuf;
+ rp = (ACPI_RESOURCE *)buf->Pointer;
i = index;
- while (i > 0) {
- /* range check */
- if (p > ((u_int8_t *)resbuf + resbuf->Length))
+ while (i-- > 0) {
+ /* range check */
+ if (rp > (ACPI_RESOURCE *)((u_int8_t *)buf->Pointer + buf->Length))
return(AE_BAD_PARAMETER);
- p += ((ACPI_RESOURCE *)p)->Length;
- i--;
+ /* check for terminator */
+ if ((rp->Id == ACPI_RSTYPE_END_TAG) ||
+ (rp->Length == 0))
+ return(AE_NOT_FOUND);
+ rp = ACPI_RESOURCE_NEXT(rp);
}
if (resp != NULL)
- *resp = (ACPI_RESOURCE *)p;
+ *resp = rp;
+ return(AE_OK);
+}
+
+/*
+ * Append an ACPI_RESOURCE to an ACPI_BUFFER.
+ *
+ * Given a pointer to an ACPI_RESOURCE structure, expand the ACPI_BUFFER
+ * provided to contain it. If the ACPI_BUFFER is empty, allocate a sensible
+ * backing block. If the ACPI_RESOURCE is NULL, return an empty set of
+ * resources.
+ */
+#define ACPI_INITIAL_RESOURCE_BUFFER_SIZE 512
+
+ACPI_STATUS
+acpi_AppendBufferResource(ACPI_BUFFER *buf, ACPI_RESOURCE *res)
+{
+ ACPI_RESOURCE *rp;
+ void *newp;
+
+ /*
+ * Initialise the buffer if necessary.
+ */
+ if (buf->Pointer == NULL) {
+ buf->Length = ACPI_INITIAL_RESOURCE_BUFFER_SIZE;
+ if ((buf->Pointer = AcpiOsAllocate(buf->Length)) == NULL)
+ return(AE_NO_MEMORY);
+ rp = (ACPI_RESOURCE *)buf->Pointer;
+ rp->Id = ACPI_RSTYPE_END_TAG;
+ rp->Length = 0;
+ }
+ if (res == NULL)
+ return(AE_OK);
+
+ /*
+ * Scan the current buffer looking for the terminator.
+ * This will either find the terminator or hit the end
+ * of the buffer and return an error.
+ */
+ rp = (ACPI_RESOURCE *)buf->Pointer;
+ for (;;) {
+ /* range check, don't go outside the buffer */
+ if (rp >= (ACPI_RESOURCE *)((u_int8_t *)buf->Pointer + buf->Length))
+ return(AE_BAD_PARAMETER);
+ if ((rp->Id == ACPI_RSTYPE_END_TAG) ||
+ (rp->Length == 0)) {
+ break;
+ }
+ rp = ACPI_RESOURCE_NEXT(rp);
+ }
+
+ /*
+ * Check the size of the buffer and expand if required.
+ *
+ * Required size is:
+ * size of existing resources before terminator +
+ * size of new resource and header +
+ * size of terminator.
+ *
+ * Note that this loop should really only run once, unless
+ * for some reason we are stuffing a *really* huge resource.
+ */
+ while ((((u_int8_t *)rp - (u_int8_t *)buf->Pointer) +
+ res->Length + ACPI_RESOURCE_LENGTH_NO_DATA +
+ ACPI_RESOURCE_LENGTH) >= buf->Length) {
+ if ((newp = AcpiOsAllocate(buf->Length * 2)) == NULL)
+ return(AE_NO_MEMORY);
+ bcopy(buf->Pointer, newp, buf->Length);
+ AcpiOsFree(buf->Pointer);
+ buf->Pointer = newp;
+ buf->Length += buf->Length;
+ }
+
+ /*
+ * Insert the new resource.
+ */
+ bcopy(res, rp, res->Length + ACPI_RESOURCE_LENGTH_NO_DATA);
+
+ /*
+ * And add the terminator.
+ */
+ rp = ACPI_RESOURCE_NEXT(rp);
+ rp->Id = ACPI_RSTYPE_END_TAG;
+ rp->Length = 0;
+
return(AE_OK);
}
diff --git a/sys/dev/acpica/acpivar.h b/sys/dev/acpica/acpivar.h
index f6c21a3..42cfec7 100644
--- a/sys/dev/acpica/acpivar.h
+++ b/sys/dev/acpica/acpivar.h
@@ -206,7 +206,8 @@ extern ACPI_STATUS acpi_EvaluateInteger(ACPI_HANDLE handle, char *path, int *num
extern ACPI_STATUS acpi_ForeachPackageObject(ACPI_OBJECT *obj,
void (* func)(ACPI_OBJECT *comp, void *arg),
void *arg);
-extern ACPI_STATUS acpi_FindIndexedResource(ACPI_RESOURCE *resbuf, int index, ACPI_RESOURCE **resp);
+extern ACPI_STATUS acpi_FindIndexedResource(ACPI_BUFFER *buf, int index, ACPI_RESOURCE **resp);
+extern ACPI_STATUS acpi_AppendBufferResource(ACPI_BUFFER *buf, ACPI_RESOURCE *res);
extern ACPI_STATUS acpi_SetSleepState(struct acpi_softc *sc, int state);
extern ACPI_STATUS acpi_Enable(struct acpi_softc *sc);
@@ -230,6 +231,8 @@ struct acpi_parse_resource_set {
extern struct acpi_parse_resource_set acpi_res_parse_set;
extern ACPI_STATUS acpi_parse_resources(device_t dev, ACPI_HANDLE handle,
struct acpi_parse_resource_set *set);
+/* XXX until Intel fix this in their headers, based on NEXT_RESOURCE */
+#define ACPI_RESOURCE_NEXT(Res) (ACPI_RESOURCE *)((UINT8 *) Res + Res->Length)
/*
* ACPI event handling
OpenPOWER on IntegriCloud