[Midnightbsd-cvs] src: dev/acpica: merge

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Sun Nov 23 11:18:07 EST 2008


Log Message:
-----------
merge

Modified Files:
--------------
    src/sys/dev/acpica:
        acpi.c (r1.1.1.1 -> r1.2)
        acpi_acad.c (r1.1.1.1 -> r1.2)
        acpi_battery.c (r1.2 -> r1.3)
        acpi_button.c (r1.1.1.1 -> r1.2)
        acpi_cmbat.c (r1.1.1.1 -> r1.2)
        acpi_cpu.c (r1.1.1.1 -> r1.2)
        acpi_ec.c (r1.1.1.1 -> r1.2)
        acpi_if.m (r1.1.1.1 -> r1.2)
        acpi_isab.c (r1.1.1.1 -> r1.2)
        acpi_lid.c (r1.1.1.1 -> r1.2)
        acpi_package.c (r1.1.1.1 -> r1.2)
        acpi_pci.c (r1.1.1.1 -> r1.2)
        acpi_pci_link.c (r1.1.1.2 -> r1.2)
        acpi_pcib.c (r1.1.1.1 -> r1.2)
        acpi_pcib_acpi.c (r1.1.1.1 -> r1.2)
        acpi_pcib_pci.c (r1.1.1.1 -> r1.2)
        acpi_perf.c (r1.1.1.2 -> r1.2)
        acpi_powerres.c (r1.1.1.1 -> r1.2)
        acpi_quirk.c (r1.1.1.1 -> r1.2)
        acpi_resource.c (r1.1.1.1 -> r1.2)
        acpi_smbat.c (r1.1.1.2 -> r1.2)
        acpi_smbus.h (r1.1.1.1 -> r1.2)
        acpi_thermal.c (r1.1.1.1 -> r1.2)
        acpi_throttle.c (r1.2 -> r1.3)
        acpi_timer.c (r1.1.1.1 -> r1.2)
        acpi_video.c (r1.1.1.2 -> r1.2)
        acpiio.h (r1.1.1.1 -> r1.2)
        acpivar.h (r1.1.1.1 -> r1.2)
    src/sys/dev/acpica/Osd:
        OsdDebug.c (r1.1.1.1 -> r1.2)
        OsdHardware.c (r1.1.1.1 -> r1.2)
        OsdInterrupt.c (r1.1.1.1 -> r1.2)
        OsdMemory.c (r1.1.1.1 -> r1.2)
        OsdSchedule.c (r1.2 -> r1.3)
        OsdStream.c (r1.1.1.1 -> r1.2)
        OsdSynch.c (r1.1.1.1 -> r1.2)
        OsdTable.c (r1.1.1.1 -> r1.2)

Added Files:
-----------
    src/sys/dev/acpica:
        acpi_dock.c (r1.1)
        acpi_hpet.c (r1.1)
        acpi_hpet.h (r1.1)

-------------- next part --------------
Index: acpi_throttle.c
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/acpi_throttle.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/acpica/acpi_throttle.c -L sys/dev/acpica/acpi_throttle.c -u -r1.2 -r1.3
--- sys/dev/acpica/acpi_throttle.c
+++ sys/dev/acpica/acpi_throttle.c
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_throttle.c,v 1.7.2.1 2005/11/07 09:53:23 obrien Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_throttle.c,v 1.11 2007/03/22 18:16:40 jkim Exp $");
 
 #include "opt_acpi.h"
 #include <sys/param.h>
@@ -141,7 +141,7 @@
 	handle = acpi_get_handle(parent);
 	if (handle == NULL)
 		return;
-	if (AcpiGbl_FADT->DutyWidth == 0 ||
+	if (AcpiGbl_FADT.DutyWidth == 0 ||
 	    acpi_get_type(parent) != ACPI_TYPE_PROCESSOR)
 		return;
 
@@ -242,8 +242,8 @@
 
 	/* Get throttling parameters from the FADT.  0 means not supported. */
 	if (device_get_unit(sc->cpu_dev) == 0) {
-		cpu_duty_offset = AcpiGbl_FADT->DutyOffset;
-		cpu_duty_width = AcpiGbl_FADT->DutyWidth;
+		cpu_duty_offset = AcpiGbl_FADT.DutyOffset;
+		cpu_duty_width = AcpiGbl_FADT.DutyWidth;
 	}
 	if (cpu_duty_width == 0 || (thr_quirks & CPU_QUIRK_NO_THROTTLE) != 0)
 		return (ENXIO);
@@ -278,7 +278,7 @@
 		}
 		memcpy(&gas, obj.Buffer.Pointer + 3, sizeof(gas));
 		acpi_bus_alloc_gas(sc->cpu_dev, &sc->cpu_p_type, &thr_rid,
-		    &gas, &sc->cpu_p_cnt);
+		    &gas, &sc->cpu_p_cnt, 0);
 		if (sc->cpu_p_cnt != NULL && bootverbose) {
 			device_printf(sc->cpu_dev, "P_CNT from _PTC %#jx\n",
 			    gas.Address);
@@ -295,10 +295,10 @@
 		if (sc->cpu_p_blk_len < 4)
 			return (ENXIO);
 		gas.Address = sc->cpu_p_blk;
-		gas.AddressSpaceId = ACPI_ADR_SPACE_SYSTEM_IO;
-		gas.RegisterBitWidth = 32;
+		gas.SpaceId = ACPI_ADR_SPACE_SYSTEM_IO;
+		gas.BitWidth = 32;
 		acpi_bus_alloc_gas(sc->cpu_dev, &sc->cpu_p_type, &thr_rid,
-		    &gas, &sc->cpu_p_cnt);
+		    &gas, &sc->cpu_p_cnt, 0);
 		if (sc->cpu_p_cnt != NULL) {
 			if (bootverbose)
 				device_printf(sc->cpu_dev,
Index: acpi_pcib.c
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/acpi_pcib.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/dev/acpica/acpi_pcib.c -L sys/dev/acpica/acpi_pcib.c -u -r1.1.1.1 -r1.2
--- sys/dev/acpica/acpi_pcib.c
+++ sys/dev/acpica/acpi_pcib.c
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_pcib.c,v 1.56.2.4 2005/12/12 19:33:32 jhb Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_pcib.c,v 1.60 2005/12/03 21:17:17 jhb Exp $");
 
 #include "opt_acpi.h"
 #include <sys/param.h>
Index: acpi_quirk.c
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/acpi_quirk.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/dev/acpica/acpi_quirk.c -L sys/dev/acpica/acpi_quirk.c -u -r1.1.1.1 -r1.2
--- sys/dev/acpica/acpi_quirk.c
+++ sys/dev/acpica/acpi_quirk.c
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_quirk.c,v 1.1.8.2 2005/11/07 09:53:23 obrien Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_quirk.c,v 1.4 2007/03/22 18:16:40 jkim Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -47,10 +47,8 @@
 	CREATOR_REV,
 };
 
-#define ACPI_TABLE_END		(ACPI_TABLE_MAX + 1)
-
 struct acpi_q_rule {
-    int 	sig;		/* Table signature to match */
+    char	sig[ACPI_NAME_SIZE];	/* Table signature to match */
     enum val_t	val;
     union {
 	char	*id;
@@ -141,33 +139,35 @@
 {
     const struct acpi_q_entry *entry;
     const struct acpi_q_rule *match;
-    ACPI_TABLE_HEADER *hdr;
+    ACPI_TABLE_HEADER fadt, dsdt, xsdt, *hdr;
     int done;
 
     /* First, allow the machdep system to set its idea of quirks. */
     KASSERT(quirks != NULL, ("acpi quirks ptr is NULL"));
     acpi_machdep_quirks(quirks);
 
+    if (ACPI_FAILURE(AcpiGetTableHeader(ACPI_SIG_FADT, 0, &fadt)))
+	bzero(&fadt, sizeof(fadt));
+    if (ACPI_FAILURE(AcpiGetTableHeader(ACPI_SIG_DSDT, 0, &dsdt)))
+	bzero(&fadt, sizeof(dsdt));
+    if (ACPI_FAILURE(AcpiGetTableHeader(ACPI_SIG_XSDT, 0, &xsdt)))
+	bzero(&fadt, sizeof(xsdt));
+
     /* Then, override the quirks with any matched from table signatures. */
     for (entry = acpi_quirks_table; entry->match; entry++) {
 	done = TRUE;
-	for (match = entry->match; match->sig != ACPI_TABLE_END; match++) {
-	    switch (match->sig) {
-	    case ACPI_TABLE_FADT:
-		hdr = (ACPI_TABLE_HEADER *)AcpiGbl_FADT;
-		break;
-	    case ACPI_TABLE_DSDT:
-		hdr = (ACPI_TABLE_HEADER *)AcpiGbl_DSDT;
-		break;
-	    case ACPI_TABLE_XSDT:
-		hdr = (ACPI_TABLE_HEADER *)AcpiGbl_XSDT;
-		break;
-	    default:
+	for (match = entry->match; match->sig[0] != '\0'; match++) {
+	    if (!strncmp(match->sig, "FADT", ACPI_NAME_SIZE))
+		hdr = &fadt;
+	    else if (!strncmp(match->sig, ACPI_SIG_DSDT, ACPI_NAME_SIZE))
+		hdr = &dsdt;
+	    else if (!strncmp(match->sig, ACPI_SIG_XSDT, ACPI_NAME_SIZE))
+		hdr = &xsdt;
+	    else
 		panic("invalid quirk header\n");
-	    }
 
 	    /* If we don't match any, skip to the next entry. */
-	    if (!aq_match_header(hdr, match)) {
+	    if (aq_match_header(hdr, match) == FALSE) {
 		done = FALSE;
 		break;
 	    }
Index: acpi_pci_link.c
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/acpi_pci_link.c,v
retrieving revision 1.1.1.2
retrieving revision 1.2
diff -L sys/dev/acpica/acpi_pci_link.c -L sys/dev/acpica/acpi_pci_link.c -u -r1.1.1.2 -r1.2
--- sys/dev/acpica/acpi_pci_link.c
+++ sys/dev/acpica/acpi_pci_link.c
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_pci_link.c,v 1.44.2.6 2006/01/10 21:37:18 jhb Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_pci_link.c,v 1.56.2.1 2007/11/08 20:21:40 jhb Exp $");
 
 #include "opt_acpi.h"
 #include <sys/param.h>
@@ -119,7 +119,7 @@
 	int	link_index;
 };
 
-MALLOC_DEFINE(M_PCI_LINK, "PCI Link", "ACPI PCI Link structures");
+MALLOC_DEFINE(M_PCI_LINK, "pci_link", "ACPI PCI Link structures");
 
 static int pci_link_interrupt_weights[NUM_ACPI_INTERRUPTS];
 static int pci_link_bios_isa_irqs;
@@ -169,8 +169,8 @@
 	struct link_count_request *req;
 
 	req = (struct link_count_request *)context;
-	switch (res->Id) {
-	case ACPI_RSTYPE_START_DPF:
+	switch (res->Type) {
+	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
 		switch (req->in_dpf) {
 		case DPF_OUTSIDE:
 			/* We've started the first DPF. */
@@ -182,14 +182,14 @@
 			break;
 		}
 		break;
-	case ACPI_RSTYPE_END_DPF:
+	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
 		/* We are finished with DPF parsing. */
 		KASSERT(req->in_dpf != DPF_OUTSIDE,
 		    ("%s: end dpf when not parsing a dpf", __func__));
 		req->in_dpf = DPF_OUTSIDE;
 		break;
-	case ACPI_RSTYPE_IRQ:
-	case ACPI_RSTYPE_EXT_IRQ:
+	case ACPI_RESOURCE_TYPE_IRQ:
+	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
 		/*
 		 * Don't count resources if we are in a DPF set that we are
 		 * ignoring.
@@ -208,8 +208,8 @@
 
 	ACPI_SERIAL_ASSERT(pci_link);
 	req = (struct link_res_request *)context;
-	switch (res->Id) {
-	case ACPI_RSTYPE_START_DPF:
+	switch (res->Type) {
+	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
 		switch (req->in_dpf) {
 		case DPF_OUTSIDE:
 			/* We've started the first DPF. */
@@ -223,14 +223,14 @@
 			break;
 		}
 		break;
-	case ACPI_RSTYPE_END_DPF:
+	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
 		/* We are finished with DPF parsing. */
 		KASSERT(req->in_dpf != DPF_OUTSIDE,
 		    ("%s: end dpf when not parsing a dpf", __func__));
 		req->in_dpf = DPF_OUTSIDE;
 		break;
-	case ACPI_RSTYPE_IRQ:
-	case ACPI_RSTYPE_EXT_IRQ:
+	case ACPI_RESOURCE_TYPE_IRQ:
+	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
 		KASSERT(req->link_index < req->sc->pl_num_links,
 		    ("%s: array boundary violation", __func__));
 		link = &req->sc->pl_links[req->link_index];
@@ -243,10 +243,10 @@
 		 * systems return multiple IRQs (which is nonsense for _CRS)
 		 * when the link hasn't been programmed.
 		 */
-		if (res->Id == ACPI_RSTYPE_IRQ) {
-			if (res->Data.Irq.NumberOfInterrupts == 1)
+		if (res->Type == ACPI_RESOURCE_TYPE_IRQ) {
+			if (res->Data.Irq.InterruptCount == 1)
 				link->l_irq = res->Data.Irq.Interrupts[0];
-		} else if (res->Data.ExtendedIrq.NumberOfInterrupts == 1)
+		} else if (res->Data.ExtendedIrq.InterruptCount == 1)
 			link->l_irq = res->Data.ExtendedIrq.Interrupts[0];
 
 		/*
@@ -269,13 +269,14 @@
 {
 	struct link_res_request *req;
 	struct link *link;
-	UINT32 *irqs;
-	int i;
+	UINT8 *irqs = NULL;
+	UINT32 *ext_irqs = NULL;
+	int i, is_ext_irq = 1;
 
 	ACPI_SERIAL_ASSERT(pci_link);
 	req = (struct link_res_request *)context;
-	switch (res->Id) {
-	case ACPI_RSTYPE_START_DPF:
+	switch (res->Type) {
+	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
 		switch (req->in_dpf) {
 		case DPF_OUTSIDE:
 			/* We've started the first DPF. */
@@ -287,14 +288,16 @@
 			break;
 		}
 		break;
-	case ACPI_RSTYPE_END_DPF:
+	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
 		/* We are finished with DPF parsing. */
 		KASSERT(req->in_dpf != DPF_OUTSIDE,
 		    ("%s: end dpf when not parsing a dpf", __func__));
 		req->in_dpf = DPF_OUTSIDE;
 		break;
-	case ACPI_RSTYPE_IRQ:
-	case ACPI_RSTYPE_EXT_IRQ:
+	case ACPI_RESOURCE_TYPE_IRQ:
+		is_ext_irq = 0;
+		/* fall through */
+	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
 		/*
 		 * Don't parse resources if we are in a DPF set that we are
 		 * ignoring.
@@ -318,13 +321,13 @@
 		 * _SRS.
 		 */
 		bcopy(res, &link->l_prs_template, sizeof(ACPI_RESOURCE));
-		if (res->Id == ACPI_RSTYPE_IRQ) {
-			link->l_num_irqs = res->Data.Irq.NumberOfInterrupts;
-			irqs = res->Data.Irq.Interrupts;
-		} else {
+		if (is_ext_irq) {
 			link->l_num_irqs =
-			    res->Data.ExtendedIrq.NumberOfInterrupts;
-			irqs = res->Data.ExtendedIrq.Interrupts;
+			    res->Data.ExtendedIrq.InterruptCount;
+			ext_irqs = res->Data.ExtendedIrq.Interrupts;
+		} else {
+			link->l_num_irqs = res->Data.Irq.InterruptCount;
+			irqs = res->Data.Irq.Interrupts;
 		}
 		if (link->l_num_irqs == 0)
 			break;
@@ -338,9 +341,15 @@
 		link->l_irqs = malloc(sizeof(int) * link->l_num_irqs,
 		    M_PCI_LINK, M_WAITOK | M_ZERO);
 		for (i = 0; i < link->l_num_irqs; i++) {
-			link->l_irqs[i] = irqs[i];
-			if (irqs[i] >= NUM_ISA_INTERRUPTS)
-				link->l_isa_irq = FALSE;
+			if (is_ext_irq) {
+				link->l_irqs[i] = ext_irqs[i];
+				if (ext_irqs[i] >= NUM_ISA_INTERRUPTS)
+					link->l_isa_irq = FALSE;
+			} else {
+				link->l_irqs[i] = irqs[i];
+				if (irqs[i] >= NUM_ISA_INTERRUPTS)
+					link->l_isa_irq = FALSE;
+			}
 		}
 		break;
 	default:
@@ -375,7 +384,7 @@
 	 * For links routed via an ISA interrupt, if the SCI is routed via
 	 * an ISA interrupt, the SCI is always treated as a valid IRQ.
 	 */
-	if (link->l_isa_irq && AcpiGbl_FADT->SciInt == irq &&
+	if (link->l_isa_irq && AcpiGbl_FADT.SciInterrupt == irq &&
 	    irq < NUM_ISA_INTERRUPTS)
 		return (TRUE);
 
@@ -384,17 +393,23 @@
 }
 
 static void
-acpi_pci_link_dump(struct acpi_pci_link_softc *sc)
+acpi_pci_link_dump(struct acpi_pci_link_softc *sc, int header, const char *tag)
 {
 	struct link *link;
+	char buf[16];
 	int i, j;
 
 	ACPI_SERIAL_ASSERT(pci_link);
-	printf("Index  IRQ  Rtd  Ref  IRQs\n");
+	if (header) {
+		snprintf(buf, sizeof(buf), "%s:",
+		    device_get_nameunit(sc->pl_dev));
+		printf("%-16.16s  Index  IRQ  Rtd  Ref  IRQs\n", buf);
+	}
 	for (i = 0; i < sc->pl_num_links; i++) {
 		link = &sc->pl_links[i];
-		printf("%5d  %3d   %c   %3d ", i, link->l_irq,
-		    link->l_routed ? 'Y' : 'N',  link->l_references);
+		printf("  %-14.14s  %5d  %3d   %c   %3d ", i == 0 ? tag : "", i,
+		    link->l_irq, link->l_routed ? 'Y' : 'N',
+		    link->l_references);
 		if (link->l_num_irqs == 0)
 			printf(" none");
 		else for (j = 0; j < link->l_num_irqs; j++)
@@ -488,10 +503,8 @@
 		    AcpiFormatException(status));
 		goto fail;
 	}
-	if (bootverbose) {
-		device_printf(dev, "Links after initial probe:\n");
-		acpi_pci_link_dump(sc);
-	}
+	if (bootverbose)
+		acpi_pci_link_dump(sc, 1, "Initial Probe");
 
 	/* Verify initial IRQs if we have _PRS. */
 	if (status != AE_NOT_FOUND)
@@ -499,10 +512,8 @@
 			if (!link_valid_irq(&sc->pl_links[i],
 			    sc->pl_links[i].l_irq))
 				sc->pl_links[i].l_irq = PCI_INVALID_IRQ;
-	if (bootverbose) {
-		device_printf(dev, "Links after initial validation:\n");
-		acpi_pci_link_dump(sc);
-	}
+	if (bootverbose)
+		acpi_pci_link_dump(sc, 0, "Validation");
 
 	/* Save initial IRQs. */
 	for (i = 0; i < sc->pl_num_links; i++)
@@ -522,10 +533,8 @@
 		for (i = 0; i < sc->pl_num_links; i++)
 			if (PCI_INTERRUPT_VALID(sc->pl_links[i].l_irq))
 				sc->pl_links[i].l_routed = TRUE;
-	if (bootverbose) {
-		device_printf(dev, "Links after disable:\n");
-		acpi_pci_link_dump(sc);
-	}
+	if (bootverbose)
+		acpi_pci_link_dump(sc, 0, "After Disable");
 	ACPI_SERIAL_END(pci_link);
 	return (0);
 fail:
@@ -707,8 +716,8 @@
 	resource = (ACPI_RESOURCE *)crsbuf.Pointer;
 	end = (ACPI_RESOURCE *)((char *)crsbuf.Pointer + crsbuf.Length);
 	for (;;) {
-		switch (resource->Id) {
-		case ACPI_RSTYPE_START_DPF:
+		switch (resource->Type) {
+		case ACPI_RESOURCE_TYPE_START_DEPENDENT:
 			switch (in_dpf) {
 			case DPF_OUTSIDE:
 				/* We've started the first DPF. */
@@ -723,19 +732,19 @@
 			}
 			resptr = NULL;
 			break;
-		case ACPI_RSTYPE_END_DPF:
+		case ACPI_RESOURCE_TYPE_END_DEPENDENT:
 			/* We are finished with DPF parsing. */
 			KASSERT(in_dpf != DPF_OUTSIDE,
 			    ("%s: end dpf when not parsing a dpf", __func__));
 			in_dpf = DPF_OUTSIDE;
 			resptr = NULL;
 			break;
-		case ACPI_RSTYPE_IRQ:
+		case ACPI_RESOURCE_TYPE_IRQ:
 			MPASS(i < sc->pl_num_links);
-			MPASS(link->l_prs_template.Id == ACPI_RSTYPE_IRQ);
+			MPASS(link->l_prs_template.Type == ACPI_RESOURCE_TYPE_IRQ);
 			newres = link->l_prs_template;
 			resptr = &newres;
-			resptr->Data.Irq.NumberOfInterrupts = 1;
+			resptr->Data.Irq.InterruptCount = 1;
 			if (PCI_INTERRUPT_VALID(link->l_irq)) {
 				KASSERT(link->l_irq < NUM_ISA_INTERRUPTS,
 		("%s: can't put non-ISA IRQ %d in legacy IRQ resource type",
@@ -746,12 +755,12 @@
 			link++;
 			i++;
 			break;
-		case ACPI_RSTYPE_EXT_IRQ:
+		case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
 			MPASS(i < sc->pl_num_links);
-			MPASS(link->l_prs_template.Id == ACPI_RSTYPE_EXT_IRQ);
+			MPASS(link->l_prs_template.Type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ);
 			newres = link->l_prs_template;
 			resptr = &newres;
-			resptr->Data.ExtendedIrq.NumberOfInterrupts = 1;
+			resptr->Data.ExtendedIrq.InterruptCount = 1;
 			if (PCI_INTERRUPT_VALID(link->l_irq))
 				resptr->Data.ExtendedIrq.Interrupts[0] =
 				    link->l_irq;
@@ -775,7 +784,7 @@
 				return (status);
 			}
 		}
-		if (resource->Id == ACPI_RSTYPE_END_TAG)
+		if (resource->Type == ACPI_RESOURCE_TYPE_END_TAG)
 			break;
 		resource = ACPI_NEXT_RESOURCE(resource);
 		if (resource >= end)
@@ -802,10 +811,10 @@
 		/* Add a new IRQ resource from each link. */
 		link = &sc->pl_links[i];
 		newres = link->l_prs_template;
-		if (newres.Id == ACPI_RSTYPE_IRQ) {
+		if (newres.Type == ACPI_RESOURCE_TYPE_IRQ) {
 
 			/* Build an IRQ resource. */
-			newres.Data.Irq.NumberOfInterrupts = 1;
+			newres.Data.Irq.InterruptCount = 1;
 			if (PCI_INTERRUPT_VALID(link->l_irq)) {
 				KASSERT(link->l_irq < NUM_ISA_INTERRUPTS,
 		("%s: can't put non-ISA IRQ %d in legacy IRQ resource type",
@@ -816,7 +825,7 @@
 		} else {
 
 			/* Build an ExtIRQ resuorce. */
-			newres.Data.ExtendedIrq.NumberOfInterrupts = 1;
+			newres.Data.ExtendedIrq.InterruptCount = 1;
 			if (PCI_INTERRUPT_VALID(link->l_irq))
 				newres.Data.ExtendedIrq.Interrupts[0] =
 				    link->l_irq;
@@ -873,11 +882,11 @@
 	resource = (ACPI_RESOURCE *)srsbuf.Pointer;
 	end = (ACPI_RESOURCE *)((char *)srsbuf.Pointer + srsbuf.Length);
 	for (;;) {
-		if (resource->Id == ACPI_RSTYPE_END_TAG)
+		if (resource->Type == ACPI_RESOURCE_TYPE_END_TAG)
 			break;
-		switch (resource->Id) {
-		case ACPI_RSTYPE_IRQ:
-		case ACPI_RSTYPE_EXT_IRQ:
+		switch (resource->Type) {
+		case ACPI_RESOURCE_TYPE_IRQ:
+		case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
 			MPASS(i < sc->pl_num_links);
 
 			/*
@@ -907,10 +916,26 @@
 static int
 acpi_pci_link_resume(device_t dev)
 {
+	struct acpi_pci_link_softc *sc;
 	ACPI_STATUS status;
+	int i, routed;
 
+	/*
+	 * If all of our links are routed, then restore the link via _SRS,
+	 * otherwise, disable the link via _DIS.
+	 */
 	ACPI_SERIAL_BEGIN(pci_link);
-	status = acpi_pci_link_route_irqs(dev);
+	sc = device_get_softc(dev);
+	routed = 0;
+	for (i = 0; i < sc->pl_num_links; i++)
+		if (sc->pl_links[i].l_routed)
+			routed++;
+	if (routed == sc->pl_num_links)
+		status = acpi_pci_link_route_irqs(dev);
+	else {
+		AcpiEvaluateObject(acpi_get_handle(dev), "_DIS", NULL, NULL);
+		status = AE_OK;
+	}
 	ACPI_SERIAL_END(pci_link);
 	if (ACPI_FAILURE(status))
 		return (ENXIO);
@@ -932,19 +957,27 @@
 	KASSERT(!PCI_INTERRUPT_VALID(link->l_irq),
 	    ("%s: link already has an IRQ", __func__));
 
-	/* Check for a tunable override and use it if it is valid. */
+	/* Check for a tunable override. */
 	if (ACPI_SUCCESS(acpi_short_name(acpi_get_handle(dev), link_name,
 	    sizeof(link_name)))) {
 		snprintf(tunable_buffer, sizeof(tunable_buffer),
 		    "hw.pci.link.%s.%d.irq", link_name, link->l_res_index);
-		if (getenv_int(tunable_buffer, &i) &&
-		    PCI_INTERRUPT_VALID(i) && link_valid_irq(link, i))
+		if (getenv_int(tunable_buffer, &i) && PCI_INTERRUPT_VALID(i)) {
+			if (!link_valid_irq(link, i))
+				device_printf(dev,
+				    "Warning, IRQ %d is not listed as valid\n",
+				    i);
 			return (i);
+		}
 		snprintf(tunable_buffer, sizeof(tunable_buffer),
 		    "hw.pci.link.%s.irq", link_name);
-		if (getenv_int(tunable_buffer, &i) &&
-		    PCI_INTERRUPT_VALID(i) && link_valid_irq(link, i))
+		if (getenv_int(tunable_buffer, &i) && PCI_INTERRUPT_VALID(i)) {
+			if (!link_valid_irq(link, i))
+				device_printf(dev,
+				    "Warning, IRQ %d is not listed as valid\n",
+				    i);
 			return (i);
+		}
 	}
 
 	/*
@@ -985,7 +1018,7 @@
 	 * interrupt as a fallback.
 	 */
 	if (link->l_isa_irq) {
-		pos_irq = AcpiGbl_FADT->SciInt;
+		pos_irq = AcpiGbl_FADT.SciInterrupt;
 		pos_weight = pci_link_interrupt_weights[pos_irq];
 		if (pos_weight < best_weight) {
 			best_weight = pos_weight;
@@ -1062,8 +1095,8 @@
 	 * if we are using the APIC, we also shouldn't be having any PCI
 	 * interrupts routed via ISA IRQs, so this is probably ok.
 	 */
-	if (AcpiGbl_FADT->SciInt < NUM_ISA_INTERRUPTS)
-		pci_link_bios_isa_irqs |= (1 << AcpiGbl_FADT->SciInt);
+	if (AcpiGbl_FADT.SciInterrupt < NUM_ISA_INTERRUPTS)
+		pci_link_bios_isa_irqs |= (1 << AcpiGbl_FADT.SciInterrupt);
 }
 
 static device_method_t acpi_pci_link_methods[] = {
Index: acpi_pcib_acpi.c
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/acpi_pcib_acpi.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/dev/acpica/acpi_pcib_acpi.c -L sys/dev/acpica/acpi_pcib_acpi.c -u -r1.1.1.1 -r1.2
--- sys/dev/acpica/acpi_pcib_acpi.c
+++ sys/dev/acpica/acpi_pcib_acpi.c
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_pcib_acpi.c,v 1.47.2.2 2005/11/07 09:53:22 obrien Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_pcib_acpi.c,v 1.55 2007/09/30 11:05:14 marius Exp $");
 
 #include "opt_acpi.h"
 #include <sys/param.h>
@@ -74,6 +74,12 @@
 			    int func, int reg, uint32_t data, int bytes);
 static int		acpi_pcib_acpi_route_interrupt(device_t pcib,
 			    device_t dev, int pin);
+static int		acpi_pcib_alloc_msi(device_t pcib, device_t dev,
+			    int count, int maxcount, int *irqs);
+static int		acpi_pcib_map_msi(device_t pcib, device_t dev,
+			    int irq, uint64_t *addr, uint32_t *data);
+static int		acpi_pcib_alloc_msix(device_t pcib, device_t dev,
+			    int *irq);
 static struct resource *acpi_pcib_acpi_alloc_resource(device_t dev,
 			    device_t child, int type, int *rid,
 			    u_long start, u_long end, u_long count,
@@ -103,16 +109,19 @@
     DEVMETHOD(pcib_read_config,		acpi_pcib_read_config),
     DEVMETHOD(pcib_write_config,	acpi_pcib_write_config),
     DEVMETHOD(pcib_route_interrupt,	acpi_pcib_acpi_route_interrupt),
+    DEVMETHOD(pcib_alloc_msi,		acpi_pcib_alloc_msi),
+    DEVMETHOD(pcib_release_msi,		pcib_release_msi),
+    DEVMETHOD(pcib_alloc_msix,		acpi_pcib_alloc_msix),
+    DEVMETHOD(pcib_release_msix,	pcib_release_msix),
+    DEVMETHOD(pcib_map_msi,		acpi_pcib_map_msi),
 
     {0, 0}
 };
 
-static driver_t acpi_pcib_acpi_driver = {
-    "pcib",
-    acpi_pcib_acpi_methods,
-    sizeof(struct acpi_hpcib_softc),
-};
+static devclass_t pcib_devclass;
 
+DEFINE_CLASS_0(pcib, acpi_pcib_acpi_driver, acpi_pcib_acpi_methods,
+    sizeof(struct acpi_hpcib_softc));
 DRIVER_MODULE(acpi_pcib, acpi, acpi_pcib_acpi_driver, pcib_devclass, 0, 0);
 MODULE_DEPEND(acpi_pcib, acpi, 1, 1, 1);
 
@@ -250,6 +259,9 @@
     struct acpi_hpcib_softc	*sc = device_get_softc(dev);
 
     switch (which) {
+    case PCIB_IVAR_DOMAIN:
+	*result = 0;
+	return (0);
     case PCIB_IVAR_BUS:
 	*result = sc->ap_bus;
 	return (0);
@@ -269,6 +281,8 @@
     struct acpi_hpcib_softc	*sc = device_get_softc(dev);
 
     switch (which) {
+    case PCIB_IVAR_DOMAIN:
+	return (EINVAL);
     case PCIB_IVAR_BUS:
 	sc->ap_bus = value;
 	return (0);
@@ -304,6 +318,36 @@
     return (acpi_pcib_route_interrupt(pcib, dev, pin, &sc->ap_prt));
 }
 
+static int
+acpi_pcib_alloc_msi(device_t pcib, device_t dev, int count, int maxcount,
+    int *irqs)
+{
+	device_t bus;
+
+	bus = device_get_parent(pcib);
+	return (PCIB_ALLOC_MSI(device_get_parent(bus), dev, count, maxcount,
+	    irqs));
+}
+
+static int
+acpi_pcib_alloc_msix(device_t pcib, device_t dev, int *irq)
+{
+	device_t bus;
+
+	bus = device_get_parent(pcib);
+	return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, irq));
+}
+
+static int
+acpi_pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
+    uint32_t *data)
+{
+	device_t bus;
+
+	bus = device_get_parent(pcib);
+	return (PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data));
+}
+
 static u_long acpi_host_mem_start = 0x80000000;
 TUNABLE_ULONG("hw.acpi.host_mem_start", &acpi_host_mem_start);
 
--- /dev/null
+++ sys/dev/acpica/acpi_hpet.c
@@ -0,0 +1,314 @@
+/*-
+ * Copyright (c) 2005 Poul-Henning Kamp
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_hpet.c,v 1.12.4.1 2008/01/24 18:52:26 jhb Exp $");
+
+#include "opt_acpi.h"
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/time.h>
+#include <sys/timetc.h>
+
+#include <contrib/dev/acpica/acpi.h>
+#include <dev/acpica/acpivar.h>
+#include <dev/acpica/acpi_hpet.h>
+
+ACPI_SERIAL_DECL(hpet, "ACPI HPET support");
+
+static devclass_t acpi_hpet_devclass;
+
+/* ACPI CA debugging */
+#define _COMPONENT	ACPI_TIMER
+ACPI_MODULE_NAME("HPET")
+
+struct acpi_hpet_softc {
+	device_t		dev;
+	struct resource		*mem_res;
+	ACPI_HANDLE		handle;
+};
+
+static u_int hpet_get_timecount(struct timecounter *tc);
+static void acpi_hpet_test(struct acpi_hpet_softc *sc);
+
+static char *hpet_ids[] = { "PNP0103", NULL };
+
+#define DEV_HPET(x)	(acpi_get_magic(x) == (uintptr_t)&acpi_hpet_devclass)
+
+struct timecounter hpet_timecounter = {
+	.tc_get_timecount =	hpet_get_timecount,
+	.tc_counter_mask =	~0u,
+	.tc_name =		"HPET",
+	.tc_quality =		900,
+};
+
+static u_int
+hpet_get_timecount(struct timecounter *tc)
+{
+	struct acpi_hpet_softc *sc;
+
+	sc = tc->tc_priv;
+	return (bus_read_4(sc->mem_res, HPET_MAIN_COUNTER));
+}
+
+static void
+hpet_enable(struct acpi_hpet_softc *sc)
+{
+	uint32_t val;
+
+	val = bus_read_4(sc->mem_res, HPET_CONFIG);
+	bus_write_4(sc->mem_res, HPET_CONFIG, val | HPET_CNF_ENABLE);
+}
+
+static void
+hpet_disable(struct acpi_hpet_softc *sc)
+{
+	uint32_t val;
+
+	val = bus_read_4(sc->mem_res, HPET_CONFIG);
+	bus_write_4(sc->mem_res, HPET_CONFIG, val & ~HPET_CNF_ENABLE);
+}
+
+/* Discover the HPET via the ACPI table of the same name. */
+static void 
+acpi_hpet_identify(driver_t *driver, device_t parent)
+{
+	ACPI_TABLE_HPET *hpet;
+	ACPI_TABLE_HEADER *hdr;
+	ACPI_STATUS	status;
+	device_t	child;
+
+	/* Only one HPET device can be added. */
+	if (devclass_get_device(acpi_hpet_devclass, 0))
+		return;
+
+	/* Currently, ID and minimum clock tick info is unused. */
+
+	status = AcpiGetTable(ACPI_SIG_HPET, 1, (ACPI_TABLE_HEADER **)&hdr);
+	if (ACPI_FAILURE(status))
+		return;
+
+	/*
+	 * The unit number could be derived from hdr->Sequence but we only
+	 * support one HPET device.
+	 */
+	hpet = (ACPI_TABLE_HPET *)hdr;
+	if (hpet->Sequence != 0)
+		printf("ACPI HPET table warning: Sequence is non-zero (%d)\n",
+		    hpet->Sequence);
+	child = BUS_ADD_CHILD(parent, ACPI_DEV_BASE_ORDER, "acpi_hpet", 0);
+	if (child == NULL) {
+		printf("%s: can't add child\n", __func__);
+		return;
+	}
+
+	/* Record a magic value so we can detect this device later. */
+	acpi_set_magic(child, (uintptr_t)&acpi_hpet_devclass);
+	bus_set_resource(child, SYS_RES_MEMORY, 0, hpet->Address.Address,
+	    HPET_MEM_WIDTH);
+}
+
+static int
+acpi_hpet_probe(device_t dev)
+{
+	ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__);
+
+	if (acpi_disabled("hpet"))
+		return (ENXIO);
+	if (!DEV_HPET(dev) &&
+	    (ACPI_ID_PROBE(device_get_parent(dev), dev, hpet_ids) == NULL ||
+	    device_get_unit(dev) != 0))
+		return (ENXIO);
+
+	device_set_desc(dev, "High Precision Event Timer");
+	return (0);
+}
+
+static int
+acpi_hpet_attach(device_t dev)
+{
+	struct acpi_hpet_softc *sc;
+	int rid;
+	uint32_t val, val2;
+	uintmax_t freq;
+
+	ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__);
+
+	sc = device_get_softc(dev);
+	sc->dev = dev;
+	sc->handle = acpi_get_handle(dev);
+
+	rid = 0;
+	sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+	    RF_ACTIVE);
+	if (sc->mem_res == NULL)
+		return (ENOMEM);
+
+	/* Validate that we can access the whole region. */
+	if (rman_get_size(sc->mem_res) < HPET_MEM_WIDTH) {
+		device_printf(dev, "memory region width %ld too small\n",
+		    rman_get_size(sc->mem_res));
+		bus_free_resource(dev, SYS_RES_MEMORY, sc->mem_res);
+		return (ENXIO);
+	}
+
+	/* Be sure timer is enabled. */
+	hpet_enable(sc);
+
+	/* Read basic statistics about the timer. */
+	val = bus_read_4(sc->mem_res, HPET_PERIOD);
+	if (val == 0) {
+		device_printf(dev, "invalid period\n");
+		hpet_disable(sc);
+		bus_free_resource(dev, SYS_RES_MEMORY, sc->mem_res);
+		return (ENXIO);
+	}
+
+	freq = (1000000000000000LL + val / 2) / val;
+	if (bootverbose) {
+		val = bus_read_4(sc->mem_res, HPET_CAPABILITIES);
+		device_printf(dev,
+		    "vend: 0x%x rev: 0x%x num: %d hz: %jd opts:%s%s\n",
+		    val >> 16, val & HPET_CAP_REV_ID,
+		    (val & HPET_CAP_NUM_TIM) >> 8, freq,
+		    (val & HPET_CAP_LEG_RT) ? " legacy_route" : "",
+		    (val & HPET_CAP_COUNT_SIZE) ? " 64-bit" : "");
+	}
+
+	if (testenv("debug.acpi.hpet_test"))
+		acpi_hpet_test(sc);
+
+	/*
+	 * Don't attach if the timer never increments.  Since the spec
+	 * requires it to be at least 10 MHz, it has to change in 1 us.
+	 */
+	val = bus_read_4(sc->mem_res, HPET_MAIN_COUNTER);
+	DELAY(1);
+	val2 = bus_read_4(sc->mem_res, HPET_MAIN_COUNTER);
+	if (val == val2) {
+		device_printf(dev, "HPET never increments, disabling\n");
+		hpet_disable(sc);
+		bus_free_resource(dev, SYS_RES_MEMORY, sc->mem_res);
+		return (ENXIO);
+	}
+
+	hpet_timecounter.tc_frequency = freq;
+	hpet_timecounter.tc_priv = sc;
+	tc_init(&hpet_timecounter);
+
+	return (0);
+}
+
+static int
+acpi_hpet_detach(device_t dev)
+{
+	ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__);
+
+	/* XXX Without a tc_remove() function, we can't detach. */
+	return (EBUSY);
+}
+
+static int
+acpi_hpet_suspend(device_t dev)
+{
+	struct acpi_hpet_softc *sc;
+
+	/*
+	 * Disable the timer during suspend.  The timer will not lose
+	 * its state in S1 or S2, but we are required to disable
+	 * it.
+	 */
+	sc = device_get_softc(dev);
+	hpet_disable(sc);
+
+	return (0);
+}
+
+static int
+acpi_hpet_resume(device_t dev)
+{
+	struct acpi_hpet_softc *sc;
+
+	/* Re-enable the timer after a resume to keep the clock advancing. */
+	sc = device_get_softc(dev);
+	hpet_enable(sc);
+
+	return (0);
+}
+
+/* Print some basic latency/rate information to assist in debugging. */
+static void
+acpi_hpet_test(struct acpi_hpet_softc *sc)
+{
+	int i;
+	uint32_t u1, u2;
+	struct bintime b0, b1, b2;
+	struct timespec ts;
+
+	binuptime(&b0);
+	binuptime(&b0);
+	binuptime(&b1);
+	u1 = bus_read_4(sc->mem_res, HPET_MAIN_COUNTER);
+	for (i = 1; i < 1000; i++)
+		u2 = bus_read_4(sc->mem_res, HPET_MAIN_COUNTER);
+	binuptime(&b2);
+	u2 = bus_read_4(sc->mem_res, HPET_MAIN_COUNTER);
+
+	bintime_sub(&b2, &b1);
+	bintime_sub(&b1, &b0);
+	bintime_sub(&b2, &b1);
+	bintime2timespec(&b2, &ts);
+
+	device_printf(sc->dev, "%ld.%09ld: %u ... %u = %u\n",
+	    (long)ts.tv_sec, ts.tv_nsec, u1, u2, u2 - u1);
+
+	device_printf(sc->dev, "time per call: %ld ns\n", ts.tv_nsec / 1000);
+}
+
+static device_method_t acpi_hpet_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_identify, acpi_hpet_identify),
+	DEVMETHOD(device_probe, acpi_hpet_probe),
+	DEVMETHOD(device_attach, acpi_hpet_attach),
+	DEVMETHOD(device_detach, acpi_hpet_detach),
+	DEVMETHOD(device_suspend, acpi_hpet_suspend),
+	DEVMETHOD(device_resume, acpi_hpet_resume),
+
+	{0, 0}
+};
+
+static driver_t	acpi_hpet_driver = {
+	"acpi_hpet",
+	acpi_hpet_methods,
+	sizeof(struct acpi_hpet_softc),
+};
+
+
+DRIVER_MODULE(acpi_hpet, acpi, acpi_hpet_driver, acpi_hpet_devclass, 0, 0);
+MODULE_DEPEND(acpi_hpet, acpi, 1, 1, 1);
Index: acpivar.h
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/acpivar.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/dev/acpica/acpivar.h -L sys/dev/acpica/acpivar.h -u -r1.1.1.1 -r1.2
--- sys/dev/acpica/acpivar.h
+++ sys/dev/acpica/acpivar.h
@@ -25,7 +25,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/sys/dev/acpica/acpivar.h,v 1.95.2.1 2005/07/29 16:27:07 njl Exp $
+ * $FreeBSD: src/sys/dev/acpica/acpivar.h,v 1.108 2007/10/09 07:48:07 njl Exp $
  */
 
 #ifndef _ACPIVAR_H_
@@ -36,17 +36,20 @@
 #include "acpi_if.h"
 #include "bus_if.h"
 #include <sys/eventhandler.h>
-#include <sys/sysctl.h>
+#include <sys/ktr.h>
 #include <sys/lock.h>
 #include <sys/mutex.h>
+#include <sys/selinfo.h>
 #include <sys/sx.h>
+#include <sys/sysctl.h>
 
 #include <machine/bus.h>
 #include <machine/resource.h>
 
+struct apm_clone_data;
 struct acpi_softc {
     device_t		acpi_dev;
-    struct cdev *acpi_dev_t;
+    struct cdev		*acpi_dev_t;
 
     struct resource	*acpi_irq;
     int			acpi_irq_rid;
@@ -67,19 +70,25 @@
 
     int			acpi_sleep_delay;
     int			acpi_s4bios;
-    int			acpi_disable_on_poweroff;
+    int			acpi_do_disable;
     int			acpi_verbose;
+    int			acpi_handle_reboot;
 
     bus_dma_tag_t	acpi_waketag;
     bus_dmamap_t	acpi_wakemap;
     vm_offset_t		acpi_wakeaddr;
     vm_paddr_t		acpi_wakephys;
+
+    int			acpi_next_sstate;	/* Next suspend Sx state. */
+    struct apm_clone_data *acpi_clone;		/* Pseudo-dev for devd(8). */
+    STAILQ_HEAD(,apm_clone_data) apm_cdevs;	/* All apm/apmctl/acpi cdevs. */
+    struct callout	susp_force_to;		/* Force suspend if no acks. */
 };
 
 struct acpi_device {
     /* ACPI ivars */
     ACPI_HANDLE			ad_handle;
-    int				ad_magic;
+    uintptr_t			ad_magic;
     void			*ad_private;
     int				ad_flags;
 
@@ -87,6 +96,22 @@
     struct resource_list	ad_rl;
 };
 
+/* Track device (/dev/{apm,apmctl} and /dev/acpi) notification status. */
+struct apm_clone_data {
+    STAILQ_ENTRY(apm_clone_data) entries;
+    struct cdev 	*cdev;
+    int			flags;
+#define	ACPI_EVF_NONE	0	/* /dev/apm semantics */
+#define	ACPI_EVF_DEVD	1	/* /dev/acpi is handled via devd(8) */
+#define	ACPI_EVF_WRITE	2	/* Device instance is opened writable. */
+    int			notify_status;
+#define	APM_EV_NONE	0	/* Device not yet aware of pending sleep. */
+#define	APM_EV_NOTIFIED	1	/* Device saw next sleep state. */
+#define	APM_EV_ACKED	2	/* Device agreed sleep can occur. */
+    struct acpi_softc	*acpi_sc;
+    struct selinfo	sel_read;
+};
+
 #define ACPI_PRW_MAX_POWERRES	8
 
 struct acpi_prw_data {
@@ -225,7 +250,7 @@
 }
 
 __ACPI_BUS_ACCESSOR(acpi, handle, ACPI, HANDLE, ACPI_HANDLE)
-__ACPI_BUS_ACCESSOR(acpi, magic, ACPI, MAGIC, int)
+__ACPI_BUS_ACCESSOR(acpi, magic, ACPI, MAGIC, uintptr_t)
 __ACPI_BUS_ACCESSOR(acpi, private, ACPI, PRIVATE, void *)
 __ACPI_BUS_ACCESSOR(acpi, flags, ACPI, FLAGS, int)
 
@@ -302,6 +327,8 @@
 		    ACPI_RESOURCE *res);
 ACPI_STATUS	acpi_OverrideInterruptLevel(UINT32 InterruptNumber);
 ACPI_STATUS	acpi_SetIntrModel(int model);
+int		acpi_ReqSleepState(struct acpi_softc *sc, int state);
+int		acpi_AckSleepState(struct apm_clone_data *clone, int error);
 ACPI_STATUS	acpi_SetSleepState(struct acpi_softc *sc, int state);
 int		acpi_wake_init(device_t dev, int type);
 int		acpi_wake_set_enable(device_t dev, int enable);
@@ -310,7 +337,8 @@
 void		acpi_UserNotify(const char *subsystem, ACPI_HANDLE h,
 		    uint8_t notify);
 int		acpi_bus_alloc_gas(device_t dev, int *type, int *rid,
-		    ACPI_GENERIC_ADDRESS *gas, struct resource **res);
+		    ACPI_GENERIC_ADDRESS *gas, struct resource **res,
+		    u_int flags);
 
 struct acpi_parse_resource_set {
     void	(*set_init)(device_t dev, void *arg, void **context);
@@ -323,13 +351,15 @@
 		    uint32_t length);
     void	(*set_memoryrange)(device_t dev, void *context, uint32_t low,
 		    uint32_t high, uint32_t length, uint32_t align);
-    void	(*set_irq)(device_t dev, void *context, u_int32_t *irq,
+    void	(*set_irq)(device_t dev, void *context, u_int8_t *irq,
+		    int count, int trig, int pol);
+    void	(*set_ext_irq)(device_t dev, void *context, u_int32_t *irq,
 		    int count, int trig, int pol);
-    void	(*set_drq)(device_t dev, void *context, u_int32_t *drq,
+    void	(*set_drq)(device_t dev, void *context, u_int8_t *drq,
 		    int count);
-    void	(*set_start_dependant)(device_t dev, void *context,
+    void	(*set_start_dependent)(device_t dev, void *context,
 		    int preference);
-    void	(*set_end_dependant)(device_t dev, void *context);
+    void	(*set_end_dependent)(device_t dev, void *context);
 };
 
 extern struct	acpi_parse_resource_set acpi_res_parse_set;
@@ -414,11 +444,24 @@
 int		acpi_PkgInt32(ACPI_OBJECT *res, int idx, uint32_t *dst);
 int		acpi_PkgStr(ACPI_OBJECT *res, int idx, void *dst, size_t size);
 int		acpi_PkgGas(device_t dev, ACPI_OBJECT *res, int idx, int *type,
-		    int *rid, struct resource **dst);
+		    int *rid, struct resource **dst, u_int flags);
 ACPI_HANDLE	acpi_GetReference(ACPI_HANDLE scope, ACPI_OBJECT *obj);
 
+/*
+ * Base level for BUS_ADD_CHILD.  Special devices are added at orders less
+ * than this, and normal devices at or above this level.  This keeps the
+ * probe order sorted so that things like sysresource are available before
+ * their children need them.
+ */
+#define	ACPI_DEV_BASE_ORDER	10
+
 /* Default number of task queue threads to start. */
+#ifndef ACPI_MAX_THREADS
 #define ACPI_MAX_THREADS	3
+#endif
+
+/* Use the device logging level for ktr(4). */
+#define	KTR_ACPI		KTR_DEV
 
 #endif /* _KERNEL */
 #endif /* !_ACPIVAR_H_ */
Index: acpi.c
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/acpi.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/dev/acpica/acpi.c -L sys/dev/acpica/acpi.c -u -r1.1.1.1 -r1.2
--- sys/dev/acpica/acpi.c
+++ sys/dev/acpica/acpi.c
@@ -28,7 +28,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi.c,v 1.214.2.2 2005/11/07 09:53:22 obrien Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi.c,v 1.243.4.1 2008/02/06 03:35:40 iwasaki Exp $");
 
 #include "opt_acpi.h"
 #include <sys/param.h>
@@ -48,7 +48,6 @@
 #include <sys/sbuf.h>
 #include <sys/smp.h>
 
-#include <machine/clock.h>
 #include <machine/resource.h>
 #include <machine/bus.h>
 #include <sys/rman.h>
@@ -58,12 +57,15 @@
 #include <contrib/dev/acpica/acpi.h>
 #include <dev/acpica/acpivar.h>
 #include <dev/acpica/acpiio.h>
+#include <contrib/dev/acpica/achware.h>
 #include <contrib/dev/acpica/acnamesp.h>
 
 #include "pci_if.h"
 #include <dev/pci/pcivar.h>
 #include <dev/pci/pci_private.h>
 
+#include <vm/vm_param.h>
+
 MALLOC_DEFINE(M_ACPIDEV, "acpidev", "ACPI devices");
 
 /* Hooks for the ACPI CA debugging infrastructure */
@@ -106,8 +108,6 @@
 			uintptr_t value);
 static struct resource_list *acpi_get_rlist(device_t dev, device_t child);
 static int	acpi_sysres_alloc(device_t dev);
-static struct resource_list_entry *acpi_sysres_find(device_t dev, int type,
-		    u_long addr);
 static struct resource *acpi_alloc_resource(device_t bus, device_t child,
 			int type, int *rid, u_long start, u_long end,
 			u_long count, u_int flags);
@@ -136,6 +136,7 @@
 static ACPI_STATUS acpi_probe_child(ACPI_HANDLE handle, UINT32 level,
 		    void *context, void **status);
 static BOOLEAN	acpi_MatchHid(ACPI_HANDLE h, const char *hid);
+static ACPI_STATUS acpi_EnterSleepState(struct acpi_softc *sc, int state);
 static void	acpi_shutdown_final(void *arg, int howto);
 static void	acpi_enable_fixed_events(struct acpi_softc *sc);
 static int	acpi_wake_sleep_prep(ACPI_HANDLE handle, int sstate);
@@ -218,7 +219,7 @@
 static const char* sleep_state_names[] = {
     "S0", "S1", "S2", "S3", "S4", "S5", "NONE"};
 
-SYSCTL_NODE(_debug, OID_AUTO, acpi, CTLFLAG_RW, NULL, "ACPI debugging");
+SYSCTL_NODE(_debug, OID_AUTO, acpi, CTLFLAG_RD, NULL, "ACPI debugging");
 static char acpi_ca_version[12];
 SYSCTL_STRING(_debug_acpi, OID_AUTO, acpi_ca_version, CTLFLAG_RD,
 	      acpi_ca_version, 0, "Version of Intel ACPI-CA");
@@ -242,6 +243,10 @@
 /* Allow users to override quirks. */
 TUNABLE_INT("debug.acpi.quirks", &acpi_quirks);
 
+static int acpi_susp_bounce;
+SYSCTL_INT(_debug_acpi, OID_AUTO, suspend_bounce, CTLFLAG_RW,
+    &acpi_susp_bounce, 0, "Don't actually suspend, just test devices.");
+
 /*
  * 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.
@@ -275,39 +280,28 @@
 acpi_Startup(void)
 {
     static int started = 0;
-    int error, val;
+    ACPI_STATUS status;
+    int val;
 
     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
 
     /* Only run the startup code once.  The MADT driver also calls this. */
     if (started)
-	return_VALUE (0);
+	return_VALUE (AE_OK);
     started = 1;
 
-    /* Initialise the ACPI mutex */
-    mtx_init(&acpi_mutex, "ACPI global lock", NULL, MTX_DEF);
-
     /*
-     * Set the globals from our tunables.  This is needed because ACPI-CA
-     * uses UINT8 for some values and we have no tunable_byte.
+     * Pre-allocate space for RSDT/XSDT and DSDT tables and allow resizing
+     * if more tables exist.
      */
-    AcpiGbl_AllMethodsSerialized = acpi_serialize_methods;
-    AcpiGbl_EnableInterpreterSlack = TRUE;
-
-    /* Start up the ACPI CA subsystem. */
-    if (ACPI_FAILURE(error = AcpiInitializeSubsystem())) {
-	printf("ACPI: initialisation failed: %s\n", AcpiFormatException(error));
-	return_VALUE (error);
-    }
-
-    if (ACPI_FAILURE(error = AcpiLoadTables())) {
-	printf("ACPI: table load failed: %s\n", AcpiFormatException(error));
-	AcpiTerminate();
-	return_VALUE (error);
+    if (ACPI_FAILURE(status = AcpiInitializeTables(NULL, 2, TRUE))) {
+	printf("ACPI: Table initialisation failed: %s\n",
+	    AcpiFormatException(status));
+	return_VALUE (status);
     }
 
     /* Set up any quirks we have for this system. */
-    if (acpi_quirks == 0)
+    if (acpi_quirks == ACPI_Q_OK)
 	acpi_table_quirks(&acpi_quirks);
 
     /* If the user manually set the disabled hint to 0, force-enable ACPI. */
@@ -315,11 +309,10 @@
 	acpi_quirks &= ~ACPI_Q_BROKEN;
     if (acpi_quirks & ACPI_Q_BROKEN) {
 	printf("ACPI disabled by blacklist.  Contact your BIOS vendor.\n");
-	AcpiTerminate();
-	return_VALUE (AE_ERROR);
+	status = AE_SUPPORT;
     }
 
-    return_VALUE (AE_OK);
+    return_VALUE (status);
 }
 
 /*
@@ -343,14 +336,16 @@
     if (device_find_child(parent, "acpi", 0) != NULL)
 	return_VOID;
 
-    /* Initialize ACPI-CA. */
-    if (ACPI_FAILURE(acpi_Startup()))
-	return_VOID;
+    snprintf(acpi_ca_version, sizeof(acpi_ca_version), "%x", ACPI_CA_VERSION);
 
-    snprintf(acpi_ca_version, sizeof(acpi_ca_version), "%#x", ACPI_CA_VERSION);
+    /* Initialize root tables. */
+    if (ACPI_FAILURE(acpi_Startup())) {
+	printf("ACPI: Try disabling either ACPI or apic support.\n");
+	return_VOID;
+    }
 
     /* Attach the actual ACPI device. */
-    if ((child = BUS_ADD_CHILD(parent, 0, "acpi", 0)) == NULL) {
+    if ((child = BUS_ADD_CHILD(parent, 10, "acpi", 0)) == NULL) {
 	device_printf(parent, "device_identify failed\n");
 	return_VOID;
     }
@@ -362,11 +357,11 @@
 static int
 acpi_probe(device_t dev)
 {
-    ACPI_TABLE_HEADER	th;
-    char		buf[20];
-    int			error;
+    ACPI_TABLE_RSDP	*rsdp;
+    ACPI_TABLE_HEADER	*rsdt;
+    ACPI_PHYSICAL_ADDRESS paddr;
+    char		buf[ACPI_OEM_ID_SIZE + ACPI_OEM_TABLE_ID_SIZE + 2];
     struct sbuf		sb;
-    ACPI_STATUS		status;
 
     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
 
@@ -376,30 +371,36 @@
 	return_VALUE (ENXIO);
     }
 
-    if (ACPI_FAILURE(status = AcpiGetTableHeader(ACPI_TABLE_XSDT, 1, &th))) {
-	device_printf(dev, "couldn't get XSDT header: %s\n",
-		      AcpiFormatException(status));
-	error = ENXIO;
-    } else {
-	sbuf_new(&sb, buf, sizeof(buf), SBUF_FIXEDLEN);
-	sbuf_bcat(&sb, th.OemId, 6);
-	sbuf_trim(&sb);
-	sbuf_putc(&sb, ' ');
-	sbuf_bcat(&sb, th.OemTableId, 8);
-	sbuf_trim(&sb);
-	sbuf_finish(&sb);
-	device_set_desc_copy(dev, sbuf_data(&sb));
-	sbuf_delete(&sb);
-	error = 0;
-    }
+    if ((paddr = AcpiOsGetRootPointer()) == 0 ||
+	(rsdp = AcpiOsMapMemory(paddr, sizeof(ACPI_TABLE_RSDP))) == NULL)
+	return_VALUE (ENXIO);
+    if (rsdp->Revision > 1 && rsdp->XsdtPhysicalAddress != 0)
+	paddr = (ACPI_PHYSICAL_ADDRESS)rsdp->XsdtPhysicalAddress;
+    else
+	paddr = (ACPI_PHYSICAL_ADDRESS)rsdp->RsdtPhysicalAddress;
+    AcpiOsUnmapMemory(rsdp, sizeof(ACPI_TABLE_RSDP));
 
-    return_VALUE (error);
+    if ((rsdt = AcpiOsMapMemory(paddr, sizeof(ACPI_TABLE_HEADER))) == NULL)
+	return_VALUE (ENXIO);
+    sbuf_new(&sb, buf, sizeof(buf), SBUF_FIXEDLEN);
+    sbuf_bcat(&sb, rsdt->OemId, ACPI_OEM_ID_SIZE);
+    sbuf_trim(&sb);
+    sbuf_putc(&sb, ' ');
+    sbuf_bcat(&sb, rsdt->OemTableId, ACPI_OEM_TABLE_ID_SIZE);
+    sbuf_trim(&sb);
+    sbuf_finish(&sb);
+    device_set_desc_copy(dev, sbuf_data(&sb));
+    sbuf_delete(&sb);
+    AcpiOsUnmapMemory(rsdt, sizeof(ACPI_TABLE_HEADER));
+
+    return_VALUE (0);
 }
 
 static int
 acpi_attach(device_t dev)
 {
     struct acpi_softc	*sc;
+    ACPI_TABLE_FACS	*facs;
     ACPI_STATUS		status;
     int			error, state;
     UINT32		flags;
@@ -410,23 +411,51 @@
 
     sc = device_get_softc(dev);
     sc->acpi_dev = dev;
+    callout_init(&sc->susp_force_to, TRUE);
+
+    error = ENXIO;
 
     /* Initialize resource manager. */
     acpi_rman_io.rm_type = RMAN_ARRAY;
     acpi_rman_io.rm_start = 0;
     acpi_rman_io.rm_end = 0xffff;
-    acpi_rman_io.rm_descr = "I/O ports";
+    acpi_rman_io.rm_descr = "ACPI I/O ports";
     if (rman_init(&acpi_rman_io) != 0)
 	panic("acpi rman_init IO ports failed");
     acpi_rman_mem.rm_type = RMAN_ARRAY;
     acpi_rman_mem.rm_start = 0;
     acpi_rman_mem.rm_end = ~0ul;
-    acpi_rman_mem.rm_descr = "I/O memory addresses";
+    acpi_rman_mem.rm_descr = "ACPI I/O memory addresses";
     if (rman_init(&acpi_rman_mem) != 0)
 	panic("acpi rman_init memory failed");
 
+    /* Initialise the ACPI mutex */
+    mtx_init(&acpi_mutex, "ACPI global lock", NULL, MTX_DEF);
+
+    /*
+     * Set the globals from our tunables.  This is needed because ACPI-CA
+     * uses UINT8 for some values and we have no tunable_byte.
+     */
+    AcpiGbl_AllMethodsSerialized = acpi_serialize_methods;
+    AcpiGbl_EnableInterpreterSlack = TRUE;
+
+    /* Start up the ACPI CA subsystem. */
+    status = AcpiInitializeSubsystem();
+    if (ACPI_FAILURE(status)) {
+	device_printf(dev, "Could not initialize Subsystem: %s\n",
+		      AcpiFormatException(status));
+	goto out;
+    }
+
+    /* Load ACPI name space. */
+    status = AcpiLoadTables();
+    if (ACPI_FAILURE(status)) {
+	device_printf(dev, "Could not load Namespace: %s\n",
+		      AcpiFormatException(status));
+	goto out;
+    }
+
     /* Install the default address space handlers. */
-    error = ENXIO;
     status = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
 		ACPI_ADR_SPACE_SYSTEM_MEMORY, ACPI_DEFAULT_HANDLER, NULL, NULL);
     if (ACPI_FAILURE(status)) {
@@ -474,6 +503,10 @@
     /*
      * Call the ECDT probe function to provide EC functionality before
      * the namespace has been evaluated.
+     *
+     * XXX This happens before the sysresource devices have been probed and
+     * attached so its resources come from nexus0.  In practice, this isn't
+     * a problem but should be addressed eventually.
      */
     acpi_ec_ecdt_probe(dev);
 
@@ -512,14 +545,18 @@
 	OID_AUTO, "suspend_state", CTLTYPE_STRING | CTLFLAG_RW,
 	&sc->acpi_suspend_sx, 0, acpi_sleep_state_sysctl, "A", "");
     SYSCTL_ADD_INT(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
-	OID_AUTO, "sleep_delay", CTLFLAG_RD | CTLFLAG_RW,
-	&sc->acpi_sleep_delay, 0, "sleep delay");
+	OID_AUTO, "sleep_delay", CTLFLAG_RW, &sc->acpi_sleep_delay, 0,
+	"sleep delay");
+    SYSCTL_ADD_INT(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
+	OID_AUTO, "s4bios", CTLFLAG_RW, &sc->acpi_s4bios, 0, "S4BIOS mode");
     SYSCTL_ADD_INT(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
-	OID_AUTO, "s4bios", CTLFLAG_RD | CTLFLAG_RW,
-	&sc->acpi_s4bios, 0, "S4BIOS mode");
+	OID_AUTO, "verbose", CTLFLAG_RW, &sc->acpi_verbose, 0, "verbose mode");
     SYSCTL_ADD_INT(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
-	OID_AUTO, "verbose", CTLFLAG_RD | CTLFLAG_RW,
-	&sc->acpi_verbose, 0, "verbose mode");
+	OID_AUTO, "disable_on_reboot", CTLFLAG_RW,
+	&sc->acpi_do_disable, 0, "Disable ACPI when rebooting/halting system");
+    SYSCTL_ADD_INT(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
+	OID_AUTO, "handle_reboot", CTLFLAG_RW,
+	&sc->acpi_handle_reboot, 0, "Use ACPI Reset Register to reboot");
 
     /*
      * Default to 1 second before sleeping to give some machines time to
@@ -535,7 +572,14 @@
     }
 
     /* Only enable S4BIOS by default if the FACS says it is available. */
-    if (AcpiGbl_FACS->S4Bios_f != 0)
+    status = AcpiGetTable(ACPI_SIG_FACS, 0, (ACPI_TABLE_HEADER **)&facs);
+    if (ACPI_FAILURE(status)) {
+	device_printf(dev, "couldn't get FACS: %s\n",
+		      AcpiFormatException(status));
+	error = ENXIO;
+	goto out;
+    }
+    if (facs->Flags & ACPI_FACS_S4_BIOS_PRESENT)
 	sc->acpi_s4bios = 1;
 
     /*
@@ -549,7 +593,7 @@
 
     /* Pick the first valid sleep state for the sleep button default. */
     sc->acpi_sleep_button_sx = ACPI_S_STATES_MAX + 1;
-    for (state = ACPI_STATE_S1; state < ACPI_STATE_S5; state++)
+    for (state = ACPI_STATE_S1; state <= ACPI_STATE_S4; state++)
 	if (ACPI_SUCCESS(AcpiGetSleepTypeData(state, &TypeA, &TypeB))) {
 	    sc->acpi_sleep_button_sx = state;
 	    break;
@@ -825,7 +869,7 @@
 	*(ACPI_HANDLE *)result = ad->ad_handle;
 	break;
     case ACPI_IVAR_MAGIC:
-	*(int *)result = ad->ad_magic;
+	*(uintptr_t *)result = ad->ad_magic;
 	break;
     case ACPI_IVAR_PRIVATE:
 	*(void **)result = ad->ad_private;
@@ -863,7 +907,7 @@
 	ad->ad_handle = (ACPI_HANDLE)value;
 	break;
     case ACPI_IVAR_MAGIC:
-	ad->ad_magic = (int)value;
+	ad->ad_magic = (uintptr_t)value;
 	break;
     case ACPI_IVAR_PRIVATE:
 	ad->ad_private = (void *)value;
@@ -902,6 +946,21 @@
     struct resource_list *rl;
     struct resource_list_entry *rle;
     struct rman *rm;
+    char *sysres_ids[] = { "PNP0C01", "PNP0C02", NULL };
+    device_t *children;
+    int child_count, i;
+
+    /*
+     * Probe/attach any sysresource devices.  This would be unnecessary if we
+     * had multi-pass probe/attach.
+     */
+    if (device_get_children(dev, &children, &child_count) != 0)
+	return (ENXIO);
+    for (i = 0; i < child_count; i++) {
+	if (ACPI_ID_PROBE(dev, children[i], sysres_ids) != NULL)
+	    device_probe_and_attach(children[i]);
+    }
+    free(children, M_TEMP);
 
     rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev);
     STAILQ_FOREACH(rle, rl, link) {
@@ -935,31 +994,6 @@
     return (0);
 }
 
-/* Find if we manage a given resource. */
-static struct resource_list_entry *
-acpi_sysres_find(device_t dev, int type, u_long addr)
-{
-    struct resource_list *rl;
-    struct resource_list_entry *rle;
-
-    ACPI_SERIAL_ASSERT(acpi);
-
-    /* We only consider IO and memory resources for our pool. */
-    rle = NULL;
-    if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY)
-	goto out;
-
-    rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev);
-    STAILQ_FOREACH(rle, rl, link) {
-	if (type == rle->type && addr >= rle->start &&
-	    addr < rle->start + rle->count)
-	    break;
-    }
-
-out:
-    return (rle);
-}
-
 static struct resource *
 acpi_alloc_resource(device_t bus, device_t child, int type, int *rid,
     u_long start, u_long end, u_long count, u_int flags)
@@ -972,6 +1006,19 @@
     struct rman *rm;
 
     res = NULL;
+
+    /* We only handle memory and IO resources through rman. */
+    switch (type) {
+    case SYS_RES_IOPORT:
+	rm = &acpi_rman_io;
+	break;
+    case SYS_RES_MEMORY:
+	rm = &acpi_rman_mem;
+	break;
+    default:
+	rm = NULL;
+    }
+	    
     ACPI_SERIAL_BEGIN(acpi);
 
     /*
@@ -988,34 +1035,19 @@
 	count = rle->count;
     }
 
-    /* If we don't manage this address, pass the request up to the parent. */
-    rle = acpi_sysres_find(bus, type, start);
-    if (rle == NULL) {
+    /*
+     * If this is an allocation of a specific range, see if we can satisfy
+     * the request from our system resource regions.  If we can't, pass the
+     * request up to the parent.
+     */
+    if (start + count - 1 == end && rm != NULL)
+	res = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE,
+	    child);
+    if (res == NULL) {
 	res = BUS_ALLOC_RESOURCE(device_get_parent(bus), child, type, rid,
 	    start, end, count, flags);
     } else {
-
-	/* We only handle memory and IO resources through rman. */
-	switch (type) {
-	case SYS_RES_IOPORT:
-	    rm = &acpi_rman_io;
-	    break;
-	case SYS_RES_MEMORY:
-	    rm = &acpi_rman_mem;
-	    break;
-	default:
-	    panic("acpi_alloc_resource: invalid res type %d", type);
-	}
-
-	/* If we do know it, allocate it from the local pool. */
-	res = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE,
-	    child);
-	if (res == NULL)
-	    goto out;
-
-	/* Copy the bus tag and handle from the pre-allocated resource. */
-	rman_set_bustag(res, rman_get_bustag(rle->res));
-	rman_set_bushandle(res, rman_get_start(res));
+	rman_set_rid(res, *rid);
 
 	/* If requested, activate the resource using the parent's method. */
 	if (flags & RF_ACTIVE)
@@ -1051,15 +1083,29 @@
 acpi_release_resource(device_t bus, device_t child, int type, int rid,
     struct resource *r)
 {
+    struct rman *rm;
     int ret;
 
+    /* We only handle memory and IO resources through rman. */
+    switch (type) {
+    case SYS_RES_IOPORT:
+	rm = &acpi_rman_io;
+	break;
+    case SYS_RES_MEMORY:
+	rm = &acpi_rman_mem;
+	break;
+    default:
+	rm = NULL;
+    }
+
     ACPI_SERIAL_BEGIN(acpi);
 
     /*
-     * If we know about this address, deactivate it and release it to the
-     * local pool.  If we don't, pass this request up to the parent.
+     * If this resource belongs to one of our internal managers,
+     * deactivate it and release it to the local pool.  If it doesn't,
+     * pass this request up to the parent.
      */
-    if (acpi_sysres_find(bus, type, rman_get_start(r)) == NULL) {
+    if (rm != NULL && rman_is_region_manager(r, rm)) {
 	if (rman_get_flags(r) & RF_ACTIVE) {
 	    ret = bus_deactivate_resource(child, type, rid, r);
 	    if (ret != 0)
@@ -1086,7 +1132,7 @@
 /* Allocate an IO port or memory resource, given its GAS. */
 int
 acpi_bus_alloc_gas(device_t dev, int *type, int *rid, ACPI_GENERIC_ADDRESS *gas,
-    struct resource **res)
+    struct resource **res, u_int flags)
 {
     int error, res_type;
 
@@ -1095,7 +1141,7 @@
 	return (EINVAL);
 
     /* We only support memory and IO spaces. */
-    switch (gas->AddressSpaceId) {
+    switch (gas->SpaceId) {
     case ACPI_ADR_SPACE_SYSTEM_MEMORY:
 	res_type = SYS_RES_MEMORY;
 	break;
@@ -1110,16 +1156,16 @@
      * If the register width is less than 8, assume the BIOS author means
      * it is a bit field and just allocate a byte.
      */
-    if (gas->RegisterBitWidth && gas->RegisterBitWidth < 8)
-	gas->RegisterBitWidth = 8;
+    if (gas->BitWidth && gas->BitWidth < 8)
+	gas->BitWidth = 8;
 
     /* Validate the address after we're sure we support the space. */
-    if (!ACPI_VALID_ADDRESS(gas->Address) || gas->RegisterBitWidth == 0)
+    if (gas->Address == 0 || gas->BitWidth == 0)
 	return (EINVAL);
 
     bus_set_resource(dev, res_type, *rid, gas->Address,
-	gas->RegisterBitWidth / 8);
-    *res = bus_alloc_resource_any(dev, res_type, rid, RF_ACTIVE);
+	gas->BitWidth / 8);
+    *res = bus_alloc_resource_any(dev, res_type, rid, RF_ACTIVE | flags);
     if (*res != NULL) {
 	*type = res_type;
 	error = 0;
@@ -1487,26 +1533,19 @@
 static int
 acpi_probe_order(ACPI_HANDLE handle, int *order)
 {
-    int ret;
 
     /*
      * 1. I/O port and memory system resource holders
      * 2. Embedded controllers (to handle early accesses)
      * 3. PCI Link Devices
      */
-    ret = 0;
-    if (acpi_MatchHid(handle, "PNP0C01") || acpi_MatchHid(handle, "PNP0C02")) {
+    if (acpi_MatchHid(handle, "PNP0C01") || acpi_MatchHid(handle, "PNP0C02"))
 	*order = 1;
-	ret = 1;
-    } else if (acpi_MatchHid(handle, "PNP0C09")) {
+    else if (acpi_MatchHid(handle, "PNP0C09"))
 	*order = 2;
-	ret = 1;
-    } else if (acpi_MatchHid(handle, "PNP0C0F")) {
+    else if (acpi_MatchHid(handle, "PNP0C0F"))
 	*order = 3;
-	ret = 1;
-    }
-
-    return (ret);
+    return (0);
 }
 
 /*
@@ -1517,8 +1556,9 @@
 acpi_probe_child(ACPI_HANDLE handle, UINT32 level, void *context, void **status)
 {
     ACPI_OBJECT_TYPE type;
+    ACPI_HANDLE h;
     device_t bus, child;
-    int order, probe_now;
+    int order;
     char *handle_str, **search;
     static char *scopes[] = {"\\_PR_", "\\_TZ_", "\\_SI_", "\\_SB_", NULL};
 
@@ -1553,12 +1593,13 @@
 	    /* 
 	     * Create a placeholder device for this node.  Sort the placeholder
 	     * so that the probe/attach passes will run breadth-first.  Orders
-	     * less than 10 are reserved for special objects (i.e., system
-	     * resources).  Larger values are used for all other devices.
+	     * less than ACPI_DEV_BASE_ORDER are reserved for special objects
+	     * (i.e., system resources).  Larger values are used for all other
+	     * devices.
 	     */
 	    ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "scanning '%s'\n", handle_str));
-	    order = (level + 1) * 10;
-	    probe_now = acpi_probe_order(handle, &order);
+	    order = (level + 1) * ACPI_DEV_BASE_ORDER;
+	    acpi_probe_order(handle, &order);
 	    child = BUS_ADD_CHILD(bus, order, NULL, -1);
 	    if (child == NULL)
 		break;
@@ -1576,8 +1617,17 @@
 	     * "functional" (i.e. if disabled).  Go ahead and probe them
 	     * anyway since we may enable them later.
 	     */
-	    if (type == ACPI_TYPE_DEVICE && !acpi_DeviceIsPresent(child) &&
-		!acpi_MatchHid(handle, "PNP0C0F")) {
+	    if (type == ACPI_TYPE_DEVICE && !acpi_DeviceIsPresent(child)) {
+		/* Never disable PCI link devices. */
+		if (acpi_MatchHid(handle, "PNP0C0F"))
+		    break;
+		/*
+		 * Docking stations should remain enabled since the system
+		 * may be undocked at boot.
+		 */
+		if (ACPI_SUCCESS(AcpiGetHandle(handle, "_DCK", &h)))
+		    break;
+
 		device_disable(child);
 		break;
 	    }
@@ -1590,10 +1640,6 @@
 	     * device not to have any resources.
 	     */
 	    acpi_parse_resources(child, handle, &acpi_res_parse_set, NULL);
-
-	    /* If order was overridden, probe/attach now rather than later. */
-	    if (probe_now)
-		device_probe_and_attach(child);
 	    break;
 	}
     }
@@ -1613,13 +1659,15 @@
 static void
 acpi_shutdown_final(void *arg, int howto)
 {
-    ACPI_STATUS	status;
+    struct acpi_softc *sc;
+    ACPI_STATUS status;
 
     /*
      * XXX Shutdown code should only run on the BSP (cpuid 0).
      * Some chipsets do not power off the system correctly if called from
      * an AP.
      */
+    sc = arg;
     if ((howto & RB_POWEROFF) != 0) {
 	status = AcpiEnterSleepStatePrep(ACPI_STATE_S5);
 	if (ACPI_FAILURE(status)) {
@@ -1636,7 +1684,24 @@
 	    DELAY(1000000);
 	    printf("ACPI power-off failed - timeout\n");
 	}
-    } else if (panicstr == NULL) {
+    } else if ((howto & RB_HALT) == 0 &&
+	(AcpiGbl_FADT.Flags & ACPI_FADT_RESET_REGISTER) &&
+	sc->acpi_handle_reboot) {
+	/* Reboot using the reset register. */
+	status = AcpiHwLowLevelWrite(
+	    AcpiGbl_FADT.ResetRegister.BitWidth,
+	    AcpiGbl_FADT.ResetValue, &AcpiGbl_FADT.ResetRegister);
+	if (ACPI_FAILURE(status)) {
+	    printf("ACPI reset failed - %s\n", AcpiFormatException(status));
+	} else {
+	    DELAY(1000000);
+	    printf("ACPI reset failed - timeout\n");
+	}
+    } else if (sc->acpi_do_disable && panicstr == NULL) {
+	/*
+	 * Only disable ACPI if the user requested.  On some systems, writing
+	 * the disable value to SMI_CMD hangs the system.
+	 */
 	printf("Shutting down ACPI\n");
 	AcpiTerminate();
     }
@@ -1648,14 +1713,14 @@
     static int	first_time = 1;
 
     /* Enable and clear fixed events and install handlers. */
-    if (AcpiGbl_FADT != NULL && AcpiGbl_FADT->PwrButton == 0) {
+    if ((AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON) == 0) {
 	AcpiClearEvent(ACPI_EVENT_POWER_BUTTON);
 	AcpiInstallFixedEventHandler(ACPI_EVENT_POWER_BUTTON,
 				     acpi_event_power_button_sleep, sc);
 	if (first_time)
 	    device_printf(sc->acpi_dev, "Power Button (fixed)\n");
     }
-    if (AcpiGbl_FADT != NULL && AcpiGbl_FADT->SleepButton == 0) {
+    if ((AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON) == 0) {
 	AcpiClearEvent(ACPI_EVENT_SLEEP_BUTTON);
 	AcpiInstallFixedEventHandler(ACPI_EVENT_SLEEP_BUTTON,
 				     acpi_event_sleep_button_sleep, sc);
@@ -1807,10 +1872,10 @@
 
     if (end >= start)
 	delta = end - start;
-    else if (AcpiGbl_FADT->TmrValExt == 0)
-	delta = ((0x00FFFFFF - start) + end + 1) & 0x00FFFFFF;
-    else
+    else if (AcpiGbl_FADT.Flags & ACPI_FADT_32BIT_TIMER)
 	delta = ((0xFFFFFFFF - start) + end + 1);
+    else
+	delta = ((0x00FFFFFF - start) + end + 1) & 0x00FFFFFF;
     return (delta);
 }
 
@@ -1957,7 +2022,7 @@
 	    return (AE_BAD_PARAMETER);
 
 	/* Check for terminator */
-	if (rp->Id == ACPI_RSTYPE_END_TAG || rp->Length == 0)
+	if (rp->Type == ACPI_RESOURCE_TYPE_END_TAG || rp->Length == 0)
 	    return (AE_NOT_FOUND);
 	rp = ACPI_NEXT_RESOURCE(rp);
     }
@@ -1989,7 +2054,7 @@
 	if ((buf->Pointer = AcpiOsAllocate(buf->Length)) == NULL)
 	    return (AE_NO_MEMORY);
 	rp = (ACPI_RESOURCE *)buf->Pointer;
-	rp->Id = ACPI_RSTYPE_END_TAG;
+	rp->Type = ACPI_RESOURCE_TYPE_END_TAG;
 	rp->Length = 0;
     }
     if (res == NULL)
@@ -2005,7 +2070,7 @@
 	/* 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)
+	if (rp->Type == ACPI_RESOURCE_TYPE_END_TAG || rp->Length == 0)
 	    break;
 	rp = ACPI_NEXT_RESOURCE(rp);
     }
@@ -2022,8 +2087,8 @@
      * 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) {
+	    res->Length + ACPI_RS_SIZE_NO_DATA +
+	    ACPI_RS_SIZE_MIN) >= buf->Length) {
 	if ((newp = AcpiOsAllocate(buf->Length * 2)) == NULL)
 	    return (AE_NO_MEMORY);
 	bcopy(buf->Pointer, newp, buf->Length);
@@ -2035,11 +2100,11 @@
     }
 
     /* Insert the new resource. */
-    bcopy(res, rp, res->Length + ACPI_RESOURCE_LENGTH_NO_DATA);
+    bcopy(res, rp, res->Length + ACPI_RS_SIZE_NO_DATA);
 
     /* And add the terminator. */
     rp = ACPI_NEXT_RESOURCE(rp);
-    rp->Id = ACPI_RSTYPE_END_TAG;
+    rp->Type = ACPI_RESOURCE_TYPE_END_TAG;
     rp->Length = 0;
 
     return (AE_OK);
@@ -2055,6 +2120,170 @@
     return (acpi_SetInteger(ACPI_ROOT_OBJECT, "_PIC", model));
 }
 
+/*
+ * DEPRECATED.  This interface has serious deficiencies and will be
+ * removed.
+ *
+ * Immediately enter the sleep state.  In the old model, acpiconf(8) ran
+ * rc.suspend and rc.resume so we don't have to notify devd(8) to do this.
+ */
+ACPI_STATUS
+acpi_SetSleepState(struct acpi_softc *sc, int state)
+{
+    static int once;
+
+    if (!once) {
+	printf(
+"warning: acpi_SetSleepState() deprecated, need to update your software\n");
+	once = 1;
+    }
+    return (acpi_EnterSleepState(sc, state));
+}
+
+static void
+acpi_sleep_force(void *arg)
+{
+    struct acpi_softc *sc;
+
+    printf("acpi: suspend request timed out, forcing sleep now\n");
+    sc = arg;
+    if (ACPI_FAILURE(acpi_EnterSleepState(sc, sc->acpi_next_sstate)))
+	printf("acpi: force sleep state S%d failed\n", sc->acpi_next_sstate);
+}
+
+/*
+ * Request that the system enter the given suspend state.  All /dev/apm
+ * devices and devd(8) will be notified.  Userland then has a chance to
+ * save state and acknowledge the request.  The system sleeps once all
+ * acks are in.
+ */
+int
+acpi_ReqSleepState(struct acpi_softc *sc, int state)
+{
+    struct apm_clone_data *clone;
+
+    if (state < ACPI_STATE_S1 || state > ACPI_STATE_S5)
+	return (EINVAL);
+
+    /* S5 (soft-off) should be entered directly with no waiting. */
+    if (state == ACPI_STATE_S5) {
+	if (ACPI_SUCCESS(acpi_EnterSleepState(sc, state)))
+	    return (0);
+	else
+	    return (ENXIO);
+    }
+
+#if !defined(__i386__)
+    /* This platform does not support acpi suspend/resume. */
+    return (EOPNOTSUPP);
+#endif
+
+    /* If a suspend request is already in progress, just return. */
+    ACPI_LOCK(acpi);
+    if (sc->acpi_next_sstate != 0) {
+    	ACPI_UNLOCK(acpi);
+	return (0);
+    }
+
+    /* Record the pending state and notify all apm devices. */
+    sc->acpi_next_sstate = state;
+    STAILQ_FOREACH(clone, &sc->apm_cdevs, entries) {
+	clone->notify_status = APM_EV_NONE;
+	if ((clone->flags & ACPI_EVF_DEVD) == 0) {
+	    selwakeuppri(&clone->sel_read, PZERO);
+	    KNOTE_UNLOCKED(&clone->sel_read.si_note, 0);
+	}
+    }
+
+    /* If devd(8) is not running, immediately enter the sleep state. */
+    if (devctl_process_running() == FALSE) {
+	ACPI_UNLOCK(acpi);
+	if (ACPI_SUCCESS(acpi_EnterSleepState(sc, sc->acpi_next_sstate))) {
+	    return (0);
+	} else {
+	    return (ENXIO);
+	}
+    }
+
+    /* Now notify devd(8) also. */
+    acpi_UserNotify("Suspend", ACPI_ROOT_OBJECT, state);
+
+    /*
+     * Set a timeout to fire if userland doesn't ack the suspend request
+     * in time.  This way we still eventually go to sleep if we were
+     * overheating or running low on battery, even if userland is hung.
+     * We cancel this timeout once all userland acks are in or the
+     * suspend request is aborted.
+     */
+    callout_reset(&sc->susp_force_to, 10 * hz, acpi_sleep_force, sc);
+    ACPI_UNLOCK(acpi);
+    return (0);
+}
+
+/*
+ * Acknowledge (or reject) a pending sleep state.  The caller has
+ * prepared for suspend and is now ready for it to proceed.  If the
+ * error argument is non-zero, it indicates suspend should be cancelled
+ * and gives an errno value describing why.  Once all votes are in,
+ * we suspend the system.
+ */
+int
+acpi_AckSleepState(struct apm_clone_data *clone, int error)
+{
+    struct acpi_softc *sc;
+    int ret, sleeping;
+
+#if !defined(__i386__)
+    /* This platform does not support acpi suspend/resume. */
+    return (EOPNOTSUPP);
+#endif
+
+    /* If no pending sleep state, return an error. */
+    ACPI_LOCK(acpi);
+    sc = clone->acpi_sc;
+    if (sc->acpi_next_sstate == 0) {
+    	ACPI_UNLOCK(acpi);
+	return (ENXIO);
+    }
+
+    /* Caller wants to abort suspend process. */
+    if (error) {
+	sc->acpi_next_sstate = 0;
+	callout_stop(&sc->susp_force_to);
+	printf("acpi: listener on %s cancelled the pending suspend\n",
+	    devtoname(clone->cdev));
+    	ACPI_UNLOCK(acpi);
+	return (0);
+    }
+
+    /*
+     * Mark this device as acking the suspend request.  Then, walk through
+     * all devices, seeing if they agree yet.  We only count devices that
+     * are writable since read-only devices couldn't ack the request.
+     */
+    clone->notify_status = APM_EV_ACKED;
+    sleeping = TRUE;
+    STAILQ_FOREACH(clone, &sc->apm_cdevs, entries) {
+	if ((clone->flags & ACPI_EVF_WRITE) != 0 &&
+	    clone->notify_status != APM_EV_ACKED) {
+	    sleeping = FALSE;
+	    break;
+	}
+    }
+
+    /* If all devices have voted "yes", we will suspend now. */
+    if (sleeping)
+	callout_stop(&sc->susp_force_to);
+    ACPI_UNLOCK(acpi);
+    ret = 0;
+    if (sleeping) {
+	if (ACPI_FAILURE(acpi_EnterSleepState(sc, sc->acpi_next_sstate)))
+		ret = ENODEV;
+    }
+
+    return (ret);
+}
+
 static void
 acpi_sleep_enable(void *arg)
 {
@@ -2071,12 +2300,12 @@
 };
 
 /*
- * Set the system sleep state
+ * Enter the desired system sleep state.
  *
  * Currently we support S1-S5 but S4 is only S4BIOS
  */
-ACPI_STATUS
-acpi_SetSleepState(struct acpi_softc *sc, int state)
+static ACPI_STATUS
+acpi_EnterSleepState(struct acpi_softc *sc, int state)
 {
     ACPI_STATUS	status;
     UINT8	TypeA;
@@ -2085,14 +2314,13 @@
 
     ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, state);
 
+    /* Re-entry once we're suspending is not allowed. */
     status = AE_OK;
     ACPI_LOCK(acpi);
     if (sc->acpi_sleep_disabled) {
-	if (sc->acpi_sstate != ACPI_STATE_S0)
-	    status = AE_ERROR;
 	ACPI_UNLOCK(acpi);
 	printf("acpi: suspend request ignored (not ready yet)\n");
-	return (status);
+	return (AE_ERROR);
     }
     sc->acpi_sleep_disabled = 1;
     ACPI_UNLOCK(acpi);
@@ -2139,6 +2367,10 @@
 	}
 	slp_state = ACPI_SS_DEV_SUSPEND;
 
+	/* If testing device suspend only, back out of everything here. */
+	if (acpi_susp_bounce)
+	    break;
+
 	status = AcpiEnterSleepStatePrep(state);
 	if (ACPI_FAILURE(status)) {
 	    device_printf(sc->acpi_dev, "AcpiEnterSleepStatePrep failed - %s\n",
@@ -2184,6 +2416,7 @@
      * Back out state according to how far along we got in the suspend
      * process.  This handles both the error and success cases.
      */
+    sc->acpi_next_sstate = 0;
     if (slp_state >= ACPI_SS_GPE_SET) {
 	acpi_wake_prep_walk(state);
 	sc->acpi_sstate = ACPI_STATE_S0;
@@ -2197,7 +2430,10 @@
 
     /* Allow another sleep request after a while. */
     if (state != ACPI_STATE_S5)
-	timeout(acpi_sleep_enable, (caddr_t)sc, hz * ACPI_MINIMUM_AWAKETIME);
+	timeout(acpi_sleep_enable, sc, hz * ACPI_MINIMUM_AWAKETIME);
+
+    /* Run /etc/rc.resume after we are back. */
+    acpi_UserNotify("Resume", ACPI_ROOT_OBJECT, state);
 
     mtx_unlock(&Giant);
     return_ACPI_STATUS (status);
@@ -2227,13 +2463,11 @@
 acpi_wake_set_enable(device_t dev, int enable)
 {
     struct acpi_prw_data prw;
-    ACPI_HANDLE handle;
     ACPI_STATUS status;
     int flags;
 
     /* Make sure the device supports waking the system and get the GPE. */
-    handle = acpi_get_handle(dev);
-    if (acpi_parse_prw(handle, &prw) != 0)
+    if (acpi_parse_prw(acpi_get_handle(dev), &prw) != 0)
 	return (ENXIO);
 
     flags = acpi_get_flags(dev);
@@ -2509,11 +2743,19 @@
 static void
 acpi_system_eventhandler_sleep(void *arg, int state)
 {
+    int ret;
 
     ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, state);
 
-    if (state >= ACPI_STATE_S0 && state <= ACPI_S_STATES_MAX)
-	acpi_SetSleepState((struct acpi_softc *)arg, state);
+    /* Check if button action is disabled. */
+    if (state == ACPI_S_STATES_MAX + 1)
+	return;
+
+    /* Request that the system prepare to enter the given suspend state. */
+    ret = acpi_ReqSleepState((struct acpi_softc *)arg, state);
+    if (ret != 0)
+	printf("acpi: request to enter state S%d failed (err %d)\n",
+	    state, ret);
 
     return_VOID;
 }
@@ -2775,7 +3017,20 @@
 
     /* Core system ioctls. */
     switch (cmd) {
-    case ACPIIO_SETSLPSTATE:
+    case ACPIIO_REQSLPSTATE:
+	state = *(int *)addr;
+	if (state != ACPI_STATE_S5)
+	    error = acpi_ReqSleepState(sc, state);
+	else {
+	    printf("power off via acpi ioctl not supported\n");
+	    error = ENXIO;
+	}
+	break;
+    case ACPIIO_ACKSLPSTATE:
+	error = *(int *)addr;
+	error = acpi_AckSleepState(sc->acpi_clone, error);
+	break;
+    case ACPIIO_SETSLPSTATE:	/* DEPRECATED */
 	error = EINVAL;
 	state = *(int *)addr;
 	if (state >= ACPI_STATE_S0 && state <= ACPI_S_STATES_MAX)
@@ -3106,7 +3361,8 @@
 			goto out;
 		}
 
-		acpi_SetSleepState(sc, acpi_state);
+		if (ACPI_FAILURE(acpi_EnterSleepState(sc, acpi_state)))
+			error = ENXIO;
 		break;
 	default:
 		error = EINVAL;
Index: acpi_timer.c
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/acpi_timer.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/dev/acpica/acpi_timer.c -L sys/dev/acpica/acpi_timer.c -u -r1.1.1.1 -r1.2
--- sys/dev/acpica/acpi_timer.c
+++ sys/dev/acpica/acpi_timer.c
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_timer.c,v 1.38.2.1 2005/11/07 09:53:23 obrien Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_timer.c,v 1.42 2007/07/30 15:21:26 njl Exp $");
 
 #include "opt_acpi.h"
 #include <sys/param.h>
@@ -96,7 +96,7 @@
 	0,				/* no default counter_mask */
 	0,				/* no default frequency */
 	"ACPI",				/* name */
-	1000				/* quality */
+	-1				/* quality (chosen later) */
 };
 
 static u_int
@@ -119,7 +119,7 @@
     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
 
     if (acpi_disabled("timer") || (acpi_quirks & ACPI_Q_TIMER) ||
-	AcpiGbl_FADT == NULL || acpi_timer_dev)
+	acpi_timer_dev)
 	return_VOID;
 
     if ((dev = BUS_ADD_CHILD(parent, 0, "acpi_timer", 0)) == NULL) {
@@ -129,10 +129,10 @@
     acpi_timer_dev = dev;
 
     rid = 0;
-    rtype = AcpiGbl_FADT->XPmTmrBlk.AddressSpaceId ?
+    rtype = AcpiGbl_FADT.XPmTimerBlock.SpaceId ?
 	SYS_RES_IOPORT : SYS_RES_MEMORY;
-    rlen = AcpiGbl_FADT->PmTmLen;
-    rstart = AcpiGbl_FADT->XPmTmrBlk.Address;
+    rlen = AcpiGbl_FADT.PmTimerLength;
+    rstart = AcpiGbl_FADT.XPmTimerBlock.Address;
     if (bus_set_resource(dev, rtype, rid, rstart, rlen))
 	device_printf(dev, "couldn't set resource (%s 0x%lx+0x%lx)\n",
 	    (rtype == SYS_RES_IOPORT) ? "port" : "mem", rstart, rlen);
@@ -151,18 +151,18 @@
 	return (ENXIO);
 
     rid = 0;
-    rtype = AcpiGbl_FADT->XPmTmrBlk.AddressSpaceId ?
+    rtype = AcpiGbl_FADT.XPmTimerBlock.SpaceId ?
 	SYS_RES_IOPORT : SYS_RES_MEMORY;
     acpi_timer_reg = bus_alloc_resource_any(dev, rtype, &rid, RF_ACTIVE);
     if (acpi_timer_reg == NULL) {
 	device_printf(dev, "couldn't allocate resource (%s 0x%lx)\n",
 	    (rtype == SYS_RES_IOPORT) ? "port" : "mem",
-	    (u_long)AcpiGbl_FADT->XPmTmrBlk.Address);
+	    (u_long)AcpiGbl_FADT.XPmTimerBlock.Address);
 	return (ENXIO);
     }
     acpi_timer_bsh = rman_get_bushandle(acpi_timer_reg);
     acpi_timer_bst = rman_get_bustag(acpi_timer_reg);
-    if (AcpiGbl_FADT->TmrValExt != 0)
+    if (AcpiGbl_FADT.Flags & ACPI_FADT_32BIT_TIMER)
 	acpi_timer_timecounter.tc_counter_mask = 0xffffffff;
     else
 	acpi_timer_timecounter.tc_counter_mask = 0x00ffffff;
@@ -185,14 +185,16 @@
     if (j == 10) {
 	acpi_timer_timecounter.tc_name = "ACPI-fast";
 	acpi_timer_timecounter.tc_get_timecount = acpi_timer_get_timecount;
+	acpi_timer_timecounter.tc_quality = 1000;
     } else {
 	acpi_timer_timecounter.tc_name = "ACPI-safe";
 	acpi_timer_timecounter.tc_get_timecount = acpi_timer_get_timecount_safe;
+	acpi_timer_timecounter.tc_quality = 850;
     }
     tc_init(&acpi_timer_timecounter);
 
     sprintf(desc, "%d-bit timer at 3.579545MHz",
-	AcpiGbl_FADT->TmrValExt ? 32 : 24);
+	(AcpiGbl_FADT.Flags & ACPI_FADT_32BIT_TIMER) ? 32 : 24);
     device_set_desc_copy(dev, desc);
 
     /* Release the resource, we'll allocate it again during attach. */
@@ -208,7 +210,7 @@
     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
 
     rid = 0;
-    rtype = AcpiGbl_FADT->XPmTmrBlk.AddressSpaceId ?
+    rtype = AcpiGbl_FADT.XPmTimerBlock.SpaceId ?
 	SYS_RES_IOPORT : SYS_RES_MEMORY;
     acpi_timer_reg = bus_alloc_resource_any(dev, rtype, &rid, RF_ACTIVE);
     if (acpi_timer_reg == NULL)
@@ -262,7 +264,7 @@
     if (acpi_timer_timecounter.tc_frequency == 0)
 	return (EOPNOTSUPP);
     freq = acpi_timer_frequency;
-    error = sysctl_handle_int(oidp, &freq, sizeof(freq), req);
+    error = sysctl_handle_int(oidp, &freq, 0, req);
     if (error == 0 && req->newptr != NULL) {
 	acpi_timer_frequency = freq;
 	acpi_timer_timecounter.tc_frequency = acpi_timer_frequency;
--- /dev/null
+++ sys/dev/acpica/acpi_dock.c
@@ -0,0 +1,539 @@
+/*-
+ * Copyright (c) 2005-2006 Mitsuru IWASAKI <iwasaki at FreeBSD.org>
+ * 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: src/sys/dev/acpica/acpi_dock.c,v 1.6 2007/05/31 08:49:51 takawata Exp $
+ */
+
+#include "opt_acpi.h"
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+
+#include <contrib/dev/acpica/acpi.h>
+#include <contrib/dev/acpica/acnamesp.h>
+#include <dev/acpica/acpivar.h>
+#include <dev/acpica/acpiio.h>
+
+/* Hooks for the ACPI CA debugging infrastructure */
+#define _COMPONENT	ACPI_DOCK
+ACPI_MODULE_NAME("DOCK")
+
+/* For Docking status */
+#define ACPI_DOCK_STATUS_UNKNOWN	-1
+#define ACPI_DOCK_STATUS_UNDOCKED	0
+#define ACPI_DOCK_STATUS_DOCKED		1
+
+#define ACPI_DOCK_UNLOCK		0 /* Allow device to be ejected */
+#define ACPI_DOCK_LOCK			1 /* Prevent dev from being removed */
+
+#define ACPI_DOCK_ISOLATE		0 /* Isolate from dock connector */
+#define ACPI_DOCK_CONNECT		1 /* Connect to dock */
+
+struct acpi_dock_softc {
+	int		_sta;
+	int		_bdn;
+	int		_uid;
+	int		status;
+	struct sysctl_ctx_list	*sysctl_ctx;
+	struct sysctl_oid	*sysctl_tree;
+};
+
+ACPI_SERIAL_DECL(dock, "ACPI Docking Station");
+
+/*
+ * Utility functions
+ */
+
+static void
+acpi_dock_get_info(device_t dev)
+{
+	struct acpi_dock_softc *sc;
+	ACPI_HANDLE	h;
+
+	sc = device_get_softc(dev);
+	h = acpi_get_handle(dev);
+
+	if (ACPI_FAILURE(acpi_GetInteger(h, "_STA", &sc->_sta)))
+		sc->_sta = ACPI_DOCK_STATUS_UNKNOWN;
+	if (ACPI_FAILURE(acpi_GetInteger(h, "_BDN", &sc->_bdn)))
+		sc->_bdn = ACPI_DOCK_STATUS_UNKNOWN;
+	if (ACPI_FAILURE(acpi_GetInteger(h, "_UID", &sc->_uid)))
+		sc->_uid = ACPI_DOCK_STATUS_UNKNOWN;
+	ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
+		    "_STA: %04x, _BDN: %04x, _UID: %04x\n", sc->_sta,
+		    sc->_bdn, sc->_uid);
+}
+
+static int
+acpi_dock_execute_dck(device_t dev, int dock)
+{
+	ACPI_HANDLE	h;
+	ACPI_OBJECT	argobj;
+	ACPI_OBJECT_LIST args;
+	ACPI_BUFFER	buf;
+	ACPI_OBJECT	retobj;
+	ACPI_STATUS	status;
+
+	h = acpi_get_handle(dev);
+
+	argobj.Type = ACPI_TYPE_INTEGER;
+	argobj.Integer.Value = dock;
+	args.Count = 1;
+	args.Pointer = &argobj;
+	buf.Pointer = &retobj;
+	buf.Length = sizeof(retobj);
+	status = AcpiEvaluateObject(h, "_DCK", &args, &buf);
+
+	/*
+	 * When _DCK is called with 0, OSPM will ignore the return value.
+	 */
+	if (dock == ACPI_DOCK_ISOLATE)
+		return (0);
+
+	/* If _DCK returned 1, the request succeeded. */
+	if (ACPI_SUCCESS(status) && retobj.Type == ACPI_TYPE_INTEGER &&
+	    retobj.Integer.Value == 1)
+		return (0);
+
+	return (-1);
+}
+
+/* Lock devices while docked to prevent surprise removal. */
+static void
+acpi_dock_execute_lck(device_t dev, int lock)
+{
+	ACPI_HANDLE	h;
+
+	h = acpi_get_handle(dev);
+	acpi_SetInteger(h, "_LCK", lock);
+}
+
+/* Eject a device (i.e., motorized). */
+static int
+acpi_dock_execute_ejx(device_t dev, int eject, int state)
+{
+	ACPI_HANDLE	h;
+	ACPI_STATUS	status;
+	char		ejx[5];
+
+	h = acpi_get_handle(dev);
+	snprintf(ejx, sizeof(ejx), "_EJ%d", state);
+	status = acpi_SetInteger(h, ejx, eject);
+	if (ACPI_SUCCESS(status))
+		return (0);
+
+	return (-1);
+}
+
+/* Find dependent devices.  When their parent is removed, so are they. */
+static int
+acpi_dock_is_ejd_device(ACPI_HANDLE dock_handle, ACPI_HANDLE handle)
+{
+	int		ret;
+	ACPI_STATUS	ret_status;
+	ACPI_BUFFER	ejd_buffer;
+	ACPI_OBJECT	*obj;
+
+	ret = 0;
+
+	ejd_buffer.Pointer = NULL;
+	ejd_buffer.Length = ACPI_ALLOCATE_BUFFER;
+	ret_status = AcpiEvaluateObject(handle, "_EJD", NULL, &ejd_buffer);
+	if (ACPI_FAILURE(ret_status))
+		goto out;
+
+	obj = (ACPI_OBJECT *)ejd_buffer.Pointer;
+	if (dock_handle == acpi_GetReference(NULL, obj))
+		ret = 1;
+
+out:
+	if (ejd_buffer.Pointer != NULL)
+		AcpiOsFree(ejd_buffer.Pointer);
+
+	return (ret);
+}
+
+/*
+ * Docking functions
+ */
+
+static void
+acpi_dock_attach_later(void *context)
+{
+	device_t	dev;
+
+	dev = (device_t)context;
+
+	if (!device_is_enabled(dev))
+		device_enable(dev);
+
+	mtx_lock(&Giant);
+	device_probe_and_attach(dev);
+	mtx_unlock(&Giant);
+}
+
+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, &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_dock_insert_children(device_t dev)
+{
+	ACPI_STATUS	status;
+	ACPI_HANDLE	sb_handle;
+
+	status = AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_SB_", &sb_handle);
+	if (ACPI_SUCCESS(status)) {
+		AcpiWalkNamespace(ACPI_TYPE_DEVICE, sb_handle,
+		    100, acpi_dock_insert_child, dev, NULL);
+	}
+}
+
+static void
+acpi_dock_insert(device_t dev)
+{
+	struct acpi_dock_softc *sc;
+	ACPI_HANDLE	h;
+
+	ACPI_SERIAL_ASSERT(dock);
+
+	sc = device_get_softc(dev);
+	h = acpi_get_handle(dev);
+
+	if (sc->status == ACPI_DOCK_STATUS_UNDOCKED ||
+	    sc->status == ACPI_DOCK_STATUS_UNKNOWN) {
+		acpi_dock_execute_lck(dev, ACPI_DOCK_LOCK);
+		if (acpi_dock_execute_dck(dev, ACPI_DOCK_CONNECT) != 0) {
+			device_printf(dev, "_DCK failed\n");
+			return;
+		}
+
+		if (!cold)
+			acpi_dock_insert_children(dev);
+		sc->status = ACPI_DOCK_STATUS_DOCKED;
+	}
+}
+
+/*
+ * Undock
+ */
+
+static ACPI_STATUS
+acpi_dock_eject_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),
+	    "ejecting device for %s\n", acpi_name(handle));
+
+	dev = acpi_get_device(handle);
+	if (dev != NULL && device_is_attached(dev)) {
+		mtx_lock(&Giant);
+		device_detach(dev);
+		mtx_unlock(&Giant);
+	}
+
+	acpi_SetInteger(handle, "_EJ0", 0);
+out:
+	return (AE_OK);
+}
+
+static void
+acpi_dock_eject_children(device_t dev)
+{
+	ACPI_HANDLE	sb_handle;
+	ACPI_STATUS	status;
+
+	status = AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_SB_", &sb_handle);
+	if (ACPI_SUCCESS(status)) {
+		AcpiWalkNamespace(ACPI_TYPE_DEVICE, sb_handle,
+		    100, acpi_dock_eject_child, &dev, NULL);
+	}
+}
+
+static void
+acpi_dock_removal(device_t dev)
+{
+	struct acpi_dock_softc *sc;
+
+	ACPI_SERIAL_ASSERT(dock);
+
+	sc = device_get_softc(dev);
+	if (sc->status == ACPI_DOCK_STATUS_DOCKED ||
+	    sc->status == ACPI_DOCK_STATUS_UNKNOWN) {
+		acpi_dock_eject_children(dev);
+		if (acpi_dock_execute_dck(dev, ACPI_DOCK_ISOLATE) != 0)
+			return;
+
+		acpi_dock_execute_lck(dev, ACPI_DOCK_UNLOCK);
+
+		if (acpi_dock_execute_ejx(dev, 1, 0) != 0) {
+			device_printf(dev, "_EJ0 failed\n");
+			return;
+		}
+
+		sc->status = ACPI_DOCK_STATUS_UNDOCKED;
+	}
+
+	acpi_dock_get_info(dev);
+	if (sc->_sta != 0)
+		device_printf(dev, "mechanical failure (%#x).\n", sc->_sta);
+}
+
+/*
+ * Device/Bus check
+ */
+
+static void
+acpi_dock_device_check(device_t dev)
+{
+	struct acpi_dock_softc *sc;
+
+	ACPI_SERIAL_ASSERT(dock);
+
+	sc = device_get_softc(dev);
+	acpi_dock_get_info(dev);
+
+	/*
+	 * If the _STA method indicates 'present' and 'functioning', the
+	 * system is docked.  If _STA does not exist for this device, it
+	 * is always present.
+	 */
+	if (sc->_sta == ACPI_DOCK_STATUS_UNKNOWN ||
+	    ACPI_DEVICE_PRESENT(sc->_sta))
+		acpi_dock_insert(dev);
+	else if (sc->_sta == 0)
+		acpi_dock_removal(dev);
+}
+
+/*
+ * Notify Handler
+ */
+
+static void
+acpi_dock_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context)
+{
+	device_t	dev;
+
+	dev = (device_t) context;
+	ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
+		    "got notification %#x\n", notify);
+
+	ACPI_SERIAL_BEGIN(dock);
+	switch (notify) {
+	case ACPI_NOTIFY_BUS_CHECK:
+	case ACPI_NOTIFY_DEVICE_CHECK:
+		acpi_dock_device_check(dev);
+		break;
+	case ACPI_NOTIFY_EJECT_REQUEST:
+		acpi_dock_removal(dev);
+		break;
+	default:
+		device_printf(dev, "unknown notify %#x\n", notify);
+		break;
+	}
+	ACPI_SERIAL_END(dock);
+}
+
+static int
+acpi_dock_status_sysctl(SYSCTL_HANDLER_ARGS)
+{
+	struct acpi_dock_softc *sc;
+	device_t	dev;
+	int		status, err;
+
+	err = 0;
+	dev = (device_t)arg1;
+
+	sc = device_get_softc(dev);
+	status = sc->status;
+
+	ACPI_SERIAL_BEGIN(dock);
+	err = sysctl_handle_int(oidp, &status, 0, req);
+	if (err != 0 || req->newptr == NULL)
+		goto out;
+
+	if (status != ACPI_DOCK_STATUS_UNDOCKED &&
+	    status != ACPI_DOCK_STATUS_DOCKED) {
+		err = EINVAL;
+		goto out;
+	}
+
+	if (status == sc->status)
+		goto out;
+
+	switch (status) {
+	case ACPI_DOCK_STATUS_UNDOCKED:
+		acpi_dock_removal(dev);
+		break;
+	case ACPI_DOCK_STATUS_DOCKED:
+		acpi_dock_device_check(dev);
+		break;
+	default:
+		err = EINVAL;
+		break;
+	}
+out:
+	ACPI_SERIAL_END(dock);
+	return (err);
+}
+
+static int
+acpi_dock_probe(device_t dev)
+{
+	ACPI_HANDLE	h, tmp;
+
+	h = acpi_get_handle(dev);
+	if (acpi_disabled("dock") ||
+	    ACPI_FAILURE(AcpiGetHandle(h, "_DCK", &tmp)))
+		return (ENXIO);
+
+	device_set_desc(dev, "ACPI Docking Station");
+
+	/*
+	 * XXX Somewhere else in the kernel panics on "sysctl kern" if we
+	 * return a negative value here (reprobe ok).
+	 */
+	return (0);
+}
+
+static int
+acpi_dock_attach(device_t dev)
+{
+	struct acpi_dock_softc *sc;
+	ACPI_HANDLE	h;
+
+	sc = device_get_softc(dev);
+	h = acpi_get_handle(dev);
+	if (sc == NULL || h == NULL)
+		return (ENXIO);
+
+	sc->status = ACPI_DOCK_STATUS_UNKNOWN;
+
+	AcpiEvaluateObject(h, "_INI", NULL, NULL);
+
+	ACPI_SERIAL_BEGIN(dock);
+
+	acpi_dock_device_check(dev);
+
+	/* Get the sysctl tree */
+	sc->sysctl_ctx = device_get_sysctl_ctx(dev);
+	sc->sysctl_tree = device_get_sysctl_tree(dev);
+
+	SYSCTL_ADD_INT(sc->sysctl_ctx,
+		SYSCTL_CHILDREN(sc->sysctl_tree),
+		OID_AUTO, "_sta", CTLFLAG_RD,
+		&sc->_sta, 0, "Dock _STA");
+	SYSCTL_ADD_INT(sc->sysctl_ctx,
+		SYSCTL_CHILDREN(sc->sysctl_tree),
+		OID_AUTO, "_bdn", CTLFLAG_RD,
+		&sc->_bdn, 0, "Dock _BDN");
+	SYSCTL_ADD_INT(sc->sysctl_ctx,
+		SYSCTL_CHILDREN(sc->sysctl_tree),
+		OID_AUTO, "_uid", CTLFLAG_RD,
+		&sc->_uid, 0, "Dock _UID");
+	SYSCTL_ADD_PROC(sc->sysctl_ctx,
+		SYSCTL_CHILDREN(sc->sysctl_tree),
+		OID_AUTO, "status",
+		CTLTYPE_INT|CTLFLAG_RW, dev, 0,
+		acpi_dock_status_sysctl, "I",
+		"Dock/Undock operation");
+
+	ACPI_SERIAL_END(dock);
+
+	AcpiInstallNotifyHandler(h, ACPI_ALL_NOTIFY,
+				 acpi_dock_notify_handler, dev);
+
+	return (0);
+}
+
+static device_method_t acpi_dock_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe, acpi_dock_probe),
+	DEVMETHOD(device_attach, acpi_dock_attach),
+
+	{0, 0}
+};
+
+static driver_t	acpi_dock_driver = {
+	"acpi_dock",
+	acpi_dock_methods,
+	sizeof(struct acpi_dock_softc),
+};
+
+static devclass_t acpi_dock_devclass;
+
+DRIVER_MODULE(acpi_dock, acpi, acpi_dock_driver, acpi_dock_devclass, 0, 0);
+MODULE_DEPEND(acpi_dock, acpi, 1, 1, 1);
+
Index: acpi_isab.c
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/acpi_isab.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/dev/acpica/acpi_isab.c -L sys/dev/acpica/acpi_isab.c -u -r1.1.1.1 -r1.2
--- sys/dev/acpica/acpi_isab.c
+++ sys/dev/acpica/acpi_isab.c
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_isab.c,v 1.9.8.1 2005/11/07 09:53:22 obrien Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_isab.c,v 1.10 2005/09/11 18:39:01 obrien Exp $");
 
 /*
  * ISA Bridge driver for Generic ISA Bus Devices.  See section 10.7 of the
Index: acpi_battery.c
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/acpi_battery.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/acpica/acpi_battery.c -L sys/dev/acpica/acpi_battery.c -u -r1.2 -r1.3
--- sys/dev/acpica/acpi_battery.c
+++ sys/dev/acpica/acpi_battery.c
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_battery.c,v 1.12.2.4 2005/11/24 05:29:15 njl Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_battery.c,v 1.25.4.1 2008/01/23 00:15:22 jkim Exp $");
 
 #include "opt_acpi.h"
 #include <sys/param.h>
@@ -167,11 +167,12 @@
 	    dev_idx = i;
 
 	/*
-	 * Be sure we can get various info from the battery.  Note that we
-	 * can't check acpi_BatteryIsPresent() because smart batteries only
+	 * Be sure we can get various info from the battery.  Note that
+	 * acpi_BatteryIsPresent() is not enough because smart batteries only
 	 * return that the device is present.
 	 */
-	if (ACPI_BATT_GET_STATUS(batt_dev, &bst[i]) != 0 ||
+	if (!acpi_BatteryIsPresent(batt_dev) ||
+	    ACPI_BATT_GET_STATUS(batt_dev, &bst[i]) != 0 ||
 	    ACPI_BATT_GET_INFO(batt_dev, bif) != 0)
 	    continue;
 
@@ -192,9 +193,11 @@
 
 	/*
 	 * If the battery info is in terms of mA, convert to mW by
-	 * multiplying by the design voltage.
+	 * multiplying by the design voltage.  If the design voltage
+	 * is 0 (due to some error reading the battery), skip this
+	 * conversion.
 	 */
-	if (bif->units == ACPI_BIF_UNITS_MA) {
+	if (bif->units == ACPI_BIF_UNITS_MA && bif->dvol != 0) {
 	    bst[i].rate = (bst[i].rate * bif->dvol) / 1000;
 	    bst[i].cap = (bst[i].cap * bif->dvol) / 1000;
 	    bif->lfcap = (bif->lfcap * bif->dvol) / 1000;
@@ -483,7 +486,7 @@
 	NULL, 0, acpi_battery_units_sysctl, "I", "number of batteries");
     SYSCTL_ADD_INT(&acpi_battery_sysctl_ctx,
 	SYSCTL_CHILDREN(acpi_battery_sysctl_tree),
-	OID_AUTO, "info_expire", CTLFLAG_RD | CTLFLAG_RW,
+	OID_AUTO, "info_expire", CTLFLAG_RW,
 	&acpi_battery_info_expire, 0,
 	"time in seconds until info is refreshed");
 
Index: acpi_cmbat.c
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/acpi_cmbat.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/dev/acpica/acpi_cmbat.c -L sys/dev/acpica/acpi_cmbat.c -u -r1.1.1.1 -r1.2
--- sys/dev/acpica/acpi_cmbat.c
+++ sys/dev/acpica/acpi_cmbat.c
@@ -28,7 +28,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_cmbat.c,v 1.39.2.4 2005/11/26 07:37:40 njl Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_cmbat.c,v 1.46 2007/03/22 18:16:40 jkim Exp $");
 
 #include "opt_acpi.h"
 #include <sys/param.h>
@@ -149,7 +149,7 @@
     AcpiInstallNotifyHandler(handle, ACPI_ALL_NOTIFY,
 	acpi_cmbat_notify_handler, dev);
 
-    AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_cmbat_init_battery, dev);
+    AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_cmbat_init_battery, dev);
 
     return (0);
 }
@@ -157,7 +157,10 @@
 static int
 acpi_cmbat_detach(device_t dev)
 {
+    ACPI_HANDLE	handle;
 
+    handle = acpi_get_handle(dev);
+    AcpiRemoveNotifyHandler(handle, ACPI_ALL_NOTIFY, acpi_cmbat_notify_handler);
     acpi_battery_remove(dev);
     return (0);
 }
@@ -166,7 +169,7 @@
 acpi_cmbat_resume(device_t dev)
 {
 
-    AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_cmbat_init_battery, dev);
+    AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_cmbat_init_battery, dev);
     return (0);
 }
 
@@ -194,7 +197,7 @@
 	 * Queue a callback to get the current battery info from thread
 	 * context.  It's not safe to block in a notify handler.
 	 */
-	AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_cmbat_get_bif_task, dev);
+	AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_cmbat_get_bif_task, dev);
 	break;
     }
 
@@ -435,6 +438,10 @@
      * to wait a while.
      */
     for (retry = 0; retry < ACPI_CMBAT_RETRY_MAX; retry++, AcpiOsSleep(10000)) {
+	/* batteries on DOCK can be ejected w/ DOCK during retrying */
+	if (!device_is_attached(dev))
+	    return;
+
 	if (!acpi_BatteryIsPresent(dev))
 	    continue;
 
Index: acpi_perf.c
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/acpi_perf.c,v
retrieving revision 1.1.1.2
retrieving revision 1.2
diff -L sys/dev/acpica/acpi_perf.c -L sys/dev/acpica/acpi_perf.c -u -r1.1.1.2 -r1.2
--- sys/dev/acpica/acpi_perf.c
+++ sys/dev/acpica/acpi_perf.c
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_perf.c,v 1.21.2.2 2005/12/19 11:19:26 bruno Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_perf.c,v 1.26 2007/03/22 18:16:40 jkim Exp $");
 
 #include "opt_acpi.h"
 #include <sys/param.h>
@@ -191,7 +191,7 @@
 	pkg = (ACPI_OBJECT *)buf.Pointer;
 	if (ACPI_PKG_VALID(pkg, 2)) {
 		rid = 0;
-		error = acpi_PkgGas(dev, pkg, 0, &type, &rid, &res);
+		error = acpi_PkgGas(dev, pkg, 0, &type, &rid, &res, 0);
 		switch (error) {
 		case 0:
 			bus_release_resource(dev, type, rid, res);
@@ -221,7 +221,7 @@
 	sc->px_curr_state = CPUFREQ_VAL_UNKNOWN;
 	if (acpi_perf_evaluate(dev) != 0)
 		return (ENXIO);
-	AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_px_startup, NULL);
+	AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_px_startup, NULL);
 	if (!sc->info_only)
 		cpufreq_register(dev);
 
@@ -299,6 +299,12 @@
 		    sc->px_states[count].core_freq >= 0xffff)
 			continue;
 
+		/* Check for duplicate entries */
+		if (count > 0 &&
+		    sc->px_states[count - 1].core_freq ==
+			sc->px_states[count].core_freq)
+			continue;
+
 		count++;
 	}
 	sc->px_count = count;
@@ -323,7 +329,7 @@
 	}
 
 	error = acpi_PkgGas(sc->dev, pkg, 0, &sc->perf_ctrl_type, &sc->px_rid,
-	    &sc->perf_ctrl);
+	    &sc->perf_ctrl, 0);
 	if (error) {
 		/*
 		 * If the register is of type FFixedHW, we can only return
@@ -339,7 +345,7 @@
 	sc->px_rid++;
 
 	error = acpi_PkgGas(sc->dev, pkg, 1, &sc->perf_sts_type, &sc->px_rid,
-	    &sc->perf_status);
+	    &sc->perf_status, 0);
 	if (error) {
 		if (error == EOPNOTSUPP) {
 			sc->info_only = TRUE;
@@ -387,10 +393,10 @@
 {
 
 	/* Signal to the platform that we are taking over CPU control. */
-	if (AcpiGbl_FADT->PstateCnt == 0)
+	if (AcpiGbl_FADT.PstateControl == 0)
 		return;
 	ACPI_LOCK(acpi);
-	AcpiOsWritePort(AcpiGbl_FADT->SmiCmd, AcpiGbl_FADT->PstateCnt, 8);
+	AcpiOsWritePort(AcpiGbl_FADT.SmiCommand, AcpiGbl_FADT.PstateControl, 8);
 	ACPI_UNLOCK(acpi);
 }
 
Index: acpi_if.m
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/acpi_if.m,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/dev/acpica/acpi_if.m -L sys/dev/acpica/acpi_if.m -u -r1.1.1.1 -r1.2
--- sys/dev/acpica/acpi_if.m
+++ sys/dev/acpica/acpi_if.m
@@ -23,7 +23,7 @@
 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 # SUCH DAMAGE.
 #
-# $FreeBSD: src/sys/dev/acpica/acpi_if.m,v 1.6.2.2 2005/11/07 09:53:22 obrien Exp $
+# $FreeBSD: src/sys/dev/acpica/acpi_if.m,v 1.8 2005/09/11 18:39:01 obrien Exp $
 #
 
 #include <sys/bus.h>
Index: acpi_smbus.h
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/acpi_smbus.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/dev/acpica/acpi_smbus.h -L sys/dev/acpica/acpi_smbus.h -u -r1.1.1.1 -r1.2
--- sys/dev/acpica/acpi_smbus.h
+++ sys/dev/acpica/acpi_smbus.h
@@ -23,7 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	$FreeBSD: src/sys/dev/acpica/acpi_smbus.h,v 1.1.2.1 2005/11/05 23:55:56 njl Exp $
+ *	$FreeBSD: src/sys/dev/acpica/acpi_smbus.h,v 1.1 2005/10/23 00:20:13 njl Exp $
  */
 
 #ifndef _ACPI_SMBUS_H_
Index: acpi_resource.c
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/acpi_resource.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/dev/acpica/acpi_resource.c -L sys/dev/acpica/acpi_resource.c -u -r1.1.1.1 -r1.2
--- sys/dev/acpica/acpi_resource.c
+++ sys/dev/acpica/acpi_resource.c
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_resource.c,v 1.34.2.1 2005/11/07 09:53:23 obrien Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_resource.c,v 1.40 2007/03/22 18:16:40 jkim Exp $");
 
 #include "opt_acpi.h"
 #include <sys/param.h>
@@ -60,14 +60,14 @@
     struct lookup_irq_request *req;
     u_int irqnum, irq;
 
-    switch (res->Id) {
-    case ACPI_RSTYPE_IRQ:
-    case ACPI_RSTYPE_EXT_IRQ:
-	if (res->Id == ACPI_RSTYPE_IRQ) {
-	    irqnum = res->Data.Irq.NumberOfInterrupts;
+    switch (res->Type) {
+    case ACPI_RESOURCE_TYPE_IRQ:
+    case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
+	if (res->Type == ACPI_RESOURCE_TYPE_IRQ) {
+	    irqnum = res->Data.Irq.InterruptCount;
 	    irq = res->Data.Irq.Interrupts[0];
 	} else {
-	    irqnum = res->Data.ExtendedIrq.NumberOfInterrupts;
+	    irqnum = res->Data.ExtendedIrq.InterruptCount;
 	    irq = res->Data.ExtendedIrq.Interrupts[0];
 	}
 	if (irqnum != 1)
@@ -111,23 +111,23 @@
     u_int irq;
     int pol, trig;
 
-    switch (res->Id) {
-    case ACPI_RSTYPE_IRQ:
-	KASSERT(res->Data.Irq.NumberOfInterrupts == 1,
+    switch (res->Type) {
+    case ACPI_RESOURCE_TYPE_IRQ:
+	KASSERT(res->Data.Irq.InterruptCount == 1,
 	    ("%s: multiple interrupts", __func__));
 	irq = res->Data.Irq.Interrupts[0];
-	trig = res->Data.Irq.EdgeLevel;
-	pol = res->Data.Irq.ActiveHighLow;
+	trig = res->Data.Irq.Triggering;
+	pol = res->Data.Irq.Polarity;
 	break;
-    case ACPI_RSTYPE_EXT_IRQ:
-	KASSERT(res->Data.ExtendedIrq.NumberOfInterrupts == 1,
+    case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
+	KASSERT(res->Data.ExtendedIrq.InterruptCount == 1,
 	    ("%s: multiple interrupts", __func__));
 	irq = res->Data.ExtendedIrq.Interrupts[0];
-	trig = res->Data.ExtendedIrq.EdgeLevel;
-	pol = res->Data.ExtendedIrq.ActiveHighLow;
+	trig = res->Data.ExtendedIrq.Triggering;
+	pol = res->Data.ExtendedIrq.Polarity;
 	break;
     default:
-	panic("%s: bad resource type %u", __func__, res->Id);
+	panic("%s: bad resource type %u", __func__, res->Type);
     }
     BUS_CONFIG_INTR(dev, irq, (trig == ACPI_EDGE_SENSITIVE) ?
 	INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL, (pol == ACPI_ACTIVE_HIGH) ?
@@ -169,7 +169,7 @@
     /* Fetch the device's current resources. */
     buf.Length = ACPI_ALLOCATE_BUFFER;
     if (ACPI_FAILURE((status = AcpiGetCurrentResources(handle, &buf)))) {
-	if (status != AE_NOT_FOUND)
+	if (status != AE_NOT_FOUND && status != AE_TYPE)
 	    printf("can't fetch resources for %s - %s\n",
 		   acpi_name(handle), AcpiFormatException(status));
 	return_ACPI_STATUS (status);
@@ -186,129 +186,129 @@
 	curr += res->Length;
 
 	/* Handle the individual resource types */
-	switch(res->Id) {
-	case ACPI_RSTYPE_END_TAG:
+	switch(res->Type) {
+	case ACPI_RESOURCE_TYPE_END_TAG:
 	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "EndTag\n"));
 	    curr = last;
 	    break;
-	case ACPI_RSTYPE_FIXED_IO:
-	    if (res->Data.FixedIo.RangeLength <= 0)
+	case ACPI_RESOURCE_TYPE_FIXED_IO:
+	    if (res->Data.FixedIo.AddressLength <= 0)
 		break;
 	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedIo 0x%x/%d\n",
-			     res->Data.FixedIo.BaseAddress,
-			     res->Data.FixedIo.RangeLength));
+			     res->Data.FixedIo.Address,
+			     res->Data.FixedIo.AddressLength));
 	    set->set_ioport(dev, context,
-			    res->Data.FixedIo.BaseAddress,
-			    res->Data.FixedIo.RangeLength);
+			    res->Data.FixedIo.Address,
+			    res->Data.FixedIo.AddressLength);
 	    break;
-	case ACPI_RSTYPE_IO:
-	    if (res->Data.Io.RangeLength <= 0)
+	case ACPI_RESOURCE_TYPE_IO:
+	    if (res->Data.Io.AddressLength <= 0)
 		break;
-	    if (res->Data.Io.MinBaseAddress == res->Data.Io.MaxBaseAddress) {
+	    if (res->Data.Io.Minimum == res->Data.Io.Maximum) {
 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x/%d\n",
-				 res->Data.Io.MinBaseAddress,
-				 res->Data.Io.RangeLength));
+				 res->Data.Io.Minimum,
+				 res->Data.Io.AddressLength));
 		set->set_ioport(dev, context,
-				res->Data.Io.MinBaseAddress,
-				res->Data.Io.RangeLength);
+				res->Data.Io.Minimum,
+				res->Data.Io.AddressLength);
 	    } else {
 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x-0x%x/%d\n",
-				 res->Data.Io.MinBaseAddress,
-				 res->Data.Io.MaxBaseAddress, 
-				 res->Data.Io.RangeLength));
+				 res->Data.Io.Minimum,
+				 res->Data.Io.Maximum, 
+				 res->Data.Io.AddressLength));
 		set->set_iorange(dev, context,
-				 res->Data.Io.MinBaseAddress,
-				 res->Data.Io.MaxBaseAddress, 
-				 res->Data.Io.RangeLength,
+				 res->Data.Io.Minimum,
+				 res->Data.Io.Maximum, 
+				 res->Data.Io.AddressLength,
 				 res->Data.Io.Alignment);
 	    }
 	    break;
-	case ACPI_RSTYPE_FIXED_MEM32:
-	    if (res->Data.FixedMemory32.RangeLength <= 0)
+	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
+	    if (res->Data.FixedMemory32.AddressLength <= 0)
 		break;
 	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedMemory32 0x%x/%d\n",
-			      res->Data.FixedMemory32.RangeBaseAddress, 
-			      res->Data.FixedMemory32.RangeLength));
+			      res->Data.FixedMemory32.Address, 
+			      res->Data.FixedMemory32.AddressLength));
 	    set->set_memory(dev, context,
-			    res->Data.FixedMemory32.RangeBaseAddress, 
-			    res->Data.FixedMemory32.RangeLength);
+			    res->Data.FixedMemory32.Address, 
+			    res->Data.FixedMemory32.AddressLength);
 	    break;
-	case ACPI_RSTYPE_MEM32:
-	    if (res->Data.Memory32.RangeLength <= 0)
+	case ACPI_RESOURCE_TYPE_MEMORY32:
+	    if (res->Data.Memory32.AddressLength <= 0)
 		break;
-	    if (res->Data.Memory32.MinBaseAddress ==
-		res->Data.Memory32.MaxBaseAddress) {
+	    if (res->Data.Memory32.Minimum ==
+		res->Data.Memory32.Maximum) {
 
 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x/%d\n",
-				  res->Data.Memory32.MinBaseAddress, 
-				  res->Data.Memory32.RangeLength));
+				  res->Data.Memory32.Minimum, 
+				  res->Data.Memory32.AddressLength));
 		set->set_memory(dev, context,
-				res->Data.Memory32.MinBaseAddress,
-				res->Data.Memory32.RangeLength);
+				res->Data.Memory32.Minimum,
+				res->Data.Memory32.AddressLength);
 	    } else {
 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x-0x%x/%d\n",
-				 res->Data.Memory32.MinBaseAddress, 
-				 res->Data.Memory32.MaxBaseAddress,
-				 res->Data.Memory32.RangeLength));
+				 res->Data.Memory32.Minimum, 
+				 res->Data.Memory32.Maximum,
+				 res->Data.Memory32.AddressLength));
 		set->set_memoryrange(dev, context,
-				     res->Data.Memory32.MinBaseAddress,
-				     res->Data.Memory32.MaxBaseAddress,
-				     res->Data.Memory32.RangeLength,
+				     res->Data.Memory32.Minimum,
+				     res->Data.Memory32.Maximum,
+				     res->Data.Memory32.AddressLength,
 				     res->Data.Memory32.Alignment);
 	    }
 	    break;
-	case ACPI_RSTYPE_MEM24:
-	    if (res->Data.Memory24.RangeLength <= 0)
+	case ACPI_RESOURCE_TYPE_MEMORY24:
+	    if (res->Data.Memory24.AddressLength <= 0)
 		break;
-	    if (res->Data.Memory24.MinBaseAddress ==
-		res->Data.Memory24.MaxBaseAddress) {
+	    if (res->Data.Memory24.Minimum ==
+		res->Data.Memory24.Maximum) {
 
 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x/%d\n",
-				 res->Data.Memory24.MinBaseAddress, 
-				 res->Data.Memory24.RangeLength));
-		set->set_memory(dev, context, res->Data.Memory24.MinBaseAddress,
-				res->Data.Memory24.RangeLength);
+				 res->Data.Memory24.Minimum, 
+				 res->Data.Memory24.AddressLength));
+		set->set_memory(dev, context, res->Data.Memory24.Minimum,
+				res->Data.Memory24.AddressLength);
 	    } else {
 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x-0x%x/%d\n",
-				 res->Data.Memory24.MinBaseAddress, 
-				 res->Data.Memory24.MaxBaseAddress,
-				 res->Data.Memory24.RangeLength));
+				 res->Data.Memory24.Minimum, 
+				 res->Data.Memory24.Maximum,
+				 res->Data.Memory24.AddressLength));
 		set->set_memoryrange(dev, context,
-				     res->Data.Memory24.MinBaseAddress,
-				     res->Data.Memory24.MaxBaseAddress,
-				     res->Data.Memory24.RangeLength,
+				     res->Data.Memory24.Minimum,
+				     res->Data.Memory24.Maximum,
+				     res->Data.Memory24.AddressLength,
 				     res->Data.Memory24.Alignment);
 	    }
 	    break;
-	case ACPI_RSTYPE_IRQ:
+	case ACPI_RESOURCE_TYPE_IRQ:
 	    /*
 	     * from 1.0b 6.4.2 
 	     * "This structure is repeated for each separate interrupt
 	     * required"
 	     */
 	    set->set_irq(dev, context, res->Data.Irq.Interrupts,
-		res->Data.Irq.NumberOfInterrupts, res->Data.Irq.EdgeLevel,
-		res->Data.Irq.ActiveHighLow);
+		res->Data.Irq.InterruptCount, res->Data.Irq.Triggering,
+		res->Data.Irq.Polarity);
 	    break;
-	case ACPI_RSTYPE_DMA:
+	case ACPI_RESOURCE_TYPE_DMA:
 	    /*
 	     * from 1.0b 6.4.3 
 	     * "This structure is repeated for each separate dma channel
 	     * required"
 	     */
 	    set->set_drq(dev, context, res->Data.Dma.Channels,
-			 res->Data.Dma.NumberOfChannels);
+			 res->Data.Dma.ChannelCount);
 	    break;
-	case ACPI_RSTYPE_START_DPF:
-	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "start dependant functions\n"));
-	    set->set_start_dependant(dev, context,
+	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
+	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "start dependent functions\n"));
+	    set->set_start_dependent(dev, context,
 				     res->Data.StartDpf.CompatibilityPriority);
 	    break;
-	case ACPI_RSTYPE_END_DPF:
-	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "end dependant functions\n"));
-	    set->set_end_dependant(dev, context);
+	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
+	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "end dependent functions\n"));
+	    set->set_end_dependent(dev, context);
 	    break;
-	case ACPI_RSTYPE_ADDRESS32:
+	case ACPI_RESOURCE_TYPE_ADDRESS32:
 	    if (res->Data.Address32.AddressLength <= 0)
 		break;
 	    if (res->Data.Address32.ProducerConsumer != ACPI_CONSUMER) {
@@ -331,47 +331,47 @@
 		if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) {
 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
 				     "Address32/Memory 0x%x/%d\n",
-				     res->Data.Address32.MinAddressRange,
+				     res->Data.Address32.Minimum,
 				     res->Data.Address32.AddressLength));
 		    set->set_memory(dev, context,
-				    res->Data.Address32.MinAddressRange,
+				    res->Data.Address32.Minimum,
 				    res->Data.Address32.AddressLength);
 		} else {
 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
 				     "Address32/IO 0x%x/%d\n",
-				     res->Data.Address32.MinAddressRange,
+				     res->Data.Address32.Minimum,
 				     res->Data.Address32.AddressLength));
 		    set->set_ioport(dev, context,
-				    res->Data.Address32.MinAddressRange,
+				    res->Data.Address32.Minimum,
 				    res->Data.Address32.AddressLength);
 		}
 	    } else {
 		if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) {
 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
 				     "Address32/Memory 0x%x-0x%x/%d\n",
-				     res->Data.Address32.MinAddressRange,
-				     res->Data.Address32.MaxAddressRange,
+				     res->Data.Address32.Minimum,
+				     res->Data.Address32.Maximum,
 				     res->Data.Address32.AddressLength));
 		    set->set_memoryrange(dev, context,
-					  res->Data.Address32.MinAddressRange,
-					  res->Data.Address32.MaxAddressRange,
+					  res->Data.Address32.Minimum,
+					  res->Data.Address32.Maximum,
 					  res->Data.Address32.AddressLength,
 					  res->Data.Address32.Granularity);
 		} else {
 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
 				     "Address32/IO 0x%x-0x%x/%d\n",
-				     res->Data.Address32.MinAddressRange,
-				     res->Data.Address32.MaxAddressRange,
+				     res->Data.Address32.Minimum,
+				     res->Data.Address32.Maximum,
 				     res->Data.Address32.AddressLength));
 		    set->set_iorange(dev, context,
-				     res->Data.Address32.MinAddressRange,
-				     res->Data.Address32.MaxAddressRange,
+				     res->Data.Address32.Minimum,
+				     res->Data.Address32.Maximum,
 				     res->Data.Address32.AddressLength,
 				     res->Data.Address32.Granularity);
 		}
 	    }		    
 	    break;
-	case ACPI_RSTYPE_ADDRESS16:
+	case ACPI_RESOURCE_TYPE_ADDRESS16:
 	    if (res->Data.Address16.AddressLength <= 0)
 		break;
 	    if (res->Data.Address16.ProducerConsumer != ACPI_CONSUMER) {
@@ -394,62 +394,62 @@
 		if (res->Data.Address16.ResourceType == ACPI_MEMORY_RANGE) {
 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
 				     "Address16/Memory 0x%x/%d\n",
-				     res->Data.Address16.MinAddressRange,
+				     res->Data.Address16.Minimum,
 				     res->Data.Address16.AddressLength));
 		    set->set_memory(dev, context,
-				    res->Data.Address16.MinAddressRange,
+				    res->Data.Address16.Minimum,
 				    res->Data.Address16.AddressLength);
 		} else {
 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
 				     "Address16/IO 0x%x/%d\n",
-				     res->Data.Address16.MinAddressRange,
+				     res->Data.Address16.Minimum,
 				     res->Data.Address16.AddressLength));
 		    set->set_ioport(dev, context,
-				    res->Data.Address16.MinAddressRange,
+				    res->Data.Address16.Minimum,
 				    res->Data.Address16.AddressLength);
 		}
 	    } else {
 		if (res->Data.Address16.ResourceType == ACPI_MEMORY_RANGE) {
 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
 				     "Address16/Memory 0x%x-0x%x/%d\n",
-				     res->Data.Address16.MinAddressRange,
-				     res->Data.Address16.MaxAddressRange,
+				     res->Data.Address16.Minimum,
+				     res->Data.Address16.Maximum,
 				     res->Data.Address16.AddressLength));
 		    set->set_memoryrange(dev, context,
-					  res->Data.Address16.MinAddressRange,
-					  res->Data.Address16.MaxAddressRange,
+					  res->Data.Address16.Minimum,
+					  res->Data.Address16.Maximum,
 					  res->Data.Address16.AddressLength,
 					  res->Data.Address16.Granularity);
 		} else {
 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
 				     "Address16/IO 0x%x-0x%x/%d\n",
-				     res->Data.Address16.MinAddressRange,
-				     res->Data.Address16.MaxAddressRange,
+				     res->Data.Address16.Minimum,
+				     res->Data.Address16.Maximum,
 				     res->Data.Address16.AddressLength));
 		    set->set_iorange(dev, context,
-				     res->Data.Address16.MinAddressRange,
-				     res->Data.Address16.MaxAddressRange,
+				     res->Data.Address16.Minimum,
+				     res->Data.Address16.Maximum,
 				     res->Data.Address16.AddressLength,
 				     res->Data.Address16.Granularity);
 		}
 	    }		    
 	    break;
-	case ACPI_RSTYPE_ADDRESS64:
+	case ACPI_RESOURCE_TYPE_ADDRESS64:
 	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
 			     "unimplemented Address64 resource\n"));
 	    break;
-	case ACPI_RSTYPE_EXT_IRQ:
+	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
 	    if (res->Data.ExtendedIrq.ProducerConsumer != ACPI_CONSUMER) {
 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
 		    "ignored ExtIRQ producer\n"));
 		break;
 	    }
-	    set->set_irq(dev, context,res->Data.ExtendedIrq.Interrupts,
-		res->Data.ExtendedIrq.NumberOfInterrupts,
-		res->Data.ExtendedIrq.EdgeLevel,
-		res->Data.ExtendedIrq.ActiveHighLow);
+	    set->set_ext_irq(dev, context, res->Data.ExtendedIrq.Interrupts,
+		res->Data.ExtendedIrq.InterruptCount,
+		res->Data.ExtendedIrq.Triggering,
+		res->Data.ExtendedIrq.Polarity);
 	    break;
-	case ACPI_RSTYPE_VENDOR:
+	case ACPI_RESOURCE_TYPE_VENDOR:
 	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
 			     "unimplemented VendorSpecific resource\n"));
 	    break;
@@ -479,13 +479,15 @@
 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_irq(device_t dev, void *context, u_int8_t *irq,
 				 int count, int trig, int pol);
-static void	acpi_res_set_drq(device_t dev, void *context, u_int32_t *drq,
+static void	acpi_res_set_ext_irq(device_t dev, void *context,
+				 u_int32_t *irq, int count, int trig, int pol);
+static void	acpi_res_set_drq(device_t dev, void *context, u_int8_t *drq,
 				 int count);
-static void	acpi_res_set_start_dependant(device_t dev, void *context,
+static void	acpi_res_set_start_dependent(device_t dev, void *context,
 					     int preference);
-static void	acpi_res_set_end_dependant(device_t dev, void *context);
+static void	acpi_res_set_end_dependent(device_t dev, void *context);
 
 struct acpi_parse_resource_set acpi_res_parse_set = {
     acpi_res_set_init,
@@ -495,9 +497,10 @@
     acpi_res_set_memory,
     acpi_res_set_memoryrange,
     acpi_res_set_irq,
+    acpi_res_set_ext_irq,
     acpi_res_set_drq,
-    acpi_res_set_start_dependant,
-    acpi_res_set_end_dependant
+    acpi_res_set_start_dependent,
+    acpi_res_set_end_dependent
 };
 
 struct acpi_res_context {
@@ -576,7 +579,7 @@
 }
 
 static void
-acpi_res_set_irq(device_t dev, void *context, u_int32_t *irq, int count,
+acpi_res_set_irq(device_t dev, void *context, u_int8_t *irq, int count,
     int trig, int pol)
 {
     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
@@ -592,7 +595,23 @@
 }
 
 static void
-acpi_res_set_drq(device_t dev, void *context, u_int32_t *drq, int count)
+acpi_res_set_ext_irq(device_t dev, void *context, u_int32_t *irq, int count,
+    int trig, int pol)
+{
+    struct acpi_res_context	*cp = (struct acpi_res_context *)context;
+
+    if (cp == NULL || irq == NULL)
+	return;
+
+    /* This implements no resource relocation. */
+    if (count != 1)
+	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_int8_t *drq, int count)
 {
     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
 
@@ -607,23 +626,23 @@
 }
 
 static void
-acpi_res_set_start_dependant(device_t dev, void *context, int preference)
+acpi_res_set_start_dependent(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\n");
+    device_printf(dev, "dependent functions not supported\n");
 }
 
 static void
-acpi_res_set_end_dependant(device_t dev, void *context)
+acpi_res_set_end_dependent(device_t dev, void *context)
 {
     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
 
     if (cp == NULL)
 	return;
-    device_printf(dev, "dependant functions not supported\n");
+    device_printf(dev, "dependent functions not supported\n");
 }
 
 /*
@@ -669,7 +688,7 @@
 
     device_set_desc(dev, "System Resource");
     device_quiet(dev);
-    return (-100);
+    return (BUS_PROBE_DEFAULT);
 }
 
 static int
Index: acpi_video.c
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/acpi_video.c,v
retrieving revision 1.1.1.2
retrieving revision 1.2
diff -L sys/dev/acpica/acpi_video.c -L sys/dev/acpica/acpi_video.c -u -r1.1.1.2 -r1.2
--- sys/dev/acpica/acpi_video.c
+++ sys/dev/acpica/acpi_video.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_video.c,v 1.10.2.1 2005/11/07 09:53:23 obrien Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_video.c,v 1.13 2006/08/10 13:18:02 bruno Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -70,6 +70,7 @@
 
 /* interfaces */
 static int	acpi_video_modevent(struct module*, int, void *);
+static void	acpi_video_identify(driver_t *driver, device_t parent);
 static int	acpi_video_probe(device_t);
 static int	acpi_video_attach(device_t);
 static int	acpi_video_detach(device_t);
@@ -108,16 +109,22 @@
 #define DOS_BRIGHTNESS_BY_BIOS	(1 << 2)
 
 /* _DOD and subdev's _ADR */
-#define DOD_DEVID_MASK		0xffff
+#define DOD_DEVID_MASK		0x0f00
+#define DOD_DEVID_MASK_FULL	0xffff
+#define DOD_DEVID_MASK_DISPIDX	0x000f
+#define DOD_DEVID_MASK_DISPPORT	0x00f0
 #define DOD_DEVID_MONITOR	0x0100
-#define DOD_DEVID_PANEL		0x0110
+#define DOD_DEVID_LCD		0x0110
 #define DOD_DEVID_TV		0x0200
+#define DOD_DEVID_EXT		0x0300
+#define DOD_DEVID_INTDFP	0x0400
 #define DOD_BIOS		(1 << 16)
 #define DOD_NONVGA		(1 << 17)
 #define DOD_HEAD_ID_SHIFT	18
 #define DOD_HEAD_ID_BITS	3
 #define DOD_HEAD_ID_MASK \
 		(((1 << DOD_HEAD_ID_BITS) - 1) << DOD_HEAD_ID_SHIFT)
+#define DOD_DEVID_SCHEME_STD	(1 << 31)
 
 /* _BCL related constants */
 #define BCL_FULLPOWER		0
@@ -137,6 +144,7 @@
 #define DSS_COMMIT		(1 << 31)
 
 static device_method_t acpi_video_methods[] = {
+	DEVMETHOD(device_identify, acpi_video_identify),
 	DEVMETHOD(device_probe, acpi_video_probe),
 	DEVMETHOD(device_attach, acpi_video_attach),
 	DEVMETHOD(device_detach, acpi_video_detach),
@@ -152,14 +160,14 @@
 
 static devclass_t acpi_video_devclass;
 
-DRIVER_MODULE(acpi_video, pci, acpi_video_driver, acpi_video_devclass,
+DRIVER_MODULE(acpi_video, vgapci, acpi_video_driver, acpi_video_devclass,
 	      acpi_video_modevent, NULL);
 MODULE_DEPEND(acpi_video, acpi, 1, 1, 1);
 
 static struct sysctl_ctx_list	acpi_video_sysctl_ctx;
 static struct sysctl_oid	*acpi_video_sysctl_tree;
-static struct acpi_video_output_queue lcd_units, crt_units, tv_units,
-    other_units;
+static struct acpi_video_output_queue crt_units, tv_units,
+    ext_units, lcd_units, other_units;
 
 ACPI_SERIAL_DECL(video, "ACPI video");
 MALLOC_DEFINE(M_ACPIVIDEO, "acpivideo", "ACPI video extension");
@@ -173,9 +181,10 @@
 	switch (evt) {
 	case MOD_LOAD:
 		sysctl_ctx_init(&acpi_video_sysctl_ctx);
-		STAILQ_INIT(&lcd_units);
 		STAILQ_INIT(&crt_units);
 		STAILQ_INIT(&tv_units);
+		STAILQ_INIT(&ext_units);
+		STAILQ_INIT(&lcd_units);
 		STAILQ_INIT(&other_units);
 		break;
 	case MOD_UNLOAD:
@@ -189,6 +198,14 @@
 	return (err);
 }
 
+static void
+acpi_video_identify(driver_t *driver, device_t parent)
+{
+
+	if (device_find_child(parent, "acpi_video", -1) == NULL)
+		device_add_child(parent, "acpi_video", -1);
+}
+
 static int
 acpi_video_probe(device_t dev)
 {
@@ -394,27 +411,44 @@
 {
 	struct acpi_video_output *vn, *vo, *vp;
 	int n, x;
+	int display_index;
+	int display_port;
 	char name[8], env[32];
 	const char *type, *desc;
 	struct acpi_video_output_queue *voqh;
 
 	ACPI_SERIAL_ASSERT(video);
+	display_index = adr & DOD_DEVID_MASK_DISPIDX;
+	display_port = (adr & DOD_DEVID_MASK_DISPPORT) >> 4;
+
 	switch (adr & DOD_DEVID_MASK) {
 	case DOD_DEVID_MONITOR:
-		desc = "CRT monitor";
-		type = "crt";
-		voqh = &crt_units;
-		break;
-	case DOD_DEVID_PANEL:
-		desc = "LCD panel";
-		type = "lcd";
-		voqh = &lcd_units;
+		if ((adr & DOD_DEVID_MASK_FULL) == DOD_DEVID_LCD) {
+			/* DOD_DEVID_LCD is a common, backward compatible ID */
+			desc = "Internal/Integrated Digital Flat Panel";
+			type = "lcd";
+			voqh = &lcd_units;
+		} else {
+			desc = "VGA CRT or VESA Compatible Analog Monitor";
+			type = "crt";
+			voqh = &crt_units;
+		}
 		break;
 	case DOD_DEVID_TV:
-		desc = "TV";
+		desc = "TV/HDTV or Analog-Video Monitor";
 		type = "tv";
 		voqh = &tv_units;
 		break;
+	case DOD_DEVID_EXT:
+		desc = "External Digital Monitor";
+		type = "ext";
+		voqh = &ext_units;
+		break;
+	case DOD_DEVID_INTDFP:
+		desc = "Internal/Integrated Digital Flat Panel";
+		type = "lcd";
+		voqh = &lcd_units;
+		break;
 	default:
 		desc = "unknown output";
 		type = "out";
@@ -498,13 +532,16 @@
 		printf("%s: softc allocation failed\n", type);
 
 	if (bootverbose) {
-		printf("found %s(%x)", desc, adr & DOD_DEVID_MASK);
+		printf("found %s(%x)", desc, adr & DOD_DEVID_MASK_FULL);
+		printf(", idx#%x", adr & DOD_DEVID_MASK_DISPIDX);
+		printf(", port#%x", (adr & DOD_DEVID_MASK_DISPPORT) >> 4);
 		if (adr & DOD_BIOS)
 			printf(", detectable by BIOS");
 		if (adr & DOD_NONVGA)
-			printf(" (not a VGA output)");
+			printf(" (Non-VGA output device whose power "
+			    "is related to the VGA device)");
 		printf(", head #%d\n",
-		   (adr & DOD_HEAD_ID_MASK) >> DOD_HEAD_ID_SHIFT);
+			(adr & DOD_HEAD_ID_MASK) >> DOD_HEAD_ID_SHIFT);
 	}
 	return (vo);
 }
@@ -547,12 +584,15 @@
 	case DOD_DEVID_MONITOR:
 		voqh = &crt_units;
 		break;
-	case DOD_DEVID_PANEL:
-		voqh = &lcd_units;
-		break;
 	case DOD_DEVID_TV:
 		voqh = &tv_units;
 		break;
+	case DOD_DEVID_EXT:
+		voqh = &ext_units;
+		break;
+	case DOD_DEVID_INTDFP:
+		voqh = &lcd_units;
+		break;
 	default:
 		voqh = &other_units;
 	}
@@ -741,7 +781,7 @@
 
 	for (i = 0; i < argset->dod_pkg->Package.Count; i++) {
 		if (acpi_PkgInt32(argset->dod_pkg, i, &val) == 0 &&
-		    (val & DOD_DEVID_MASK) == adr) {
+		    (val & DOD_DEVID_MASK_FULL) == adr) {
 			argset->callback(handle, val, argset->context);
 			argset->count++;
 		}
Index: acpi_cpu.c
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/acpi_cpu.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/dev/acpica/acpi_cpu.c -L sys/dev/acpica/acpi_cpu.c -u -r1.1.1.1 -r1.2
--- sys/dev/acpica/acpi_cpu.c
+++ sys/dev/acpica/acpi_cpu.c
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_cpu.c,v 1.57.2.1 2005/11/05 23:49:39 njl Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_cpu.c,v 1.67.2.1 2007/11/06 20:13:33 njl Exp $");
 
 #include "opt_acpi.h"
 #include <sys/param.h>
@@ -51,9 +51,6 @@
 
 /*
  * Support for ACPI Processor devices, including C[1-3] sleep states.
- *
- * TODO: implement scans of all CPUs to be sure all Cx states are
- * equivalent.
  */
 
 /* Hooks for the ACPI CA debugging infrastructure */
@@ -80,10 +77,20 @@
     int			 cpu_cx_count;	/* Number of valid Cx states. */
     int			 cpu_prev_sleep;/* Last idle sleep duration. */
     int			 cpu_features;	/* Child driver supported features. */
+    /* Runtime state. */
+    int			 cpu_non_c3;	/* Index of lowest non-C3 state. */
+    int			 cpu_short_slp;	/* Count of < 1us sleeps. */
+    u_int		 cpu_cx_stats[MAX_CX_STATES];/* Cx usage history. */
+    /* Values for sysctl. */
+    struct sysctl_ctx_list cpu_sysctl_ctx;
+    struct sysctl_oid	*cpu_sysctl_tree;
+    int			 cpu_cx_lowest;
+    char 		 cpu_cx_supported[64];
+    int			 cpu_rid;
 };
 
 struct acpi_cpu_device {
-    struct resource_list        ad_rl;
+    struct resource_list	ad_rl;
 };
 
 #define CPU_GET_REG(reg, width) 					\
@@ -110,20 +117,17 @@
 /* Platform hardware resource information. */
 static uint32_t		 cpu_smi_cmd;	/* Value to write to SMI_CMD. */
 static uint8_t		 cpu_cst_cnt;	/* Indicate we are _CST aware. */
-static int		 cpu_rid;	/* Driver-wide resource id. */
 static int		 cpu_quirks;	/* Indicate any hardware bugs. */
 
 /* Runtime state. */
-static int		 cpu_cx_count;	/* Number of valid states */
-static int		 cpu_non_c3;	/* Index of lowest non-C3 state. */
-static int		 cpu_short_slp;	/* Count of < 1us sleeps. */
-static u_int		 cpu_cx_stats[MAX_CX_STATES];/* Cx usage history. */
+static int		 cpu_disable_idle; /* Disable entry to idle function */
+static int		 cpu_cx_count;	/* Number of valid Cx states */
 
 /* Values for sysctl. */
-static struct sysctl_ctx_list acpi_cpu_sysctl_ctx;
-static struct sysctl_oid *acpi_cpu_sysctl_tree;
+static struct sysctl_ctx_list cpu_sysctl_ctx;
+static struct sysctl_oid *cpu_sysctl_tree;
+static int		 cpu_cx_generic;
 static int		 cpu_cx_lowest;
-static char 		 cpu_cx_supported[64];
 
 static device_t		*cpu_devices;
 static int		 cpu_ndevices;
@@ -132,6 +136,8 @@
 
 static int	acpi_cpu_probe(device_t dev);
 static int	acpi_cpu_attach(device_t dev);
+static int	acpi_cpu_suspend(device_t dev);
+static int	acpi_cpu_resume(device_t dev);
 static int	acpi_pcpu_get_id(uint32_t idx, uint32_t *acpi_id,
 		    uint32_t *cpu_id);
 static struct resource_list *acpi_cpu_get_rlist(device_t dev, device_t child);
@@ -140,15 +146,18 @@
 static int	acpi_cpu_read_ivar(device_t dev, device_t child, int index,
 		    uintptr_t *result);
 static int	acpi_cpu_shutdown(device_t dev);
-static int	acpi_cpu_cx_probe(struct acpi_cpu_softc *sc);
+static void	acpi_cpu_cx_probe(struct acpi_cpu_softc *sc);
+static void	acpi_cpu_generic_cx_probe(struct acpi_cpu_softc *sc);
 static int	acpi_cpu_cx_cst(struct acpi_cpu_softc *sc);
 static void	acpi_cpu_startup(void *arg);
-static void	acpi_cpu_startup_cx(void);
+static void	acpi_cpu_startup_cx(struct acpi_cpu_softc *sc);
 static void	acpi_cpu_idle(void);
 static void	acpi_cpu_notify(ACPI_HANDLE h, UINT32 notify, void *context);
-static int	acpi_cpu_quirks(struct acpi_cpu_softc *sc);
+static int	acpi_cpu_quirks(void);
 static int	acpi_cpu_usage_sysctl(SYSCTL_HANDLER_ARGS);
+static int	acpi_cpu_set_cx_lowest(struct acpi_cpu_softc *sc, int val);
 static int	acpi_cpu_cx_lowest_sysctl(SYSCTL_HANDLER_ARGS);
+static int	acpi_cpu_global_cx_lowest_sysctl(SYSCTL_HANDLER_ARGS);
 
 static device_method_t acpi_cpu_methods[] = {
     /* Device interface */
@@ -156,8 +165,8 @@
     DEVMETHOD(device_attach,	acpi_cpu_attach),
     DEVMETHOD(device_detach,	bus_generic_detach),
     DEVMETHOD(device_shutdown,	acpi_cpu_shutdown),
-    DEVMETHOD(device_suspend,	bus_generic_suspend),
-    DEVMETHOD(device_resume,	bus_generic_resume),
+    DEVMETHOD(device_suspend,	acpi_cpu_suspend),
+    DEVMETHOD(device_resume,	acpi_cpu_resume),
 
     /* Bus interface */
     DEVMETHOD(bus_add_child,	acpi_cpu_add_child),
@@ -248,7 +257,7 @@
 acpi_cpu_attach(device_t dev)
 {
     ACPI_BUFFER		   buf;
-    ACPI_OBJECT		   arg, *obj;
+    ACPI_OBJECT		   arg[4], *obj;
     ACPI_OBJECT_LIST	   arglist;
     struct pcpu		   *pcpu_data;
     struct acpi_cpu_softc *sc;
@@ -259,6 +268,11 @@
     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);
@@ -269,8 +283,8 @@
     pcpu_data = pcpu_find(cpu_id);
     pcpu_data->pc_device = dev;
     sc->cpu_pcpu = pcpu_data;
-    cpu_smi_cmd = AcpiGbl_FADT->SmiCmd;
-    cpu_cst_cnt = AcpiGbl_FADT->CstCnt;
+    cpu_smi_cmd = AcpiGbl_FADT.SmiCommand;
+    cpu_cst_cnt = AcpiGbl_FADT.CstControl;
 
     buf.Pointer = NULL;
     buf.Length = ACPI_ALLOCATE_BUFFER;
@@ -288,11 +302,24 @@
     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));
 
-    acpi_sc = acpi_device_get_parent_softc(dev);
-    sysctl_ctx_init(&acpi_cpu_sysctl_ctx);
-    acpi_cpu_sysctl_tree = SYSCTL_ADD_NODE(&acpi_cpu_sysctl_ctx,
-	SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree), OID_AUTO, "cpu",
-	CTLFLAG_RD, 0, "");
+    /*
+     * 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
@@ -312,32 +339,43 @@
     /*
      * CPU capabilities are specified as a buffer of 32-bit integers:
      * revision, count, and one or more capabilities.  The revision of
-     * "1" is not specified anywhere but seems to match Linux.  We should
-     * also support _OSC here.
+     * "1" is not specified anywhere but seems to match Linux.
      */
     if (sc->cpu_features) {
-	arglist.Pointer = &arg;
+	arglist.Pointer = arg;
 	arglist.Count = 1;
-	arg.Type = ACPI_TYPE_BUFFER;
-	arg.Buffer.Length = sizeof(cap_set);
-	arg.Buffer.Pointer = (uint8_t *)cap_set;
+	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);
+
+	/*
+	 * On some systems we need to evaluate _OSC so that the ASL
+	 * loads the _PSS and/or _PDC methods at runtime.
+	 *
+	 * TODO: evaluate failure of _OSC.
+	 */
+	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;
+	AcpiEvaluateObject(sc->cpu_handle, "_OSC", &arglist, NULL);
     }
 
-    /*
-     * Probe for Cx state support.  If it isn't present, free up unused
-     * resources.
-     */
-    if (acpi_cpu_cx_probe(sc) == 0) {
-	status = AcpiInstallNotifyHandler(sc->cpu_handle, ACPI_DEVICE_NOTIFY,
-					  acpi_cpu_notify, sc);
-	if (device_get_unit(dev) == 0)
-	    AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_cpu_startup, NULL);
-    } else
-	sysctl_ctx_free(&acpi_cpu_sysctl_ctx);
+    /* Probe for Cx state support. */
+    acpi_cpu_cx_probe(sc);
 
     /* Finally,  call identify and probe/attach for child devices. */
     bus_generic_probe(dev);
@@ -347,6 +385,30 @@
 }
 
 /*
+ * Disable any entry to the idle function during suspend and re-enable it
+ * during resume.
+ */
+static int
+acpi_cpu_suspend(device_t dev)
+{
+    int error;
+
+    error = bus_generic_suspend(dev);
+    if (error)
+	return (error);
+    cpu_disable_idle = TRUE;
+    return (0);
+}
+
+static int
+acpi_cpu_resume(device_t dev)
+{
+
+    cpu_disable_idle = FALSE;
+    return (bus_generic_resume(dev));
+}
+
+/*
  * Find the nth present CPU and return its pc_cpuid as well as set the
  * pc_acpi_id from the most reliable source.
  */
@@ -371,7 +433,7 @@
 	     * return the pc_cpuid to reference this processor.
 	     */
 	    if (pcpu_data->pc_acpi_id == 0xffffffff)
-		 pcpu_data->pc_acpi_id = *acpi_id;
+		pcpu_data->pc_acpi_id = *acpi_id;
 	    else if (pcpu_data->pc_acpi_id != *acpi_id)
 		*acpi_id = pcpu_data->pc_acpi_id;
 	    *cpu_id = pcpu_data->pc_cpuid;
@@ -396,17 +458,17 @@
 static device_t
 acpi_cpu_add_child(device_t dev, int order, const char *name, int unit)
 {
-    struct acpi_cpu_device  *ad;
-    device_t            child;
+    struct acpi_cpu_device *ad;
+    device_t child;
 
     if ((ad = malloc(sizeof(*ad), M_TEMP, M_NOWAIT | M_ZERO)) == NULL)
-        return (NULL);
+	return (NULL);
 
     resource_list_init(&ad->ad_rl);
     
     child = device_add_child_ordered(dev, order, name, unit);
     if (child != NULL)
-        device_set_ivars(child, ad);
+	device_set_ivars(child, ad);
     else
 	free(ad, M_TEMP);
     return (child);
@@ -439,114 +501,111 @@
     /* Allow children to shutdown first. */
     bus_generic_shutdown(dev);
 
-    /* Disable any entry to the idle function. */
-    cpu_cx_count = 0;
-
-    /* Signal and wait for all processors to exit acpi_cpu_idle(). */
-    smp_rendezvous(NULL, NULL, NULL, NULL);
+    /*
+     * Disable any entry to the idle function.  There is a small race where
+     * an idle thread have passed this check but not gone to sleep.  This
+     * is ok since device_shutdown() does not free the softc, otherwise
+     * we'd have to be sure all threads were evicted before returning.
+     */
+    cpu_disable_idle = TRUE;
 
     return_VALUE (0);
 }
 
-static int
+static void
 acpi_cpu_cx_probe(struct acpi_cpu_softc *sc)
 {
-    ACPI_GENERIC_ADDRESS gas;
-    struct acpi_cx	*cx_ptr;
-    int			 error;
-
     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
 
+    /* Use initial sleep value of 1 sec. to start with lowest idle state. */
+    sc->cpu_prev_sleep = 1000000;
+    sc->cpu_cx_lowest = 0;
+
     /*
-     * Bus mastering arbitration control is needed to keep caches coherent
-     * while sleeping in C3.  If it's not present but a working flush cache
-     * instruction is present, flush the caches before entering C3 instead.
-     * Otherwise, just disable C3 completely.
+     * Check for the ACPI 2.0 _CST sleep states object. If we can't find
+     * any, we'll revert to generic FADT/P_BLK Cx control method which will
+     * be handled by acpi_cpu_startup. We need to defer to after having
+     * probed all the cpus in the system before probing for generic Cx
+     * states as we may already have found cpus with valid _CST packages
      */
-    if (AcpiGbl_FADT->V1_Pm2CntBlk == 0 || AcpiGbl_FADT->Pm2CntLen == 0) {
-	if (AcpiGbl_FADT->WbInvd && AcpiGbl_FADT->WbInvdFlush == 0) {
-	    cpu_quirks |= CPU_QUIRK_NO_BM_CTRL;
-	    ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-		"acpi_cpu%d: no BM control, using flush cache method\n",
-		device_get_unit(sc->cpu_dev)));
-	} else {
-	    cpu_quirks |= CPU_QUIRK_NO_C3;
-	    ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-		"acpi_cpu%d: no BM control, C3 not available\n",
-		device_get_unit(sc->cpu_dev)));
-	}
+    if (!cpu_cx_generic && acpi_cpu_cx_cst(sc) != 0) {
+	/*
+	 * We were unable to find a _CST package for this cpu or there
+	 * was an error parsing it. Switch back to generic mode.
+	 */
+	cpu_cx_generic = TRUE;
+	if (bootverbose)
+	    device_printf(sc->cpu_dev, "switching to generic Cx mode\n");
     }
 
     /*
-     * First, check for the ACPI 2.0 _CST sleep states object.
-     * If not usable, fall back to the P_BLK's P_LVL2 and P_LVL3.
+     * TODO: _CSD Package should be checked here.
      */
+}
+
+static void
+acpi_cpu_generic_cx_probe(struct acpi_cpu_softc *sc)
+{
+    ACPI_GENERIC_ADDRESS	 gas;
+    struct acpi_cx		*cx_ptr;
+
     sc->cpu_cx_count = 0;
-    error = acpi_cpu_cx_cst(sc);
-    if (error != 0) {
-	cx_ptr = sc->cpu_cx_states;
-
-	/* C1 has been required since just after ACPI 1.0 */
-	cx_ptr->type = ACPI_STATE_C1;
-	cx_ptr->trans_lat = 0;
-	cpu_non_c3 = 0;
-	cx_ptr++;
-	sc->cpu_cx_count++;
-
-	/* 
-	 * The spec says P_BLK must be 6 bytes long.  However, some systems
-	 * use it to indicate a fractional set of features present so we
-	 * take 5 as C2.  Some may also have a value of 7 to indicate
-	 * another C3 but most use _CST for this (as required) and having
-	 * "only" C1-C3 is not a hardship.
-	 */
-	if (sc->cpu_p_blk_len < 5)
-	    goto done;
+    cx_ptr = sc->cpu_cx_states;
 
-	/* Validate and allocate resources for C2 (P_LVL2). */
-	gas.AddressSpaceId = ACPI_ADR_SPACE_SYSTEM_IO;
-	gas.RegisterBitWidth = 8;
-	if (AcpiGbl_FADT->Plvl2Lat <= 100) {
-	    gas.Address = sc->cpu_p_blk + 4;
-	    acpi_bus_alloc_gas(sc->cpu_dev, &cx_ptr->res_type, &cpu_rid, &gas,
-		&cx_ptr->p_lvlx);
-	    if (cx_ptr->p_lvlx != NULL) {
-		cpu_rid++;
-		cx_ptr->type = ACPI_STATE_C2;
-		cx_ptr->trans_lat = AcpiGbl_FADT->Plvl2Lat;
-		cpu_non_c3 = 1;
-		cx_ptr++;
-		sc->cpu_cx_count++;
-	    }
-	}
-	if (sc->cpu_p_blk_len < 6)
-	    goto done;
+    /* Use initial sleep value of 1 sec. to start with lowest idle state. */
+    sc->cpu_prev_sleep = 1000000;
 
-	/* Validate and allocate resources for C3 (P_LVL3). */
-	if (AcpiGbl_FADT->Plvl3Lat <= 1000 &&
-	    (cpu_quirks & CPU_QUIRK_NO_C3) == 0) {
-	    gas.Address = sc->cpu_p_blk + 5;
-	    acpi_bus_alloc_gas(sc->cpu_dev, &cx_ptr->res_type, &cpu_rid, &gas,
-		&cx_ptr->p_lvlx);
-	    if (cx_ptr->p_lvlx != NULL) {
-		cpu_rid++;
-		cx_ptr->type = ACPI_STATE_C3;
-		cx_ptr->trans_lat = AcpiGbl_FADT->Plvl3Lat;
-		cx_ptr++;
-		sc->cpu_cx_count++;
-	    }
+    /* C1 has been required since just after ACPI 1.0 */
+    cx_ptr->type = ACPI_STATE_C1;
+    cx_ptr->trans_lat = 0;
+    cx_ptr++;
+    sc->cpu_cx_count++;
+
+    /* 
+     * The spec says P_BLK must be 6 bytes long.  However, some systems
+     * use it to indicate a fractional set of features present so we
+     * take 5 as C2.  Some may also have a value of 7 to indicate
+     * another C3 but most use _CST for this (as required) and having
+     * "only" C1-C3 is not a hardship.
+     */
+    if (sc->cpu_p_blk_len < 5)
+	return; 
+
+    /* Validate and allocate resources for C2 (P_LVL2). */
+    gas.SpaceId = ACPI_ADR_SPACE_SYSTEM_IO;
+    gas.BitWidth = 8;
+    if (AcpiGbl_FADT.C2Latency <= 100) {
+	gas.Address = sc->cpu_p_blk + 4;
+	acpi_bus_alloc_gas(sc->cpu_dev, &cx_ptr->res_type, &sc->cpu_rid,
+	    &gas, &cx_ptr->p_lvlx, RF_SHAREABLE);
+	if (cx_ptr->p_lvlx != NULL) {
+	    sc->cpu_rid++;
+	    cx_ptr->type = ACPI_STATE_C2;
+	    cx_ptr->trans_lat = AcpiGbl_FADT.C2Latency;
+	    cx_ptr++;
+	    sc->cpu_cx_count++;
 	}
     }
+    if (sc->cpu_p_blk_len < 6)
+	return;
 
-done:
-    /* If no valid registers were found, don't attach. */
-    if (sc->cpu_cx_count == 0)
-	return (ENXIO);
-
-    /* Use initial sleep value of 1 sec. to start with lowest idle state. */
-    sc->cpu_prev_sleep = 1000000;
+    /* Validate and allocate resources for C3 (P_LVL3). */
+    if (AcpiGbl_FADT.C3Latency <= 1000) {
+	gas.Address = sc->cpu_p_blk + 5;
+	acpi_bus_alloc_gas(sc->cpu_dev, &cx_ptr->res_type, &sc->cpu_rid, &gas,
+	    &cx_ptr->p_lvlx, RF_SHAREABLE);
+	if (cx_ptr->p_lvlx != NULL) {
+	    sc->cpu_rid++;
+	    cx_ptr->type = ACPI_STATE_C3;
+	    cx_ptr->trans_lat = AcpiGbl_FADT.C3Latency;
+	    cx_ptr++;
+	    sc->cpu_cx_count++;
+	}
+    }
 
-    return (0);
+    /* Update the largest cx_count seen so far */
+    if (sc->cpu_cx_count > cpu_cx_count)
+	cpu_cx_count = sc->cpu_cx_count;
 }
 
 /*
@@ -576,12 +635,12 @@
     /* _CST is a package with a count and at least one Cx package. */
     top = (ACPI_OBJECT *)buf.Pointer;
     if (!ACPI_PKG_VALID(top, 2) || acpi_PkgInt32(top, 0, &count) != 0) {
-	device_printf(sc->cpu_dev, "Invalid _CST package\n");
+	device_printf(sc->cpu_dev, "invalid _CST package\n");
 	AcpiOsFree(buf.Pointer);
 	return (ENXIO);
     }
     if (count != top->Package.Count - 1) {
-	device_printf(sc->cpu_dev, "Invalid _CST state count (%d != %d)\n",
+	device_printf(sc->cpu_dev, "invalid _CST state count (%d != %d)\n",
 	       count, top->Package.Count - 1);
 	count = top->Package.Count - 1;
     }
@@ -607,7 +666,7 @@
 	/* Validate the state to see if we should use it. */
 	switch (cx_ptr->type) {
 	case ACPI_STATE_C1:
-	    cpu_non_c3 = i;
+	    sc->cpu_non_c3 = i;
 	    cx_ptr++;
 	    sc->cpu_cx_count++;
 	    continue;
@@ -618,7 +677,7 @@
 				 device_get_unit(sc->cpu_dev), i));
 		continue;
 	    }
-	    cpu_non_c3 = i;
+	    sc->cpu_non_c3 = i;
 	    break;
 	case ACPI_STATE_C3:
 	default:
@@ -642,10 +701,10 @@
 #endif
 
 	/* Allocate the control register for C2 or C3. */
-	acpi_PkgGas(sc->cpu_dev, pkg, 0, &cx_ptr->res_type, &cpu_rid,
-	    &cx_ptr->p_lvlx);
+	acpi_PkgGas(sc->cpu_dev, pkg, 0, &cx_ptr->res_type, &sc->cpu_rid,
+	    &cx_ptr->p_lvlx, RF_SHAREABLE);
 	if (cx_ptr->p_lvlx) {
-	    cpu_rid++;
+	    sc->cpu_rid++;
 	    ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 			     "acpi_cpu%d: Got C%d - %d latency\n",
 			     device_get_unit(sc->cpu_dev), cx_ptr->type,
@@ -666,81 +725,119 @@
 acpi_cpu_startup(void *arg)
 {
     struct acpi_cpu_softc *sc;
-    int count, i;
+    int i;
 
     /* Get set of CPU devices */
     devclass_get_devices(acpi_cpu_devclass, &cpu_devices, &cpu_ndevices);
 
-    /* Check for quirks via the first CPU device. */
-    sc = device_get_softc(cpu_devices[0]);
-    acpi_cpu_quirks(sc);
-
     /*
-     * Make sure all the processors' Cx counts match.  We should probably
-     * also check the contents of each.  However, no known systems have
-     * non-matching Cx counts so we'll deal with this later.
+     * Setup any quirks that might necessary now that we have probed
+     * all the CPUs
      */
-    count = MAX_CX_STATES;
+    acpi_cpu_quirks();
+
+    cpu_cx_count = 0;
+    if (cpu_cx_generic) {
+	/*
+	 * We are using generic Cx mode, probe for available Cx states
+	 * for all processors.
+	 */
+	for (i = 0; i < cpu_ndevices; i++) {
+	    sc = device_get_softc(cpu_devices[i]);
+	    acpi_cpu_generic_cx_probe(sc);
+	}
+
+	/*
+	 * Find the highest Cx state common to all CPUs
+	 * in the system, taking quirks into account.
+	 */
+	for (i = 0; i < cpu_ndevices; i++) {
+	    sc = device_get_softc(cpu_devices[i]);
+	    if (sc->cpu_cx_count < cpu_cx_count)
+		cpu_cx_count = sc->cpu_cx_count;
+	}
+    } else {
+	/*
+	 * We are using _CST mode, remove C3 state if necessary.
+	 * Update the largest Cx state supported in the global cpu_cx_count.
+	 * It will be used in the global Cx sysctl handler.
+	 * As we now know for sure that we will be using _CST mode
+	 * install our notify handler.
+	 */
+	for (i = 0; i < cpu_ndevices; i++) {
+	    sc = device_get_softc(cpu_devices[i]);
+	    if (cpu_quirks && CPU_QUIRK_NO_C3) {
+		sc->cpu_cx_count = sc->cpu_non_c3 + 1;
+	    }
+	    if (sc->cpu_cx_count > cpu_cx_count)
+		cpu_cx_count = sc->cpu_cx_count;
+	    AcpiInstallNotifyHandler(sc->cpu_handle, ACPI_DEVICE_NOTIFY,
+		acpi_cpu_notify, sc);
+	}
+    }
+
+    /* Perform Cx final initialization. */
     for (i = 0; i < cpu_ndevices; i++) {
 	sc = device_get_softc(cpu_devices[i]);
-	count = min(sc->cpu_cx_count, count);
+	acpi_cpu_startup_cx(sc);
     }
-    cpu_cx_count = count;
 
-    /* Perform Cx final initialization. */
-    sc = device_get_softc(cpu_devices[0]);
-    if (cpu_cx_count > 0)
-	acpi_cpu_startup_cx();
+    /* Add a sysctl handler to handle global Cx lowest setting */
+    SYSCTL_ADD_PROC(&cpu_sysctl_ctx, SYSCTL_CHILDREN(cpu_sysctl_tree),
+	OID_AUTO, "cx_lowest", CTLTYPE_STRING | CTLFLAG_RW,
+	NULL, 0, acpi_cpu_global_cx_lowest_sysctl, "A",
+	"Global lowest Cx sleep state to use");
+
+    /* Take over idling from cpu_idle_default(). */
+    cpu_cx_lowest = 0;
+    cpu_disable_idle = FALSE;
+    cpu_idle_hook = acpi_cpu_idle;
 }
 
 static void
-acpi_cpu_startup_cx()
+acpi_cpu_startup_cx(struct acpi_cpu_softc *sc)
 {
-    struct acpi_cpu_softc *sc;
     struct sbuf sb;
     int i;
 
     /*
-     * Set up the list of Cx states, eliminating C3 states by truncating
-     * cpu_cx_count if quirks indicate C3 is not usable.
+     * Set up the list of Cx states
      */
-    sc = device_get_softc(cpu_devices[0]);
-    sbuf_new(&sb, cpu_cx_supported, sizeof(cpu_cx_supported), SBUF_FIXEDLEN);
-    for (i = 0; i < cpu_cx_count; i++) {
-	if ((cpu_quirks & CPU_QUIRK_NO_C3) == 0 ||
-	    sc->cpu_cx_states[i].type != ACPI_STATE_C3)
-	    sbuf_printf(&sb, "C%d/%d ", i + 1, sc->cpu_cx_states[i].trans_lat);
-	else
-	    cpu_cx_count = i;
+    sc->cpu_non_c3 = 0;
+    sbuf_new(&sb, sc->cpu_cx_supported, sizeof(sc->cpu_cx_supported),
+	SBUF_FIXEDLEN);
+    for (i = 0; i < sc->cpu_cx_count; i++) {
+	sbuf_printf(&sb, "C%d/%d ", i + 1, sc->cpu_cx_states[i].trans_lat);
+	if (sc->cpu_cx_states[i].type < ACPI_STATE_C3)
+	    sc->cpu_non_c3 = i;
     }
     sbuf_trim(&sb);
     sbuf_finish(&sb);
-    SYSCTL_ADD_STRING(&acpi_cpu_sysctl_ctx,
-		      SYSCTL_CHILDREN(acpi_cpu_sysctl_tree),
-		      OID_AUTO, "cx_supported", CTLFLAG_RD, cpu_cx_supported,
-		      0, "Cx/microsecond values for supported Cx states");
-    SYSCTL_ADD_PROC(&acpi_cpu_sysctl_ctx,
-		    SYSCTL_CHILDREN(acpi_cpu_sysctl_tree),
+
+    SYSCTL_ADD_STRING(&sc->cpu_sysctl_ctx,
+		      SYSCTL_CHILDREN(device_get_sysctl_tree(sc->cpu_dev)),
+		      OID_AUTO, "cx_supported", CTLFLAG_RD,
+		      sc->cpu_cx_supported, 0,
+		      "Cx/microsecond values for supported Cx states");
+    SYSCTL_ADD_PROC(&sc->cpu_sysctl_ctx,
+		    SYSCTL_CHILDREN(device_get_sysctl_tree(sc->cpu_dev)),
 		    OID_AUTO, "cx_lowest", CTLTYPE_STRING | CTLFLAG_RW,
-		    NULL, 0, acpi_cpu_cx_lowest_sysctl, "A",
+		    (void *)sc, 0, acpi_cpu_cx_lowest_sysctl, "A",
 		    "lowest Cx sleep state to use");
-    SYSCTL_ADD_PROC(&acpi_cpu_sysctl_ctx,
-		    SYSCTL_CHILDREN(acpi_cpu_sysctl_tree),
+    SYSCTL_ADD_PROC(&sc->cpu_sysctl_ctx,
+		    SYSCTL_CHILDREN(device_get_sysctl_tree(sc->cpu_dev)),
 		    OID_AUTO, "cx_usage", CTLTYPE_STRING | CTLFLAG_RD,
-		    NULL, 0, acpi_cpu_usage_sysctl, "A",
+		    (void *)sc, 0, acpi_cpu_usage_sysctl, "A",
 		    "percent usage for each Cx state");
 
 #ifdef notyet
     /* Signal platform that we can handle _CST notification. */
-    if (cpu_cst_cnt != 0) {
+    if (!cpu_cx_generic && cpu_cst_cnt != 0) {
 	ACPI_LOCK(acpi);
 	AcpiOsWritePort(cpu_smi_cmd, cpu_cst_cnt, 8);
 	ACPI_UNLOCK(acpi);
     }
 #endif
-
-    /* Take over idling from cpu_idle_default(). */
-    cpu_idle_hook = acpi_cpu_idle;
 }
 
 /*
@@ -758,7 +855,7 @@
     int		bm_active, cx_next_idx, i;
 
     /* If disabled, return immediately. */
-    if (cpu_cx_count == 0) {
+    if (cpu_disable_idle) {
 	ACPI_ENABLE_IRQS();
 	return;
     }
@@ -779,28 +876,34 @@
      * find the lowest state that has a latency less than or equal to
      * the length of our last sleep.
      */
-    cx_next_idx = cpu_cx_lowest;
+    cx_next_idx = sc->cpu_cx_lowest;
     if (sc->cpu_prev_sleep < 100) {
 	/*
 	 * If we sleep too short all the time, this system may not implement
 	 * C2/3 correctly (i.e. reads return immediately).  In this case,
 	 * back off and use the next higher level.
+	 * It seems that when you have a dual core cpu (like the Intel Core Duo)
+	 * that both cores will get out of C3 state as soon as one of them
+	 * requires it. This breaks the sleep detection logic as the sleep
+	 * counter is local to each cpu. Disable the sleep logic for now as a
+	 * workaround if there's more than one CPU. The right fix would probably
+	 * be to add quirks for system that don't really support C3 state.
 	 */
-	if (sc->cpu_prev_sleep <= 1) {
-	    cpu_short_slp++;
-	    if (cpu_short_slp == 1000 && cpu_cx_lowest != 0) {
-		if (cpu_non_c3 == cpu_cx_lowest && cpu_non_c3 != 0)
-		    cpu_non_c3--;
-		cpu_cx_lowest--;
-		cpu_short_slp = 0;
+	if (mp_ncpus < 2 && sc->cpu_prev_sleep <= 1) {
+	    sc->cpu_short_slp++;
+	    if (sc->cpu_short_slp == 1000 && sc->cpu_cx_lowest != 0) {
+		if (sc->cpu_non_c3 == sc->cpu_cx_lowest && sc->cpu_non_c3 != 0)
+		    sc->cpu_non_c3--;
+		sc->cpu_cx_lowest--;
+		sc->cpu_short_slp = 0;
 		device_printf(sc->cpu_dev,
 		    "too many short sleeps, backing off to C%d\n",
-		    cpu_cx_lowest + 1);
+		    sc->cpu_cx_lowest + 1);
 	    }
 	} else
-	    cpu_short_slp = 0;
+	    sc->cpu_short_slp = 0;
 
-	for (i = cpu_cx_lowest; i >= 0; i--)
+	for (i = sc->cpu_cx_lowest; i >= 0; i--)
 	    if (sc->cpu_cx_states[i].trans_lat <= sc->cpu_prev_sleep) {
 		cx_next_idx = i;
 		break;
@@ -814,18 +917,16 @@
      * time if USB is loaded.
      */
     if ((cpu_quirks & CPU_QUIRK_NO_BM_CTRL) == 0) {
-	AcpiGetRegister(ACPI_BITREG_BUS_MASTER_STATUS, &bm_active,
-	    ACPI_MTX_DO_NOT_LOCK);
+	AcpiGetRegister(ACPI_BITREG_BUS_MASTER_STATUS, &bm_active);
 	if (bm_active != 0) {
-	    AcpiSetRegister(ACPI_BITREG_BUS_MASTER_STATUS, 1,
-		ACPI_MTX_DO_NOT_LOCK);
-	    cx_next_idx = min(cx_next_idx, cpu_non_c3);
+	    AcpiSetRegister(ACPI_BITREG_BUS_MASTER_STATUS, 1);
+	    cx_next_idx = min(cx_next_idx, sc->cpu_non_c3);
 	}
     }
 
     /* Select the next state and update statistics. */
     cx_next = &sc->cpu_cx_states[cx_next_idx];
-    cpu_cx_stats[cx_next_idx]++;
+    sc->cpu_cx_stats[cx_next_idx]++;
     KASSERT(cx_next->type != ACPI_STATE_C0, ("acpi_cpu_idle: C0 sleep"));
 
     /*
@@ -845,9 +946,8 @@
      */
     if (cx_next->type == ACPI_STATE_C3) {
 	if ((cpu_quirks & CPU_QUIRK_NO_BM_CTRL) == 0) {
-	    AcpiSetRegister(ACPI_BITREG_ARB_DISABLE, 1, ACPI_MTX_DO_NOT_LOCK);
-	    AcpiSetRegister(ACPI_BITREG_BUS_MASTER_RLD, 1,
-		ACPI_MTX_DO_NOT_LOCK);
+	    AcpiSetRegister(ACPI_BITREG_ARB_DISABLE, 1);
+	    AcpiSetRegister(ACPI_BITREG_BUS_MASTER_RLD, 1);
 	} else
 	    ACPI_FLUSH_CPU_CACHE();
     }
@@ -858,7 +958,7 @@
      * get the time very close to the CPU start/stop clock logic, this
      * is the only reliable time source.
      */
-    AcpiHwLowLevelRead(32, &start_time, &AcpiGbl_FADT->XPmTmrBlk);
+    AcpiHwLowLevelRead(32, &start_time, &AcpiGbl_FADT.XPmTimerBlock);
     CPU_GET_REG(cx_next->p_lvlx, 1);
 
     /*
@@ -867,14 +967,14 @@
      * the processor has stopped.  Doing it again provides enough
      * margin that we are certain to have a correct value.
      */
-    AcpiHwLowLevelRead(32, &end_time, &AcpiGbl_FADT->XPmTmrBlk);
-    AcpiHwLowLevelRead(32, &end_time, &AcpiGbl_FADT->XPmTmrBlk);
+    AcpiHwLowLevelRead(32, &end_time, &AcpiGbl_FADT.XPmTimerBlock);
+    AcpiHwLowLevelRead(32, &end_time, &AcpiGbl_FADT.XPmTimerBlock);
 
     /* Enable bus master arbitration and disable bus master wakeup. */
     if (cx_next->type == ACPI_STATE_C3 &&
 	(cpu_quirks & CPU_QUIRK_NO_BM_CTRL) == 0) {
-	AcpiSetRegister(ACPI_BITREG_ARB_DISABLE, 0, ACPI_MTX_DO_NOT_LOCK);
-	AcpiSetRegister(ACPI_BITREG_BUS_MASTER_RLD, 0, ACPI_MTX_DO_NOT_LOCK);
+	AcpiSetRegister(ACPI_BITREG_ARB_DISABLE, 0);
+	AcpiSetRegister(ACPI_BITREG_BUS_MASTER_RLD, 0);
     }
     ACPI_ENABLE_IRQS();
 
@@ -901,16 +1001,41 @@
 }
 
 static int
-acpi_cpu_quirks(struct acpi_cpu_softc *sc)
+acpi_cpu_quirks(void)
 {
     device_t acpi_dev;
 
+    ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
+
     /*
-     * C3 on multiple CPUs requires using the expensive flush cache
-     * instruction.
+     * Bus mastering arbitration control is needed to keep caches coherent
+     * while sleeping in C3.  If it's not present but a working flush cache
+     * instruction is present, flush the caches before entering C3 instead.
+     * Otherwise, just disable C3 completely.
      */
-    if (mp_ncpus > 1)
+    if (AcpiGbl_FADT.Pm2ControlBlock == 0 ||
+	AcpiGbl_FADT.Pm2ControlLength == 0) {
+	if ((AcpiGbl_FADT.Flags & ACPI_FADT_WBINVD) &&
+	    (AcpiGbl_FADT.Flags & ACPI_FADT_WBINVD_FLUSH) == 0) {
+	    cpu_quirks |= CPU_QUIRK_NO_BM_CTRL;
+	    ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+		"acpi_cpu: no BM control, using flush cache method\n"));
+	} else {
+	    cpu_quirks |= CPU_QUIRK_NO_C3;
+	    ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+		"acpi_cpu: no BM control, C3 not available\n"));
+	}
+    }
+
+    /*
+     * If we are using generic Cx mode, C3 on multiple CPUs requires using
+     * the expensive flush cache instruction.
+     */
+    if (cpu_cx_generic && mp_ncpus > 1) {
 	cpu_quirks |= CPU_QUIRK_NO_BM_CTRL;
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+	    "acpi_cpu: SMP, using flush cache mode for C3\n"));
+    }
 
     /* Look for various quirks of the PIIX4 part. */
     acpi_dev = pci_find_device(PCI_VENDOR_INTEL, PCI_DEVICE_82371AB_3);
@@ -931,6 +1056,8 @@
 	case PCI_REVISION_4E:
 	case PCI_REVISION_4M:
 	    cpu_quirks |= CPU_QUIRK_NO_C3;
+	    ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+		"acpi_cpu: working around PIIX4 bug, disabling C3\n"));
 	    break;
 	default:
 	    break;
@@ -943,18 +1070,20 @@
 static int
 acpi_cpu_usage_sysctl(SYSCTL_HANDLER_ARGS)
 {
+    struct acpi_cpu_softc *sc;
     struct sbuf	 sb;
     char	 buf[128];
     int		 i;
     uintmax_t	 fract, sum, whole;
 
+    sc = (struct acpi_cpu_softc *) arg1;
     sum = 0;
-    for (i = 0; i < cpu_cx_count; i++)
-	sum += cpu_cx_stats[i];
+    for (i = 0; i < sc->cpu_cx_count; i++)
+	sum += sc->cpu_cx_stats[i];
     sbuf_new(&sb, buf, sizeof(buf), SBUF_FIXEDLEN);
-    for (i = 0; i < cpu_cx_count; i++) {
+    for (i = 0; i < sc->cpu_cx_count; i++) {
 	if (sum > 0) {
-	    whole = (uintmax_t)cpu_cx_stats[i] * 100;
+	    whole = (uintmax_t)sc->cpu_cx_stats[i] * 100;
 	    fract = (whole % sum) * 100;
 	    sbuf_printf(&sb, "%u.%02u%% ", (u_int)(whole / sum),
 		(u_int)(fract / sum));
@@ -970,37 +1099,76 @@
 }
 
 static int
+acpi_cpu_set_cx_lowest(struct acpi_cpu_softc *sc, int val)
+{
+    int i;
+
+    ACPI_SERIAL_ASSERT(cpu);
+    sc->cpu_cx_lowest = val;
+
+    /* If not disabling, cache the new lowest non-C3 state. */
+    sc->cpu_non_c3 = 0;
+    for (i = sc->cpu_cx_lowest; i >= 0; i--) {
+	if (sc->cpu_cx_states[i].type < ACPI_STATE_C3) {
+	    sc->cpu_non_c3 = i;
+	    break;
+	}
+    }
+
+    /* Reset the statistics counters. */
+    bzero(sc->cpu_cx_stats, sizeof(sc->cpu_cx_stats));
+    return (0);
+}
+
+static int
 acpi_cpu_cx_lowest_sysctl(SYSCTL_HANDLER_ARGS)
 {
     struct	 acpi_cpu_softc *sc;
     char	 state[8];
-    int		 val, error, i;
+    int		 val, error;
 
-    sc = device_get_softc(cpu_devices[0]);
-    snprintf(state, sizeof(state), "C%d", cpu_cx_lowest + 1);
+    sc = (struct acpi_cpu_softc *) arg1;
+    snprintf(state, sizeof(state), "C%d", sc->cpu_cx_lowest + 1);
     error = sysctl_handle_string(oidp, state, sizeof(state), req);
     if (error != 0 || req->newptr == NULL)
 	return (error);
     if (strlen(state) < 2 || toupper(state[0]) != 'C')
 	return (EINVAL);
     val = (int) strtol(state + 1, NULL, 10) - 1;
-    if (val < 0 || val > cpu_cx_count - 1)
+    if (val < 0 || val > sc->cpu_cx_count - 1)
 	return (EINVAL);
 
     ACPI_SERIAL_BEGIN(cpu);
+    acpi_cpu_set_cx_lowest(sc, val);
+    ACPI_SERIAL_END(cpu);
+
+    return (0);
+}
+
+static int
+acpi_cpu_global_cx_lowest_sysctl(SYSCTL_HANDLER_ARGS)
+{
+    struct	acpi_cpu_softc *sc;
+    char	state[8];
+    int		val, error, i;
+
+    snprintf(state, sizeof(state), "C%d", cpu_cx_lowest + 1);
+    error = sysctl_handle_string(oidp, state, sizeof(state), req);
+    if (error != 0 || req->newptr == NULL)
+	return (error);
+    if (strlen(state) < 2 || toupper(state[0]) != 'C')
+	return (EINVAL);
+    val = (int) strtol(state + 1, NULL, 10) - 1;
+    if (val < 0 || val > cpu_cx_count - 1)
+	return (EINVAL);
     cpu_cx_lowest = val;
 
-    /* If not disabling, cache the new lowest non-C3 state. */
-    cpu_non_c3 = 0;
-    for (i = cpu_cx_lowest; i >= 0; i--) {
-	if (sc->cpu_cx_states[i].type < ACPI_STATE_C3) {
-	    cpu_non_c3 = i;
-	    break;
-	}
+    /* Update the new lowest useable Cx state for all CPUs. */
+    ACPI_SERIAL_BEGIN(cpu);
+    for (i = 0; i < cpu_ndevices; i++) {
+	sc = device_get_softc(cpu_devices[i]);
+	acpi_cpu_set_cx_lowest(sc, val);
     }
-
-    /* Reset the statistics counters. */
-    bzero(cpu_cx_stats, sizeof(cpu_cx_stats));
     ACPI_SERIAL_END(cpu);
 
     return (0);
Index: acpiio.h
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/acpiio.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/dev/acpica/acpiio.h -L sys/dev/acpica/acpiio.h -u -r1.1.1.1 -r1.2
--- sys/dev/acpica/acpiio.h
+++ sys/dev/acpica/acpiio.h
@@ -24,7 +24,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/sys/dev/acpica/acpiio.h,v 1.14.2.2 2005/11/05 23:55:56 njl Exp $
+ * $FreeBSD: src/sys/dev/acpica/acpiio.h,v 1.17 2007/06/21 22:50:37 njl Exp $
  */
 
 #ifndef _ACPIIO_H_
@@ -33,7 +33,13 @@
 /*
  * Core ACPI subsystem ioctls
  */
-#define ACPIIO_SETSLPSTATE	_IOW('P', 3, int)
+#define ACPIIO_SETSLPSTATE	_IOW('P', 3, int) /* DEPRECATED */
+
+/* Request S1-5 sleep state. User is notified and then sleep proceeds. */
+#define ACPIIO_REQSLPSTATE	_IOW('P', 4, int)
+
+/* Allow suspend to continue (0) or abort it (errno). */
+#define ACPIIO_ACKSLPSTATE	_IOW('P', 5, int)
 
 struct acpi_battinfo {
     int	 cap;				/* percent */
Index: acpi_thermal.c
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/acpi_thermal.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/dev/acpica/acpi_thermal.c -L sys/dev/acpica/acpi_thermal.c -u -r1.1.1.1 -r1.2
--- sys/dev/acpica/acpi_thermal.c
+++ sys/dev/acpica/acpi_thermal.c
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_thermal.c,v 1.53.2.3 2005/11/07 09:53:23 obrien Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_thermal.c,v 1.64.4.1 2008/01/07 21:26:38 jhb Exp $");
 
 #include "opt_acpi.h"
 #include <sys/param.h>
@@ -53,7 +53,7 @@
 ACPI_MODULE_NAME("THERMAL")
 
 #define TZ_ZEROC	2732
-#define TZ_KELVTOC(x)	(((x) - TZ_ZEROC) / 10), (((x) - TZ_ZEROC) % 10)
+#define TZ_KELVTOC(x)	(((x) - TZ_ZEROC) / 10), abs(((x) - TZ_ZEROC) % 10)
 
 #define TZ_NOTIFY_TEMPERATURE	0x80 /* Temperature changed. */
 #define TZ_NOTIFY_LEVELS	0x81 /* Cooling levels changed. */
@@ -132,6 +132,7 @@
 static void	acpi_tz_sanity(struct acpi_tz_softc *sc, int *val, char *what);
 static int	acpi_tz_active_sysctl(SYSCTL_HANDLER_ARGS);
 static int	acpi_tz_cooling_sysctl(SYSCTL_HANDLER_ARGS);
+static int	acpi_tz_temp_sysctl(SYSCTL_HANDLER_ARGS);
 static void	acpi_tz_notify_handler(ACPI_HANDLE h, UINT32 notify,
 				       void *context);
 static void	acpi_tz_signal(struct acpi_tz_softc *sc, int flags);
@@ -163,8 +164,9 @@
 static struct sysctl_oid	*acpi_tz_sysctl_tree;
 
 /* Minimum cooling run time */
-static int			acpi_tz_min_runtime = 0;
+static int			acpi_tz_min_runtime;
 static int			acpi_tz_polling_rate = TZ_POLLRATE;
+static int			acpi_tz_override;
 
 /* Timezone polling thread */
 static struct proc		*acpi_tz_proc;
@@ -242,13 +244,17 @@
 			      OID_AUTO, "thermal", CTLFLAG_RD, 0, "");
 	SYSCTL_ADD_INT(&acpi_tz_sysctl_ctx,
 		       SYSCTL_CHILDREN(acpi_tz_sysctl_tree),
-		       OID_AUTO, "min_runtime", CTLFLAG_RD | CTLFLAG_RW,
+		       OID_AUTO, "min_runtime", CTLFLAG_RW,
 		       &acpi_tz_min_runtime, 0,
 		       "minimum cooling run time in sec");
 	SYSCTL_ADD_INT(&acpi_tz_sysctl_ctx,
 		       SYSCTL_CHILDREN(acpi_tz_sysctl_tree),
-		       OID_AUTO, "polling_rate", CTLFLAG_RD | CTLFLAG_RW,
+		       OID_AUTO, "polling_rate", CTLFLAG_RW,
 		       &acpi_tz_polling_rate, 0, "monitor polling rate");
+	SYSCTL_ADD_INT(&acpi_tz_sysctl_ctx,
+		       SYSCTL_CHILDREN(acpi_tz_sysctl_tree), OID_AUTO,
+		       "user_override", CTLFLAG_RW, &acpi_tz_override, 0,
+		       "allow override of thermal settings");
     }
     sysctl_ctx_init(&sc->tz_sysctl_ctx);
     sprintf(oidname, "tz%d", device_get_unit(dev));
@@ -261,23 +267,29 @@
 		      "current thermal zone temperature");
     SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
 		    OID_AUTO, "active", CTLTYPE_INT | CTLFLAG_RW,
-		    sc, 0, acpi_tz_active_sysctl, "I", "");
+		    sc, 0, acpi_tz_active_sysctl, "I", "cooling is active");
     SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
 		    OID_AUTO, "passive_cooling", CTLTYPE_INT | CTLFLAG_RW,
-		    sc, 0, acpi_tz_cooling_sysctl, "I", "");
+		    sc, 0, acpi_tz_cooling_sysctl, "I",
+		    "enable passive (speed reduction) cooling");
 
     SYSCTL_ADD_INT(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
 		   OID_AUTO, "thermal_flags", CTLFLAG_RD,
 		   &sc->tz_thflags, 0, "thermal zone flags");
-    SYSCTL_ADD_OPAQUE(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
-		      OID_AUTO, "_PSV", CTLFLAG_RD, &sc->tz_zone.psv,
-		      sizeof(sc->tz_zone.psv), "IK", "");
-    SYSCTL_ADD_OPAQUE(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
-		      OID_AUTO, "_HOT", CTLFLAG_RD, &sc->tz_zone.hot,
-		      sizeof(sc->tz_zone.hot), "IK", "");
-    SYSCTL_ADD_OPAQUE(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
-		      OID_AUTO, "_CRT", CTLFLAG_RD, &sc->tz_zone.crt,
-		      sizeof(sc->tz_zone.crt), "IK", "");
+    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
+		    OID_AUTO, "_PSV", CTLTYPE_INT | CTLFLAG_RW,
+		    sc, offsetof(struct acpi_tz_softc, tz_zone.psv),
+		    acpi_tz_temp_sysctl, "IK", "passive cooling temp setpoint");
+    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
+		    OID_AUTO, "_HOT", CTLTYPE_INT | CTLFLAG_RW,
+		    sc, offsetof(struct acpi_tz_softc, tz_zone.hot),
+		    acpi_tz_temp_sysctl, "IK",
+		    "too hot temp setpoint (suspend now)");
+    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
+		    OID_AUTO, "_CRT", CTLTYPE_INT | CTLFLAG_RW,
+		    sc, offsetof(struct acpi_tz_softc, tz_zone.crt),
+		    acpi_tz_temp_sysctl, "IK",
+		    "critical temp setpoint (shutdown now)");
     SYSCTL_ADD_OPAQUE(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
 		      OID_AUTO, "_ACx", CTLFLAG_RD, &sc->tz_zone.ac,
 		      sizeof(sc->tz_zone.ac), "IK", "");
@@ -422,10 +434,12 @@
 {
     int		temp;
     ACPI_STATUS	status;
+    static char	*tmp_name = "_TMP";
 
     ACPI_FUNCTION_NAME ("acpi_tz_get_temperature");
 
-    status = acpi_GetInteger(sc->tz_handle, "_TMP", &temp);
+    /* Evaluate the thermal zone's _TMP method. */
+    status = acpi_GetInteger(sc->tz_handle, tmp_name, &temp);
     if (ACPI_FAILURE(status)) {
 	ACPI_VPRINT(sc->tz_dev, acpi_device_get_parent_softc(sc->tz_dev),
 	    "error fetching current temperature -- %s\n",
@@ -433,6 +447,11 @@
 	return (FALSE);
     }
 
+    /* Check it for validity. */
+    acpi_tz_sanity(sc, &temp, tmp_name);
+    if (temp == -1)
+	return (FALSE);
+
     ACPI_DEBUG_PRINT((ACPI_DB_VALUES, "got %d.%dC\n", TZ_KELVTOC(temp)));
     sc->tz_temperature = temp;
     return (TRUE);
@@ -634,12 +653,12 @@
 
 /*
  * Sanity-check a temperature value.  Assume that setpoints
- * should be between 0C and 150C.
+ * should be between 0C and 200C.
  */
 static void
 acpi_tz_sanity(struct acpi_tz_softc *sc, int *val, char *what)
 {
-    if (*val != -1 && (*val < TZ_ZEROC || *val > TZ_ZEROC + 1500)) {
+    if (*val != -1 && (*val < TZ_ZEROC || *val > TZ_ZEROC + 2000)) {
 	device_printf(sc->tz_dev, "%s value is absurd, ignored (%d.%dC)\n",
 		      what, TZ_KELVTOC(*val));
 	*val = -1;
@@ -700,6 +719,35 @@
     return (error);
 }
 
+static int
+acpi_tz_temp_sysctl(SYSCTL_HANDLER_ARGS)
+{
+    struct acpi_tz_softc	*sc;
+    int				temp, *temp_ptr;
+    int		 		error;
+
+    sc = oidp->oid_arg1;
+    temp_ptr = (int *)((uintptr_t)sc + oidp->oid_arg2);
+    temp = *temp_ptr;
+    error = sysctl_handle_int(oidp, &temp, 0, req);
+
+    /* Error or no new value */
+    if (error != 0 || req->newptr == NULL)
+	return (error);
+
+    /* Only allow changing settings if override is set. */
+    if (!acpi_tz_override)
+	return (EPERM);
+
+    /* Check user-supplied value for sanity. */
+    acpi_tz_sanity(sc, &temp, "user-supplied temp");
+    if (temp == -1)
+	return (EINVAL);
+
+    *temp_ptr = temp;
+    return (0);
+}
+
 static void
 acpi_tz_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context)
 {
@@ -826,7 +874,7 @@
 
     for (;;) {
 	/* If the number of devices has changed, re-evaluate. */
-	if (devclass_get_maxunit(acpi_tz_devclass) != devcount) {
+	if (devclass_get_count(acpi_tz_devclass) != devcount) {
 	    if (devs != NULL) {
 		free(devs, M_TEMP);
 		free(sc, M_TEMP);
Index: acpi_pcib_pci.c
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/acpi_pcib_pci.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/dev/acpica/acpi_pcib_pci.c -L sys/dev/acpica/acpi_pcib_pci.c -u -r1.1.1.1 -r1.2
--- sys/dev/acpica/acpi_pcib_pci.c
+++ sys/dev/acpica/acpi_pcib_pci.c
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_pcib_pci.c,v 1.12.2.1 2005/11/07 09:53:23 obrien Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_pcib_pci.c,v 1.17 2007/05/02 17:50:35 jhb Exp $");
 
 #include "opt_acpi.h"
 
@@ -93,16 +93,19 @@
     DEVMETHOD(pcib_read_config,		pcib_read_config),
     DEVMETHOD(pcib_write_config,	pcib_write_config),
     DEVMETHOD(pcib_route_interrupt,	acpi_pcib_pci_route_interrupt),
+    DEVMETHOD(pcib_alloc_msi,		pcib_alloc_msi),
+    DEVMETHOD(pcib_release_msi,		pcib_release_msi),
+    DEVMETHOD(pcib_alloc_msix,		pcib_alloc_msix),
+    DEVMETHOD(pcib_release_msix,	pcib_release_msix),
+    DEVMETHOD(pcib_map_msi,		pcib_map_msi),
 
     {0, 0}
 };
 
-static driver_t acpi_pcib_pci_driver = {
-    "pcib",
-    acpi_pcib_pci_methods,
-    sizeof(struct acpi_pcib_softc),
-};
+static devclass_t pcib_devclass;
 
+DEFINE_CLASS_0(pcib, acpi_pcib_pci_driver, acpi_pcib_pci_methods,
+    sizeof(struct acpi_pcib_softc));
 DRIVER_MODULE(acpi_pcib, pci, acpi_pcib_pci_driver, pcib_devclass, 0, 0);
 MODULE_DEPEND(acpi_pcib, acpi, 1, 1, 1);
 
Index: acpi_acad.c
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/acpi_acad.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/dev/acpica/acpi_acad.c -L sys/dev/acpica/acpi_acad.c -u -r1.1.1.1 -r1.2
--- sys/dev/acpica/acpi_acad.c
+++ sys/dev/acpica/acpi_acad.c
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_acad.c,v 1.33.2.2 2005/11/05 23:48:38 njl Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_acad.c,v 1.38 2007/03/22 18:16:40 jkim Exp $");
 
 #include "opt_acpi.h"
 #include <sys/param.h>
@@ -128,7 +128,7 @@
     case ACPI_NOTIFY_DEVICE_CHECK:
     case ACPI_POWERSOURCE_STAT_CHANGE:
 	/* Temporarily.  It is better to notify policy manager */
-	AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_acad_get_status, context);
+	AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_acad_get_status, context);
 	break;
     default:
 	device_printf(dev, "unknown notify %#x\n", notify);
@@ -181,7 +181,7 @@
      */
     AcpiInstallNotifyHandler(handle, ACPI_ALL_NOTIFY,
 			     acpi_acad_notify_handler, dev);
-    AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_acad_init_acline, dev);
+    AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_acad_init_acline, dev);
 
     return (0);
 }
Index: acpi_button.c
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/acpi_button.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/dev/acpica/acpi_button.c -L sys/dev/acpica/acpi_button.c -u -r1.1.1.1 -r1.2
--- sys/dev/acpica/acpi_button.c
+++ sys/dev/acpica/acpi_button.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_button.c,v 1.30.2.1 2005/11/07 09:53:22 obrien Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_button.c,v 1.32 2007/03/22 18:16:40 jkim Exp $");
 
 #include "opt_acpi.h"
 #include <sys/param.h>
@@ -248,12 +248,10 @@
     sc = (struct acpi_button_softc *)context;
     switch (notify) {
     case ACPI_NOTIFY_BUTTON_PRESSED_FOR_SLEEP:
-	AcpiOsQueueForExecution(OSD_PRIORITY_LO,
-				acpi_button_notify_sleep, sc);
+	AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_button_notify_sleep, sc);
 	break;   
     case ACPI_NOTIFY_BUTTON_PRESSED_FOR_WAKEUP:
-	AcpiOsQueueForExecution(OSD_PRIORITY_LO,
-				acpi_button_notify_wakeup, sc);
+	AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_button_notify_wakeup, sc);
 	break;   
     default:
 	device_printf(sc->button_dev, "unknown notify %#x\n", notify);
Index: acpi_smbat.c
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/acpi_smbat.c,v
retrieving revision 1.1.1.2
retrieving revision 1.2
diff -L sys/dev/acpica/acpi_smbat.c -L sys/dev/acpica/acpi_smbat.c -u -r1.1.1.2 -r1.2
--- sys/dev/acpica/acpi_smbat.c
+++ sys/dev/acpica/acpi_smbat.c
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_smbat.c,v 1.1.2.3 2006/01/16 09:13:53 bruno Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_smbat.c,v 1.5 2006/02/21 03:16:58 njl Exp $");
 
 #include "opt_acpi.h"
 #include <sys/param.h>
@@ -134,9 +134,7 @@
 static int
 acpi_smbat_shutdown(device_t dev)
 {
-	struct acpi_smbat_softc *sc;
 
-	sc = device_get_softc(dev);
 	acpi_battery_remove(dev);
 	return (0);
 }
Index: acpi_package.c
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/acpi_package.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/dev/acpica/acpi_package.c -L sys/dev/acpica/acpi_package.c -u -r1.1.1.1 -r1.2
--- sys/dev/acpica/acpi_package.c
+++ sys/dev/acpica/acpi_package.c
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_package.c,v 1.6.2.2 2005/11/07 09:53:22 obrien Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_package.c,v 1.9 2007/01/07 21:53:42 njl Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -104,7 +104,7 @@
 
 int
 acpi_PkgGas(device_t dev, ACPI_OBJECT *res, int idx, int *type, int *rid,
-    struct resource **dst)
+    struct resource **dst, u_int flags)
 {
     ACPI_GENERIC_ADDRESS gas;
     ACPI_OBJECT *obj;
@@ -116,7 +116,7 @@
 
     memcpy(&gas, obj->Buffer.Pointer + 3, sizeof(gas));
 
-    return (acpi_bus_alloc_gas(dev, type, rid, &gas, dst));
+    return (acpi_bus_alloc_gas(dev, type, rid, &gas, dst, flags));
 }
 
 ACPI_HANDLE
Index: acpi_ec.c
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/acpi_ec.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/dev/acpica/acpi_ec.c -L sys/dev/acpica/acpi_ec.c -u -r1.1.1.1 -r1.2
--- sys/dev/acpica/acpi_ec.c
+++ sys/dev/acpica/acpi_ec.c
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2003 Nate Lawson
+ * Copyright (c) 2003-2007 Nate Lawson
  * Copyright (c) 2000 Michael Smith
  * Copyright (c) 2000 BSDi
  * All rights reserved.
@@ -25,123 +25,15 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-/*-
- ******************************************************************************
- *
- * 1. Copyright Notice
- *
- * Some or all of this work - Copyright (c) 1999, Intel Corp.  All rights
- * reserved.
- *
- * 2. License
- *
- * 2.1. This is your license from Intel Corp. under its intellectual property
- * rights.  You may have additional license terms from the party that provided
- * you this software, covering your right to use that party's intellectual
- * property rights.
- *
- * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
- * copy of the source code appearing in this file ("Covered Code") an
- * irrevocable, perpetual, worldwide license under Intel's copyrights in the
- * base code distributed originally by Intel ("Original Intel Code") to copy,
- * make derivatives, distribute, use and display any portion of the Covered
- * Code in any form, with the right to sublicense such rights; and
- *
- * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
- * license (with the right to sublicense), under only those claims of Intel
- * patents that are infringed by the Original Intel Code, to make, use, sell,
- * offer to sell, and import the Covered Code and derivative works thereof
- * solely to the minimum extent necessary to exercise the above copyright
- * license, and in no event shall the patent license extend to any additions
- * to or modifications of the Original Intel Code.  No other license or right
- * is granted directly or by implication, estoppel or otherwise;
- *
- * The above copyright and patent license is granted only if the following
- * conditions are met:
- *
- * 3. Conditions 
- *
- * 3.1. Redistribution of Source with Rights to Further Distribute Source.  
- * Redistribution of source code of any substantial portion of the Covered
- * Code or modification with rights to further distribute source must include
- * the above Copyright Notice, the above License, this list of Conditions,
- * and the following Disclaimer and Export Compliance provision.  In addition,
- * Licensee must cause all Covered Code to which Licensee contributes to
- * contain a file documenting the changes Licensee made to create that Covered
- * Code and the date of any change.  Licensee must include in that file the
- * documentation of any changes made by any predecessor Licensee.  Licensee 
- * must include a prominent statement that the modification is derived,
- * directly or indirectly, from Original Intel Code.
- *
- * 3.2. Redistribution of Source with no Rights to Further Distribute Source.  
- * Redistribution of source code of any substantial portion of the Covered
- * Code or modification without rights to further distribute source must
- * include the following Disclaimer and Export Compliance provision in the
- * documentation and/or other materials provided with distribution.  In
- * addition, Licensee may not authorize further sublicense of source of any
- * portion of the Covered Code, and must include terms to the effect that the
- * license from Licensee to its licensee is limited to the intellectual
- * property embodied in the software Licensee provides to its licensee, and
- * not to intellectual property embodied in modifications its licensee may
- * make.
- *
- * 3.3. Redistribution of Executable. Redistribution in executable form of any
- * substantial portion of the Covered Code or modification must reproduce the
- * above Copyright Notice, and the following Disclaimer and Export Compliance
- * provision in the documentation and/or other materials provided with the
- * distribution.
- *
- * 3.4. Intel retains all right, title, and interest in and to the Original
- * Intel Code.
- *
- * 3.5. Neither the name Intel nor any other trademark owned or controlled by
- * Intel shall be used in advertising or otherwise to promote the sale, use or
- * other dealings in products derived from or relating to the Covered Code
- * without prior written authorization from Intel.
- *
- * 4. Disclaimer and Export Compliance
- *
- * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
- * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
- * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
- * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
- * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
- * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
- * PARTICULAR PURPOSE. 
- *
- * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
- * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
- * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
- * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
- * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
- * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
- * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
- * LIMITED REMEDY.
- *
- * 4.3. Licensee shall not export, either directly or indirectly, any of this
- * software or system incorporating such software without first obtaining any
- * required license or other approval from the U. S. Department of Commerce or
- * any other agency or department of the United States Government.  In the
- * event Licensee exports any such software from the United States or
- * re-exports any such software from a foreign destination, Licensee shall
- * ensure that the distribution and export/re-export of the software is in
- * compliance with all laws, regulations, orders, or other restrictions of the
- * U.S. Export Administration Regulations. Licensee agrees that neither it nor
- * any of its subsidiaries will export/re-export any technical data, process,
- * software, or service, directly or indirectly, to any country for which the
- * United States government or any agency thereof requires an export license,
- * other governmental approval, or letter of assurance, without first obtaining
- * such license, approval or letter.
- *
- *****************************************************************************/
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_ec.c,v 1.65.2.1 2005/11/07 09:53:22 obrien Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_ec.c,v 1.76.2.1 2007/11/08 21:21:27 njl Exp $");
 
 #include "opt_acpi.h"
 #include <sys/param.h>
 #include <sys/kernel.h>
 #include <sys/bus.h>
+#include <sys/lock.h>
 #include <sys/malloc.h>
 #include <sys/module.h>
 #include <sys/sx.h>
@@ -170,7 +62,7 @@
 #define EC_COMMAND_BURST_DISABLE	((EC_COMMAND) 0x83)
 #define EC_COMMAND_QUERY		((EC_COMMAND) 0x84)
 
-/* 
+/*
  * EC_STATUS:
  * ----------
  * The encoding of the EC status register is illustrated below.
@@ -187,15 +79,15 @@
  *  | | | +--------- Burst Mode Enabled?
  *  | | +----------- SCI Event?
  *  | +------------- SMI Event?
- *  +--------------- <Reserved>
+ *  +--------------- <reserved>
  *
  */
 typedef UINT8				EC_STATUS;
 
 #define EC_FLAG_OUTPUT_BUFFER		((EC_STATUS) 0x01)
 #define EC_FLAG_INPUT_BUFFER		((EC_STATUS) 0x02)
+#define EC_FLAG_DATA_IS_CMD		((EC_STATUS) 0x08)
 #define EC_FLAG_BURST_MODE		((EC_STATUS) 0x10)
-#define EC_FLAG_SCI			((EC_STATUS) 0x20)
 
 /*
  * EC_EVENT:
@@ -207,6 +99,10 @@
 #define EC_EVENT_OUTPUT_BUFFER_FULL	((EC_EVENT) 0x01)
 #define EC_EVENT_INPUT_BUFFER_EMPTY	((EC_EVENT) 0x02)
 #define EC_EVENT_SCI			((EC_EVENT) 0x20)
+#define EC_EVENT_SMI			((EC_EVENT) 0x40)
+
+/* Data byte returned after burst enable indicating it was successful. */
+#define EC_BURST_ACK			0x90
 
 /*
  * Register access primitives
@@ -223,16 +119,6 @@
 #define EC_SET_CSR(sc, v)						\
 	bus_space_write_1((sc)->ec_csr_tag, (sc)->ec_csr_handle, 0, (v))
 
-/* Embedded Controller Boot Resources Table (ECDT) */
-typedef struct {
-    ACPI_TABLE_HEADER		header;
-    ACPI_GENERIC_ADDRESS	control;
-    ACPI_GENERIC_ADDRESS	data;
-    UINT32			uid;
-    UINT8			gpe_bit;
-    char			ec_id[0];
-} ACPI_TABLE_ECDT;
-
 /* Additional params to pass from the probe routine */
 struct acpi_ec_params {
     int		glk;
@@ -242,7 +128,7 @@
 };
 
 /* Indicate that this device has already been probed via ECDT. */
-#define DEV_ECDT(x)		(acpi_get_magic(x) == (int)&acpi_ec_devclass)
+#define DEV_ECDT(x)	(acpi_get_magic(x) == (uintptr_t)&acpi_ec_devclass)
 
 /*
  * Driver softc.
@@ -253,8 +139,7 @@
     int			ec_uid;
     ACPI_HANDLE		ec_gpehandle;
     UINT8		ec_gpebit;
-    UINT8		ec_csrvalue;
-    
+
     int			ec_data_rid;
     struct resource	*ec_data_res;
     bus_space_tag_t	ec_data_tag;
@@ -267,6 +152,10 @@
 
     int			ec_glk;
     int			ec_glkhandle;
+    int			ec_burstactive;
+    int			ec_sci_pend;
+    u_int		ec_gencount;
+    int			ec_suspending;
 };
 
 /*
@@ -276,11 +165,11 @@
  */
 #define EC_LOCK_TIMEOUT	1000
 
-/* Default interval in microseconds for the status polling loop. */
-#define EC_POLL_DELAY	10
+/* Default delay in microseconds between each run of the status polling loop. */
+#define EC_POLL_DELAY	5
 
-/* Total time in ms spent in the poll loop waiting for a response. */
-#define EC_POLL_TIMEOUT	100
+/* Total time in ms spent waiting for a response from EC. */
+#define EC_TIMEOUT	750
 
 #define EVENT_READY(event, status)			\
 	(((event) == EC_EVENT_OUTPUT_BUFFER_FULL &&	\
@@ -288,46 +177,57 @@
 	 ((event) == EC_EVENT_INPUT_BUFFER_EMPTY && 	\
 	 ((status) & EC_FLAG_INPUT_BUFFER) == 0))
 
-static int	ec_poll_timeout = EC_POLL_TIMEOUT;
-TUNABLE_INT("hw.acpi.ec.poll_timeout", &ec_poll_timeout);
-
 ACPI_SERIAL_DECL(ec, "ACPI embedded controller");
 
-static __inline ACPI_STATUS
+SYSCTL_DECL(_debug_acpi);
+SYSCTL_NODE(_debug_acpi, OID_AUTO, ec, CTLFLAG_RD, NULL, "EC debugging");
+
+static int	ec_burst_mode;
+TUNABLE_INT("debug.acpi.ec.burst", &ec_burst_mode);
+SYSCTL_INT(_debug_acpi_ec, OID_AUTO, burst, CTLFLAG_RW, &ec_burst_mode, 0,
+    "Enable use of burst mode (faster for nearly all systems)");
+static int	ec_polled_mode;
+TUNABLE_INT("debug.acpi.ec.polled", &ec_polled_mode);
+SYSCTL_INT(_debug_acpi_ec, OID_AUTO, polled, CTLFLAG_RW, &ec_polled_mode, 0,
+    "Force use of polled mode (only if interrupt mode doesn't work)");
+static int	ec_timeout = EC_TIMEOUT;
+TUNABLE_INT("debug.acpi.ec.timeout", &ec_timeout);
+SYSCTL_INT(_debug_acpi_ec, OID_AUTO, timeout, CTLFLAG_RW, &ec_timeout,
+    EC_TIMEOUT, "Total time spent waiting for a response (poll+sleep)");
+
+static ACPI_STATUS
 EcLock(struct acpi_ec_softc *sc)
 {
     ACPI_STATUS	status;
 
-    /* Always acquire the exclusive lock. */
+    /* If _GLK is non-zero, acquire the global lock. */
     status = AE_OK;
-    ACPI_SERIAL_BEGIN(ec);
-
-    /* If _GLK is non-zero, also acquire the global lock. */
     if (sc->ec_glk) {
 	status = AcpiAcquireGlobalLock(EC_LOCK_TIMEOUT, &sc->ec_glkhandle);
 	if (ACPI_FAILURE(status))
-	    ACPI_SERIAL_END(ec);
+	    return (status);
     }
-
+    ACPI_SERIAL_BEGIN(ec);
     return (status);
 }
 
-static __inline void
+static void
 EcUnlock(struct acpi_ec_softc *sc)
 {
+    ACPI_SERIAL_END(ec);
     if (sc->ec_glk)
 	AcpiReleaseGlobalLock(sc->ec_glkhandle);
-    ACPI_SERIAL_END(ec);
 }
 
 static uint32_t		EcGpeHandler(void *Context);
-static ACPI_STATUS	EcSpaceSetup(ACPI_HANDLE Region, UINT32 Function, 
+static ACPI_STATUS	EcSpaceSetup(ACPI_HANDLE Region, UINT32 Function,
 				void *Context, void **return_Context);
 static ACPI_STATUS	EcSpaceHandler(UINT32 Function,
 				ACPI_PHYSICAL_ADDRESS Address,
 				UINT32 width, ACPI_INTEGER *Value,
 				void *Context, void *RegionContext);
-static ACPI_STATUS	EcWaitEvent(struct acpi_ec_softc *sc, EC_EVENT Event);
+static ACPI_STATUS	EcWaitEvent(struct acpi_ec_softc *sc, EC_EVENT Event,
+				u_int gen_count);
 static ACPI_STATUS	EcCommand(struct acpi_ec_softc *sc, EC_COMMAND cmd);
 static ACPI_STATUS	EcRead(struct acpi_ec_softc *sc, UINT8 Address,
 				UINT8 *Data);
@@ -335,6 +235,8 @@
 				UINT8 *Data);
 static int		acpi_ec_probe(device_t dev);
 static int		acpi_ec_attach(device_t dev);
+static int		acpi_ec_suspend(device_t dev);
+static int		acpi_ec_resume(device_t dev);
 static int		acpi_ec_shutdown(device_t dev);
 static int		acpi_ec_read_method(device_t dev, u_int addr,
 				ACPI_INTEGER *val, int width);
@@ -345,6 +247,8 @@
     /* Device interface */
     DEVMETHOD(device_probe,	acpi_ec_probe),
     DEVMETHOD(device_attach,	acpi_ec_attach),
+    DEVMETHOD(device_suspend,	acpi_ec_suspend),
+    DEVMETHOD(device_resume,	acpi_ec_resume),
     DEVMETHOD(device_shutdown,	acpi_ec_shutdown),
 
     /* Embedded controller interface */
@@ -365,16 +269,17 @@
 MODULE_DEPEND(acpi_ec, acpi, 1, 1, 1);
 
 /*
- * Look for an ECDT and if we find one, set up default GPE and 
+ * Look for an ECDT and if we find one, set up default GPE and
  * space handlers to catch attempts to access EC space before
  * we have a real driver instance in place.
- * TODO: if people report invalid ECDTs, add a tunable to disable them.
+ *
+ * TODO: Some old Gateway laptops need us to fake up an ECDT or
+ * otherwise attach early so that _REG methods can run.
  */
 void
 acpi_ec_ecdt_probe(device_t parent)
 {
     ACPI_TABLE_ECDT *ecdt;
-    ACPI_TABLE_HEADER *hdr;
     ACPI_STATUS	     status;
     device_t	     child;
     ACPI_HANDLE	     h;
@@ -383,23 +288,22 @@
     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
 
     /* Find and validate the ECDT. */
-    status = AcpiGetFirmwareTable("ECDT", 1, ACPI_LOGICAL_ADDRESSING, &hdr);
-    ecdt = (ACPI_TABLE_ECDT *)hdr;
+    status = AcpiGetTable(ACPI_SIG_ECDT, 1, (ACPI_TABLE_HEADER **)&ecdt);
     if (ACPI_FAILURE(status) ||
-	ecdt->control.RegisterBitWidth != 8 ||
-	ecdt->data.RegisterBitWidth != 8) {
+	ecdt->Control.BitWidth != 8 ||
+	ecdt->Data.BitWidth != 8) {
 	return;
     }
 
     /* Create the child device with the given unit number. */
-    child = BUS_ADD_CHILD(parent, 0, "acpi_ec", ecdt->uid);
+    child = BUS_ADD_CHILD(parent, 0, "acpi_ec", ecdt->Uid);
     if (child == NULL) {
 	printf("%s: can't add child\n", __func__);
 	return;
     }
 
     /* Find and save the ACPI handle for this device. */
-    status = AcpiGetHandle(NULL, ecdt->ec_id, &h);
+    status = AcpiGetHandle(NULL, ecdt->Id, &h);
     if (ACPI_FAILURE(status)) {
 	device_delete_child(parent, child);
 	printf("%s: can't get handle\n", __func__);
@@ -408,9 +312,9 @@
     acpi_set_handle(child, h);
 
     /* Set the data and CSR register addresses. */
-    bus_set_resource(child, SYS_RES_IOPORT, 0, ecdt->data.Address,
+    bus_set_resource(child, SYS_RES_IOPORT, 0, ecdt->Data.Address,
 	/*count*/1);
-    bus_set_resource(child, SYS_RES_IOPORT, 1, ecdt->control.Address,
+    bus_set_resource(child, SYS_RES_IOPORT, 1, ecdt->Control.Address,
 	/*count*/1);
 
     /*
@@ -422,11 +326,11 @@
      */
     params = malloc(sizeof(struct acpi_ec_params), M_TEMP, M_WAITOK | M_ZERO);
     params->gpe_handle = NULL;
-    params->gpe_bit = ecdt->gpe_bit;
-    params->uid = ecdt->uid;
+    params->gpe_bit = ecdt->Gpe;
+    params->uid = ecdt->Uid;
     acpi_GetInteger(h, "_GLK", &params->glk);
     acpi_set_private(child, params);
-    acpi_set_magic(child, (int)&acpi_ec_devclass);
+    acpi_set_magic(child, (uintptr_t)&acpi_ec_devclass);
 
     /* Finish the attach process. */
     if (device_probe_and_attach(child) != 0)
@@ -564,6 +468,7 @@
     sc->ec_gpebit = params->gpe_bit;
     sc->ec_gpehandle = params->gpe_handle;
     sc->ec_uid = params->uid;
+    sc->ec_suspending = FALSE;
     free(params, M_TEMP);
 
     /* Attach bus resources for data and command/status ports. */
@@ -600,7 +505,7 @@
 	goto error;
     }
 
-    /* 
+    /*
      * Install address space handler
      */
     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "attaching address space handler\n"));
@@ -635,7 +540,7 @@
     AcpiRemoveAddressSpaceHandler(sc->ec_handle, ACPI_ADR_SPACE_EC,
 	EcSpaceHandler);
     if (sc->ec_csr_res)
-	bus_release_resource(sc->ec_dev, SYS_RES_IOPORT, sc->ec_csr_rid, 
+	bus_release_resource(sc->ec_dev, SYS_RES_IOPORT, sc->ec_csr_rid,
 			     sc->ec_csr_res);
     if (sc->ec_data_res)
 	bus_release_resource(sc->ec_dev, SYS_RES_IOPORT, sc->ec_data_rid,
@@ -644,6 +549,26 @@
 }
 
 static int
+acpi_ec_suspend(device_t dev)
+{
+    struct acpi_ec_softc	*sc;
+
+    sc = device_get_softc(dev);
+    sc->ec_suspending = TRUE;
+    return (0);
+}
+
+static int
+acpi_ec_resume(device_t dev)
+{
+    struct acpi_ec_softc	*sc;
+
+    sc = device_get_softc(dev);
+    sc->ec_suspending = FALSE;
+    return (0);
+}
+
+static int
 acpi_ec_shutdown(device_t dev)
 {
     struct acpi_ec_softc	*sc;
@@ -687,98 +612,94 @@
     struct acpi_ec_softc	*sc = (struct acpi_ec_softc *)Context;
     UINT8			Data;
     ACPI_STATUS			Status;
-    EC_STATUS			EcStatus;
     char			qxx[5];
 
     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
     KASSERT(Context != NULL, ("EcGpeQueryHandler called with NULL"));
 
+    /* Serialize user access with EcSpaceHandler(). */
     Status = EcLock(sc);
     if (ACPI_FAILURE(Status)) {
-	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
-		    "GpeQuery lock error: %s\n", AcpiFormatException(Status));
+	device_printf(sc->ec_dev, "GpeQuery lock error: %s\n",
+	    AcpiFormatException(Status));
 	return;
     }
 
     /*
-     * If the EC_SCI bit of the status register is not set, then pass
-     * it along to any potential waiters as it may be an IBE/OBF event.
-     */
-    EcStatus = EC_GET_CSR(sc);
-    if ((EcStatus & EC_EVENT_SCI) == 0) {
-	sc->ec_csrvalue = EcStatus;
-	wakeup(&sc->ec_csrvalue);
-	EcUnlock(sc);
-	goto re_enable;
-    }
-
-    /*
      * Send a query command to the EC to find out which _Qxx call it
      * wants to make.  This command clears the SCI bit and also the
-     * interrupt source since we are edge-triggered.
+     * interrupt source since we are edge-triggered.  To prevent the GPE
+     * that may arise from running the query from causing another query
+     * to be queued, we clear the pending flag only after running it.
      */
     Status = EcCommand(sc, EC_COMMAND_QUERY);
+    sc->ec_sci_pend = FALSE;
     if (ACPI_FAILURE(Status)) {
 	EcUnlock(sc);
-	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
-		    "GPE query failed - %s\n", AcpiFormatException(Status));
-	goto re_enable;
+	device_printf(sc->ec_dev, "GPE query failed: %s\n",
+	    AcpiFormatException(Status));
+	return;
     }
     Data = EC_GET_DATA(sc);
+
+    /*
+     * We have to unlock before running the _Qxx method below since that
+     * method may attempt to read/write from EC address space, causing
+     * recursive acquisition of the lock.
+     */
     EcUnlock(sc);
 
     /* Ignore the value for "no outstanding event". (13.3.5) */
+    CTR2(KTR_ACPI, "ec query ok,%s running _Q%02X", Data ? "" : " not", Data);
     if (Data == 0)
-	goto re_enable;
+	return;
 
     /* Evaluate _Qxx to respond to the controller. */
-    sprintf(qxx, "_Q%02x", Data);
+    snprintf(qxx, sizeof(qxx), "_Q%02X", Data);
     AcpiUtStrupr(qxx);
     Status = AcpiEvaluateObject(sc->ec_handle, qxx, NULL, NULL);
     if (ACPI_FAILURE(Status) && Status != AE_NOT_FOUND) {
-	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
-		    "evaluation of GPE query method %s failed - %s\n", 
-		    qxx, AcpiFormatException(Status));
+	device_printf(sc->ec_dev, "evaluation of query method %s failed: %s\n",
+	    qxx, AcpiFormatException(Status));
     }
-
-re_enable:
-    /* Re-enable the GPE event so we'll get future requests. */
-    Status = AcpiEnableGpe(sc->ec_gpehandle, sc->ec_gpebit, ACPI_NOT_ISR);
-    if (ACPI_FAILURE(Status))
-	printf("EcGpeQueryHandler: AcpiEnableEvent failed\n");
 }
 
 /*
- * Handle a GPE.  Currently we only handle SCI events as others must
- * be handled by polling in EcWaitEvent().  This is because some ECs
- * treat events as level when they should be edge-triggered.
+ * The GPE handler is called when IBE/OBF or SCI events occur.  We are
+ * called from an unknown lock context.
  */
 static uint32_t
 EcGpeHandler(void *Context)
 {
     struct acpi_ec_softc *sc = Context;
     ACPI_STATUS		       Status;
+    EC_STATUS		       EcStatus;
 
     KASSERT(Context != NULL, ("EcGpeHandler called with NULL"));
+    CTR0(KTR_ACPI, "ec gpe handler start");
 
     /*
-     * Disable further GPEs while we handle this one.  Since we are directly
-     * called by ACPI-CA and it may have unknown locks held, we specify the
-     * ACPI_ISR flag to keep it from acquiring any more mutexes (which could
-     * potentially sleep.)
+     * Notify EcWaitEvent() that the status register is now fresh.  If we
+     * didn't do this, it wouldn't be possible to distinguish an old IBE
+     * from a new one, for example when doing a write transaction (writing
+     * address and then data values.)
      */
-    AcpiDisableGpe(sc->ec_gpehandle, sc->ec_gpebit, ACPI_ISR);
+    atomic_add_int(&sc->ec_gencount, 1);
+    wakeup(&sc->ec_gencount);
 
-    /* Schedule the GPE query handler. */
-    Status = AcpiOsQueueForExecution(OSD_PRIORITY_GPE, EcGpeQueryHandler,
-		Context);
-    if (ACPI_FAILURE(Status)) {
-	printf("Queuing GPE query handler failed.\n");
-	Status = AcpiEnableGpe(sc->ec_gpehandle, sc->ec_gpebit, ACPI_ISR);
-	if (ACPI_FAILURE(Status))
-	    printf("EcGpeHandler: AcpiEnableEvent failed\n");
+    /*
+     * If the EC_SCI bit of the status register is set, queue a query handler.
+     * It will run the query and _Qxx method later, under the lock.
+     */
+    EcStatus = EC_GET_CSR(sc);
+    if ((EcStatus & EC_EVENT_SCI) && !sc->ec_sci_pend) {
+	CTR0(KTR_ACPI, "ec gpe queueing query handler");
+	Status = AcpiOsExecute(OSL_GPE_HANDLER, EcGpeQueryHandler, Context);
+	if (ACPI_SUCCESS(Status))
+	    sc->ec_sci_pend = TRUE;
+	else
+	    printf("EcGpeHandler: queuing GPE query handler failed\n");
     }
-
     return (0);
 }
 
@@ -822,6 +743,18 @@
     EcAddr = Address;
     Status = AE_ERROR;
 
+    /*
+     * If booting, check if we need to run the query handler.  If so, we
+     * we call it directly here since our thread taskq is not active yet.
+     */
+    if (cold || rebooting) {
+	if ((EC_GET_CSR(sc) & EC_EVENT_SCI)) {
+	    CTR0(KTR_ACPI, "ec running gpe handler directly");
+	    EcGpeQueryHandler(sc);
+	}
+    }
+
+    /* Serialize with EcGpeQueryHandler() at transaction granularity. */
     Status = EcLock(sc);
     if (ACPI_FAILURE(Status))
 	return_ACPI_STATUS (Status);
@@ -853,190 +786,258 @@
 }
 
 static ACPI_STATUS
-EcWaitEvent(struct acpi_ec_softc *sc, EC_EVENT Event)
+EcCheckStatus(struct acpi_ec_softc *sc, const char *msg, EC_EVENT event)
+{
+    ACPI_STATUS status;
+    EC_STATUS ec_status;
+
+    status = AE_NO_HARDWARE_RESPONSE;
+    ec_status = EC_GET_CSR(sc);
+    if (sc->ec_burstactive && !(ec_status & EC_FLAG_BURST_MODE)) {
+	CTR1(KTR_ACPI, "ec burst disabled in waitevent (%s)", msg);
+	sc->ec_burstactive = FALSE;
+    }
+    if (EVENT_READY(event, ec_status)) {
+	CTR2(KTR_ACPI, "ec %s wait ready, status %#x", msg, ec_status);
+	status = AE_OK;
+    }
+    return (status);
+}
+
+static ACPI_STATUS
+EcWaitEvent(struct acpi_ec_softc *sc, EC_EVENT Event, u_int gen_count)
 {
-    EC_STATUS	EcStatus;
     ACPI_STATUS	Status;
-    int		count, i, period, retval, slp_ival;
-    static int	EcDbgMaxDelay;
+    int		count, i, slp_ival;
 
     ACPI_SERIAL_ASSERT(ec);
     Status = AE_NO_HARDWARE_RESPONSE;
-
-    /* 
-     * Wait for 1 us before checking the CSR.  Testing shows about
-     * 50% of requests complete in 1 us and 90% of them complete
-     * in 5 us or less.
-     */
-    AcpiOsStall(1);
-
+    int need_poll = cold || rebooting || ec_polled_mode || sc->ec_suspending;
     /*
-     * Poll the EC status register for up to 1 ms in chunks of 10 us 
-     * to detect completion of the last command.
+     * The main CPU should be much faster than the EC.  So the status should
+     * be "not ready" when we start waiting.  But if the main CPU is really
+     * slow, it's possible we see the current "ready" response.  Since that
+     * can't be distinguished from the previous response in polled mode,
+     * this is a potential issue.  We really should have interrupts enabled
+     * during boot so there is no ambiguity in polled mode.
+     *
+     * If this occurs, we add an additional delay before actually entering
+     * the status checking loop, hopefully to allow the EC to go to work
+     * and produce a non-stale status.
      */
-    for (i = 0; i < 1000 / EC_POLL_DELAY; i++) {
-	EcStatus = EC_GET_CSR(sc);
-	if (EVENT_READY(Event, EcStatus)) {
-	    Status = AE_OK;
-	    break;
+    if (need_poll) {
+	static int	once;
+
+	if (EcCheckStatus(sc, "pre-check", Event) == AE_OK) {
+	    if (!once) {
+		device_printf(sc->ec_dev,
+		    "warning: EC done before starting event wait\n");
+		once = 1;
+	    }
+	    AcpiOsStall(10);
 	}
-	AcpiOsStall(EC_POLL_DELAY);
     }
-    period = i * EC_POLL_DELAY;
 
-    /*
-     * If we still don't have a response and we're up and running, wait up
-     * to ec_poll_timeout ms for completion, sleeping for chunks of 10 ms.
-     */
-    slp_ival = 0;
-    if (Status != AE_OK) {
-	retval = ENXIO;
-	count = ec_poll_timeout / 10;
+    /* Wait for event by polling or GPE (interrupt). */
+    if (need_poll) {
+	count = (ec_timeout * 1000) / EC_POLL_DELAY;
 	if (count == 0)
 	    count = 1;
-	slp_ival = hz / 100;
-	if (slp_ival == 0)
-	    slp_ival = 1;
 	for (i = 0; i < count; i++) {
-	    if (retval != 0)
-		EcStatus = EC_GET_CSR(sc);
-	    else
-		EcStatus = sc->ec_csrvalue;
-	    if (EVENT_READY(Event, EcStatus)) {
-		Status = AE_OK;
+	    Status = EcCheckStatus(sc, "poll", Event);
+	    if (Status == AE_OK)
 		break;
+	    AcpiOsStall(EC_POLL_DELAY);
+	}
+    } else {
+	slp_ival = hz / 1000;
+	if (slp_ival != 0) {
+	    count = ec_timeout;
+	} else {
+	    /* hz has less than 1 ms resolution so scale timeout. */
+	    slp_ival = 1;
+	    count = ec_timeout / (1000 / hz);
+	}
+
+	/*
+	 * Wait for the GPE to signal the status changed, checking the
+	 * status register each time we get one.  It's possible to get a
+	 * GPE for an event we're not interested in here (i.e., SCI for
+	 * EC query).
+	 */
+	for (i = 0; i < count; i++) {
+	    if (gen_count != sc->ec_gencount) {
+		/*
+		 * Record new generation count.  It's possible the GPE was
+		 * just to notify us that a query is needed and we need to
+		 * wait for a second GPE to signal the completion of the
+		 * event we are actually waiting for.
+		 */
+		gen_count = sc->ec_gencount;
+		Status = EcCheckStatus(sc, "sleep", Event);
+		if (Status == AE_OK)
+		    break;
 	    }
-	    if (!cold)
-		retval = tsleep(&sc->ec_csrvalue, PZERO, "ecpoll", slp_ival);
-	    else
-		AcpiOsStall(10000);
+	    tsleep(&sc->ec_gencount, PZERO, "ecgpe", slp_ival);
 	}
-    }
 
-    /* Calculate new delay and print it if it exceeds the max. */
-    if (slp_ival > 0)
-	period += i * 10000;
-    if (period > EcDbgMaxDelay) {
-	EcDbgMaxDelay = period;
-	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
-		    "info: new max delay is %d us\n", period);
+	/*
+	 * We finished waiting for the GPE and it never arrived.  Try to
+	 * read the register once and trust whatever value we got.  This is
+	 * the best we can do at this point.  Then, force polled mode on
+	 * since this system doesn't appear to generate GPEs.
+	 */
+	if (Status != AE_OK) {
+	    Status = EcCheckStatus(sc, "sleep_end", Event);
+	    device_printf(sc->ec_dev,
+		"wait timed out (%sresponse), forcing polled mode\n",
+		Status == AE_OK ? "" : "no ");
+	    ec_polled_mode = TRUE;
+	}
     }
-
+    if (Status != AE_OK)
+	    CTR0(KTR_ACPI, "error: ec wait timed out");
     return (Status);
-}    
+}
 
 static ACPI_STATUS
 EcCommand(struct acpi_ec_softc *sc, EC_COMMAND cmd)
 {
-    ACPI_STATUS	Status;
-    EC_EVENT	Event;
+    ACPI_STATUS	status;
+    EC_EVENT	event;
+    EC_STATUS	ec_status;
+    u_int	gen_count;
 
     ACPI_SERIAL_ASSERT(ec);
 
+    /* Don't use burst mode if user disabled it. */
+    if (!ec_burst_mode && cmd == EC_COMMAND_BURST_ENABLE)
+	return (AE_ERROR);
+
     /* Decide what to wait for based on command type. */
     switch (cmd) {
     case EC_COMMAND_READ:
     case EC_COMMAND_WRITE:
     case EC_COMMAND_BURST_DISABLE:
-	Event = EC_EVENT_INPUT_BUFFER_EMPTY;
+	event = EC_EVENT_INPUT_BUFFER_EMPTY;
 	break;
     case EC_COMMAND_QUERY:
     case EC_COMMAND_BURST_ENABLE:
-	Event = EC_EVENT_OUTPUT_BUFFER_FULL;
+	event = EC_EVENT_OUTPUT_BUFFER_FULL;
 	break;
     default:
-	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
-		    "EcCommand: Invalid command %#x\n", cmd);
+	device_printf(sc->ec_dev, "EcCommand: invalid command %#x\n", cmd);
 	return (AE_BAD_PARAMETER);
     }
 
     /* Run the command and wait for the chosen event. */
+    CTR1(KTR_ACPI, "ec running command %#x", cmd);
+    gen_count = sc->ec_gencount;
     EC_SET_CSR(sc, cmd);
-    Status = EcWaitEvent(sc, Event);
-    if (ACPI_FAILURE(Status)) {
-	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
-		    "EcCommand: no response to %#x\n", cmd);
-    }
-
-    return (Status);
+    status = EcWaitEvent(sc, event, gen_count);
+    if (ACPI_SUCCESS(status)) {
+	/* If we succeeded, burst flag should now be present. */
+	if (cmd == EC_COMMAND_BURST_ENABLE) {
+	    ec_status = EC_GET_CSR(sc);
+	    if ((ec_status & EC_FLAG_BURST_MODE) == 0)
+		status = AE_ERROR;
+	}
+    } else
+	device_printf(sc->ec_dev, "EcCommand: no response to %#x\n", cmd);
+    return (status);
 }
 
 static ACPI_STATUS
 EcRead(struct acpi_ec_softc *sc, UINT8 Address, UINT8 *Data)
 {
-    ACPI_STATUS	Status;
+    ACPI_STATUS	status;
+    UINT8 data;
+    u_int gen_count;
 
     ACPI_SERIAL_ASSERT(ec);
+    CTR1(KTR_ACPI, "ec read from %#x", Address);
 
-#ifdef notyet
     /* If we can't start burst mode, continue anyway. */
-    EcCommand(sc, EC_COMMAND_BURST_ENABLE);
-#endif
+    status = EcCommand(sc, EC_COMMAND_BURST_ENABLE);
+    if (status == AE_OK) {
+    	data = EC_GET_DATA(sc);
+	if (data == EC_BURST_ACK) {
+	    CTR0(KTR_ACPI, "ec burst enabled");
+	    sc->ec_burstactive = TRUE;
+	}
+    }
 
-    Status = EcCommand(sc, EC_COMMAND_READ);
-    if (ACPI_FAILURE(Status))
-	return (Status);
+    status = EcCommand(sc, EC_COMMAND_READ);
+    if (ACPI_FAILURE(status))
+	return (status);
 
+    gen_count = sc->ec_gencount;
     EC_SET_DATA(sc, Address);
-    Status = EcWaitEvent(sc, EC_EVENT_OUTPUT_BUFFER_FULL);
-    if (ACPI_FAILURE(Status)) {
-	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
-		    "EcRead: Failed waiting for EC to send data.\n");
-	return (Status);
+    status = EcWaitEvent(sc, EC_EVENT_OUTPUT_BUFFER_FULL, gen_count);
+    if (ACPI_FAILURE(status)) {
+	device_printf(sc->ec_dev, "EcRead: failed waiting to get data\n");
+	return (status);
     }
-
     *Data = EC_GET_DATA(sc);
 
-#ifdef notyet
     if (sc->ec_burstactive) {
-	Status = EcCommand(sc, EC_COMMAND_BURST_DISABLE);
-	if (ACPI_FAILURE(Status))
-	    return (Status);
+	sc->ec_burstactive = FALSE;
+	status = EcCommand(sc, EC_COMMAND_BURST_DISABLE);
+	if (ACPI_FAILURE(status))
+	    return (status);
+	CTR0(KTR_ACPI, "ec disabled burst ok");
     }
-#endif
 
     return (AE_OK);
-}    
+}
 
 static ACPI_STATUS
 EcWrite(struct acpi_ec_softc *sc, UINT8 Address, UINT8 *Data)
 {
-    ACPI_STATUS	Status;
+    ACPI_STATUS	status;
+    UINT8 data;
+    u_int gen_count;
 
     ACPI_SERIAL_ASSERT(ec);
+    CTR2(KTR_ACPI, "ec write to %#x, data %#x", Address, *Data);
 
-#ifdef notyet
     /* If we can't start burst mode, continue anyway. */
-    EcCommand(sc, EC_COMMAND_BURST_ENABLE);
-#endif
+    status = EcCommand(sc, EC_COMMAND_BURST_ENABLE);
+    if (status == AE_OK) {
+    	data = EC_GET_DATA(sc);
+	if (data == EC_BURST_ACK) {
+	    CTR0(KTR_ACPI, "ec burst enabled");
+	    sc->ec_burstactive = TRUE;
+	}
+    }
 
-    Status = EcCommand(sc, EC_COMMAND_WRITE);
-    if (ACPI_FAILURE(Status))
-	return (Status);
+    status = EcCommand(sc, EC_COMMAND_WRITE);
+    if (ACPI_FAILURE(status))
+	return (status);
 
+    gen_count = sc->ec_gencount;
     EC_SET_DATA(sc, Address);
-    Status = EcWaitEvent(sc, EC_EVENT_INPUT_BUFFER_EMPTY);
-    if (ACPI_FAILURE(Status)) {
-	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
-		    "EcRead: Failed waiting for EC to process address\n");
-	return (Status);
+    status = EcWaitEvent(sc, EC_EVENT_INPUT_BUFFER_EMPTY, gen_count);
+    if (ACPI_FAILURE(status)) {
+	device_printf(sc->ec_dev, "EcRead: failed waiting for sent address\n");
+	return (status);
     }
 
+    gen_count = sc->ec_gencount;
     EC_SET_DATA(sc, *Data);
-    Status = EcWaitEvent(sc, EC_EVENT_INPUT_BUFFER_EMPTY);
-    if (ACPI_FAILURE(Status)) {
-	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
-		    "EcWrite: Failed waiting for EC to process data\n");
-	return (Status);
+    status = EcWaitEvent(sc, EC_EVENT_INPUT_BUFFER_EMPTY, gen_count);
+    if (ACPI_FAILURE(status)) {
+	device_printf(sc->ec_dev, "EcWrite: failed waiting for sent data\n");
+	return (status);
     }
 
-#ifdef notyet
     if (sc->ec_burstactive) {
-	Status = EcCommand(sc, EC_COMMAND_BURST_DISABLE);
-	if (ACPI_FAILURE(Status))
-	    return (Status);
+	sc->ec_burstactive = FALSE;
+	status = EcCommand(sc, EC_COMMAND_BURST_DISABLE);
+	if (ACPI_FAILURE(status))
+	    return (status);
+	CTR0(KTR_ACPI, "ec disabled burst ok");
     }
-#endif
 
     return (AE_OK);
 }
Index: acpi_pci.c
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/acpi_pci.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/dev/acpica/acpi_pci.c -L sys/dev/acpica/acpi_pci.c -u -r1.1.1.1 -r1.2
--- sys/dev/acpica/acpi_pci.c
+++ sys/dev/acpica/acpi_pci.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_pci.c,v 1.26.2.1 2005/11/07 09:53:22 obrien Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_pci.c,v 1.31.2.1 2007/10/31 16:10:12 jhb Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -83,50 +83,21 @@
 	/* Device interface */
 	DEVMETHOD(device_probe,		acpi_pci_probe),
 	DEVMETHOD(device_attach,	acpi_pci_attach),
-	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
-	DEVMETHOD(device_suspend,	pci_suspend),
-	DEVMETHOD(device_resume,	pci_resume),
 
 	/* Bus interface */
-	DEVMETHOD(bus_print_child,	pci_print_child),
-	DEVMETHOD(bus_probe_nomatch,	pci_probe_nomatch),
 	DEVMETHOD(bus_read_ivar,	acpi_pci_read_ivar),
 	DEVMETHOD(bus_write_ivar,	acpi_pci_write_ivar),
-	DEVMETHOD(bus_driver_added,	pci_driver_added),
-	DEVMETHOD(bus_setup_intr,	bus_generic_setup_intr),
-	DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
-
-	DEVMETHOD(bus_get_resource_list,pci_get_resource_list),
-	DEVMETHOD(bus_set_resource,	bus_generic_rl_set_resource),
-	DEVMETHOD(bus_get_resource,	bus_generic_rl_get_resource),
-	DEVMETHOD(bus_delete_resource,	pci_delete_resource),
-	DEVMETHOD(bus_alloc_resource,	pci_alloc_resource),
-	DEVMETHOD(bus_release_resource,	bus_generic_rl_release_resource),
-	DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
-	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
-	DEVMETHOD(bus_child_pnpinfo_str, pci_child_pnpinfo_str_method),
 	DEVMETHOD(bus_child_location_str, acpi_pci_child_location_str_method),
 
 	/* PCI interface */
-	DEVMETHOD(pci_read_config,	pci_read_config_method),
-	DEVMETHOD(pci_write_config,	pci_write_config_method),
-	DEVMETHOD(pci_enable_busmaster,	pci_enable_busmaster_method),
-	DEVMETHOD(pci_disable_busmaster, pci_disable_busmaster_method),
-	DEVMETHOD(pci_enable_io,	pci_enable_io_method),
-	DEVMETHOD(pci_disable_io,	pci_disable_io_method),
-	DEVMETHOD(pci_get_powerstate,	pci_get_powerstate_method),
 	DEVMETHOD(pci_set_powerstate,	acpi_pci_set_powerstate_method),
-	DEVMETHOD(pci_assign_interrupt, pci_assign_interrupt_method),
 
 	{ 0, 0 }
 };
 
-static driver_t acpi_pci_driver = {
-	"pci",
-	acpi_pci_methods,
-	0,			/* no softc */
-};
+static devclass_t pci_devclass;
 
+DEFINE_CLASS_1(pci, acpi_pci_driver, acpi_pci_methods, 0, pci_driver);
 DRIVER_MODULE(acpi_pci, pcib, acpi_pci_driver, pci_devclass, 0, 0);
 MODULE_DEPEND(acpi_pci, acpi, 1, 1, 1);
 MODULE_DEPEND(acpi_pci, pci, 1, 1, 1);
@@ -237,8 +208,19 @@
 	 */
 	child = acpi_get_device(handle);
 	if (child != NULL) {
-		KASSERT(!device_is_alive(child), ("%s: deleting alive child %s",
-		    __func__, device_get_nameunit(child)));
+		if (device_is_alive(child)) {
+			/*
+			 * The TabletPC TC1000 has a second PCI-ISA bridge
+			 * that has a _HID for an acpi_sysresource device.
+			 * In that case, leave ACPI-CA's device data pointing
+			 * at the ACPI-enumerated device.
+			 */
+			device_printf(child,
+			    "Conflicts with PCI device %d:%d:%d\n",
+			    pci_get_bus(pci_child), pci_get_slot(pci_child),
+			    pci_get_function(pci_child));
+			return;
+		}
 		KASSERT(device_get_parent(child) ==
 		    devclass_get_device(devclass_find("acpi"), 0),
 		    ("%s: child (%s)'s parent is not acpi0", __func__,
@@ -304,17 +286,19 @@
 static int
 acpi_pci_attach(device_t dev)
 {
-	int busno;
+	int busno, domain;
 
 	/*
 	 * Since there can be multiple independantly numbered PCI
-	 * busses on some large alpha systems, we can't use the unit
-	 * number to decide what bus we are probing. We ask the parent 
-	 * pcib what our bus number is.
+	 * busses on systems with multiple PCI domains, we can't use
+	 * the unit number to decide which bus we are probing. We ask
+	 * the parent pcib what our domain and bus numbers are.
 	 */
+	domain = pcib_get_domain(dev);
 	busno = pcib_get_bus(dev);
 	if (bootverbose)
-		device_printf(dev, "physical bus=%d\n", busno);
+		device_printf(dev, "domain=%d, physical bus=%d\n",
+		    domain, busno);
 
 	/*
 	 * First, PCI devices are added as in the normal PCI bus driver.
@@ -326,7 +310,7 @@
 	 * pci_add_children() doesn't find.  We currently just ignore
 	 * these devices.
 	 */
-	pci_add_children(dev, busno, sizeof(struct acpi_pci_devinfo));
+	pci_add_children(dev, domain, busno, sizeof(struct acpi_pci_devinfo));
 	AcpiWalkNamespace(ACPI_TYPE_DEVICE, acpi_get_handle(dev), 1,
 	    acpi_pci_save_handle, dev, NULL);
 
Index: acpi_powerres.c
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/acpi_powerres.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/dev/acpica/acpi_powerres.c -L sys/dev/acpica/acpi_powerres.c -u -r1.1.1.1 -r1.2
--- sys/dev/acpica/acpi_powerres.c
+++ sys/dev/acpica/acpi_powerres.c
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_powerres.c,v 1.28.2.1 2005/11/07 09:53:23 obrien Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_powerres.c,v 1.30 2006/04/21 19:06:29 jkim Exp $");
 
 #include "opt_acpi.h"
 #include <sys/param.h>
@@ -247,7 +247,7 @@
     ACPI_SERIAL_ASSERT(powerres);
 
     /* Check to see whether we know about this consumer already */
-    if ((pc = acpi_pwr_find_consumer(consumer)) != NULL)
+    if (acpi_pwr_find_consumer(consumer) != NULL)
 	return_ACPI_STATUS (AE_OK);
     
     /* Allocate a new power consumer */
Index: acpi_lid.c
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/acpi_lid.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/dev/acpica/acpi_lid.c -L sys/dev/acpica/acpi_lid.c -u -r1.1.1.1 -r1.2
--- sys/dev/acpica/acpi_lid.c
+++ sys/dev/acpica/acpi_lid.c
@@ -28,7 +28,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_lid.c,v 1.27.2.1 2005/11/07 09:53:22 obrien Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_lid.c,v 1.29 2007/03/22 18:16:40 jkim Exp $");
 
 #include "opt_acpi.h"
 #include <sys/param.h>
@@ -184,8 +184,8 @@
     sc = (struct acpi_lid_softc *)context;
     switch (notify) {
     case ACPI_NOTIFY_STATUS_CHANGED:
-	AcpiOsQueueForExecution(OSD_PRIORITY_LO,
-				acpi_lid_notify_status_changed, sc);
+	AcpiOsExecute(OSL_NOTIFY_HANDLER,
+		      acpi_lid_notify_status_changed, sc);
 	break;
     default:
 	device_printf(sc->lid_dev, "unknown notify %#x\n", notify);
--- /dev/null
+++ sys/dev/acpica/acpi_hpet.h
@@ -0,0 +1,65 @@
+/*-
+ * Copyright (c) 2005 Poul-Henning Kamp
+ * 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: src/sys/dev/acpica/acpi_hpet.h,v 1.1.6.1 2008/01/24 18:52:26 jhb Exp $
+ */
+
+#ifndef __ACPI_HPET_H__
+#define	__ACPI_HPET_H__
+
+#define HPET_MEM_WIDTH		0x400	/* Expected memory region size */
+
+/* General registers */
+#define HPET_CAPABILITIES	0x0	/* General capabilities and ID */
+#define	HPET_CAP_VENDOR_ID	0xffff0000
+#define	HPET_CAP_LEG_RT		0x00008000
+#define	HPET_CAP_COUNT_SIZE	0x00002000 /* 1 = 64-bit, 0 = 32-bit */
+#define	HPET_CAP_NUM_TIM	0x00001f00
+#define	HPET_CAP_REV_ID		0x000000ff
+#define HPET_PERIOD		0x4	/* Period (1/hz) of timer */
+#define HPET_CONFIG		0x10	/* General configuration register */
+#define	HPET_CNF_LEG_RT		0x00000002
+#define	HPET_CNF_ENABLE		0x00000001
+#define	HPET_ISR		0x20	/* General interrupt status register */
+#define HPET_MAIN_COUNTER	0xf0	/* Main counter register */
+
+/* Timer registers */
+#define	HPET_TIMER_CAP_CNF(x)	((x) * 0x20 + 0x100)
+#define	HPET_TCAP_INT_ROUTE	0xffffffff00000000
+#define	HPET_TCAP_FSB_INT_DEL	0x00008000
+#define	HPET_TCNF_FSB_EN	0x00004000
+#define	HPET_TCNF_INT_ROUTE	0x00003e00
+#define	HPET_TCNF_32MODE	0x00000100
+#define	HPET_TCNF_VAL_SET	0x00000040
+#define	HPET_TCAP_SIZE		0x00000020 /* 1 = 64-bit, 0 = 32-bit */
+#define	HPET_TCAP_PER_INT	0x00000010 /* Supports periodic interrupts */
+#define	HPET_TCNF_TYPE		0x00000008 /* 1 = periodic, 0 = one-shot */
+#define	HPET_TCNF_INT_ENB	0x00000004
+#define	HPET_TCNT_INT_TYPE	0x00000002 /* 1 = level triggered, 0 = edge */
+#define	HPET_TIMER_COMPARATOR(x) ((x) * 0x20 + 0x108)
+#define	HPET_TIMER_FSB_VAL(x)	((x) * 0x20 + 0x110)
+#define	HPET_TIMER_FSB_ADDR(x)	((x) * 0x20 + 0x114)
+
+#endif /* !__ACPI_HPET_H__ */
Index: OsdMemory.c
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/Osd/OsdMemory.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/dev/acpica/Osd/OsdMemory.c -L sys/dev/acpica/Osd/OsdMemory.c -u -r1.1.1.1 -r1.2
--- sys/dev/acpica/Osd/OsdMemory.c
+++ sys/dev/acpica/Osd/OsdMemory.c
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/acpica/Osd/OsdMemory.c,v 1.11.8.2 2005/11/07 09:53:23 obrien Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/acpica/Osd/OsdMemory.c,v 1.15 2007/03/22 18:16:41 jkim Exp $");
 
 #include <contrib/dev/acpica/acpi.h>
 
@@ -54,20 +54,16 @@
     free(Memory, M_ACPICA);
 }
 
-ACPI_STATUS
-AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS PhysicalAddress, ACPI_SIZE Length,
-    void **LogicalAddress)
+void *
+AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS PhysicalAddress, ACPI_NATIVE_UINT Length)
 {
-    *LogicalAddress = pmap_mapdev((vm_offset_t)PhysicalAddress, Length);
-    if (*LogicalAddress == NULL)
-	return (AE_BAD_ADDRESS);
-    return (AE_OK);
+    return (pmap_mapbios((vm_offset_t)PhysicalAddress, Length));
 }
 
 void
 AcpiOsUnmapMemory(void *LogicalAddress, ACPI_SIZE Length)
 {
-    pmap_unmapdev((vm_offset_t)LogicalAddress, Length);
+    pmap_unmapbios((vm_offset_t)LogicalAddress, Length);
 }
 
 ACPI_STATUS
@@ -78,10 +74,23 @@
     return (AE_BAD_ADDRESS);
 }
 
+ACPI_STATUS
+AcpiOsValidateInterface (char *Interface)
+{
+    return (AE_SUPPORT);
+}
+
 /*
  * There is no clean way to do this.  We make the charitable assumption
  * that callers will not pass garbage to us.
  */
+ACPI_STATUS
+AcpiOsValidateAddress (UINT8 SpaceId, ACPI_PHYSICAL_ADDRESS Address,
+    ACPI_SIZE Length)
+{
+    return (AE_OK);
+}
+
 BOOLEAN
 AcpiOsReadable (void *Pointer, ACPI_SIZE Length)
 {
@@ -99,7 +108,8 @@
 {
     void	*LogicalAddress;
 
-    if (AcpiOsMapMemory(Address, Width / 8, &LogicalAddress) != AE_OK)
+    LogicalAddress = AcpiOsMapMemory(Address, Width / 8);
+    if (LogicalAddress == NULL)
 	return (AE_NOT_EXIST);
 
     switch (Width) {
@@ -130,7 +140,8 @@
 {
     void	*LogicalAddress;
 
-    if (AcpiOsMapMemory(Address, Width / 8, &LogicalAddress) != AE_OK)
+    LogicalAddress = AcpiOsMapMemory(Address, Width / 8);
+    if (LogicalAddress == NULL)
 	return (AE_NOT_EXIST);
 
     switch (Width) {
Index: OsdDebug.c
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/Osd/OsdDebug.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/dev/acpica/Osd/OsdDebug.c -L sys/dev/acpica/Osd/OsdDebug.c -u -r1.1.1.1 -r1.2
--- sys/dev/acpica/Osd/OsdDebug.c
+++ sys/dev/acpica/Osd/OsdDebug.c
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/acpica/Osd/OsdDebug.c,v 1.9.2.2 2005/11/07 09:53:23 obrien Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/acpica/Osd/OsdDebug.c,v 1.13 2007/03/22 18:16:41 jkim Exp $");
 
 #include "opt_ddb.h"
 #include <sys/param.h>
@@ -62,14 +62,6 @@
 #endif /* DDB */
 }
 
-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)
 {
@@ -78,9 +70,11 @@
     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",
+	printf("ACPI fatal signal, type 0x%x code 0x%x argument 0x%x",
 	      fatal->Type, fatal->Code, fatal->Argument);
+#ifdef ACPI_DEBUG
 	kdb_enter("AcpiOsSignal");
+#endif
 	break;
 
     case ACPI_SIGNAL_BREAKPOINT:
Index: OsdTable.c
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/Osd/OsdTable.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/dev/acpica/Osd/OsdTable.c -L sys/dev/acpica/Osd/OsdTable.c -u -r1.1.1.1 -r1.2
--- sys/dev/acpica/Osd/OsdTable.c
+++ sys/dev/acpica/Osd/OsdTable.c
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/acpica/Osd/OsdTable.c,v 1.8.2.2 2005/11/07 09:53:24 obrien Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/acpica/Osd/OsdTable.c,v 1.12 2007/03/22 18:16:41 jkim Exp $");
 
 #include <sys/param.h>
 #include <sys/endian.h>
@@ -40,26 +40,22 @@
 #include <contrib/dev/acpica/actables.h>
 
 #undef _COMPONENT
-#define _COMPONENT      ACPI_TABLES
+#define	_COMPONENT      ACPI_TABLES
 
 static char acpi_osname[128];
 TUNABLE_STR("hw.acpi.osname", acpi_osname, sizeof(acpi_osname));
 
-static struct {
-    ACPI_TABLE_HEADER_DEF
-    uint32_t no_op;
-} __packed fake_ssdt;
-
 ACPI_STATUS
-AcpiOsPredefinedOverride (
-    const ACPI_PREDEFINED_NAMES *InitVal,
-    ACPI_STRING                 *NewVal)
+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 && strlen(acpi_osname) > 0) {
+    if (strncmp(InitVal->Name, "_OS_", ACPI_NAME_SIZE) == 0 &&
+	strlen(acpi_osname) > 0) {
 	printf("ACPI: Overriding _OS definition with \"%s\"\n", acpi_osname);
 	*NewVal = acpi_osname;
     }
@@ -68,9 +64,8 @@
 }
 
 ACPI_STATUS
-AcpiOsTableOverride (
-    ACPI_TABLE_HEADER       *ExistingTable,
-    ACPI_TABLE_HEADER       **NewTable)
+AcpiOsTableOverride(ACPI_TABLE_HEADER *ExistingTable,
+    ACPI_TABLE_HEADER **NewTable)
 {
     caddr_t acpi_dsdt, p;
 
@@ -78,36 +73,11 @@
 	return (AE_BAD_PARAMETER);
 
     /* If we're not overriding the DSDT, just return. */
-    *NewTable = NULL;
-    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);
-
-    /*
-     * Override the DSDT with the user's custom version.  Override the
-     * contents of any SSDTs with a simple no-op table since the user's
-     * DSDT is expected to contain their contents as well.
-     */
-    if (strncmp(ExistingTable->Signature, "DSDT", 4) == 0) {
-	printf("ACPI: overriding DSDT/SSDT with custom table\n");
-	*NewTable = *(void **)p;
-    } else if (strncmp(ExistingTable->Signature, "SSDT", 4) == 0) {
-	if (fake_ssdt.Length == 0) {
-	    sprintf(fake_ssdt.Signature, "%.4s", "SSDT");
-	    fake_ssdt.Length = htole32(sizeof(fake_ssdt));
-	    fake_ssdt.Revision = 2;
-	    fake_ssdt.Checksum = 0;
-	    sprintf(fake_ssdt.OemId, "%.6s", "FBSD  ");
-	    sprintf(fake_ssdt.OemTableId, "%.8s", "NullSSDT");
-	    fake_ssdt.OemRevision = htole32(1);
-	    sprintf(fake_ssdt.AslCompilerId, "%.4s", "FBSD");
-	    fake_ssdt.AslCompilerRevision = htole32(1);
-	    fake_ssdt.no_op = htole32(0x005c0310); /* Scope(\) */
-	    fake_ssdt.Checksum -= AcpiTbChecksum(&fake_ssdt, sizeof(fake_ssdt));
-	}
-	*NewTable = (void *)&fake_ssdt;
-    }
+    if ((acpi_dsdt = preload_search_by_type("acpi_dsdt")) == NULL ||
+	(p = preload_search_info(acpi_dsdt, MODINFO_ADDR)) == NULL) {
+	*NewTable = NULL;
+    } else
+	*NewTable = *(ACPI_TABLE_HEADER **)p;
 
     return (AE_OK);
 }
Index: OsdSynch.c
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/Osd/OsdSynch.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/dev/acpica/Osd/OsdSynch.c -L sys/dev/acpica/Osd/OsdSynch.c -u -r1.1.1.1 -r1.2
--- sys/dev/acpica/Osd/OsdSynch.c
+++ sys/dev/acpica/Osd/OsdSynch.c
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/acpica/Osd/OsdSynch.c,v 1.22.8.2 2005/11/07 09:53:23 obrien Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/acpica/Osd/OsdSynch.c,v 1.32 2007/03/26 23:04:02 jkim Exp $");
 
 #include <contrib/dev/acpica/acpi.h>
 
@@ -62,10 +62,12 @@
     UINT32	as_timeouts;
 };
 
+/* Default number of maximum pending threads. */
 #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);
@@ -75,7 +77,7 @@
 
 ACPI_STATUS
 AcpiOsCreateSemaphore(UINT32 MaxUnits, UINT32 InitialUnits,
-    ACPI_HANDLE *OutHandle)
+    ACPI_SEMAPHORE *OutHandle)
 {
 #ifndef ACPI_NO_SEMAPHORES
     struct acpi_semaphore	*as;
@@ -108,7 +110,7 @@
 }
 
 ACPI_STATUS
-AcpiOsDeleteSemaphore(ACPI_HANDLE Handle)
+AcpiOsDeleteSemaphore(ACPI_SEMAPHORE Handle)
 {
 #ifndef ACPI_NO_SEMAPHORES
     struct acpi_semaphore *as = (struct acpi_semaphore *)Handle;
@@ -129,7 +131,7 @@
  * use getmicrotime() to correctly adjust the timeout after being woken up.
  */
 ACPI_STATUS
-AcpiOsWaitSemaphore(ACPI_HANDLE Handle, UINT32 Units, UINT16 Timeout)
+AcpiOsWaitSemaphore(ACPI_SEMAPHORE Handle, UINT32 Units, UINT16 Timeout)
 {
 #ifndef ACPI_NO_SEMAPHORES
     ACPI_STATUS			result;
@@ -195,7 +197,7 @@
 	    break;
 	}
 
-	/* limit number of pending treads */
+	/* limit number of pending threads */
 	if (as->as_pendings >= ACPI_SEMAPHORES_MAX_PENDING) {
 	    result = AE_TIME;
 	    break;
@@ -257,8 +259,8 @@
 	    tmo = 1;
 
 	if (acpi_semaphore_debug) {
-	    printf("%s: Wakeup timeleft(%lu, %lu), tmo %u, sem %p, thread %d\n",
-		__func__, timelefttv.tv_sec, timelefttv.tv_usec, tmo, as,
+	    printf("%s: Wakeup timeleft(%jd, %lu), tmo %u, sem %p, thread %d\n",
+		__func__, (intmax_t)timelefttv.tv_sec, timelefttv.tv_usec, tmo, as,
 		AcpiOsGetThreadId());
 	}
     }
@@ -288,7 +290,7 @@
 }
 
 ACPI_STATUS
-AcpiOsSignalSemaphore(ACPI_HANDLE Handle, UINT32 Units)
+AcpiOsSignalSemaphore(ACPI_SEMAPHORE Handle, UINT32 Units)
 {
 #ifndef ACPI_NO_SEMAPHORES
     struct acpi_semaphore	*as = (struct acpi_semaphore *)Handle;
@@ -320,30 +322,44 @@
     return_ACPI_STATUS (AE_OK);
 }
 
+/* Combined mutex + mutex name storage since the latter must persist. */
+struct acpi_spinlock {
+    struct mtx	lock;
+    char	name[32];
+};
+
 ACPI_STATUS
-AcpiOsCreateLock (ACPI_HANDLE *OutHandle)
+AcpiOsCreateLock (ACPI_SPINLOCK *OutHandle)
 {
-    struct mtx *m;
+    struct acpi_spinlock *h;
 
     if (OutHandle == NULL)
 	return (AE_BAD_PARAMETER);
-    m = malloc(sizeof(*m), M_ACPISEM, M_NOWAIT | M_ZERO);
-    if (m == NULL)
+    h = malloc(sizeof(*h), M_ACPISEM, M_NOWAIT | M_ZERO);
+    if (h == NULL)
 	return (AE_NO_MEMORY);
 
-    mtx_init(m, "acpica subsystem lock", NULL, MTX_DEF);
-    *OutHandle = (ACPI_HANDLE)m;
+    /* Build a unique name based on the address of the handle. */
+    if (OutHandle == &AcpiGbl_GpeLock)
+	snprintf(h->name, sizeof(h->name), "acpi subsystem GPE lock");
+    else if (OutHandle == &AcpiGbl_HardwareLock)
+	snprintf(h->name, sizeof(h->name), "acpi subsystem HW lock");
+    else
+	snprintf(h->name, sizeof(h->name), "acpi subsys %p", OutHandle);
+    mtx_init(&h->lock, h->name, NULL, MTX_DEF);
+    *OutHandle = (ACPI_SPINLOCK)h;
     return (AE_OK);
 }
 
 void
-AcpiOsDeleteLock (ACPI_HANDLE Handle)
+AcpiOsDeleteLock (ACPI_SPINLOCK Handle)
 {
-    struct mtx *m = (struct mtx *)Handle;
+    struct acpi_spinlock *h = (struct acpi_spinlock *)Handle;
 
     if (Handle == NULL)
         return;
-    mtx_destroy(m);
+    mtx_destroy(&h->lock);
+    free(h, M_ACPISEM);
 }
 
 /*
@@ -351,24 +367,25 @@
  * (and thus can't block) but since we have ithreads, we don't worry
  * about potentially blocking.
  */
-void
-AcpiOsAcquireLock (ACPI_HANDLE Handle, UINT32 Flags)
+ACPI_NATIVE_UINT
+AcpiOsAcquireLock (ACPI_SPINLOCK Handle)
 {
-    struct mtx *m = (struct mtx *)Handle;
+    struct acpi_spinlock *h = (struct acpi_spinlock *)Handle;
 
     if (Handle == NULL)
-	return;
-    mtx_lock(m);
+	return (0);
+    mtx_lock(&h->lock);
+    return (0);
 }
 
 void
-AcpiOsReleaseLock (ACPI_HANDLE Handle, UINT32 Flags)
+AcpiOsReleaseLock (ACPI_SPINLOCK Handle, ACPI_CPU_FLAGS Flags)
 {
-    struct mtx *m = (struct mtx *)Handle;
+    struct acpi_spinlock *h = (struct acpi_spinlock *)Handle;
 
     if (Handle == NULL)
 	return;
-    mtx_unlock(m);
+    mtx_unlock(&h->lock);
 }
 
 /* Section 5.2.9.1:  global lock acquire/release functions */
Index: OsdStream.c
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/Osd/OsdStream.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/dev/acpica/Osd/OsdStream.c -L sys/dev/acpica/Osd/OsdStream.c -u -r1.1.1.1 -r1.2
--- sys/dev/acpica/Osd/OsdStream.c
+++ sys/dev/acpica/Osd/OsdStream.c
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/acpica/Osd/OsdStream.c,v 1.4.8.2 2005/11/07 09:53:23 obrien Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/acpica/Osd/OsdStream.c,v 1.6 2005/09/11 18:39:02 obrien Exp $");
 
 #include <contrib/dev/acpica/acpi.h>
 
Index: OsdSchedule.c
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/Osd/OsdSchedule.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/acpica/Osd/OsdSchedule.c -L sys/dev/acpica/Osd/OsdSchedule.c -u -r1.2 -r1.3
--- sys/dev/acpica/Osd/OsdSchedule.c
+++ sys/dev/acpica/Osd/OsdSchedule.c
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: /repoman/r/ncvs/src/sys/dev/acpica/Osd/OsdSchedule.c,v 1.32.2.6 2006/07/06 08:32:49 glebius Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/acpica/Osd/OsdSchedule.c,v 1.39.4.1 2008/01/16 01:22:15 njl Exp $");
 
 #include "opt_acpi.h"
 #include <sys/param.h>
@@ -42,7 +42,6 @@
 #include <sys/malloc.h>
 #include <sys/proc.h>
 #include <sys/taskqueue.h>
-#include <machine/clock.h>
 
 #include <contrib/dev/acpica/acpi.h>
 #include <dev/acpica/acpivar.h>
@@ -66,7 +65,8 @@
 };
 
 TASKQUEUE_DEFINE(acpi, taskqueue_thread_enqueue, &taskqueue_acpi,
-    taskqueue_start_threads(&taskqueue_acpi, 3, PWAIT, "acpi_task"));
+    taskqueue_start_threads(&taskqueue_acpi, acpi_max_threads, PWAIT,
+    "acpi_task"));
 
 /*
  * Bounce through this wrapper function since ACPI-CA doesn't understand
@@ -87,7 +87,7 @@
  * We allocate and queue a task for one of our taskqueue threads to process.
  */
 ACPI_STATUS
-AcpiOsQueueForExecution(UINT32 Priority, ACPI_OSD_EXEC_CALLBACK Function,
+AcpiOsExecute(ACPI_EXECUTE_TYPE Type, ACPI_OSD_EXEC_CALLBACK Function,
     void *Context)
 {
     struct acpi_task_ctx *at;
@@ -104,18 +104,24 @@
 
     at->at_function = Function;
     at->at_context = Context;
-    switch (Priority) {
-    case OSD_PRIORITY_GPE:
-	pri = 4;
+    switch (Type) {
+    case OSL_GPE_HANDLER:
+    case OSL_NOTIFY_HANDLER:
+	/*
+	 * Run GPEs and Notifies at the same priority.  This allows
+	 * Notifies that are generated by running a GPE's method (e.g., _L00)
+	 * to not be pre-empted by a later GPE that arrives during the
+	 * Notify handler execution.
+	 */
+	pri = 10;
 	break;
-    case OSD_PRIORITY_HIGH:
-	pri = 3;
+    case OSL_GLOBAL_LOCK_HANDLER:
+    case OSL_EC_POLL_HANDLER:
+    case OSL_EC_BURST_HANDLER:
+	pri = 5;
 	break;
-    case OSD_PRIORITY_MED:
-	pri = 2;
-	break;
-    case OSD_PRIORITY_LO:
-	pri = 1;
+    case OSL_DEBUGGER_THREAD:
+	pri = 0;
 	break;
     default:
 	free(at, M_ACPITASK);
@@ -132,7 +138,6 @@
 AcpiOsSleep(ACPI_INTEGER Milliseconds)
 {
     int		timo;
-    static int	dummy;
 
     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
 
@@ -143,7 +148,7 @@
      * DELAY instead for better granularity.
      */
     if (timo > 0)
-	tsleep(&dummy, 0, "acpislp", timo);
+	pause("acpislp", timo);
     else
 	DELAY(Milliseconds * 1000);
 
@@ -179,7 +184,7 @@
     return_VOID;
 }
 
-UINT32
+ACPI_THREAD_ID
 AcpiOsGetThreadId(void)
 {
     struct proc *p;
Index: OsdInterrupt.c
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/Osd/OsdInterrupt.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/dev/acpica/Osd/OsdInterrupt.c -L sys/dev/acpica/Osd/OsdInterrupt.c -u -r1.1.1.1 -r1.2
--- sys/dev/acpica/Osd/OsdInterrupt.c
+++ sys/dev/acpica/Osd/OsdInterrupt.c
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/acpica/Osd/OsdInterrupt.c,v 1.19.2.2 2005/11/07 09:53:23 obrien Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/acpica/Osd/OsdInterrupt.c,v 1.22 2007/02/23 12:18:29 piso Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -86,7 +86,7 @@
 	goto error;
     }
     if (bus_setup_intr(sc->acpi_dev, sc->acpi_irq, INTR_TYPE_MISC|INTR_MPSAFE,
-	(driver_intr_t *)ServiceRoutine, Context, &sc->acpi_irq_handle)) {
+	NULL, (driver_intr_t *)ServiceRoutine, Context, &sc->acpi_irq_handle)) {
 	device_printf(sc->acpi_dev, "could not set up interrupt\n");
 	goto error;
     }
Index: OsdHardware.c
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/Osd/OsdHardware.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/dev/acpica/Osd/OsdHardware.c -L sys/dev/acpica/Osd/OsdHardware.c -u -r1.1.1.1 -r1.2
--- sys/dev/acpica/Osd/OsdHardware.c
+++ sys/dev/acpica/Osd/OsdHardware.c
@@ -30,19 +30,22 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/acpica/Osd/OsdHardware.c,v 1.15.2.2 2005/11/07 09:53:23 obrien Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/acpica/Osd/OsdHardware.c,v 1.22 2007/05/31 00:52:32 njl Exp $");
 
 #include <contrib/dev/acpica/acpi.h>
 
+#include <sys/bus.h>
+#include <sys/kernel.h>
 #include <machine/bus.h>
 #include <machine/pci_cfgreg.h>
+#include <dev/acpica/acpivar.h>
 #include <dev/pci/pcireg.h>
 
 /*
  * 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 
+ * 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.
  *
@@ -62,9 +65,76 @@
 #define ACPI_BUS_HANDLE		0
 #endif
 
+/*
+ * Some BIOS vendors use AML to read/write directly to IO space.  This
+ * can cause a problem if such accesses interfere with the OS's access to
+ * the same ports.  Windows XP and newer systems block accesses to certain
+ * IO ports.  We print a message or block accesses based on a tunable.
+ */
+static int illegal_bios_ports[] = {
+	0x000, 0x00f,	/* DMA controller 1 */
+	0x020, 0x021,	/* PIC */
+	0x040, 0x043,	/* Timer 1 */
+	0x048, 0x04b,	/* Timer 2 failsafe */
+	0x070, 0x071,	/* CMOS and RTC */
+	0x074, 0x076,	/* Extended CMOS */
+	0x081, 0x083,	/* DMA1 page registers */
+	0x087, 0x087,	/* DMA1 ch0 low page */
+	0x089, 0x08b,	/* DMA2 ch2 (0x89), ch3 low page (0x8a, 0x8b) */
+	0x08f, 0x091,	/* DMA2 low page refresh (0x8f) */
+			/* Arb ctrl port, card select feedback (0x90, 0x91) */
+	0x093, 0x094,	/* System board setup */
+	0x096, 0x097,	/* POS channel select */
+	0x0a0, 0x0a1,	/* PIC (cascaded) */
+	0x0c0, 0x0df,	/* ISA DMA */
+	0x4d0, 0x4d1,	/* PIC ELCR (edge/level control) */
+	0xcf8, 0xcff,	/* PCI config space. Microsoft adds 0xd00 also but
+			   that seems incorrect. */
+	-1, -1
+};
+
+/* Block accesses to bad IO port addresses or just print a warning. */
+static int block_bad_io;
+TUNABLE_INT("debug.acpi.block_bad_io", &block_bad_io);
+
+/*
+ * Look up bad ports in our table.  Returns 0 if ok, 1 if marked bad but
+ * access is still allowed, or -1 to deny access.
+ */
+static int
+acpi_os_check_port(UINT32 addr, UINT32 width)
+{
+	int error, *port;
+
+	error = 0;
+	for (port = illegal_bios_ports; *port != -1; port += 2) {
+		if ((addr >= port[0] && addr <= port[1]) ||
+		    (addr < port[0] && addr + (width / 8) > port[0])) {
+			if (block_bad_io)
+			    error = -1;
+			else
+			    error = 1;
+			break;
+		}
+	}
+
+	return (error);
+}
+
 ACPI_STATUS
 AcpiOsReadPort(ACPI_IO_ADDRESS InPort, UINT32 *Value, UINT32 Width)
 {
+    int error;
+
+    error = acpi_os_check_port(InPort, Width);
+    if (error != 0) {
+	if (bootverbose)
+		printf("acpi: bad read from port 0x%03x (%d)\n",
+			(int)InPort, Width);
+	if (error == -1)
+	    return (AE_BAD_PARAMETER);
+    }
+
     switch (Width) {
     case 8:
         *(u_int8_t *)Value = bus_space_read_1(ACPI_BUS_SPACE_IO,
@@ -89,6 +159,17 @@
 ACPI_STATUS
 AcpiOsWritePort(ACPI_IO_ADDRESS OutPort, UINT32	Value, UINT32 Width)
 {
+    int error;
+
+    error = acpi_os_check_port(OutPort, Width);
+    if (error != 0) {
+	if (bootverbose)
+		printf("acpi: bad write to port 0x%03x (%d), val %#x\n",
+			(int)OutPort, Width, Value);
+	if (error == -1)
+	    return (AE_BAD_PARAMETER);
+    }
+
     switch (Width) {
     case 8:
         bus_space_write_1(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, OutPort, Value);
@@ -133,7 +214,7 @@
 	/* debug trap goes here */
 	break;
     }
-    
+
     return (AE_OK);
 }
 
@@ -153,10 +234,6 @@
     return (AE_OK);
 }
 
-/* XXX should use acpivar.h but too many include dependencies */
-extern ACPI_STATUS acpi_GetInteger(ACPI_HANDLE handle, char *path, int
-    *number);
-
 /*
  * Depth-first recursive case for finding the bus, given the slot/function.
  */
@@ -180,7 +257,7 @@
     status = AcpiGetParent(curr, &parent);
     if (ACPI_FAILURE(status))
 	return (bus);
-    
+
     /* First, recurse up the tree until we find the host bus. */
     bus = acpi_bus_number(root, parent, PciId);
 
@@ -192,10 +269,8 @@
 
     /* Get the parent's slot and function. */
     status = acpi_GetInteger(parent, "_ADR", &adr);
-    if (ACPI_FAILURE(status)) {
-	printf("acpi_bus_number: can't get _ADR\n");
+    if (ACPI_FAILURE(status))
 	return (bus);
-    }
     slot = ACPI_HIWORD(adr);
     func = ACPI_LOWORD(adr);
 
@@ -209,7 +284,7 @@
     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)
+    else if (header == PCIM_HDRTYPE_CARDBUS && subclass == PCIS_BRIDGE_CARDBUS)
 	bus = pci_cfgregread(bus, slot, func, PCIR_SECBUS_2, 1);
     return (bus);
 }
@@ -249,7 +324,8 @@
 	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);
+	printf("AcpiOsDerivePciId: %s -> bus %d dev %d func %d\n",
+	    acpi_name(chandle), (*PciId)->Bus, (*PciId)->Device,
+	    (*PciId)->Function);
     }
 }


More information about the Midnightbsd-cvs mailing list