[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", ¶ms->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