Index: conf/files =================================================================== RCS file: /home/ncvs/src/sys/conf/files,v retrieving revision 1.584 diff -u -r1.584 files --- conf/files 27 Nov 2001 23:08:33 -0000 1.584 +++ conf/files 3 Dec 2001 11:28:00 -0000 @@ -1229,6 +1229,7 @@ dev/pccbb/pccbb.c optional pccbb pci/simos.c optional simos pci/uhci_pci.c optional uhci +pci/vga_pci.c optional pci pci/xrpu.c optional xrpu posix4/ksched.c optional _kposix_priority_scheduling posix4/p1003_1b.c standard Index: dev/acpica/acpi.c =================================================================== RCS file: /home/ncvs/src/sys/dev/acpica/acpi.c,v retrieving revision 1.52 diff -u -r1.52 acpi.c --- dev/acpica/acpi.c 30 Nov 2001 16:06:00 -0000 1.52 +++ dev/acpica/acpi.c 3 Dec 2001 11:28:00 -0000 @@ -470,6 +470,12 @@ acpi_EnterDebugger(); #endif +#ifndef ACPI_NO_THREADS + if ((error = acpi_task_thread_init())) { + goto out; + } +#endif + if ((error = acpi_machdep_init(dev))) { goto out; } Index: dev/acpica/acpi_ec.c =================================================================== RCS file: /home/ncvs/src/sys/dev/acpica/acpi_ec.c,v retrieving revision 1.20 diff -u -r1.20 acpi_ec.c --- dev/acpica/acpi_ec.c 28 Nov 2001 04:36:29 -0000 1.20 +++ dev/acpica/acpi_ec.c 3 Dec 2001 11:28:00 -0000 @@ -251,7 +251,9 @@ ACPI_STATUS status; status = AcpiAcquireGlobalLock(); - (sc)->ec_locked = 1; + if (status == AE_OK) + (sc)->ec_locked = 1; + return(status); } Index: dev/acpica/acpi_thermal.c =================================================================== RCS file: /home/ncvs/src/sys/dev/acpica/acpi_thermal.c,v retrieving revision 1.19 diff -u -r1.19 acpi_thermal.c --- dev/acpica/acpi_thermal.c 18 Nov 2001 18:12:07 -0000 1.19 +++ dev/acpica/acpi_thermal.c 3 Dec 2001 11:28:00 -0000 @@ -51,7 +51,7 @@ #define TZ_NOTIFY_DEVICES 0x81 #define TZ_NOTIFY_LEVELS 0x82 -#define TZ_POLLRATE (hz * 10) /* every ten seconds */ +#define TZ_POLLRATE 30 /* every 30 seconds by default */ #define TZ_NUMLEVELS 10 /* defined by ACPI spec */ struct acpi_tz_zone { @@ -127,6 +127,7 @@ static struct sysctl_oid *acpi_tz_sysctl_tree; static int acpi_tz_min_runtime = 0;/* minimum cooling run time */ +static int acpi_tz_polling_rate = TZ_POLLRATE; /* * Match an ACPI thermal zone. @@ -199,6 +200,10 @@ SYSCTL_CHILDREN(acpi_tz_sysctl_tree), OID_AUTO, "min_runtime", CTLFLAG_RD | 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, + &acpi_tz_polling_rate, 0, "monitor polling rate"); } sysctl_ctx_init(&sc->tz_sysctl_ctx); sprintf(oidname, "tz%d", device_get_unit(dev)); @@ -249,7 +254,7 @@ * Start the timeout routine, with enough delay for the rest of the * subsystem to come up. */ - sc->tz_timeout = timeout(acpi_tz_timeout, sc, TZ_POLLRATE); + sc->tz_timeout = timeout(acpi_tz_timeout, sc, acpi_tz_polling_rate * hz); return_VALUE(error); } @@ -693,7 +698,7 @@ /* XXX passive cooling actions? */ /* re-register ourself */ - sc->tz_timeout = timeout(acpi_tz_timeout, sc, TZ_POLLRATE); + sc->tz_timeout = timeout(acpi_tz_timeout, sc, acpi_tz_polling_rate * hz); ACPI_UNLOCK; } Index: dev/acpica/acpivar.h =================================================================== RCS file: /home/ncvs/src/sys/dev/acpica/acpivar.h,v retrieving revision 1.23 diff -u -r1.23 acpivar.h --- dev/acpica/acpivar.h 18 Nov 2001 18:12:07 -0000 1.23 +++ dev/acpica/acpivar.h 3 Dec 2001 11:28:00 -0000 @@ -361,3 +361,11 @@ typedef void (*powerprofile_change_hook)(void *); EVENTHANDLER_DECLARE(powerprofile_change, powerprofile_change_hook); + +#ifndef ACPI_NO_THREADS +/* + * ACPI task kernel thread initialization. + */ +extern int acpi_task_thread_init(void); +#endif + Index: dev/acpica/Osd/OsdSchedule.c =================================================================== RCS file: /home/ncvs/src/sys/dev/acpica/Osd/OsdSchedule.c,v retrieving revision 1.14 diff -u -r1.14 OsdSchedule.c --- dev/acpica/Osd/OsdSchedule.c 26 Oct 2001 18:46:46 -0000 1.14 +++ dev/acpica/Osd/OsdSchedule.c 3 Dec 2001 11:28:00 -0000 @@ -33,12 +33,20 @@ #include "acpi.h" +#include "opt_acpi.h" #include +#include +#include #include +#include #include #include #include +#include + +#include + #define _COMPONENT ACPI_OS_SERVICES MODULE_NAME("SCHEDULE") @@ -60,6 +68,73 @@ void *at_context; }; +struct acpi_task_queue { + STAILQ_ENTRY(acpi_task_queue) at_q; + struct acpi_task *at; +}; + +#ifndef ACPI_NO_THREADS +#ifndef ACPI_MAX_THREADS +#define ACPI_MAX_THREADS 1 +#endif + +STAILQ_HEAD(, acpi_task_queue) acpi_task_queue; +static struct mtx acpi_task_mtx; + +static void +acpi_task_thread(void *arg) +{ + struct acpi_task_queue *atq; + OSD_EXECUTION_CALLBACK Function; + void *Context; + + for (;;) { + mtx_lock(&acpi_task_mtx); + if ((atq = STAILQ_FIRST(&acpi_task_queue)) == NULL) { + msleep(&acpi_task_queue, &acpi_task_mtx, PCATCH, "actask", 0); + mtx_unlock(&acpi_task_mtx); + continue; + } + + STAILQ_REMOVE_HEAD(&acpi_task_queue, at_q); + mtx_unlock(&acpi_task_mtx); + + Function = (OSD_EXECUTION_CALLBACK)atq->at->at_function; + Context = atq->at->at_context; + + mtx_lock(&Giant); + Function(Context); + + free(atq->at, M_ACPITASK); + free(atq, M_ACPITASK); + mtx_unlock(&Giant); + } + + kthread_exit(0); +} + +int +acpi_task_thread_init(void) +{ + int i, err; + struct proc *acpi_kthread_proc; + + err = 0; + STAILQ_INIT(&acpi_task_queue); + mtx_init(&acpi_task_mtx, "ACPI task", MTX_DEF); + + for (i = 0; i < ACPI_MAX_THREADS; i++) { + err = kthread_create(acpi_task_thread, NULL, &acpi_kthread_proc, + 0, "acpi_task%d", i); + if (err != 0) { + printf(__func__ ": kthread_create failed(%d)\n", err); + break; + } + } + return (err); +} +#endif + ACPI_STATUS AcpiOsQueueForExecution(UINT32 Priority, OSD_EXECUTION_CALLBACK Function, void *Context) { @@ -104,18 +179,39 @@ static void AcpiOsExecuteQueue(void *arg, int pending) { - struct acpi_task *at = (struct acpi_task *)arg; + struct acpi_task *at; + struct acpi_task_queue *atq; OSD_EXECUTION_CALLBACK Function; void *Context; FUNCTION_TRACE(__func__); + at = (struct acpi_task *)arg; + atq = NULL; + Function = NULL; + Context = NULL; + +#ifndef ACPI_NO_THREADS + atq = malloc(sizeof(*atq), M_ACPITASK, M_NOWAIT); + if (atq == NULL) { + printf(__func__ ": no memory\n"); + return; + } + + atq->at = at; + + mtx_lock(&acpi_task_mtx); + STAILQ_INSERT_TAIL(&acpi_task_queue, atq, at_q); + mtx_unlock(&acpi_task_mtx); + wakeup_one(&acpi_task_queue); +#else Function = (OSD_EXECUTION_CALLBACK)at->at_function; Context = at->at_context; + Function(Context); free(at, M_ACPITASK); +#endif - Function(Context); return_VOID; } Index: dev/acpica/Osd/OsdSynch.c =================================================================== RCS file: /home/ncvs/src/sys/dev/acpica/Osd/OsdSynch.c,v retrieving revision 1.9 diff -u -r1.9 OsdSynch.c --- dev/acpica/Osd/OsdSynch.c 21 Jul 2001 04:10:01 -0000 1.9 +++ dev/acpica/Osd/OsdSynch.c 3 Dec 2001 11:28:00 -0000 @@ -33,19 +33,18 @@ #include "acpi.h" +#include "opt_acpi.h" #include #include #include #include +#include #define _COMPONENT ACPI_OS_SERVICES MODULE_NAME("SYNCH") static MALLOC_DEFINE(M_ACPISEM, "acpisem", "ACPI semaphore"); -/* disable semaphores - AML in the field doesn't use them correctly */ -#define ACPI_NO_SEMAPHORES - /* * Simple counting semaphore implemented using a mutex. (Subsequently used * in the OSI code to implement a mutex. Go figure.) @@ -54,8 +53,20 @@ struct mtx as_mtx; UINT32 as_units; UINT32 as_maxunits; + UINT32 as_pendings; + UINT32 as_timeouts; }; +#ifndef ACPI_NO_SEMAPHORES +#ifndef ACPI_SEMAPHORES_MAX_PENDING +#define ACPI_SEMAPHORES_MAX_PENDING 4 +#endif +static int acpi_semaphore_debug = 1; +TUNABLE_INT("debug.acpi_semaphore_debug", &acpi_semaphore_debug); +SYSCTL_INT(_debug, OID_AUTO, acpi_semaphore_debug, CTLFLAG_RW, + &acpi_semaphore_debug, 0, ""); +#endif + ACPI_STATUS AcpiOsCreateSemaphore(UINT32 MaxUnits, UINT32 InitialUnits, ACPI_HANDLE *OutHandle) { @@ -72,12 +83,16 @@ if ((as = malloc(sizeof(*as), M_ACPISEM, M_NOWAIT)) == NULL) return_ACPI_STATUS(AE_NO_MEMORY); + bzero(as, sizeof(*as)); mtx_init(&as->as_mtx, "ACPI semaphore", MTX_DEF); as->as_units = InitialUnits; as->as_maxunits = MaxUnits; + as->as_pendings = 0; + as->as_timeouts = 0; - DEBUG_PRINT(TRACE_MUTEX, ("created semaphore %p max %d, initial %d\n", - as, InitialUnits, MaxUnits)); + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, + "created semaphore %p max %d, initial %d\n", + as, InitialUnits, MaxUnits)); *OutHandle = (ACPI_HANDLE)as; return_ACPI_STATUS(AE_OK); @@ -95,7 +110,7 @@ FUNCTION_TRACE(__func__); - DEBUG_PRINT(TRACE_MUTEX, ("destroyed semaphore %p\n", as)); + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "destroyed semaphore %p\n", as)); mtx_destroy(&as->as_mtx); free(Handle, M_ACPISEM); return_ACPI_STATUS(AE_OK); @@ -116,27 +131,53 @@ struct acpi_semaphore *as = (struct acpi_semaphore *)Handle; ACPI_STATUS result; int rv, tmo; + struct timeval timeouttv, currenttv, timelefttv; FUNCTION_TRACE(__func__); if (as == NULL) return_ACPI_STATUS(AE_BAD_PARAMETER); - /* a timeout of -1 means "forever" */ - if (Timeout == -1) { + if (cold) + return_ACPI_STATUS(AE_OK); + + /* a timeout of 0xffffffff means "forever" */ + if (Timeout == 0xffffffff) { tmo = 0; + timeouttv.tv_sec = ((0xffff/1000) + 1); /* cf. ACPI spec */ + timeouttv.tv_usec = 0; } else { /* compute timeout using microseconds per tick */ tmo = (Timeout * 1000) / (1000000 / hz); if (tmo <= 0) tmo = 1; + timeouttv.tv_sec = Timeout / 1000; + timeouttv.tv_usec = (Timeout % 1000) * 1000; + } + + if (as->as_units < Units && as->as_timeouts > 10) { + getmicrotime(¤ttv); + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "semaphore %p too many timeouts, resetting\n", as)); + mtx_lock(&as->as_mtx); + as->as_units = as->as_maxunits; + as->as_pendings = 0; + as->as_timeouts = 0; + wakeup(as); + mtx_unlock(&as->as_mtx); + return_ACPI_STATUS(AE_TIME); } + /* calculate timeout value in timeval */ + getmicrotime(¤ttv); + timevaladd(&timeouttv, ¤ttv); + mtx_lock(&as->as_mtx); - DEBUG_PRINT(TRACE_MUTEX, ("get %d units from semaphore %p (has %d), timeout %d\n", - Units, as, as->as_units, Timeout)); + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, + "get %d units from semaphore %p (has %d), timeout %d\n", + Units, as, as->as_units, Timeout)); for (;;) { - if (as->as_inits == ACPI_NO_UNIT_LIMIT) { + if (as->as_units == ACPI_NO_UNIT_LIMIT) { result = AE_OK; break; } @@ -145,22 +186,82 @@ result = AE_OK; break; } - if (Timeout < 0) { + + /* limit number of pending treads */ + if (as->as_pendings >= ACPI_SEMAPHORES_MAX_PENDING) { + result = AE_TIME; + break; + } + + /* if timeout values of zero is specified, return immediately */ + if (Timeout == 0) { + result = AE_TIME; + break; + } + + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, + "semaphore blocked, calling msleep(%p, %p, %d, \"acsem\", %d)\n", + as, &as->as_mtx, PCATCH, tmo)); + + as->as_pendings++; + + if (acpi_semaphore_debug) { + printf(__func__ ": Sleep %d, pending %d, semaphore %p\n", + Timeout, as->as_pendings, as); + } + + mtx_unlock(&Giant); + rv = msleep(as, &as->as_mtx, PCATCH, "acsem", tmo); + mtx_lock(&Giant); + + if (as->as_pendings == 0) { + /* semaphore reset, return immediately */ result = AE_TIME; break; } - DEBUG_PRINT(TRACE_MUTEX, ("semaphore blocked, calling msleep(%p, %p, %d, \"acpisem\", %d)\n", - as, as->as_mtx, 0, tmo)); - - rv = msleep(as, &as->as_mtx, 0, "acpisem", tmo); - DEBUG_PRINT(TRACE_MUTEX, ("msleep returned %d\n", rv)); + + as->as_pendings--; + + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "msleep(%d) returned %d\n", tmo, rv)); if (rv == EWOULDBLOCK) { result = AE_TIME; break; } + + /* check if we already awaited enough */ + timelefttv = timeouttv; + getmicrotime(¤ttv); + timevalsub(&timelefttv, ¤ttv); + if (timelefttv.tv_sec < 0) { + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "await semaphore %p timeout\n", as)); + result = AE_TIME; + break; + } + + /* adjust timeout for the next sleep */ + tmo = (timelefttv.tv_sec * 1000000 + timelefttv.tv_usec) / (1000000 / hz); + if (tmo <= 0) + tmo = 1; + + if (acpi_semaphore_debug) { + printf(__func__ ": Wakeup timeleft(%lu, %lu), tmo %u, semaphore %p\n", + timelefttv.tv_sec, timelefttv.tv_usec, tmo, as); + } } + + if (result == AE_TIME) { + as->as_timeouts++; + } else { + as->as_timeouts = 0; + } + mtx_unlock(&as->as_mtx); + if (acpi_semaphore_debug && result == AE_TIME && Timeout > 0) { + printf(__func__ ": Timeout %d, pending %d, semaphore %p\n", + Timeout, as->as_pendings, as); + } + return_ACPI_STATUS(result); #else return(AE_OK); @@ -179,8 +280,9 @@ return_ACPI_STATUS(AE_BAD_PARAMETER); mtx_lock(&as->as_mtx); - DEBUG_PRINT(TRACE_MUTEX, ("return %d units to semaphore %p (has %d)\n", - Units, as, as->as_units)); + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, + "return %d units to semaphore %p (has %d)\n", + Units, as, as->as_units)); if (as->as_units != ACPI_NO_UNIT_LIMIT) { as->as_units += Units; if (as->as_units > as->as_maxunits) Index: dev/usb/ohci.c =================================================================== RCS file: /home/ncvs/src/sys/dev/usb/ohci.c,v retrieving revision 1.53 diff -u -r1.53 ohci.c --- dev/usb/ohci.c 12 Sep 2001 08:37:15 -0000 1.53 +++ dev/usb/ohci.c 3 Dec 2001 11:28:00 -0000 @@ -823,6 +823,7 @@ sc->sc_bus.methods = &ohci_bus_methods; sc->sc_bus.pipe_size = sizeof(struct ohci_pipe); + sc->sc_control = sc->sc_intre = 0; #if defined(__NetBSD__) sc->sc_powerhook = powerhook_establish(ohci_power, sc); sc->sc_shutdownhook = shutdownhook_establish(ohci_shutdown, sc); @@ -899,7 +900,6 @@ /* * Shut down the controller when the system is going down. */ -#if defined(__NetBSD__) || defined(__OpenBSD__) void ohci_shutdown(v) void *v; @@ -918,19 +918,69 @@ * are almost suspended anyway. */ void -ohci_power(why, v) - int why; - void *v; +ohci_power(int why, void *v) { -#ifdef OHCI_DEBUG ohci_softc_t *sc = v; + u_int32_t ctl; + int s; +#ifdef OHCI_DEBUG DPRINTF(("ohci_power: sc=%p, why=%d\n", sc, why)); - /* XXX should suspend/resume */ ohci_dumpregs(sc); #endif -} + + s = splusb(); + switch (why) { + case PWR_SUSPEND: +#if 0 + case PWR_STANDBY: #endif + sc->sc_bus.use_polling++; + ctl = OREAD4(sc, OHCI_CONTROL) & ~OHCI_HCFS_MASK; + if (sc->sc_control == 0) { + /* + * Preserve register values, in case that APM BIOS + * does not recover them. + */ + sc->sc_control = ctl; + sc->sc_intre = OREAD4(sc, OHCI_INTERRUPT_ENABLE); + } + ctl |= OHCI_HCFS_SUSPEND; + OWRITE4(sc, OHCI_CONTROL, ctl); + usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT); + sc->sc_bus.use_polling--; + break; + case PWR_RESUME: + sc->sc_bus.use_polling++; + /* Some broken BIOSes do not recover these values */ + OWRITE4(sc, OHCI_HCCA, DMAADDR(&sc->sc_hccadma, 0)); + OWRITE4(sc, OHCI_CONTROL_HEAD_ED, sc->sc_ctrl_head->physaddr); + OWRITE4(sc, OHCI_BULK_HEAD_ED, sc->sc_bulk_head->physaddr); + if (sc->sc_intre) + OWRITE4(sc, OHCI_INTERRUPT_ENABLE, + sc->sc_intre & (OHCI_ALL_INTRS | OHCI_MIE)); + if (sc->sc_control) + ctl = sc->sc_control; + else + ctl = OREAD4(sc, OHCI_CONTROL); + ctl |= OHCI_HCFS_RESUME; + OWRITE4(sc, OHCI_CONTROL, ctl); + usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY); + ctl = (ctl & ~OHCI_HCFS_MASK) | OHCI_HCFS_OPERATIONAL; + OWRITE4(sc, OHCI_CONTROL, ctl); + usb_delay_ms(&sc->sc_bus, USB_RESUME_RECOVERY); + sc->sc_control = sc->sc_intre = 0; + sc->sc_bus.use_polling--; + break; +#if 0 + case PWR_SOFTSUSPEND: + case PWR_SOFTSTANDBY: + case PWR_SOFTRESUME: + break; +#endif + } + splx(s); +} #ifdef OHCI_DEBUG void Index: dev/usb/ohcivar.h =================================================================== RCS file: /home/ncvs/src/sys/dev/usb/ohcivar.h,v retrieving revision 1.22 diff -u -r1.22 ohcivar.h --- dev/usb/ohcivar.h 17 Jul 2000 18:41:19 -0000 1.22 +++ dev/usb/ohcivar.h 3 Dec 2001 11:28:00 -0000 @@ -118,6 +118,8 @@ void *sc_powerhook; void *sc_shutdownhook; /* cookie from shutdown hook */ #endif + u_int32_t sc_control; /* Preserved during suspend/standby */ + u_int32_t sc_intre; device_ptr_t sc_child; } ohci_softc_t; @@ -127,6 +129,11 @@ #if defined(__NetBSD__) || defined(__OpenBSD__) int ohci_detach(ohci_softc_t *, int); int ohci_activate(device_ptr_t, enum devact); +#endif + +#if defined(__FreeBSD__) +void ohci_power(int state, void *); +void ohci_shutdown(void *); #endif #define MS_TO_TICKS(ms) ((ms) * hz / 1000) Index: i386/apm/apm.c =================================================================== RCS file: /home/ncvs/src/sys/i386/apm/apm.c,v retrieving revision 1.124 diff -u -r1.124 apm.c --- i386/apm/apm.c 1 Nov 2001 16:33:31 -0000 1.124 +++ i386/apm/apm.c 3 Dec 2001 11:28:00 -0000 @@ -243,12 +243,161 @@ return (sc->bios.r.ebx & 0xffff); } + +#ifndef KLD_MODULE +#include +#if __FreeBSD_version >= 500001 +#include +#endif +#define APM_FIVA_HACK +#endif + +#ifdef APM_FIVA_HACK +/* + * CASSIOPEIA FIVA suspend/resume hack by iwasaki@FreeBSD.org + * The following hack was done by the translation from the FIVA + * ACPI data blocks (_PTS and _WAK) into C code. + */ + +/* FIVA _PTS (Prepare To Sleep) */ +static void +apm_fiva_pts(void) +{ + u_int8_t *bdatap, bdata; +#if __FreeBSD_version < 500001 + pcicfgregs cfg; +#endif + + /* + * Store(0x85, \_SB_.PCI0.ISA_.BCMD) + * [aml_region_write(0, 0, 0x85, 0x6ffff2c, 0x0, 0x8)] + */ + pmap_kenter((vm_offset_t)ptvmmap, (0x6ffff2c) & ~PAGE_MASK); + bdatap = (u_int8_t *) &ptvmmap[0x6ffff2c & PAGE_MASK]; + *bdatap = 0x85; + + /* + * Store(0x0, \_SB_.PCI0.ISA_.SMIC) + * [aml_region_write(1, 0, 0x0, 0x8038, 0x0, 0x8)] + */ + outb(0x8038, 0x0); + + /* + * Store(0x81, \_SB_.PCI0.ISA_.BCMD) + * [aml_region_write(0, 0, 0x81, 0x6ffff2c, 0x0, 0x8)] + */ + *bdatap = 0x81; + + /* + * Store(0x0, \_SB_.PCI0.ISA_.SMIC) + * [aml_region_write(1, 0, 0x0, 0x8038, 0x0, 0x8)] + */ + outb(0x8038, 0x0); + + /* + * Store(0x0, \_SB_.PCI0.PM__.PPCM) + * [aml_region_write(2, 1, 0x0, 0x0, 0x454, 0x1)] + * Note: pciconf -v -l gives us the following; + * chip1@pci0:17:0: + * class=0x068000 card=0x00000000 chip=0x710110b9 rev=0x00 hdr=0x00 + * vendor = 'Acer Labs Inc.' + * device = 'M7101 Power Management Controller' + * class = bridge + * subclass = PCI-unknown + */ +#if __FreeBSD_version >= 500001 + if (!pci_cfgregopen()) + return; + bdata = pci_cfgregread(0, 17, 0, 0x8a, 1); + bdata &= ~(1 << 4); + if (!pci_cfgregopen()) + return; + pci_cfgregwrite(0, 17, 0, 0x8a, bdata, 1); +#else + cfg.bus = 0; cfg.slot = 17; cfg.func = 0; + bdata = (u_int8_t)pci_cfgread(&cfg, 0x8a, 1); + bdata &= ~(1 << 4); + pci_cfgwrite(&cfg, 0x8a, (u_int32_t)bdata, 1); +#endif + + /* + * Store(0x0, \_SB_.PCI0.PM__.PVGA) + * [aml_region_write(2, 1, 0x0, 0x0, 0x455, 0x1)] + */ +#if __FreeBSD_version >= 500001 + if (!pci_cfgregopen()) + return; + bdata = pci_cfgregread(0, 17, 0, 0x8a, 1); + bdata &= ~(1 << 5); + if (!pci_cfgregopen()) + return; + pci_cfgregwrite(0, 17, 0, 0x8a, bdata, 1); +#else + bdata = (u_int8_t)pci_cfgread(&cfg, 0x8a, 1); + bdata &= ~(1 << 5); + pci_cfgwrite(&cfg, 0x8a, (u_int32_t)bdata, 1); +#endif + + pmap_kremove((vm_offset_t)ptvmmap); +} + +/* FIVA _WAK (Wakeup) */ +static void +apm_fiva_wak(void) +{ + u_int8_t bdata; +#if __FreeBSD_version < 500001 + pcicfgregs cfg; +#endif + + /* + * Store(0x1, \_SB_.PCI0.PM__.PPCM) + * [aml_region_write(2, 1, 0x1, 0x0, 0x454, 0x1)] + */ +#if __FreeBSD_version >= 500001 + if (!pci_cfgregopen()) + return; + bdata = pci_cfgregread(0, 17, 0, 0x8a, 1); + bdata |= (1 << 4); + if (!pci_cfgregopen()) + return; + pci_cfgregwrite(0, 17, 0, 0x8a, bdata, 1); +#else + cfg.bus = 0; cfg.slot = 17; cfg.func = 0; + bdata = (u_int8_t)pci_cfgread(&cfg, 0x8a, 1); + bdata |= (1 << 4); + pci_cfgwrite(&cfg, 0x8a, (u_int32_t)bdata, 1); +#endif + + /* + * Store(0x1, \_SB_.PCI0.PM__.PVGA) + * [aml_region_write(2, 1, 0x1, 0x0, 0x455, 0x1)] + */ +#if __FreeBSD_version >= 500001 + if (!pci_cfgregopen()) + return; + bdata = pci_cfgregread(0, 17, 0, 0x8a, 1); + bdata |= (1 << 5); + if (!pci_cfgregopen()) + return; + pci_cfgregwrite(0, 17, 0, 0x8a, bdata, 1); +#else + bdata = (u_int8_t)pci_cfgread(&cfg, 0x8a, 1); + bdata |= (1 << 5); + pci_cfgwrite(&cfg, 0x8a, (u_int32_t)bdata, 1); +#endif +} +#endif + /* suspend entire system */ static int apm_suspend_system(int state) { struct apm_softc *sc = &apm_softc; +#ifdef APM_FIVA_HACK + apm_fiva_pts(); +#endif sc->bios.r.eax = (APM_BIOS << 8) | APM_SETPWSTATE; sc->bios.r.ebx = PMDV_ALLDEV; sc->bios.r.ecx = state; @@ -543,6 +692,9 @@ return; sc->suspending = 0; +#ifdef APM_FIVA_HACK + apm_fiva_wak(); +#endif if (sc->initialized) { apm_execute_hook(hook[APM_HOOK_RESUME]); DEVICE_RESUME(root_bus); Index: isa/syscons_isa.c =================================================================== RCS file: /home/ncvs/src/sys/isa/syscons_isa.c,v retrieving revision 1.17 diff -u -r1.17 syscons_isa.c --- isa/syscons_isa.c 30 Jun 2001 10:15:06 -0000 1.17 +++ isa/syscons_isa.c 3 Dec 2001 11:28:00 -0000 @@ -88,6 +88,39 @@ return sc_attach_unit(device_get_unit(dev), device_get_flags(dev)); } +static int sc_cur_scr; + +static int +scsuspend(device_t dev) +{ + int retry = 10; + static int dummy; + sc_softc_t *sc; + + sc = &main_softc; + sc_cur_scr = sc->cur_scp->index; + do { + sc_switch_scr(sc, 0); + if (!sc->switch_in_progress) { + break; + } + tsleep(&dummy, 0, "scsuspend", 100); + } while (retry--); + + return (0); +} + +static int +scresume(device_t dev) +{ + sc_softc_t *sc; + + sc = &main_softc; + sc_switch_scr(sc, sc_cur_scr); + + return (0); +} + int sc_max_unit(void) { @@ -230,6 +263,8 @@ DEVMETHOD(device_identify, scidentify), DEVMETHOD(device_probe, scprobe), DEVMETHOD(device_attach, scattach), + DEVMETHOD(device_suspend, scsuspend), + DEVMETHOD(device_resume, scresume), { 0, 0 } }; Index: modules/acpi/Makefile =================================================================== RCS file: /home/ncvs/src/sys/modules/acpi/Makefile,v retrieving revision 1.17 diff -u -r1.17 Makefile --- modules/acpi/Makefile 6 Nov 2001 15:00:30 -0000 1.17 +++ modules/acpi/Makefile 3 Dec 2001 11:28:00 -0000 @@ -36,6 +36,12 @@ SRCS+= OsdStream.c OsdSynch.c OsdEnvironment.c SRCS+= opt_acpi.h opt_ddb.h SRCS+= device_if.h bus_if.h pci_if.h pcib_if.h isa_if.h +.if ACPI_NO_SEMAPHORES +CFLAGS+=-DACPI_NO_SEMAPHORES +.endif +.if ACPI_NO_THREADS +CFLAGS+=-DACPI_NO_THREADS +.endif # Debugging support .if ACPI_DEBUG Index: pci/ohci_pci.c =================================================================== RCS file: /home/ncvs/src/sys/pci/ohci_pci.c,v retrieving revision 1.25 diff -u -r1.25 ohci_pci.c --- pci/ohci_pci.c 6 Nov 2001 23:44:03 -0000 1.25 +++ pci/ohci_pci.c 3 Dec 2001 11:28:00 -0000 @@ -98,6 +98,48 @@ static int ohci_pci_attach(device_t self); static int ohci_pci_detach(device_t self); +static int ohci_pci_suspend(device_t self); +static int ohci_pci_resume(device_t self); +static int ohci_pci_shutdown(device_t self); + +static int +ohci_pci_suspend(device_t self) +{ + ohci_softc_t *sc = device_get_softc(self); + int err; + + err = bus_generic_suspend(self); + if (err) + return err; + ohci_power(PWR_SUSPEND, sc); + + return 0; +} + +static int +ohci_pci_resume(device_t self) +{ + ohci_softc_t *sc = device_get_softc(self); + + ohci_power(PWR_RESUME, sc); + bus_generic_resume(self); + + return 0; +} + +static int +ohci_pci_shutdown(device_t self) +{ + ohci_softc_t *sc = device_get_softc(self); + int err; + + err = bus_generic_shutdown(self); + if (err) + return err; + ohci_shutdown(sc); + + return 0; +} static const char * ohci_pci_match(device_t self) @@ -272,6 +314,7 @@ /* XXX or should we panic? */ device_printf(self, "Could not tear down irq, %d\n", err); + bus_release_resource(self, SYS_RES_IRQ, 0, sc->irq_res); sc->irq_res = NULL; } @@ -280,11 +323,6 @@ sc->sc_bus.bdev = NULL; } - if (sc->irq_res) { - bus_release_resource(self, SYS_RES_IOPORT, 0, sc->irq_res); - sc->irq_res = NULL; - } - if (sc->io_res) { bus_release_resource(self, SYS_RES_MEMORY,PCI_CBMEM,sc->io_res); sc->io_res = NULL; @@ -299,7 +337,9 @@ /* Device interface */ DEVMETHOD(device_probe, ohci_pci_probe), DEVMETHOD(device_attach, ohci_pci_attach), - DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_suspend, ohci_pci_suspend), + DEVMETHOD(device_resume, ohci_pci_resume), + DEVMETHOD(device_shutdown, ohci_pci_shutdown), /* Bus interface */ DEVMETHOD(bus_print_child, bus_generic_print_child), Index: pci/vga_pci.c =================================================================== RCS file: pci/vga_pci.c diff -N pci/vga_pci.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ pci/vga_pci.c 3 Dec 2001 11:28:00 -0000 @@ -0,0 +1,78 @@ +#include +#include +#include +#include + +#include +#include + +static void vga_pci_identify(driver_t *driver, device_t parent); +static int vga_pci_attach(device_t dev); +static int vga_pci_probe(device_t dev); +static int vga_pci_suspend(device_t dev); +static int vga_pci_resume(device_t dev); + +static device_method_t vga_pci_methods[] = { + /* Device interface. */ + DEVMETHOD(device_identify, vga_pci_identify), + DEVMETHOD(device_probe, vga_pci_probe), + DEVMETHOD(device_attach, vga_pci_attach), + DEVMETHOD(device_suspend, vga_pci_suspend), + DEVMETHOD(device_resume, vga_pci_resume), + + { 0, 0 } +}; + +static driver_t vga_pci_driver = { + "vga_pci", + vga_pci_methods, + 0, +}; + +static devclass_t vga_pci_devclass; + +DRIVER_MODULE(vga_pci, pci, vga_pci_driver, vga_pci_devclass, 0, 0); + +static void +vga_pci_identify(driver_t *driver, device_t parent) +{ + + BUS_ADD_CHILD(parent, 255, "vga_pci", 0); +} + +static int +vga_pci_probe(device_t dev) +{ + + if (pci_get_class(dev) == PCIC_DISPLAY && + pci_get_subclass(dev) == PCIS_DISPLAY_VGA) { + device_set_desc(dev, "Generic PCI VGA"); + return (0); + } + + return (ENXIO); +} + +static int +vga_pci_attach(device_t dev) +{ + + return (0); +} + +static int +vga_pci_suspend(device_t dev) +{ + + pci_set_powerstate(dev, PCI_POWERSTATE_D2); + return (0); +} + +static int +vga_pci_resume(device_t dev) +{ + + pci_set_powerstate(dev, PCI_POWERSTATE_D0); + return (0); +} +