diff options
| author | jmcneill <jmcneill@NetBSD.org> | 2007-12-09 20:27:42 +0000 |
|---|---|---|
| committer | jmcneill <jmcneill@NetBSD.org> | 2007-12-09 20:27:42 +0000 |
| commit | 4c1d81b2b5fa658e9fd5e7151eb40ba71ba676da (patch) | |
| tree | 3f8b0d6c63745bde8809b8c6f9e4f6b1514f335e /sys/dev | |
| parent | 3947df41d16da8b387239b9b87789bfbe950a3b2 (diff) | |
Merge jmcneill-pm branch.
Diffstat (limited to 'sys/dev')
187 files changed, 3622 insertions, 4406 deletions
diff --git a/sys/dev/acpi/acpi.c b/sys/dev/acpi/acpi.c index bed7d0a6fb4..f94dc796ada 100644 --- a/sys/dev/acpi/acpi.c +++ b/sys/dev/acpi/acpi.c @@ -1,4 +1,4 @@ -/* $NetBSD: acpi.c,v 1.103 2007/12/05 07:06:50 ad Exp $ */ +/* $NetBSD: acpi.c,v 1.104 2007/12/09 20:27:52 jmcneill Exp $ */ /*- * Copyright (c) 2003, 2007 The NetBSD Foundation, Inc. @@ -77,7 +77,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.103 2007/12/05 07:06:50 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.104 2007/12/09 20:27:52 jmcneill Exp $"); #include "opt_acpi.h" #include "opt_pcifixup.h" @@ -122,6 +122,8 @@ MALLOC_DECLARE(M_ACPI); static int acpi_dbgr = 0x00; #endif +static ACPI_TABLE_DESC acpi_initial_tables[128]; + static int acpi_match(struct device *, struct cfdata *, void *); static void acpi_attach(struct device *, struct device *, void *); @@ -203,6 +205,9 @@ acpi_probe(void) acpi_osd_debugger(); #endif + AcpiGbl_AllMethodsSerialized = FALSE; + AcpiGbl_EnableInterpreterSlack = TRUE; + rv = AcpiInitializeSubsystem(); if (ACPI_FAILURE(rv)) { printf("ACPI: unable to initialize ACPICA: %s\n", @@ -210,6 +215,20 @@ acpi_probe(void) return 0; } + rv = AcpiInitializeTables(acpi_initial_tables, 128, 0); + if (ACPI_FAILURE(rv)) { + printf("ACPI: unable to initialize ACPI tables: %s\n", + AcpiFormatException(rv)); + return 0; + } + + rv = AcpiReallocateRootTable(); + if (ACPI_FAILURE(rv)) { + printf("ACPI: unable to reallocate root table: %s\n", + AcpiFormatException(rv)); + return 0; + } + #ifdef ACPI_DEBUGGER if (acpi_dbgr & ACPI_DBGR_TABLES) acpi_osd_debugger(); @@ -222,7 +241,7 @@ acpi_probe(void) return 0; } - +#if notyet if (!acpi_force_load && (acpi_find_quirks() & ACPI_QUIRK_BROKEN)) { printf("ACPI: BIOS implementation in listed as broken:\n"); printf("ACPI: X/RSDT: OemId <%6.6s,%8.8s,%08x>, " @@ -235,6 +254,36 @@ acpi_probe(void) return 0; } + /* Install the default address space handlers. */ + rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT, + ACPI_ADR_SPACE_SYSTEM_MEMORY, ACPI_DEFAULT_HANDLER, NULL, NULL); + if (ACPI_FAILURE(rv)) { + printf("ACPI: unable to initialise SystemMemory handler: %s\n", + AcpiFormatException(rv)); + return 0; + } + rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT, + ACPI_ADR_SPACE_SYSTEM_IO, ACPI_DEFAULT_HANDLER, NULL, NULL); + if (ACPI_FAILURE(rv)) { + printf("ACPI: unable to initialise SystemIO handler: %s\n", + AcpiFormatException(rv)); + return 0; + } + rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT, + ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL); + if (ACPI_FAILURE(rv)) { + printf("ACPI: unabled to initialise PciConfig handler: %s\n", + AcpiFormatException(rv)); + return 0; + } +#endif + + rv = AcpiEnableSubsystem(~(ACPI_NO_HARDWARE_INIT|ACPI_NO_ACPI_ENABLE)); + if (ACPI_FAILURE(rv)) { + printf("ACPI: unable to enable: %s\n", AcpiFormatException(rv)); + return 0; + } + /* * Looks like we have ACPI! */ @@ -257,10 +306,10 @@ acpi_check(device_t parent, const char *ifattr) return (config_search_ia(acpi_submatch, parent, ifattr, NULL) != NULL); } -ACPI_STATUS -acpi_OsGetRootPointer(UINT32 Flags, ACPI_POINTER *PhysicalAddress) +ACPI_PHYSICAL_ADDRESS +acpi_OsGetRootPointer(void) { - ACPI_STATUS rv; + ACPI_PHYSICAL_ADDRESS PhysicalAddress; /* * IA-32: Use AcpiFindRootPointer() to locate the RSDP. @@ -271,13 +320,12 @@ acpi_OsGetRootPointer(UINT32 Flags, ACPI_POINTER *PhysicalAddress) * ways to do it. */ - rv = acpi_md_OsGetRootPointer(Flags, PhysicalAddress); + PhysicalAddress = acpi_md_OsGetRootPointer(); - if (acpi_root_pointer == 0 && ACPI_SUCCESS(rv)) - acpi_root_pointer = - (uint64_t)PhysicalAddress->Pointer.Physical; + if (acpi_root_pointer == 0) + acpi_root_pointer = PhysicalAddress; - return rv; + return PhysicalAddress; } /* @@ -324,11 +372,13 @@ acpi_attach(struct device *parent, struct device *self, void *aux) aprint_verbose("%s: using Intel ACPI CA subsystem version %08x\n", sc->sc_dev.dv_xname, ACPI_CA_VERSION); +#if 0 aprint_verbose("%s: X/RSDT: OemId <%6.6s,%8.8s,%08x>, AslId <%4.4s,%08x>\n", sc->sc_dev.dv_xname, AcpiGbl_XSDT->OemId, AcpiGbl_XSDT->OemTableId, AcpiGbl_XSDT->OemRevision, AcpiGbl_XSDT->AslCompilerId, AcpiGbl_XSDT->AslCompilerRevision); +#endif sc->sc_quirks = acpi_find_quirks(); @@ -341,6 +391,12 @@ acpi_attach(struct device *parent, struct device *self, void *aux) acpi_softc = sc; /* + * Register null power management handler + */ + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); + + /* * Bring ACPI on-line. */ #ifdef ACPI_DEBUGGER @@ -348,7 +404,22 @@ acpi_attach(struct device *parent, struct device *self, void *aux) acpi_osd_debugger(); #endif - rv = AcpiEnableSubsystem(0); +#define ACPI_ENABLE_PHASE1 \ + (ACPI_NO_HANDLER_INIT | ACPI_NO_EVENT_INIT) +#define ACPI_ENABLE_PHASE2 \ + (ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE | \ + ACPI_NO_ADDRESS_SPACE_INIT) + + rv = AcpiEnableSubsystem(ACPI_ENABLE_PHASE1); + if (ACPI_FAILURE(rv)) { + aprint_error("%s: unable to enable ACPI: %s\n", + sc->sc_dev.dv_xname, AcpiFormatException(rv)); + return; + } + + acpi_md_callback(); + + rv = AcpiEnableSubsystem(ACPI_ENABLE_PHASE2); if (ACPI_FAILURE(rv)) { aprint_error("%s: unable to enable ACPI: %s\n", sc->sc_dev.dv_xname, AcpiFormatException(rv)); @@ -356,11 +427,9 @@ acpi_attach(struct device *parent, struct device *self, void *aux) } /* early EC handler initialization if ECDT table is available */ -#if NACPIEC > 0 - acpiec_early_attach(&sc->sc_dev); -#endif + config_found_ia(&sc->sc_dev, "acpiecdtbus", NULL, NULL); - rv = AcpiInitializeObjects(0); + rv = AcpiInitializeObjects(ACPI_FULL_INITIALIZATION); if (ACPI_FAILURE(rv)) { aprint_error("%s: unable to initialize ACPI objects: %s\n", sc->sc_dev.dv_xname, AcpiFormatException(rv)); @@ -372,9 +441,9 @@ acpi_attach(struct device *parent, struct device *self, void *aux) sc->sc_sleepstate = ACPI_STATE_S0; /* Show SCI interrupt. */ - if (AcpiGbl_FADT != NULL) - aprint_verbose("%s: SCI interrupting at int %d\n", - sc->sc_dev.dv_xname, AcpiGbl_FADT->SciInt); + aprint_verbose("%s: SCI interrupting at int %d\n", + sc->sc_dev.dv_xname, AcpiGbl_FADT.SciInterrupt); + /* * Check for fixed-hardware features. */ @@ -388,7 +457,6 @@ acpi_attach(struct device *parent, struct device *self, void *aux) if (acpi_dbgr & ACPI_DBGR_PROBE) acpi_osd_debugger(); #endif - acpi_md_callback((struct device *)sc); acpi_build_tree(sc); if (acpi_root_pointer != 0 && acpi_node != CTL_EOL) { @@ -529,15 +597,18 @@ acpi_build_tree(struct acpi_softc *sc) (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED| ACPI_STA_DEV_OK)) continue; - - /* - * XXX Same problem as above... - */ - if ((ad->ad_devinfo->Valid & ACPI_VALID_HID) - == 0) - continue; } + /* + * XXX Same problem as above... + * + * Do this check only for devices, as e.g. + * a Thermal Zone doesn't have a HID. + */ + if (ad->ad_devinfo->Type == ACPI_TYPE_DEVICE && + (ad->ad_devinfo->Valid & ACPI_VALID_HID) == 0) + continue; + ad->ad_device = config_found_ia(&sc->sc_dev, "acpinodebus", &aa, acpi_print); } @@ -658,7 +729,8 @@ acpi_make_devnode(ACPI_HANDLE handle, UINT32 level, void *context, TAILQ_INSERT_TAIL(&as->as_devnodes, ad, ad_list); - if ((ad->ad_devinfo->Valid & ACPI_VALID_HID) == 0) + if (type == ACPI_TYPE_DEVICE && + (ad->ad_devinfo->Valid & ACPI_VALID_HID) == 0) goto out; #ifdef ACPI_EXTRA_DEBUG @@ -722,13 +794,15 @@ acpi_print(void *aux, const char *pnp) } #endif - } else { + aprint_normal("at %s", pnp); + } else if (aa->aa_node->ad_devinfo->Type != ACPI_TYPE_DEVICE) { aprint_normal("%s (ACPI Object Type '%s' " "[0x%02x]) ", aa->aa_node->ad_name, AcpiUtGetTypeName(aa->aa_node->ad_devinfo->Type), aa->aa_node->ad_devinfo->Type); - } - aprint_normal("at %s", pnp); + aprint_normal("at %s", pnp); + } else + return 0; } else { aprint_normal(" (%s", aa->aa_node->ad_name); if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_HID) { @@ -773,7 +847,7 @@ acpi_enable_fixed_events(struct acpi_softc *sc) * Check for fixed-hardware buttons. */ - if (AcpiGbl_FADT != NULL && AcpiGbl_FADT->PwrButton == 0) { + if ((AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON) == 0) { aprint_verbose("%s: fixed-feature power button present\n", sc->sc_dev.dv_xname); sc->sc_smpsw_power.smpsw_name = sc->sc_dev.dv_xname; @@ -794,7 +868,7 @@ acpi_enable_fixed_events(struct acpi_softc *sc) } } - if (AcpiGbl_FADT != NULL && AcpiGbl_FADT->SleepButton == 0) { + if ((AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON) == 0) { aprint_verbose("%s: fixed-feature sleep button present\n", sc->sc_dev.dv_xname); sc->sc_smpsw_sleep.smpsw_name = sc->sc_dev.dv_xname; @@ -831,7 +905,7 @@ acpi_fixed_button_handler(void *context) printf("%s: fixed button handler\n", smpsw->smpsw_name); #endif - rv = AcpiOsQueueForExecution(OSD_PRIORITY_LO, + rv = AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_fixed_button_pressed, smpsw); if (ACPI_FAILURE(rv)) printf("%s: WARNING: unable to queue fixed button pressed " @@ -1085,7 +1159,7 @@ is_available_state(struct acpi_softc *sc, int state) ACPI_STATUS acpi_enter_sleep_state(struct acpi_softc *sc, int state) { - int s; + int err; ACPI_STATUS ret = AE_OK; if (state == acpi_sleepstate) @@ -1105,32 +1179,33 @@ acpi_enter_sleep_state(struct acpi_softc *sc, int state) sc->sc_dev.dv_xname, state); break; } + + if (state != ACPI_STATE_S1 && !pmf_system_suspend()) { + aprint_error_dev(&sc->sc_dev, "aborting suspend"); + break; + } + ret = AcpiEnterSleepStatePrep(state); if (ACPI_FAILURE(ret)) { aprint_error("%s: failed preparing to sleep (%s)\n", sc->sc_dev.dv_xname, AcpiFormatException(ret)); break; } + acpi_sleepstate = state; if (state == ACPI_STATE_S1) { /* just enter the state */ acpi_md_OsDisableInterrupt(); AcpiEnterSleepState((UINT8)state); + AcpiLeaveSleepState((UINT8)state); } else { - /* XXX: powerhooks(9) framework is too poor to - * support ACPI sleep state... - */ - dopowerhooks(PWR_SOFTSUSPEND); - s = splhigh(); - dopowerhooks(PWR_SUSPEND); - acpi_md_sleep(state); - dopowerhooks(PWR_RESUME); - splx(s); - dopowerhooks(PWR_SOFTRESUME); - if (state==ACPI_STATE_S4) + err = acpi_md_sleep(state); + if (state == ACPI_STATE_S4) AcpiEnable(); + AcpiLeaveSleepState((UINT8)state); + pmf_system_resume(); } - AcpiLeaveSleepState((UINT8)state); + break; case ACPI_STATE_S5: ret = AcpiEnterSleepStatePrep(ACPI_STATE_S5); @@ -1139,6 +1214,7 @@ acpi_enter_sleep_state(struct acpi_softc *sc, int state) sc->sc_dev.dv_xname, AcpiFormatException(ret)); break; } + DELAY(1000000); acpi_sleepstate = state; acpi_md_OsDisableInterrupt(); AcpiEnterSleepState(ACPI_STATE_S5); @@ -1147,7 +1223,6 @@ acpi_enter_sleep_state(struct acpi_softc *sc, int state) break; } - aprint_normal("%s: resuming\n", sc->sc_dev.dv_xname); acpi_sleepstate = ACPI_STATE_S0; return ret; } diff --git a/sys/dev/acpi/acpi_acad.c b/sys/dev/acpi/acpi_acad.c index da2e9154292..9b762ccc462 100644 --- a/sys/dev/acpi/acpi_acad.c +++ b/sys/dev/acpi/acpi_acad.c @@ -1,4 +1,4 @@ -/* $NetBSD: acpi_acad.c,v 1.30 2007/12/05 07:06:50 ad Exp $ */ +/* $NetBSD: acpi_acad.c,v 1.31 2007/12/09 20:27:52 jmcneill Exp $ */ /* * Copyright 2001 Wasabi Systems, Inc. @@ -44,7 +44,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: acpi_acad.c,v 1.30 2007/12/05 07:06:50 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acpi_acad.c,v 1.31 2007/12/09 20:27:52 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -151,6 +151,9 @@ acpiacad_attach(device_t parent, device_t self, void *aux) sc->sc_flags = AACAD_F_VERBOSE; #endif + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); + acpiacad_init_envsys(self); } @@ -247,7 +250,7 @@ acpiacad_notify_handler(ACPI_HANDLE handle, UINT32 notify, void *context) acpiacad_clear_status(sc); mutex_exit(&sc->sc_mtx); if (sc->sc_status == -1 || !sc->sc_notifysent) { - rv = AcpiOsQueueForExecution(OSD_PRIORITY_LO, + rv = AcpiOsExecute(OSL_NOTIFY_HANDLER, acpiacad_get_status, dv); if (ACPI_FAILURE(rv)) aprint_error_dev(dv, diff --git a/sys/dev/acpi/acpi_apm.c b/sys/dev/acpi/acpi_apm.c index 64ece3a11ed..e69b2772356 100644 --- a/sys/dev/acpi/acpi_apm.c +++ b/sys/dev/acpi/acpi_apm.c @@ -1,4 +1,4 @@ -/* $NetBSD: acpi_apm.c,v 1.11 2007/10/27 19:51:29 plunky Exp $ */ +/* $NetBSD: acpi_apm.c,v 1.12 2007/12/09 20:27:52 jmcneill Exp $ */ /*- * Copyright (c) 2006 The NetBSD Foundation, Inc. @@ -42,7 +42,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: acpi_apm.c,v 1.11 2007/10/27 19:51:29 plunky Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acpi_apm.c,v 1.12 2007/12/09 20:27:52 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -337,7 +337,8 @@ acpiapm_get_powstat(void *opaque, u_int batteryid, else if (strstr(desc, " design cap")) descap = data / 1000; else if (strstr(desc, " charge") && - strstr(desc, " charge rate") == NULL) { + strstr(desc, " charge rate") == NULL && + strstr(desc, " charge state") == NULL) { cap += data / 1000; cap_valid = 1; pinfo->nbattery++; diff --git a/sys/dev/acpi/acpi_bat.c b/sys/dev/acpi/acpi_bat.c index ea32f286a71..e9778224a80 100644 --- a/sys/dev/acpi/acpi_bat.c +++ b/sys/dev/acpi/acpi_bat.c @@ -1,4 +1,4 @@ -/* $NetBSD: acpi_bat.c,v 1.63 2007/12/05 07:06:50 ad Exp $ */ +/* $NetBSD: acpi_bat.c,v 1.64 2007/12/09 20:27:52 jmcneill Exp $ */ /*- * Copyright (c) 2003 The NetBSD Foundation, Inc. @@ -86,7 +86,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: acpi_bat.c,v 1.63 2007/12/05 07:06:50 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acpi_bat.c,v 1.64 2007/12/09 20:27:52 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -239,6 +239,9 @@ acpibat_attach(device_t parent, device_t self, void *aux) ABAT_SET(sc, ABAT_F_VERBOSE); #endif + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); + acpibat_init_envsys(self); } @@ -648,8 +651,7 @@ acpibat_notify_handler(ACPI_HANDLE handle, UINT32 notify, void *context) mutex_enter(&sc->sc_mtx); acpibat_clear_presence(sc); mutex_exit(&sc->sc_mtx); - rv = AcpiOsQueueForExecution(OSD_PRIORITY_LO, - acpibat_update, dv); + rv = AcpiOsExecute(OSL_NOTIFY_HANDLER, acpibat_update, dv); if (ACPI_FAILURE(rv)) aprint_error_dev(dv, "unable to queue status check: %s\n", @@ -660,8 +662,7 @@ acpibat_notify_handler(ACPI_HANDLE handle, UINT32 notify, void *context) mutex_enter(&sc->sc_mtx); acpibat_clear_stat(sc); mutex_exit(&sc->sc_mtx); - rv = AcpiOsQueueForExecution(OSD_PRIORITY_LO, - acpibat_update, dv); + rv = AcpiOsExecute(OSL_NOTIFY_HANDLER, acpibat_update, dv); if (ACPI_FAILURE(rv)) aprint_error_dev(dv, "unable to queue status check: %s\n", diff --git a/sys/dev/acpi/acpi_button.c b/sys/dev/acpi/acpi_button.c index d38e7bf5f70..9a68ab11057 100644 --- a/sys/dev/acpi/acpi_button.c +++ b/sys/dev/acpi/acpi_button.c @@ -1,4 +1,4 @@ -/* $NetBSD: acpi_button.c,v 1.24 2007/10/24 07:05:35 joerg Exp $ */ +/* $NetBSD: acpi_button.c,v 1.25 2007/12/09 20:27:52 jmcneill Exp $ */ /* * Copyright 2001, 2003 Wasabi Systems, Inc. @@ -40,7 +40,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: acpi_button.c,v 1.24 2007/10/24 07:05:35 joerg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acpi_button.c,v 1.25 2007/12/09 20:27:52 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -151,6 +151,9 @@ acpibut_attach(device_t parent, device_t self, void *aux) /* Display the current state when it changes. */ sc->sc_flags = ACPIBUT_F_VERBOSE; #endif + + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); } /* @@ -189,7 +192,7 @@ acpibut_notify_handler(ACPI_HANDLE handle, UINT32 notify, void *context) #ifdef ACPI_BUT_DEBUG aprint_debug_dev(dv, "received ButtonPressed message\n"); #endif - rv = AcpiOsQueueForExecution(OSD_PRIORITY_LO, + rv = AcpiOsExecute(OSL_NOTIFY_HANDLER, acpibut_pressed_event, dv); if (ACPI_FAILURE(rv)) aprint_error_dev(dv, diff --git a/sys/dev/acpi/acpi_ec.c b/sys/dev/acpi/acpi_ec.c index 62dd477ab51..c3e686ff68f 100644 --- a/sys/dev/acpi/acpi_ec.c +++ b/sys/dev/acpi/acpi_ec.c @@ -1,355 +1,207 @@ -/* $NetBSD: acpi_ec.c,v 1.43 2007/12/05 07:58:29 ad Exp $ */ - -/* - * Copyright 2001 Wasabi Systems, Inc. - * All rights reserved. - * - * Written by Jason R. Thorpe for Wasabi Systems, Inc. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the NetBSD Project by - * Wasabi Systems, Inc. - * 4. The name of Wasabi Systems, Inc. may not be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC - * 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. - */ +/* $NetBSD: acpi_ec.c,v 1.44 2007/12/09 20:27:52 jmcneill Exp $ */ /*- - * Copyright (c) 2000 Michael Smith - * Copyright (c) 2000 BSDi + * Copyright (c) 2007 Joerg Sonnenberger <joerg@NetBSD.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. + * 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 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDERS 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. */ -/****************************************************************************** - * - * 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> -__KERNEL_RCSID(0, "$NetBSD: acpi_ec.c,v 1.43 2007/12/05 07:58:29 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acpi_ec.c,v 1.44 2007/12/09 20:27:52 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> +#include <sys/condvar.h> #include <sys/device.h> -#include <sys/malloc.h> -#include <sys/proc.h> #include <sys/kernel.h> +#include <sys/kthread.h> +#include <sys/mutex.h> #include <sys/bus.h> -#include <dev/acpi/acpica.h> -#include <dev/acpi/acpireg.h> #include <dev/acpi/acpivar.h> -#include <dev/acpi/acpi_ecreg.h> -MALLOC_DECLARE(M_ACPI); +/* Maximum time to wait for global ACPI lock in ms */ +#define EC_LOCK_TIMEOUT 5 + +/* Maximum time to poll for completion of a command in ms */ +#define EC_POLL_TIMEOUT 5 + +/* From ACPI 3.0b, chapter 12.3 */ +#define EC_COMMAND_READ 0x80 +#define EC_COMMAND_WRITE 0x81 +#define EC_COMMAND_BURST_EN 0x82 +#define EC_COMMAND_BURST_DIS 0x83 +#define EC_COMMAND_QUERY 0x84 -#define _COMPONENT ACPI_EC_COMPONENT -ACPI_MODULE_NAME("EC") +/* From ACPI 3.0b, chapter 12.2.1 */ +#define EC_STATUS_OBF 0x01 +#define EC_STATUS_IBF 0x02 +#define EC_STATUS_CMD 0x08 +#define EC_STATUS_BURST 0x10 +#define EC_STATUS_SCI 0x20 +#define EC_STATUS_SMI 0x40 -struct acpi_ec_softc { - struct device sc_dev; /* base device glue */ - ACPI_HANDLE sc_handle; /* ACPI handle */ +static const char *ec_hid[] = { + "PNP0C09", + NULL, +}; - UINT32 sc_gpebit; /* our GPE interrupt bit */ +enum ec_state_t { + EC_STATE_QUERY, + EC_STATE_QUERY_VAL, + EC_STATE_READ, + EC_STATE_READ_ADDR, + EC_STATE_READ_VAL, + EC_STATE_WRITE, + EC_STATE_WRITE_ADDR, + EC_STATE_WRITE_VAL, + EC_STATE_FREE +}; - bus_space_tag_t sc_data_st; /* space tag for data register */ - bus_space_handle_t sc_data_sh; /* space handle for data register */ +struct acpiec_softc { + ACPI_HANDLE sc_ech; - bus_space_tag_t sc_csr_st; /* space tag for control register */ - bus_space_handle_t sc_csr_sh; /* space handle for control register */ + ACPI_HANDLE sc_gpeh; + UINT8 sc_gpebit; - int sc_flags; /* see below */ + bus_space_tag_t sc_data_st; + bus_space_handle_t sc_data_sh; - uint32_t sc_csrvalue; /* saved control register */ - uint32_t sc_uid; /* _UID in namespace (ECDT only) */ + bus_space_tag_t sc_csr_st; + bus_space_handle_t sc_csr_sh; - kmutex_t sc_lock; /* serialize operations to this EC */ - struct simplelock sc_slock; /* protect against interrupts */ - UINT32 sc_glkhandle; /* global lock handle */ - UINT32 sc_glk; /* need global lock? */ -}; + bool sc_need_global_lock; + UINT32 sc_global_lock; -static const char * const ec_hid[] = { - "PNP0C09", - NULL + kmutex_t sc_mtx, sc_access_mtx; + kcondvar_t sc_cv, sc_cv_sci; + enum ec_state_t sc_state; + bool sc_got_sci; + + uint8_t sc_cur_addr, sc_cur_val; }; -#define EC_F_TRANSACTION 0x01 /* doing transaction */ -#define EC_F_PENDQUERY 0x02 /* query is pending */ +static int acpiecdt_match(device_t, struct cfdata *, void *); +static void acpiecdt_attach(device_t, device_t, void *); -/* - * how long to wait to acquire global lock. - * the value is taken from FreeBSD driver. - */ -#define EC_LOCK_TIMEOUT 1000 - -#define EC_DATA_READ(sc) \ - bus_space_read_1((sc)->sc_data_st, (sc)->sc_data_sh, 0) -#define EC_DATA_WRITE(sc, v) \ - bus_space_write_1((sc)->sc_data_st, (sc)->sc_data_sh, 0, (v)) - -#define EC_CSR_READ(sc) \ - bus_space_read_1((sc)->sc_csr_st, (sc)->sc_csr_sh, 0) -#define EC_CSR_WRITE(sc, v) \ - bus_space_write_1((sc)->sc_csr_st, (sc)->sc_csr_sh, 0, (v)) - -typedef struct { - EC_COMMAND Command; - UINT8 Address; - UINT8 Data; -} EC_REQUEST; - -static UINT32 EcGpeHandler(void *); -static ACPI_STATUS EcSpaceSetup(ACPI_HANDLE, UINT32, void *, void **); -static ACPI_STATUS EcSpaceHandler(UINT32, ACPI_PHYSICAL_ADDRESS, UINT32, - ACPI_INTEGER *, void *, void *); - -static ACPI_STATUS EcWaitEvent(struct acpi_ec_softc *, EC_EVENT); -static ACPI_STATUS EcQuery(struct acpi_ec_softc *, UINT8 *); -static ACPI_STATUS EcTransaction(struct acpi_ec_softc *, EC_REQUEST *); -static ACPI_STATUS EcRead(struct acpi_ec_softc *, UINT8, UINT8 *); -static ACPI_STATUS EcWrite(struct acpi_ec_softc *, UINT8, UINT8 *); -static void EcGpeQueryHandler(void *); -static inline int EcIsLocked(struct acpi_ec_softc *); -static inline void EcLock(struct acpi_ec_softc *); -static inline void EcUnlock(struct acpi_ec_softc *); - - -static int acpiec_match(struct device *, struct cfdata *, void *); -static void acpiec_attach(struct device *, struct device *, void *); - -CFATTACH_DECL(acpiec, sizeof(struct acpi_ec_softc), +static int acpiec_match(device_t, struct cfdata *, void *); +static void acpiec_attach(device_t, device_t, void *); + +static void acpiec_common_attach(device_t, device_t, ACPI_HANDLE, + bus_addr_t, bus_addr_t, ACPI_HANDLE, uint8_t); + +static bool acpiec_resume(device_t); +static bool acpiec_suspend(device_t); + +static bool acpiec_parse_gpe_package(device_t, ACPI_HANDLE, + ACPI_HANDLE *, uint8_t *); + +static void acpiec_gpe_query(void *); +static UINT32 acpiec_gpe_handler(void *); +static ACPI_STATUS acpiec_space_setup(ACPI_HANDLE, UINT32, void *, void **); +static ACPI_STATUS acpiec_space_handler(UINT32, ACPI_PHYSICAL_ADDRESS, + UINT32, ACPI_INTEGER *, void *, void *); + +static void acpiec_gpe_state_maschine(device_t); + +CFATTACH_DECL_NEW(acpiec, sizeof(struct acpiec_softc), acpiec_match, acpiec_attach, NULL, NULL); -static struct acpi_ec_softc *ecdt_sc; +CFATTACH_DECL_NEW(acpiecdt, sizeof(struct acpiec_softc), + acpiecdt_match, acpiecdt_attach, NULL, NULL); -static inline int -EcIsLocked(struct acpi_ec_softc *sc) +static device_t ec_singleton = NULL; +static bool acpiec_cold = false; + +static bool +acpiecdt_find(device_t parent, ACPI_HANDLE *ec_handle, + bus_addr_t *cmd_reg, bus_addr_t *data_reg, uint8_t *gpebit) { + ACPI_TABLE_ECDT *ecdt; + ACPI_STATUS rv; + + rv = AcpiGetTable(ACPI_SIG_ECDT, 1, (ACPI_TABLE_HEADER **)&ecdt); + if (ACPI_FAILURE(rv)) + return false; - return (mutex_owned(&sc->sc_lock)); + if (ecdt->Control.BitWidth != 8 || ecdt->Data.BitWidth != 8) { + aprint_error_dev(parent, + "ECDT register width invalid (%d/%d)\n", + ecdt->Control.BitWidth, ecdt->Data.BitWidth); + return false; + } + + rv = AcpiGetHandle(ACPI_ROOT_OBJECT, ecdt->Id, ec_handle); + if (ACPI_FAILURE(rv)) { + aprint_error_dev(parent, + "failed to look up EC object %s: %s\n", + ecdt->Id, AcpiFormatException(rv)); + return false; + } + + *cmd_reg = ecdt->Control.Address; + *data_reg = ecdt->Data.Address; + *gpebit = ecdt->Gpe; + + return true; } -static inline void -EcLock(struct acpi_ec_softc *sc) +static int +acpiecdt_match(device_t parent, struct cfdata *match, void *aux) { - ACPI_STATUS rv; - int s; - - mutex_enter(&sc->sc_lock); - if (sc->sc_glk) { - rv = AcpiAcquireGlobalLock(EC_LOCK_TIMEOUT, - &sc->sc_glkhandle); - if (ACPI_FAILURE(rv)) { - printf("%s: failed to acquire global lock\n", - sc->sc_dev.dv_xname); - mutex_exit(&sc->sc_lock); - return; - } - } + ACPI_HANDLE ec_handle; + bus_addr_t cmd_reg, data_reg; + uint8_t gpebit; - s = splvm(); /* XXX */ - simple_lock(&sc->sc_slock); - sc->sc_flags |= EC_F_TRANSACTION; - simple_unlock(&sc->sc_slock); - splx(s); + if (acpiecdt_find(parent, &ec_handle, &cmd_reg, &data_reg, &gpebit)) + return 1; + else + return 0; } -static inline void -EcUnlock(struct acpi_ec_softc *sc) +static void +acpiecdt_attach(device_t parent, device_t self, void *aux) { - ACPI_STATUS rv; - int s; + ACPI_HANDLE ec_handle; + bus_addr_t cmd_reg, data_reg; + uint8_t gpebit; - /* - * Clear & Re-Enable the EC GPE: - * ----------------------------- - * 'Consume' any EC GPE events that we generated while performing - * the transaction (e.g. IBF/OBF). Clearing the GPE here shouldn't - * have an adverse affect on outstanding EC-SCI's, as the source - * (EC-SCI) will still be high and thus should trigger the GPE - * immediately after we re-enabling it. - */ - s = splvm(); /* XXX */ - simple_lock(&sc->sc_slock); - if (sc->sc_flags & EC_F_PENDQUERY) { - ACPI_STATUS rv2; - - rv2 = AcpiOsQueueForExecution(OSD_PRIORITY_HIGH, - EcGpeQueryHandler, sc); - if (ACPI_FAILURE(rv2)) - printf("%s: unable to queue pending query: %s\n", - sc->sc_dev.dv_xname, AcpiFormatException(rv2)); - sc->sc_flags &= ~EC_F_PENDQUERY; - } - sc->sc_flags &= ~EC_F_TRANSACTION; - simple_unlock(&sc->sc_slock); - splx(s); - - if (sc->sc_glk) { - rv = AcpiReleaseGlobalLock(sc->sc_glkhandle); - if (ACPI_FAILURE(rv)) - printf("%s: failed to release global lock\n", - sc->sc_dev.dv_xname); - } - mutex_exit(&sc->sc_lock); + if (!acpiecdt_find(parent, &ec_handle, &cmd_reg, &data_reg, &gpebit)) + panic("ECDT disappeared"); + + aprint_naive(": ACPI Embedded Controller via ECDT\n"); + aprint_normal(": ACPI Embedded Controller via ECDT\n"); + + acpiec_common_attach(parent, self, ec_handle, cmd_reg, data_reg, + NULL, gpebit); } -/* - * acpiec_match: - * - * Autoconfiguration `match' routine. - */ static int -acpiec_match(struct device *parent, struct cfdata *match, - void *aux) +acpiec_match(device_t parent, struct cfdata *match, void *aux) { struct acpi_attach_args *aa = aux; @@ -359,672 +211,596 @@ acpiec_match(struct device *parent, struct cfdata *match, return acpi_match_hid(aa->aa_node->ad_devinfo, ec_hid); } -void -acpiec_early_attach(struct device *parent) +static void +acpiec_attach(device_t parent, device_t self, void *aux) { - struct acpi_softc *sc = (struct acpi_softc *)parent; - EC_BOOT_RESOURCES *ep; - ACPI_HANDLE handle; + struct acpi_attach_args *aa = aux; + struct acpi_resources ec_res; + struct acpi_io *io0, *io1; + ACPI_HANDLE gpe_handle; + uint8_t gpebit; ACPI_STATUS rv; - ACPI_INTEGER tmp; - rv = AcpiGetFirmwareTable("ECDT", 1, ACPI_LOGICAL_ADDRESSING, - (void *)&ep); - if (ACPI_FAILURE(rv)) + if (ec_singleton != NULL) { + aprint_naive(": ACPI Embedded Controller (disabled)\n"); + aprint_normal(": ACPI Embedded Controller (disabled)\n"); + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); return; + } + + aprint_naive(": ACPI Embedded Controller\n"); + aprint_normal(": ACPI Embedded Controller\n"); - if (ep->EcControl.RegisterBitWidth != 8 || - ep->EcData.RegisterBitWidth != 8) { - printf("%s: ECDT data is invalid, RegisterBitWidth=%d/%d\n", - parent->dv_xname, - ep->EcControl.RegisterBitWidth, - ep->EcData.RegisterBitWidth); + if (!acpiec_parse_gpe_package(self, aa->aa_node->ad_handle, + &gpe_handle, &gpebit)) return; - } - rv = AcpiGetHandle(ACPI_ROOT_OBJECT, ep->EcId, &handle); - if (ACPI_FAILURE(rv)) { - printf("%s: failed to look up EC object %s: %s\n", - parent->dv_xname, - ep->EcId, AcpiFormatException(rv)); + rv = acpi_resource_parse(self, aa->aa_node->ad_handle, "_CRS", + &ec_res, &acpi_resource_parse_ops_default); + if (rv != AE_OK) { + aprint_error_dev(self, "resource parsing failed: %s\n", + AcpiFormatException(rv)); return; } - ecdt_sc = malloc(sizeof(*ecdt_sc), M_ACPI, M_ZERO); + if ((io0 = acpi_res_io(&ec_res, 0)) == NULL) { + aprint_error_dev(self, "no data register resource\n"); + goto free_res; + } + if ((io1 = acpi_res_io(&ec_res, 1)) == NULL) { + aprint_error_dev(self, "no CSR register resource\n"); + goto free_res; + } - strcpy(ecdt_sc->sc_dev.dv_xname, "acpiecdt0"); /* XXX */ - ecdt_sc->sc_handle = handle; + acpiec_common_attach(parent, self, aa->aa_node->ad_handle, + io1->ar_base, io0->ar_base, gpe_handle, gpebit); - ecdt_sc->sc_gpebit = ep->GpeBit; - ecdt_sc->sc_uid = ep->Uid; +free_res: + acpi_resource_cleanup(&ec_res); +} - ecdt_sc->sc_data_st = sc->sc_iot; - if (bus_space_map(ecdt_sc->sc_data_st, - (bus_addr_t)(ep->EcData.Address), 1, 0, - &ecdt_sc->sc_data_sh) != 0) { - printf("%s: bus_space_map failed for EC data.\n", - parent->dv_xname); - goto out1; - } +static void +acpiec_common_attach(device_t parent, device_t self, + ACPI_HANDLE ec_handle, bus_addr_t cmd_reg, bus_addr_t data_reg, + ACPI_HANDLE gpe_handle, uint8_t gpebit) +{ + struct acpiec_softc *sc = device_private(self); + ACPI_STATUS rv; + ACPI_INTEGER val; - ecdt_sc->sc_csr_st = sc->sc_iot; - if (bus_space_map(ecdt_sc->sc_csr_st, - (bus_addr_t)(ep->EcControl.Address), 1, 0, - &ecdt_sc->sc_csr_sh) != 0) { - printf("%s: bus_space_map failed for EC control.\n", - parent->dv_xname); - goto out2; - } + sc->sc_ech = ec_handle; + sc->sc_gpeh = gpe_handle; + sc->sc_gpebit = gpebit; - rv = acpi_eval_integer(handle, "_GLK", &tmp); - if (ACPI_SUCCESS(rv) && tmp == 1) - ecdt_sc->sc_glk = 1; + sc->sc_state = EC_STATE_FREE; + mutex_init(&sc->sc_mtx, MUTEX_DRIVER, IPL_TTY); + mutex_init(&sc->sc_access_mtx, MUTEX_DEFAULT, IPL_NONE); + cv_init(&sc->sc_cv, "eccv"); + cv_init(&sc->sc_cv_sci, "ecsci"); - rv = AcpiInstallGpeHandler(NULL, ecdt_sc->sc_gpebit, - ACPI_GPE_EDGE_TRIGGERED, EcGpeHandler, ecdt_sc); - if (ACPI_FAILURE(rv)) { - printf("%s: unable to install GPE handler: %s\n", - parent->dv_xname, AcpiFormatException(rv)); - goto out3; + if (bus_space_map(sc->sc_data_st, data_reg, 1, 0, + &sc->sc_data_sh) != 0) { + aprint_error_dev(self, "unable to map data register\n"); + return; } - rv = AcpiSetGpeType(NULL, ecdt_sc->sc_gpebit, ACPI_GPE_TYPE_RUNTIME); - if (ACPI_FAILURE(rv)) { - printf("%s: unable to set GPE type: %s\n", - parent->dv_xname, AcpiFormatException(rv)); - goto out4; + if (bus_space_map(sc->sc_csr_st, cmd_reg, 1, 0, &sc->sc_csr_sh) != 0) { + aprint_error_dev(self, "unable to map CSR register\n"); + goto post_data_map; } - rv = AcpiEnableGpe(NULL, ecdt_sc->sc_gpebit, ACPI_NOT_ISR); - if (ACPI_FAILURE(rv)) { - printf("%s: unable to enable GPE: %s\n", - parent->dv_xname, AcpiFormatException(rv)); - goto out4; + rv = acpi_eval_integer(sc->sc_ech, "_GLK", &val); + if (rv == AE_OK) { + sc->sc_need_global_lock = val != 0; + } else if (rv != AE_NOT_FOUND) { + aprint_error_dev(self, "unable to evaluate _GLK: %s\n", + AcpiFormatException(rv)); + goto post_csr_map; + } else { + sc->sc_need_global_lock = false; } + if (sc->sc_need_global_lock) + aprint_normal_dev(self, "using global ACPI lock\n"); - rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT, - ACPI_ADR_SPACE_EC, EcSpaceHandler, EcSpaceSetup, ecdt_sc); - if (ACPI_FAILURE(rv)) { - printf("%s: unable to install address space handler: %s\n", - parent->dv_xname, + rv = AcpiInstallAddressSpaceHandler(sc->sc_ech, ACPI_ADR_SPACE_EC, + acpiec_space_handler, acpiec_space_setup, self); + if (rv != AE_OK) { + aprint_error_dev(self, + "unable to install address space handler: %s\n", AcpiFormatException(rv)); - goto out4; + goto post_csr_map; } - printf("%s: found ECDT, GPE %d\n", parent->dv_xname, - ecdt_sc->sc_gpebit); + rv = AcpiInstallGpeHandler(sc->sc_gpeh, sc->sc_gpebit, + ACPI_GPE_EDGE_TRIGGERED, acpiec_gpe_handler, self); + if (rv != AE_OK) { + aprint_error_dev(self, "unable to install GPE handler: %s\n", + AcpiFormatException(rv)); + goto post_csr_map; + } - mutex_init(&ecdt_sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); - simple_lock_init(&ecdt_sc->sc_slock); + rv = AcpiSetGpeType(sc->sc_gpeh, sc->sc_gpebit, ACPI_GPE_TYPE_RUNTIME); + if (rv != AE_OK) { + aprint_error_dev(self, "unable to set GPE type: %s\n", + AcpiFormatException(rv)); + goto post_csr_map; + } - AcpiOsUnmapMemory(ep, ep->Length); - return; + rv = AcpiEnableGpe(sc->sc_gpeh, sc->sc_gpebit, ACPI_ISR); + if (rv != AE_OK) { + aprint_error_dev(self, "unable to enable GPE: %s\n", + AcpiFormatException(rv)); + goto post_csr_map; + } - out4: - AcpiRemoveGpeHandler(NULL, ecdt_sc->sc_gpebit, EcGpeHandler); - out3: - bus_space_unmap(ecdt_sc->sc_csr_st, ecdt_sc->sc_csr_sh, 1); - out2: - bus_space_unmap(ecdt_sc->sc_data_st, ecdt_sc->sc_data_sh, 1); - out1: - free(ecdt_sc, M_ACPI); - ecdt_sc = NULL; + if (kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL, acpiec_gpe_query, + self, NULL, "acpiec sci thread")) { + aprint_error_dev(self, "unable to create query kthread\n"); + goto post_csr_map; + } + + ec_singleton = self; - AcpiOsUnmapMemory(ep, ep->Length); + if (!pmf_device_register(self, acpiec_suspend, acpiec_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); return; + +post_csr_map: + (void)AcpiRemoveGpeHandler(sc->sc_gpeh, sc->sc_gpebit, + acpiec_gpe_handler); + (void)AcpiRemoveAddressSpaceHandler(sc->sc_ech, + ACPI_ADR_SPACE_EC, acpiec_space_handler); + bus_space_unmap(sc->sc_csr_st, sc->sc_csr_sh, 1); +post_data_map: + bus_space_unmap(sc->sc_data_st, sc->sc_data_sh, 1); } -/* - * acpiec_attach: - * - * Autoconfiguration `attach' routine. - */ -static void -acpiec_attach(struct device *parent, struct device *self, void *aux) +static bool +acpiec_suspend(device_t dv) { - struct acpi_ec_softc *sc = (void *) self; - struct acpi_attach_args *aa = aux; - struct acpi_io *io0, *io1; - struct acpi_resources res; - ACPI_STATUS rv; - ACPI_INTEGER v; - - ACPI_FUNCTION_TRACE(__FUNCTION__); + acpiec_cold = true; - aprint_naive(": ACPI Embedded Controller\n"); - aprint_normal(": ACPI Embedded Controller\n"); - - mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); - simple_lock_init(&sc->sc_slock); - - sc->sc_handle = aa->aa_node->ad_handle; + return true; +} - /* Parse our resources. */ - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "parsing EC resources\n")); - rv = acpi_resource_parse(&sc->sc_dev, sc->sc_handle, "_CRS", - &res, &acpi_resource_parse_ops_default); - if (ACPI_FAILURE(rv)) - return; +static bool +acpiec_resume(device_t dv) +{ + acpiec_cold = false; -#define adi aa->aa_node->ad_devinfo - - /* check if we already attached EC via ECDT */ - if (ecdt_sc && - ((adi->Valid & ACPI_VALID_UID) == ACPI_VALID_UID) && - ecdt_sc->sc_uid == strtoul(adi->UniqueId.Value, NULL, 10)) { - /* detach all ECDT handles */ - rv = AcpiRemoveAddressSpaceHandler(ACPI_ROOT_OBJECT, - ACPI_ADR_SPACE_EC, EcSpaceHandler); - if (ACPI_FAILURE(rv)) - aprint_error("ERROR: RemoveAddressSpaceHandler: %s\n", - AcpiFormatException(rv)); - rv = AcpiRemoveGpeHandler(NULL, ecdt_sc->sc_gpebit, - EcGpeHandler); - if (ACPI_FAILURE(rv)) - aprint_error("ERROR: RemoveAddressSpaceHandler: %s\n", - AcpiFormatException(rv)); + return true; +} - bus_space_unmap(ecdt_sc->sc_csr_st, - ecdt_sc->sc_csr_sh, 1); - bus_space_unmap(ecdt_sc->sc_data_st, - ecdt_sc->sc_data_sh, 1); +static bool +acpiec_parse_gpe_package(device_t self, ACPI_HANDLE ec_handle, + ACPI_HANDLE *gpe_handle, uint8_t *gpebit) +{ + ACPI_BUFFER buf; + ACPI_OBJECT *p, *c; + ACPI_STATUS rv; - mutex_destroy(&ecdt_sc->sc_lock); - free(ecdt_sc, M_ACPI); - ecdt_sc = NULL; + rv = acpi_eval_struct(ec_handle, "_GPE", &buf); + if (rv != AE_OK) { + aprint_error_dev(self, "unable to evaluate _GPE: %s\n", + AcpiFormatException(rv)); + return false; } -#undef adi + p = buf.Pointer; - sc->sc_data_st = aa->aa_iot; - io0 = acpi_res_io(&res, 0); - if (io0 == NULL) { - aprint_error("%s: unable to find data register resource\n", - sc->sc_dev.dv_xname); - goto out; - } - if (bus_space_map(sc->sc_data_st, io0->ar_base, io0->ar_length, - 0, &sc->sc_data_sh) != 0) { - aprint_error("%s: unable to map data register\n", - sc->sc_dev.dv_xname); - goto out; + if (p->Type == ACPI_TYPE_INTEGER) { + *gpe_handle = NULL; + *gpebit = p->Integer.Value; + AcpiOsFree(p); + return true; } - sc->sc_csr_st = aa->aa_iot; - io1 = acpi_res_io(&res, 1); - if (io1 == NULL) { - aprint_error("%s: unable to find csr register resource\n", - sc->sc_dev.dv_xname); - goto out; + if (p->Type != ACPI_TYPE_PACKAGE) { + aprint_error_dev(self, "_GPE is neither integer nor package\n"); + AcpiOsFree(p); + return false; } - if (bus_space_map(sc->sc_csr_st, io1->ar_base, io1->ar_length, - 0, &sc->sc_csr_sh) != 0) { - aprint_error("%s: unable to map csr register\n", - sc->sc_dev.dv_xname); - goto out; + + if (p->Package.Count != 2) { + aprint_error_dev(self, "_GPE package does not contain 2 elements\n"); + AcpiOsFree(p); + return false; } - /* - * evaluate _GLK to see if we should acquire global lock - * when accessing the EC. - */ - rv = acpi_eval_integer(sc->sc_handle, "_GLK", &v); - if (ACPI_FAILURE(rv)) { - if (rv != AE_NOT_FOUND) - aprint_error("%s: unable to evaluate _GLK: %s\n", - sc->sc_dev.dv_xname, - AcpiFormatException(rv)); - sc->sc_glk = 0; - } else - sc->sc_glk = v; - - /* - * Install GPE handler. - * - * We evaluate the _GPE method to find the GPE bit used by the - * Embedded Controller to signal status (SCI). - */ - rv = acpi_eval_integer(sc->sc_handle, "_GPE", &v); - if (ACPI_FAILURE(rv)) { - aprint_error("%s: unable to evaluate _GPE: %s\n", - sc->sc_dev.dv_xname, AcpiFormatException(rv)); - goto out; - } - sc->sc_gpebit = v; + c = &p->Package.Elements[0]; + switch (c->Type) { + case ACPI_TYPE_LOCAL_REFERENCE: + case ACPI_TYPE_ANY: + *gpe_handle = c->Reference.Handle; + break; + case ACPI_TYPE_STRING: + /* XXX should be using real scope here */ + rv = AcpiGetHandle(NULL, p->String.Pointer, gpe_handle); + if (rv != AE_OK) { + aprint_error_dev(self, + "_GPE device reference unresolvable\n"); + AcpiOsFree(p); + return false; + } + break; + default: + aprint_error_dev(self, "_GPE device reference incorrect\n"); + AcpiOsFree(p); + return false; + } + c = &p->Package.Elements[1]; + if (c->Type != ACPI_TYPE_INTEGER) { + aprint_error_dev(self, + "_GPE package needs integer as 2nd field\n"); + AcpiOsFree(p); + return false; + } + *gpebit = c->Integer.Value; + AcpiOsFree(p); + return true; +} - /* - * Install a handler for this EC's GPE bit. Note that EC SCIs are - * treated as both edge- and level-triggered interrupts; in other words - * we clear the status bit immediately after getting an EC-SCI, then - * again after we're done processing the event. This guarantees that - * events we cause while performing a transaction (e.g. IBE/OBF) get - * cleared before re-enabling the GPE. - */ - rv = AcpiInstallGpeHandler(NULL, sc->sc_gpebit, - ACPI_GPE_EDGE_TRIGGERED, EcGpeHandler, sc); - if (ACPI_FAILURE(rv)) { - aprint_error("%s: unable to install GPE handler: %s\n", - sc->sc_dev.dv_xname, AcpiFormatException(rv)); - goto out; - } +static uint8_t +acpiec_read_data(struct acpiec_softc *sc) +{ + return bus_space_read_1(sc->sc_data_st, sc->sc_data_sh, 0); +} - rv = AcpiSetGpeType(NULL, sc->sc_gpebit, ACPI_GPE_TYPE_RUNTIME); - if (ACPI_FAILURE(rv)) { - aprint_error("%s: unable to set GPE type: %s\n", - sc->sc_dev.dv_xname, AcpiFormatException(rv)); - goto out2; - } +static void +acpiec_write_data(struct acpiec_softc *sc, uint8_t val) +{ + bus_space_write_1(sc->sc_data_st, sc->sc_data_sh, 0, val); +} - rv = AcpiEnableGpe(NULL, sc->sc_gpebit, ACPI_NOT_ISR); - if (ACPI_FAILURE(rv)) { - aprint_error("%s: unable to enable GPE: %s\n", - sc->sc_dev.dv_xname, AcpiFormatException(rv)); - goto out2; - } +static uint8_t +acpiec_read_status(struct acpiec_softc *sc) +{ + return bus_space_read_1(sc->sc_csr_st, sc->sc_csr_sh, 0); +} - /* Install address space handler. */ - rv = AcpiInstallAddressSpaceHandler(sc->sc_handle, - ACPI_ADR_SPACE_EC, EcSpaceHandler, EcSpaceSetup, sc); - if (ACPI_FAILURE(rv)) { - aprint_error("%s: unable to install address space handler: %s\n", - sc->sc_dev.dv_xname, AcpiFormatException(rv)); - goto out2; - } +static void +acpiec_write_command(struct acpiec_softc *sc, uint8_t cmd) +{ + bus_space_write_1(sc->sc_csr_st, sc->sc_csr_sh, 0, cmd); +} - return_VOID; - out2: - (void)AcpiRemoveGpeHandler(NULL, sc->sc_gpebit, EcGpeHandler); +static ACPI_STATUS +acpiec_space_setup(ACPI_HANDLE region, UINT32 func, void *arg, + void **region_arg) +{ + if (func == ACPI_REGION_DEACTIVATE) + *region_arg = NULL; + else + *region_arg = arg; - out: - acpi_resource_cleanup(&res); - return_VOID; + return AE_OK; } static void -EcGpeQueryHandler(void *Context) +acpiec_lock(device_t dv) { - struct acpi_ec_softc *sc = Context; - UINT8 Data = 0; + struct acpiec_softc *sc = device_private(dv); ACPI_STATUS rv; - char qxx[5]; - ACPI_FUNCTION_TRACE(__FUNCTION__); - - for (;;) { - /* - * Check EC_SCI. - * - * Bail out if the EC_SCI bit of the status register is not - * set. Note that this function should only be called when - * this bit is set (polling is used to detect IBE/OBF events). - * - * It is safe to do this without locking the controller, as - * it's OK to call EcQuery when there's no data ready; in the - * worst case we should just find nothing waiting for us and - * bail. - */ - if ((EC_CSR_READ(sc) & EC_EVENT_SCI) == 0) - break; - - EcLock(sc); - - /* - * Find out why the EC is signalling us - */ - rv = EcQuery(sc, &Data); - - EcUnlock(sc); - - /* - * If we failed to get anything from the EC, give up. - */ - if (ACPI_FAILURE(rv)) { - printf("%s: GPE query failed: %s\n", - sc->sc_dev.dv_xname, AcpiFormatException(rv)); - break; - } + mutex_enter(&sc->sc_access_mtx); - /* - * Evaluate _Qxx to respond to the controller. - */ - snprintf(qxx, sizeof(qxx), "_Q%02X", Data); - rv = AcpiEvaluateObject(sc->sc_handle, qxx, - NULL, NULL); - - /* - * Ignore spurious query requests. - */ - if (ACPI_FAILURE(rv) && - (Data != 0 || rv != AE_NOT_FOUND)) { - printf("%s: evaluation of GPE query method %s " - "failed: %s\n", sc->sc_dev.dv_xname, qxx, + if (sc->sc_need_global_lock) { + rv = AcpiAcquireGlobalLock(EC_LOCK_TIMEOUT, &sc->sc_global_lock); + if (rv != AE_OK) { + aprint_error_dev(dv, "failed to acquire global lock: %s\n", AcpiFormatException(rv)); + return; } } - - /* I know I request Level trigger cleanup */ - rv = AcpiClearGpe(NULL, sc->sc_gpebit, ACPI_NOT_ISR); - if (ACPI_FAILURE(rv)) - printf("%s: AcpiClearGpe failed: %s\n", sc->sc_dev.dv_xname, - AcpiFormatException(rv)); - - return_VOID; } -static UINT32 -EcGpeHandler(void *Context) +static void +acpiec_unlock(device_t dv) { - struct acpi_ec_softc *sc = Context; - uint32_t csrvalue; + struct acpiec_softc *sc = device_private(dv); ACPI_STATUS rv; - /* - * If EC is locked, the intr must process EcRead/Write wait only. - * Query request must be pending. - */ - simple_lock(&sc->sc_slock); - if (sc->sc_flags & EC_F_TRANSACTION) { - csrvalue = EC_CSR_READ(sc); - sc->sc_flags |= EC_F_PENDQUERY; - - if ((csrvalue & EC_FLAG_OUTPUT_BUFFER) != 0 || - (csrvalue & EC_FLAG_INPUT_BUFFER) == 0) { - sc->sc_csrvalue = csrvalue; - wakeup(&sc->sc_csrvalue); + if (sc->sc_need_global_lock) { + rv = AcpiReleaseGlobalLock(sc->sc_global_lock); + if (rv != AE_OK) { + aprint_error_dev(dv, "failed to release global lock: %s\n", + AcpiFormatException(rv)); } - simple_unlock(&sc->sc_slock); - } else { - simple_unlock(&sc->sc_slock); - /* Enqueue GpeQuery handler. */ - rv = AcpiOsQueueForExecution(OSD_PRIORITY_HIGH, - EcGpeQueryHandler, Context); - if (ACPI_FAILURE(rv)) - printf("%s: failed to enqueue query handler: %s\n", - sc->sc_dev.dv_xname, AcpiFormatException(rv)); + } + mutex_exit(&sc->sc_access_mtx); +} + +static ACPI_STATUS +acpiec_read(device_t dv, uint8_t addr, uint8_t *val) +{ + struct acpiec_softc *sc = device_private(dv); + int i, timeouts = 0; + + acpiec_lock(dv); + mutex_enter(&sc->sc_mtx); + +retry: + sc->sc_cur_addr = addr; + sc->sc_state = EC_STATE_READ; + + for (i = 0; i < EC_POLL_TIMEOUT; ++i) { + acpiec_gpe_state_maschine(dv); + if (sc->sc_state == EC_STATE_FREE) + goto done; + delay(1); } - return 0; /* XXX not yet used in ACPI-CA */ + if (cold || acpiec_cold) { + while (sc->sc_state != EC_STATE_FREE) { + delay(1); + acpiec_gpe_state_maschine(dv); + } + } else while (cv_timedwait(&sc->sc_cv, &sc->sc_mtx, hz)) { + mutex_exit(&sc->sc_mtx); + AcpiClearGpe(sc->sc_gpeh, sc->sc_gpebit, ACPI_NOT_ISR); + mutex_enter(&sc->sc_mtx); + if (++timeouts < 5) + goto retry; + mutex_exit(&sc->sc_mtx); + acpiec_unlock(dv); + aprint_error_dev(dv, "command takes over 5sec...\n"); + return AE_ERROR; + } + +done: + *val = sc->sc_cur_val; + + mutex_exit(&sc->sc_mtx); + acpiec_unlock(dv); + return AE_OK; } static ACPI_STATUS -EcSpaceSetup(ACPI_HANDLE Region, UINT32 Function, void *Context, - void **RegionContext) +acpiec_write(device_t dv, uint8_t addr, uint8_t val) { + struct acpiec_softc *sc = device_private(dv); + int i, timeouts = 0; - ACPI_FUNCTION_TRACE(__FUNCTION__); + acpiec_lock(dv); + mutex_enter(&sc->sc_mtx); - /* - * Just pass the context through, there's nothing to do here. - */ - if (Function == ACPI_REGION_DEACTIVATE) - *RegionContext = NULL; - else - *RegionContext = Context; +retry: + sc->sc_cur_addr = addr; + sc->sc_cur_val = val; + sc->sc_state = EC_STATE_WRITE; - return_ACPI_STATUS(AE_OK); + for (i = 0; i < EC_POLL_TIMEOUT; ++i) { + acpiec_gpe_state_maschine(dv); + if (sc->sc_state == EC_STATE_FREE) + goto done; + delay(1); + } + + if (cold || acpiec_cold) { + while (sc->sc_state != EC_STATE_FREE) { + delay(1); + acpiec_gpe_state_maschine(dv); + } + } else while (cv_timedwait(&sc->sc_cv, &sc->sc_mtx, hz)) { + mutex_exit(&sc->sc_mtx); + AcpiClearGpe(sc->sc_gpeh, sc->sc_gpebit, ACPI_NOT_ISR); + mutex_enter(&sc->sc_mtx); + if (++timeouts < 5) + goto retry; + mutex_exit(&sc->sc_mtx); + acpiec_unlock(dv); + aprint_error_dev(dv, "command takes over 5sec...\n"); + return AE_ERROR; + } + +done: + mutex_exit(&sc->sc_mtx); + acpiec_unlock(dv); + return AE_OK; } static ACPI_STATUS -EcSpaceHandler(UINT32 Function, ACPI_PHYSICAL_ADDRESS Address, UINT32 width, - ACPI_INTEGER *Value, void *Context, void *RegionContext) +acpiec_space_handler(UINT32 func, ACPI_PHYSICAL_ADDRESS paddr, + UINT32 width, ACPI_INTEGER *value, void *arg, void *region_arg) { - struct acpi_ec_softc *sc = Context; - ACPI_STATUS rv = AE_OK; - EC_REQUEST EcRequest; - int i; + device_t dv; + struct acpiec_softc *sc; + ACPI_STATUS rv; + uint8_t addr, reg; + unsigned int i; - ACPI_FUNCTION_TRACE_U32(__FUNCTION__, (UINT32)Address); + if (paddr > 0xff || width % 8 != 0 || value == NULL || arg == NULL || + paddr + width / 8 > 0xff) + return AE_BAD_PARAMETER; - if ((Address > 0xFF) || (width % 8 != 0) || (Value == NULL) || - (Context == NULL)) - return_ACPI_STATUS(AE_BAD_PARAMETER); + addr = paddr; + dv = arg; + sc = device_private(dv); - switch (Function) { + rv = AE_OK; + + switch (func) { case ACPI_READ: - EcRequest.Command = EC_COMMAND_READ; - EcRequest.Address = Address; - (*Value) = 0; + *value = 0; + for (i = 0; i < width; i += 8, ++addr) { + rv = acpiec_read(dv, addr, ®); + if (rv != AE_OK) + break; + *value |= (ACPI_INTEGER)reg << i; + } break; - case ACPI_WRITE: - EcRequest.Command = EC_COMMAND_WRITE; - EcRequest.Address = Address; + for (i = 0; i < width; i += 8, ++addr) { + reg = (*value >>i) & 0xff; + rv = acpiec_write(dv, addr, reg); + if (rv != AE_OK) + break; + } break; - default: - printf("%s: invalid Address Space function: %d\n", - sc->sc_dev.dv_xname, Function); - return_ACPI_STATUS(AE_BAD_PARAMETER); + aprint_error("%s: invalid Address Space function called: %x\n", + device_xname(dv), (unsigned int)func); + return AE_BAD_PARAMETER; } - /* - * Perform the transaction. - */ - for (i = 0; i < width; i += 8) { - if (Function == ACPI_READ) - EcRequest.Data = 0; - else - EcRequest.Data = (UINT8)((*Value) >> i); - - rv = EcTransaction(sc, &EcRequest); - if (ACPI_FAILURE(rv)) - break; - - (*Value) |= (UINT32)EcRequest.Data << i; - if (++EcRequest.Address == 0) - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - return_ACPI_STATUS(rv); + return rv; } -static ACPI_STATUS -EcWaitEventIntr(struct acpi_ec_softc *sc, EC_EVENT Event) +static void +acpiec_gpe_query(void *arg) { - EC_STATUS EcStatus; + device_t dv = arg; + struct acpiec_softc *sc = device_private(dv); + uint8_t reg; + char qxx[5]; + ACPI_STATUS rv; int i; - ACPI_FUNCTION_TRACE_U32(__FUNCTION__, (UINT32)Event); - - /* XXX Need better test for "yes, you have interrupts". */ - if (cold) - return_ACPI_STATUS(EcWaitEvent(sc, Event)); +loop: + mutex_enter(&sc->sc_mtx); - if (EcIsLocked(sc) == 0) - printf("%s: EcWaitEventIntr called without EC lock!\n", - sc->sc_dev.dv_xname); + if (sc->sc_got_sci == false) + cv_wait(&sc->sc_cv_sci, &sc->sc_mtx); + mutex_exit(&sc->sc_mtx); - EcStatus = EC_CSR_READ(sc); + acpiec_lock(dv); + mutex_enter(&sc->sc_mtx); - /* Too long? */ - for (i = 0; i < 10; i++) { - /* Check EC status against the desired event. */ - if ((Event == EC_EVENT_OUTPUT_BUFFER_FULL) && - (EcStatus & EC_FLAG_OUTPUT_BUFFER) != 0) - return_ACPI_STATUS(AE_OK); + /* The Query command can always be issued, so be defensive here. */ + sc->sc_got_sci = false; + sc->sc_state = EC_STATE_QUERY; - if ((Event == EC_EVENT_INPUT_BUFFER_EMPTY) && - (EcStatus & EC_FLAG_INPUT_BUFFER) == 0) - return_ACPI_STATUS(AE_OK); - - sc->sc_csrvalue = 0; - /* XXXJRT Sleeping with a lock held? */ - if (tsleep(&sc->sc_csrvalue, 0, "EcWait", (hz + 99) / 100) - != EWOULDBLOCK) - EcStatus = sc->sc_csrvalue; - else - EcStatus = EC_CSR_READ(sc); + for (i = 0; i < EC_POLL_TIMEOUT; ++i) { + acpiec_gpe_state_maschine(dv); + if (sc->sc_state == EC_STATE_FREE) + goto done; + delay(1); } - return_ACPI_STATUS(AE_ERROR); -} -static ACPI_STATUS -EcWaitEvent(struct acpi_ec_softc *sc, EC_EVENT Event) -{ - EC_STATUS EcStatus; - UINT32 i = 0; + cv_wait(&sc->sc_cv, &sc->sc_mtx); - if (EcIsLocked(sc) == 0) - printf("%s: EcWaitEvent called without EC lock!\n", - sc->sc_dev.dv_xname); +done: + reg = sc->sc_cur_val; - /* - * Stall 10us: - * ---------- - * Stall for 10 microseconds before reading the status register - * for the first time. This allows the EC to set the IBF/OBF - * bit to its proper state. - */ - AcpiOsStall(10); + mutex_exit(&sc->sc_mtx); + acpiec_unlock(dv); + + if (reg == 0) + goto loop; /* Spurious query result */ /* - * Wait For Event: - * --------------- - * Poll the EC status register to detect completion of the last - * command. Wait up to 100ms (in 100us chunks) for this to occur. + * Evaluate _Qxx to respond to the controller. */ - for (i = 0; i < 1000; i++) { - EcStatus = EC_CSR_READ(sc); - - if ((Event == EC_EVENT_OUTPUT_BUFFER_FULL) && - (EcStatus & EC_FLAG_OUTPUT_BUFFER) != 0) - return AE_OK; - - if ((Event == EC_EVENT_INPUT_BUFFER_EMPTY) && - (EcStatus & EC_FLAG_INPUT_BUFFER) == 0) - return AE_OK; - - AcpiOsStall(10); + snprintf(qxx, sizeof(qxx), "_Q%02X", (unsigned int)reg); + rv = AcpiEvaluateObject(sc->sc_ech, qxx, NULL, NULL); + if (rv != AE_OK && rv != AE_NOT_FOUND) { + aprint_error("%s: GPE query method %s failed: %s", + device_xname(dv), qxx, AcpiFormatException(rv)); } - return AE_ERROR; + goto loop; } -static ACPI_STATUS -EcQuery(struct acpi_ec_softc *sc, UINT8 *Data) +static void +acpiec_gpe_state_maschine(device_t dv) { - ACPI_STATUS rv; + struct acpiec_softc *sc = device_private(dv); + uint8_t reg; - if (EcIsLocked(sc) == 0) - printf("%s: EcQuery called without EC lock!\n", - sc->sc_dev.dv_xname); + reg = acpiec_read_status(sc); - EC_CSR_WRITE(sc, EC_COMMAND_QUERY); - rv = EcWaitEventIntr(sc, EC_EVENT_OUTPUT_BUFFER_FULL); - if (ACPI_SUCCESS(rv)) - *Data = EC_DATA_READ(sc); + if (reg & EC_STATUS_SCI) + sc->sc_got_sci = true; - if (ACPI_FAILURE(rv)) - printf("%s: timed out waiting for EC to respond to " - "EC_COMMAND_QUERY\n", sc->sc_dev.dv_xname); - - return rv; -} + switch (sc->sc_state) { + case EC_STATE_QUERY: + if ((reg & EC_STATUS_IBF) != 0) + break; /* Nothing of interest here. */ + acpiec_write_command(sc, EC_COMMAND_QUERY); + sc->sc_state = EC_STATE_QUERY_VAL; + break; -static ACPI_STATUS -EcTransaction(struct acpi_ec_softc *sc, EC_REQUEST *EcRequest) -{ - ACPI_STATUS rv; + case EC_STATE_QUERY_VAL: + if ((reg & EC_STATUS_OBF) == 0) + break; /* Nothing of interest here. */ - EcLock(sc); + sc->sc_cur_val = acpiec_read_data(sc); + sc->sc_state = EC_STATE_FREE; - /* - * Perform the transaction, and make sure GPE is enabled before - * doing so. - */ - rv = AcpiEnableGpe(NULL, sc->sc_gpebit, ACPI_NOT_ISR); - if (ACPI_FAILURE(rv)) - return rv; - switch (EcRequest->Command) { - case EC_COMMAND_READ: - rv = EcRead(sc, EcRequest->Address, &(EcRequest->Data)); + cv_signal(&sc->sc_cv); break; - case EC_COMMAND_WRITE: - rv = EcWrite(sc, EcRequest->Address, &(EcRequest->Data)); - break; + case EC_STATE_READ: + if ((reg & EC_STATUS_IBF) != 0) + break; /* Nothing of interest here. */ - default: - rv = AE_SUPPORT; + acpiec_write_command(sc, EC_COMMAND_READ); + sc->sc_state = EC_STATE_READ_ADDR; break; - } - EcUnlock(sc); + case EC_STATE_READ_ADDR: + if ((reg & EC_STATUS_IBF) != 0) + break; /* Nothing of interest here. */ - return rv; -} + acpiec_write_data(sc, sc->sc_cur_addr); + sc->sc_state = EC_STATE_READ_VAL; + break; -static ACPI_STATUS -EcRead(struct acpi_ec_softc *sc, UINT8 Address, UINT8 *Data) -{ - ACPI_STATUS rv; + case EC_STATE_READ_VAL: + if ((reg & EC_STATUS_OBF) == 0) + break; /* Nothing of interest here. */ + sc->sc_cur_val = acpiec_read_data(sc); + sc->sc_state = EC_STATE_FREE; - if (EcIsLocked(sc) == 0) - printf("%s: EcRead called without EC lock!\n", - sc->sc_dev.dv_xname); + cv_signal(&sc->sc_cv); + break; - /* EcBurstEnable(EmbeddedController); */ + case EC_STATE_WRITE: + if ((reg & EC_STATUS_IBF) != 0) + break; /* Nothing of interest here. */ - EC_CSR_WRITE(sc, EC_COMMAND_READ); - if ((rv = EcWaitEventIntr(sc, EC_EVENT_INPUT_BUFFER_EMPTY)) != - AE_OK) { - printf("%s: EcRead: timeout waiting for EC to process " - "read command\n", sc->sc_dev.dv_xname); - return rv; - } + acpiec_write_command(sc, EC_COMMAND_WRITE); + sc->sc_state = EC_STATE_WRITE_ADDR; + break; - EC_DATA_WRITE(sc, Address); - if ((rv = EcWaitEventIntr(sc, EC_EVENT_OUTPUT_BUFFER_FULL)) != - AE_OK) { - printf("%s: EcRead: timeout waiting for EC to send data\n", - sc->sc_dev.dv_xname); - return rv; - } + case EC_STATE_WRITE_ADDR: + if ((reg & EC_STATUS_IBF) != 0) + break; /* Nothing of interest here. */ + acpiec_write_data(sc, sc->sc_cur_addr); + sc->sc_state = EC_STATE_WRITE_VAL; + break; - (*Data) = EC_DATA_READ(sc); + case EC_STATE_WRITE_VAL: + if ((reg & EC_STATUS_IBF) != 0) + break; /* Nothing of interest here. */ + sc->sc_state = EC_STATE_FREE; + cv_signal(&sc->sc_cv); - /* EcBurstDisable(EmbeddedController); */ + acpiec_write_data(sc, sc->sc_cur_val); + break; - return AE_OK; + case EC_STATE_FREE: + if (sc->sc_got_sci) + cv_signal(&sc->sc_cv_sci); + break; + default: + panic("invalid state"); + } } -static ACPI_STATUS -EcWrite(struct acpi_ec_softc *sc, UINT8 Address, UINT8 *Data) +static UINT32 +acpiec_gpe_handler(void *arg) { - ACPI_STATUS rv; + device_t dv = arg; + struct acpiec_softc *sc = device_private(dv); - if (EcIsLocked(sc) == 0) - printf("%s: EcWrite called without EC lock!\n", - sc->sc_dev.dv_xname); + AcpiClearGpe(sc->sc_gpeh, sc->sc_gpebit, ACPI_ISR); - /* EcBurstEnable(EmbeddedController); */ + mutex_enter(&sc->sc_mtx); + acpiec_gpe_state_maschine(dv); + mutex_exit(&sc->sc_mtx); - EC_CSR_WRITE(sc, EC_COMMAND_WRITE); - if ((rv = EcWaitEventIntr(sc, EC_EVENT_INPUT_BUFFER_EMPTY)) != - AE_OK) { - printf("%s: EcWrite: timeout waiting for EC to process " - "write command\n", sc->sc_dev.dv_xname); - return rv; - } - - EC_DATA_WRITE(sc, Address); - if ((rv = EcWaitEventIntr(sc, EC_EVENT_INPUT_BUFFER_EMPTY)) != - AE_OK) { - printf("%s: EcWrite: timeout waiting for EC to process " - "address\n", sc->sc_dev.dv_xname); - return rv; - } - - EC_DATA_WRITE(sc, *Data); - if ((rv = EcWaitEventIntr(sc, EC_EVENT_INPUT_BUFFER_EMPTY)) != - AE_OK) { - printf("%s: EcWrite: timeout waiting for EC to process " - "data\n", sc->sc_dev.dv_xname); - return rv; - } - - /* EcBurstDisable(EmbeddedController); */ - - return AE_OK; + return 0; } diff --git a/sys/dev/acpi/acpi_ecreg.h b/sys/dev/acpi/acpi_ecreg.h index 3562febf905..e69de29bb2d 100644 --- a/sys/dev/acpi/acpi_ecreg.h +++ b/sys/dev/acpi/acpi_ecreg.h @@ -1,161 +0,0 @@ -/* $NetBSD: acpi_ecreg.h,v 1.3 2005/12/11 12:21:01 christos Exp $ */ - -/****************************************************************************** - * - * 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. - * - *****************************************************************************/ - -/* - * EC_COMMAND: - * ----------- - */ -typedef UINT8 EC_COMMAND; - -#define EC_COMMAND_UNKNOWN ((EC_COMMAND) 0x00) -#define EC_COMMAND_READ ((EC_COMMAND) 0x80) -#define EC_COMMAND_WRITE ((EC_COMMAND) 0x81) -#define EC_COMMAND_BURST_ENABLE ((EC_COMMAND) 0x82) -#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. - * Note that a set bit (1) indicates the property is TRUE - * (e.g. if bit 0 is set then the output buffer is full). - * +-+-+-+-+-+-+-+-+ - * |7|6|5|4|3|2|1|0| - * +-+-+-+-+-+-+-+-+ - * | | | | | | | | - * | | | | | | | +- Output Buffer Full? - * | | | | | | +--- Input Buffer Full? - * | | | | | +----- <reserved> - * | | | | +------- Data Register is Command Byte? - * | | | +--------- Burst Mode Enabled? - * | | +----------- SCI Event? - * | +------------- SMI Event? - * +--------------- <Reserved> - * - */ -typedef UINT8 EC_STATUS; - -#define EC_FLAG_OUTPUT_BUFFER ((EC_STATUS) 0x01) -#define EC_FLAG_INPUT_BUFFER ((EC_STATUS) 0x02) -#define EC_FLAG_BURST_MODE ((EC_STATUS) 0x10) -#define EC_FLAG_SCI ((EC_STATUS) 0x20) - -/* - * EC_EVENT: - * --------- - */ -typedef UINT8 EC_EVENT; - -#define EC_EVENT_UNKNOWN ((EC_EVENT) 0x00) -#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) diff --git a/sys/dev/acpi/acpi_lid.c b/sys/dev/acpi/acpi_lid.c index 447952bc966..805fe7eda6b 100644 --- a/sys/dev/acpi/acpi_lid.c +++ b/sys/dev/acpi/acpi_lid.c @@ -1,4 +1,4 @@ -/* $NetBSD: acpi_lid.c,v 1.21 2006/11/16 01:32:47 christos Exp $ */ +/* $NetBSD: acpi_lid.c,v 1.22 2007/12/09 20:27:53 jmcneill Exp $ */ /* * Copyright 2001, 2003 Wasabi Systems, Inc. @@ -40,7 +40,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: acpi_lid.c,v 1.21 2006/11/16 01:32:47 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acpi_lid.c,v 1.22 2007/12/09 20:27:53 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -72,6 +72,8 @@ CFATTACH_DECL(acpilid, sizeof(struct acpilid_softc), static void acpilid_status_changed(void *); static void acpilid_notify_handler(ACPI_HANDLE, UINT32, void *); +static bool acpilid_suspend(device_t); + /* * acpilid_match: * @@ -123,6 +125,30 @@ acpilid_attach(struct device *parent, struct device *self, void *aux) } acpi_set_wake_gpe(sc->sc_node->ad_handle); + + if (!pmf_device_register(self, acpilid_suspend, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); +} + +static void +acpilid_wake_event(struct acpilid_softc *sc, bool enable) +{ + ACPI_STATUS rv; + ACPI_OBJECT_LIST ArgList; + ACPI_OBJECT Arg; + + ArgList.Count = 1; + ArgList.Pointer = &Arg; + + Arg.Type = ACPI_TYPE_INTEGER; + Arg.Integer.Value = enable ? 1 : 0; + + rv = AcpiEvaluateObject (sc->sc_node->ad_handle, "_PSW", + &ArgList, NULL); + if (ACPI_FAILURE(rv) && rv != AE_NOT_FOUND) + aprint_error_dev(&sc->sc_dev, + "unable to evaluate _PSW handler: %s\n", + AcpiFormatException(rv)); } /* @@ -163,7 +189,7 @@ acpilid_notify_handler(ACPI_HANDLE handle, UINT32 notify, printf("%s: received LidStatusChanged message\n", sc->sc_dev.dv_xname); #endif - rv = AcpiOsQueueForExecution(OSD_PRIORITY_LO, + rv = AcpiOsExecute(OSL_NOTIFY_HANDLER, acpilid_status_changed, sc); if (ACPI_FAILURE(rv)) printf("%s: WARNING: unable to queue lid change " @@ -176,3 +202,18 @@ acpilid_notify_handler(ACPI_HANDLE handle, UINT32 notify, sc->sc_dev.dv_xname, notify); } } + +static bool +acpilid_suspend(device_t dv) +{ + struct acpilid_softc *sc = device_private(dv); + ACPI_INTEGER status; + ACPI_STATUS rv; + + rv = acpi_eval_integer(sc->sc_node->ad_handle, "_LID", &status); + if (ACPI_FAILURE(rv)) + return true; + + acpilid_wake_event(sc, status == 0); + return true; +} diff --git a/sys/dev/acpi/acpi_madt.c b/sys/dev/acpi/acpi_madt.c index d3b553554dd..bc398e29672 100644 --- a/sys/dev/acpi/acpi_madt.c +++ b/sys/dev/acpi/acpi_madt.c @@ -1,4 +1,4 @@ -/* $NetBSD: acpi_madt.c,v 1.17 2006/11/16 01:32:47 christos Exp $ */ +/* $NetBSD: acpi_madt.c,v 1.18 2007/12/09 20:27:53 jmcneill Exp $ */ /* * Copyright (c) 2003 Wasabi Systems, Inc. @@ -36,7 +36,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: acpi_madt.c,v 1.17 2006/11/16 01:32:47 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acpi_madt.c,v 1.18 2007/12/09 20:27:53 jmcneill Exp $"); #include <sys/param.h> #include <sys/ioctl.h> @@ -74,8 +74,7 @@ acpi_madt_map(void) if (madt_header != NULL) return AE_ALREADY_EXISTS; - rv = AcpiGetFirmwareTable(APIC_SIG, 1, ACPI_LOGICAL_ADDRESSING, - &madt_header); + rv = AcpiGetTable(ACPI_SIG_MADT, 1, &madt_header); if (ACPI_FAILURE(rv)) return rv; @@ -90,7 +89,6 @@ acpi_madt_map(void) void acpi_madt_unmap(void) { - AcpiOsUnmapMemory(madt_header, madt_header->Length); madt_header = NULL; } @@ -161,15 +159,15 @@ acpi_print_platint(MADT_INTERRUPT_SOURCE *p) #endif void -acpi_madt_walk(ACPI_STATUS (*func)(APIC_HEADER *, void *), void *aux) +acpi_madt_walk(ACPI_STATUS (*func)(ACPI_SUBTABLE_HEADER *, void *), void *aux) { char *madtend, *where; - APIC_HEADER *hdrp; + ACPI_SUBTABLE_HEADER *hdrp; madtend = (char *)madt_header + madt_header->Length; - where = (char *)madt_header + sizeof (MULTIPLE_APIC_TABLE); + where = (char *)madt_header + sizeof (ACPI_TABLE_MADT); while (where < madtend) { - hdrp = (APIC_HEADER *)where; + hdrp = (ACPI_SUBTABLE_HEADER *)where; if (ACPI_FAILURE(func(hdrp, aux))) break; where += hdrp->Length; @@ -193,34 +191,34 @@ acpi_madt_print(void) } static ACPI_STATUS -acpi_madt_print_entry(APIC_HEADER *hdrp, void *aux) +acpi_madt_print_entry(ACPI_SUBTABLE_HEADER *hdrp, void *aux) { switch (hdrp->Type) { - case APIC_PROCESSOR: + case ACPI_MADT_TYPE_LOCAL_APIC: acpi_print_apic_proc((void *)hdrp); break; - case APIC_IO: + case ACPI_MADT_TYPE_IO_APIC: acpi_print_ioapic((void *)hdrp); break; - case APIC_XRUPT_OVERRIDE: + case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE: acpi_print_intsrc_ovr((void *)hdrp); break; - case APIC_NMI: + case ACPI_MADT_TYPE_NMI_SOURCE: acpi_print_intsrc_nmi((void *)hdrp); break; - case APIC_LOCAL_NMI: + case ACPI_MADT_TYPE_LOCAL_APIC_NMI: acpi_print_lapic_nmi((void *)hdrp); break; - case APIC_ADDRESS_OVERRIDE: + case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE: acpi_print_lapic_addr_ovr((void *)hdrp); break; - case APIC_IO_SAPIC: + case ACPI_MADT_TYPE_IO_SAPIC: acpi_print_iosapic((void *)hdrp); break; - case APIC_LOCAL_SAPIC: + case ACPI_MADT_TYPE_LOCAL_SAPIC: acpi_print_local_sapic((void *)hdrp); break; - case APIC_XRUPT_SOURCE: + case ACPI_MADT_TYPE_INTERRUPT_SOURCE: acpi_print_platint((void *)hdrp); break; default: diff --git a/sys/dev/acpi/acpi_madt.h b/sys/dev/acpi/acpi_madt.h index 5702e76b0d8..f8588316e53 100644 --- a/sys/dev/acpi/acpi_madt.h +++ b/sys/dev/acpi/acpi_madt.h @@ -1,4 +1,4 @@ -/* $NetBSD: acpi_madt.h,v 1.6 2005/12/11 12:21:01 christos Exp $ */ +/* $NetBSD: acpi_madt.h,v 1.7 2007/12/09 20:27:53 jmcneill Exp $ */ /* * Copyright (c) 2003 Wasabi Systems, Inc. @@ -41,4 +41,4 @@ ACPI_STATUS acpi_madt_map(void); void acpi_madt_unmap(void); -void acpi_madt_walk(ACPI_STATUS (*)(APIC_HEADER *, void *), void *); +void acpi_madt_walk(ACPI_STATUS (*)(ACPI_SUBTABLE_HEADER *, void *), void *); diff --git a/sys/dev/acpi/acpi_pci_link.c b/sys/dev/acpi/acpi_pci_link.c index 15e48da0883..5d117c0cf2a 100644 --- a/sys/dev/acpi/acpi_pci_link.c +++ b/sys/dev/acpi/acpi_pci_link.c @@ -1,4 +1,4 @@ -/* $NetBSD: acpi_pci_link.c,v 1.9 2007/11/07 15:29:15 joerg Exp $ */ +/* $NetBSD: acpi_pci_link.c,v 1.10 2007/12/09 20:27:53 jmcneill Exp $ */ /*- * Copyright (c) 2002 Mitsuru IWASAKI <iwasaki@jp.freebsd.org> @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: acpi_pci_link.c,v 1.9 2007/11/07 15:29:15 joerg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acpi_pci_link.c,v 1.10 2007/12/09 20:27:53 jmcneill Exp $"); #include "opt_acpi.h" #include <sys/param.h> @@ -384,7 +384,7 @@ link_valid_irq(struct link *link, int irq) * 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); @@ -1039,7 +1039,7 @@ acpi_pci_link_choose_irq(struct acpi_pci_link_softc *sc, struct link *link) * interrupt as a fallback. */ if (link->l_isa_irq && !PCI_INTERRUPT_VALID(best_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; @@ -1136,8 +1136,8 @@ acpi_pci_link_init(struct acpi_pci_link_softc *sc) * 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); sc->pl_powerhook = powerhook_establish(acpipcilinkname, acpi_pci_link_resume, sc); diff --git a/sys/dev/acpi/acpi_quirks.c b/sys/dev/acpi/acpi_quirks.c index 972463330bf..14acc6135ce 100644 --- a/sys/dev/acpi/acpi_quirks.c +++ b/sys/dev/acpi/acpi_quirks.c @@ -1,4 +1,4 @@ -/* $NetBSD: acpi_quirks.c,v 1.8 2006/09/23 17:04:26 fvdl Exp $ */ +/* $NetBSD: acpi_quirks.c,v 1.9 2007/12/09 20:27:53 jmcneill Exp $ */ /* * Copyright 2002 Wasabi Systems, Inc. @@ -37,7 +37,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: acpi_quirks.c,v 1.8 2006/09/23 17:04:26 fvdl Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acpi_quirks.c,v 1.9 2007/12/09 20:27:53 jmcneill Exp $"); #include "opt_acpi.h" @@ -58,9 +58,9 @@ static int acpi_rev_cmp(uint32_t, uint32_t, int); * XXX add more */ static struct acpi_quirk acpi_quirks[] = { - { ACPI_TABLE_FADT, "PTLTD ", 0x06040000, AQ_LTE, " FACP ", + { ACPI_SIG_FADT, "PTLTD ", 0x06040000, AQ_LTE, " FACP ", ACPI_QUIRK_BROKEN }, - { ACPI_TABLE_FADT, "NVIDIA", 0x06040000, AQ_EQ, "CK8 ", + { ACPI_SIG_FADT, "NVIDIA", 0x06040000, AQ_EQ, "CK8 ", ACPI_QUIRK_IRQ0 }, }; @@ -106,26 +106,27 @@ acpi_find_quirks(void) { int i, nquirks; struct acpi_quirk *aqp; - ACPI_TABLE_HEADER *hdr; + ACPI_TABLE_HEADER fadt, dsdt, xsdt, *hdr; nquirks = sizeof(acpi_quirks) / sizeof(struct acpi_quirk); + if (ACPI_FAILURE(AcpiGetTableHeader(ACPI_SIG_FADT, 0, &fadt))) + memset(&fadt, 0, sizeof(fadt)); + if (ACPI_FAILURE(AcpiGetTableHeader(ACPI_SIG_DSDT, 0, &dsdt))) + memset(&dsdt, 0, sizeof(dsdt)); + if (ACPI_FAILURE(AcpiGetTableHeader(ACPI_SIG_XSDT, 0, &xsdt))) + memset(&xsdt, 0, sizeof(xsdt)); + for (i = 0; i < nquirks; i++) { aqp = &acpi_quirks[i]; - /* XXX AcpiGetTableHeader doesn't work for some reason */ - switch (aqp->aq_tabletype) { - case ACPI_TABLE_DSDT: - hdr = (ACPI_TABLE_HEADER *)AcpiGbl_DSDT; - break; - case ACPI_TABLE_XSDT: - hdr = (ACPI_TABLE_HEADER *)AcpiGbl_XSDT; - break; - case ACPI_TABLE_FADT: - hdr = (ACPI_TABLE_HEADER *)AcpiGbl_FADT; - break; - default: + if (!strncmp(aqp->aq_tabletype, ACPI_SIG_DSDT, 4)) + hdr = &dsdt; + else if (!strncmp(aqp->aq_tabletype, ACPI_SIG_XSDT, 4)) + hdr = &xsdt; + else if (!strncmp(aqp->aq_tabletype, ACPI_SIG_FADT, 4)) + hdr = &fadt; + else continue; - } if (strncmp(aqp->aq_oemid, hdr->OemId, strlen(aqp->aq_oemid))) continue; if (acpi_rev_cmp(aqp->aq_oemrev, hdr->OemRevision, diff --git a/sys/dev/acpi/acpi_tz.c b/sys/dev/acpi/acpi_tz.c index 53c00901617..2fc7e3fe24d 100644 --- a/sys/dev/acpi/acpi_tz.c +++ b/sys/dev/acpi/acpi_tz.c @@ -1,4 +1,4 @@ -/* $NetBSD: acpi_tz.c,v 1.31 2007/12/08 23:01:30 jmcneill Exp $ */ +/* $NetBSD: acpi_tz.c,v 1.32 2007/12/09 20:27:53 jmcneill Exp $ */ /* * Copyright (c) 2003 Jared D. McNeill <jmcneill@invisible.ca> @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: acpi_tz.c,v 1.31 2007/12/08 23:01:30 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acpi_tz.c,v 1.32 2007/12/09 20:27:53 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -200,6 +200,9 @@ acpitz_attach(struct device *parent, struct device *self, void *aux) acpitz_init_envsys(sc); + if (!pmf_device_register(self, NULL, NULL)) + aprint_error(": couldn't establish power handler\n"); + callout_schedule(&sc->sc_callout, sc->sc_zone.tzp * hz / 10); } @@ -523,7 +526,7 @@ acpitz_notify_handler(ACPI_HANDLE hdl, UINT32 notify, void *opaque) KASSERT(func != NULL); - rv = AcpiOsQueueForExecution(OSD_PRIORITY_LO, func, sc); + rv = AcpiOsExecute(OSL_NOTIFY_HANDLER, func, sc); if (rv != AE_OK) printf("%s: unable to queue %s\n", sc->sc_dev.dv_xname, name); @@ -564,7 +567,7 @@ acpitz_tick(void *opaque) { struct acpitz_softc *sc = opaque; - AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpitz_get_status, sc); + AcpiOsExecute(OSL_NOTIFY_HANDLER, acpitz_get_status, sc); callout_schedule(&sc->sc_callout, sc->sc_zone.tzp * hz / 10); } diff --git a/sys/dev/acpi/acpica/OsdEnvironment.c b/sys/dev/acpi/acpica/OsdEnvironment.c index 8bc26e81981..dca9b7a0ab5 100644 --- a/sys/dev/acpi/acpica/OsdEnvironment.c +++ b/sys/dev/acpi/acpica/OsdEnvironment.c @@ -1,4 +1,4 @@ -/* $NetBSD: OsdEnvironment.c,v 1.1 2006/03/23 13:41:13 kochi Exp $ */ +/* $NetBSD: OsdEnvironment.c,v 1.2 2007/12/09 20:27:53 jmcneill Exp $ */ /* * Copyright 2001 Wasabi Systems, Inc. @@ -42,7 +42,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: OsdEnvironment.c,v 1.1 2006/03/23 13:41:13 kochi Exp $"); +__KERNEL_RCSID(0, "$NetBSD: OsdEnvironment.c,v 1.2 2007/12/09 20:27:53 jmcneill Exp $"); #include <sys/types.h> @@ -100,8 +100,8 @@ AcpiOsTerminate(void) * * Obtain the Root ACPI talbe pointer (RSDP) */ -ACPI_STATUS -AcpiOsGetRootPointer(UINT32 Flags, ACPI_POINTER *PhysicalAddress) +ACPI_PHYSICAL_ADDRESS +AcpiOsGetRootPointer(void) { - return acpi_OsGetRootPointer(Flags, PhysicalAddress); + return acpi_OsGetRootPointer(); } diff --git a/sys/dev/acpi/acpica/OsdHardware.c b/sys/dev/acpi/acpica/OsdHardware.c index b9e369809ff..c2c7258205c 100644 --- a/sys/dev/acpi/acpica/OsdHardware.c +++ b/sys/dev/acpi/acpica/OsdHardware.c @@ -1,4 +1,4 @@ -/* $NetBSD: OsdHardware.c,v 1.2 2006/05/14 21:42:26 elad Exp $ */ +/* $NetBSD: OsdHardware.c,v 1.3 2007/12/09 20:27:54 jmcneill Exp $ */ /* * Copyright 2001 Wasabi Systems, Inc. @@ -44,7 +44,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: OsdHardware.c,v 1.2 2006/05/14 21:42:26 elad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: OsdHardware.c,v 1.3 2007/12/09 20:27:54 jmcneill Exp $"); #include <sys/param.h> #include <sys/device.h> @@ -129,9 +129,9 @@ AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS Address, UINT32 *Value, UINT32 Width) void *LogicalAddress; ACPI_STATUS rv; - rv = AcpiOsMapMemory(Address, Width / 8, &LogicalAddress); - if (rv != AE_OK) - return rv; + LogicalAddress = AcpiOsMapMemory(Address, Width / 8); + if (LogicalAddress == NULL) + return AE_NOT_EXIST; switch (Width) { case 8: @@ -166,9 +166,9 @@ AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address, UINT32 Value, UINT32 Width) void *LogicalAddress; ACPI_STATUS rv; - rv = AcpiOsMapMemory(Address, Width / 8, &LogicalAddress); - if (rv != AE_OK) - return rv; + LogicalAddress = AcpiOsMapMemory(Address, Width / 8); + if (LogicalAddress == NULL) + return AE_NOT_FOUND; switch (Width) { case 8: diff --git a/sys/dev/acpi/acpica/OsdMemory.c b/sys/dev/acpi/acpica/OsdMemory.c index 718983fa97c..326a0496ce0 100644 --- a/sys/dev/acpi/acpica/OsdMemory.c +++ b/sys/dev/acpi/acpica/OsdMemory.c @@ -1,4 +1,4 @@ -/* $NetBSD: OsdMemory.c,v 1.1 2006/03/23 13:41:13 kochi Exp $ */ +/* $NetBSD: OsdMemory.c,v 1.2 2007/12/09 20:27:54 jmcneill Exp $ */ /* * Copyright 2001 Wasabi Systems, Inc. @@ -42,7 +42,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: OsdMemory.c,v 1.1 2006/03/23 13:41:13 kochi Exp $"); +__KERNEL_RCSID(0, "$NetBSD: OsdMemory.c,v 1.2 2007/12/09 20:27:54 jmcneill Exp $"); #include <sys/param.h> #include <sys/malloc.h> @@ -58,12 +58,16 @@ MALLOC_DECLARE(M_ACPI); * * Map physical memory into the caller's address space. */ -ACPI_STATUS -AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS PhysicalAddress, ACPI_SIZE Length, - void **LogicalAddress) +void * +AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS PhysicalAddress, ACPI_SIZE Length) { + ACPI_STATUS Status; + void *LogicalAddress = NULL; - return acpi_md_OsMapMemory(PhysicalAddress, Length, LogicalAddress); + Status = acpi_md_OsMapMemory(PhysicalAddress, Length, &LogicalAddress); + if (ACPI_FAILURE (Status)) + return NULL; + return LogicalAddress; } /* @@ -139,3 +143,18 @@ AcpiOsWritable(void *Pointer, ACPI_SIZE Length) return acpi_md_OsWritable(Pointer, Length); } + +ACPI_STATUS +AcpiOsValidateInterface(char *Interface) +{ + + return AE_SUPPORT; +} + +ACPI_STATUS +AcpiOsValidateAddress(UINT8 SpaceId, ACPI_PHYSICAL_ADDRESS Address, + ACPI_SIZE Length) +{ + + return AE_OK; +} diff --git a/sys/dev/acpi/acpica/OsdSchedule.c b/sys/dev/acpi/acpica/OsdSchedule.c index a75b5f47f31..62a912f3519 100644 --- a/sys/dev/acpi/acpica/OsdSchedule.c +++ b/sys/dev/acpi/acpica/OsdSchedule.c @@ -1,4 +1,4 @@ -/* $NetBSD: OsdSchedule.c,v 1.1 2006/03/23 13:41:13 kochi Exp $ */ +/* $NetBSD: OsdSchedule.c,v 1.2 2007/12/09 20:27:54 jmcneill Exp $ */ /* * Copyright 2001 Wasabi Systems, Inc. @@ -42,7 +42,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: OsdSchedule.c,v 1.1 2006/03/23 13:41:13 kochi Exp $"); +__KERNEL_RCSID(0, "$NetBSD: OsdSchedule.c,v 1.2 2007/12/09 20:27:54 jmcneill Exp $"); #include <sys/param.h> #include <sys/malloc.h> @@ -96,7 +96,7 @@ acpi_osd_sched_fini(void) * * Obtain the ID of the currently executing thread. */ -UINT32 +ACPI_THREAD_ID AcpiOsGetThreadId(void) { @@ -114,30 +114,28 @@ AcpiOsGetThreadId(void) * Schedule a procedure for deferred execution. */ ACPI_STATUS -AcpiOsQueueForExecution(UINT32 Priority, ACPI_OSD_EXEC_CALLBACK Function, +AcpiOsExecute(ACPI_EXECUTE_TYPE Type, ACPI_OSD_EXEC_CALLBACK Function, void *Context) { int pri; ACPI_FUNCTION_TRACE(__FUNCTION__); - switch (Priority) { - case OSD_PRIORITY_GPE: - pri = 3; + switch (Type) { + case OSL_GPE_HANDLER: + pri = 10; break; - - case OSD_PRIORITY_HIGH: - pri = 2; + case OSL_GLOBAL_LOCK_HANDLER: + case OSL_EC_POLL_HANDLER: + case OSL_EC_BURST_HANDLER: + pri = 5; break; - - case OSD_PRIORITY_MED: - pri = 1; + case OSL_NOTIFY_HANDLER: + pri = 3; break; - - case OSD_PRIORITY_LO: + case OSL_DEBUGGER_THREAD: pri = 0; break; - default: return_ACPI_STATUS(AE_BAD_PARAMETER); } diff --git a/sys/dev/acpi/acpica/OsdSynch.c b/sys/dev/acpi/acpica/OsdSynch.c index 5ea8c88f502..2819c1980c8 100644 --- a/sys/dev/acpi/acpica/OsdSynch.c +++ b/sys/dev/acpi/acpica/OsdSynch.c @@ -1,4 +1,4 @@ -/* $NetBSD: OsdSynch.c,v 1.8 2007/12/05 07:06:51 ad Exp $ */ +/* $NetBSD: OsdSynch.c,v 1.9 2007/12/09 20:27:54 jmcneill Exp $ */ /* * Copyright 2001 Wasabi Systems, Inc. @@ -69,7 +69,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: OsdSynch.c,v 1.8 2007/12/05 07:06:51 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: OsdSynch.c,v 1.9 2007/12/09 20:27:54 jmcneill Exp $"); #include <sys/param.h> #include <sys/malloc.h> @@ -165,7 +165,7 @@ AcpiOsDeleteSemaphore(ACPI_HANDLE Handle) * Wait for units from a semaphore. */ ACPI_STATUS -AcpiOsWaitSemaphore(ACPI_HANDLE Handle, UINT32 Units, UINT16 Timeout) +AcpiOsWaitSemaphore(ACPI_SEMAPHORE Handle, UINT32 Units, UINT16 Timeout) { struct acpi_semaphore *as = (void *) Handle; ACPI_STATUS rv; @@ -181,6 +181,8 @@ AcpiOsWaitSemaphore(ACPI_HANDLE Handle, UINT32 Units, UINT16 Timeout) if (as == NULL) return_ACPI_STATUS(AE_BAD_PARAMETER); + if (cold) + return_ACPI_STATUS(AE_OK); /* A timeout of 0xFFFF means "forever". */ if (Timeout == 0xFFFF) @@ -285,7 +287,7 @@ AcpiOsCreateLock(ACPI_HANDLE *OutHandle) * Delete a lock. */ void -AcpiOsDeleteLock(ACPI_HANDLE Handle) +AcpiOsDeleteLock(ACPI_SPINLOCK Handle) { struct acpi_lock *al = (void *) Handle; @@ -308,7 +310,7 @@ AcpiOsDeleteLock(ACPI_HANDLE Handle) * Acquire a lock. */ ACPI_NATIVE_UINT -AcpiOsAcquireLock(ACPI_HANDLE Handle) +AcpiOsAcquireLock(ACPI_SPINLOCK Handle) { struct acpi_lock *al = (void *) Handle; diff --git a/sys/dev/acpi/acpica/files.acpica b/sys/dev/acpi/acpica/files.acpica index 95c58e830e5..2e178ad153c 100644 --- a/sys/dev/acpi/acpica/files.acpica +++ b/sys/dev/acpi/acpica/files.acpica @@ -1,4 +1,4 @@ -# $NetBSD: files.acpica,v 1.12 2006/03/23 13:44:10 kochi Exp $ +# $NetBSD: files.acpica,v 1.13 2007/12/09 20:27:54 jmcneill Exp $ file dev/acpi/acpica/OsdEnvironment.c acpi file dev/acpi/acpica/OsdHardware.c acpi @@ -132,11 +132,9 @@ file dist/acpica/rsutils.c acpi file dist/acpica/rsxface.c acpi # tables/ -file dist/acpica/tbconvrt.c acpi -file dist/acpica/tbget.c acpi -file dist/acpica/tbgetall.c acpi +file dist/acpica/tbfadt.c acpi +file dist/acpica/tbfind.c acpi file dist/acpica/tbinstal.c acpi -file dist/acpica/tbrsdt.c acpi file dist/acpica/tbutils.c acpi file dist/acpica/tbxface.c acpi file dist/acpica/tbxfroot.c acpi @@ -156,5 +154,6 @@ file dist/acpica/utmutex.c acpi file dist/acpica/utobject.c acpi file dist/acpica/utresrc.c acpi file dist/acpica/utstate.c acpi +file dist/acpica/uttrack.c acpi file dist/acpica/utxface.c acpi diff --git a/sys/dev/acpi/acpivar.h b/sys/dev/acpi/acpivar.h index 67a5fb97815..4a6f289c646 100644 --- a/sys/dev/acpi/acpivar.h +++ b/sys/dev/acpi/acpivar.h @@ -1,4 +1,4 @@ -/* $NetBSD: acpivar.h,v 1.30 2007/10/19 11:59:35 ad Exp $ */ +/* $NetBSD: acpivar.h,v 1.31 2007/12/09 20:27:53 jmcneill Exp $ */ /* * Copyright 2001 Wasabi Systems, Inc. @@ -260,7 +260,7 @@ extern const struct acpi_resource_parse_ops acpi_resource_parse_ops_default; int acpi_check(device_t, const char *); int acpi_probe(void); -ACPI_STATUS acpi_OsGetRootPointer(UINT32, ACPI_POINTER *); +ACPI_PHYSICAL_ADDRESS acpi_OsGetRootPointer(void); int acpi_match_hid(ACPI_DEVICE_INFO *, const char * const *); void acpi_set_wake_gpe(ACPI_HANDLE); @@ -289,19 +289,6 @@ char * acpi_pci_link_name(void *); ACPI_HANDLE acpi_pci_link_handle(void *); void acpi_pci_link_state(void); - - - -#if defined(_KERNEL_OPT) -#include "acpiec.h" - -#if NACPIEC > 0 -void acpiec_early_attach(struct device *); -#endif -#else -#define NACPIEC 0 -#endif - struct acpi_io *acpi_res_io(struct acpi_resources *, int); struct acpi_iorange *acpi_res_iorange(struct acpi_resources *, int); struct acpi_mem *acpi_res_mem(struct acpi_resources *, int); @@ -318,7 +305,7 @@ ACPI_STATUS acpi_enter_sleep_state(struct acpi_softc *, int); * quirk handling */ struct acpi_quirk { - uint32_t aq_tabletype; /* what type of table (FADT, DSDT, etc) */ + const char *aq_tabletype; /* what type of table (FADT, DSDT, etc) */ const char *aq_oemid; /* compared against the table OemId */ int aq_oemrev; /* compared against the table OemRev */ int aq_cmpop; /* how to compare the oemrev number */ diff --git a/sys/dev/acpi/files.acpi b/sys/dev/acpi/files.acpi index 28ddbee53bf..2f0badc306a 100644 --- a/sys/dev/acpi/files.acpi +++ b/sys/dev/acpi/files.acpi @@ -1,4 +1,4 @@ -# $NetBSD: files.acpi,v 1.46 2007/08/23 10:04:07 tnn Exp $ +# $NetBSD: files.acpi,v 1.47 2007/12/09 20:27:53 jmcneill Exp $ include "dev/acpi/acpica/files.acpica" @@ -8,8 +8,9 @@ defparam opt_acpi.h ACPI_DSDT_FILE := "\"/dev/null\"" define acpiapmbus { } define acpinodebus { } +define acpiecdtbus { } -device acpi: acpiapmbus, acpinodebus, sysmon_power, sysmon_taskq +device acpi: acpiapmbus, acpinodebus, acpiecdtbus, sysmon_power, sysmon_taskq attach acpi at acpibus file dev/acpi/acpi.c acpi needs-flag file dev/acpi/acpi_resource.c acpi @@ -26,7 +27,9 @@ file dev/acpi/acpi_apm.c acpiapm # ACPI Embedded Controller device acpiec attach acpiec at acpinodebus -file dev/acpi/acpi_ec.c acpiec needs-flag +device acpiecdt +attach acpiecdt at acpiecdtbus +file dev/acpi/acpi_ec.c acpiec|acpiecdt # ACPI Lid Switch device acpilid: sysmon_power diff --git a/sys/dev/acpi/pckbc_acpi.c b/sys/dev/acpi/pckbc_acpi.c index 063db3f85cd..e39b6d692ea 100644 --- a/sys/dev/acpi/pckbc_acpi.c +++ b/sys/dev/acpi/pckbc_acpi.c @@ -1,4 +1,4 @@ -/* $NetBSD: pckbc_acpi.c,v 1.22 2007/10/19 11:59:35 ad Exp $ */ +/* $NetBSD: pckbc_acpi.c,v 1.23 2007/12/09 20:27:53 jmcneill Exp $ */ /*- * Copyright (c) 2000 The NetBSD Foundation, Inc. @@ -49,7 +49,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pckbc_acpi.c,v 1.22 2007/10/19 11:59:35 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pckbc_acpi.c,v 1.23 2007/12/09 20:27:53 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -232,10 +232,14 @@ pckbc_acpi_attach(struct device *parent, struct device *self, t->t_sc = &first->sc_pckbc; first->sc_pckbc.id = t; + if (!pmf_device_register(self, NULL, pckbc_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); + first->sc_pckbc.intr_establish = pckbc_acpi_intr_establish; config_defer(&first->sc_pckbc.sc_dv, (void(*)(struct device *))pckbc_attach); - } + } else if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); out: acpi_resource_cleanup(&res); } diff --git a/sys/dev/acpi/pcppi_acpi.c b/sys/dev/acpi/pcppi_acpi.c index 5a60dc74ade..7e516caae4c 100644 --- a/sys/dev/acpi/pcppi_acpi.c +++ b/sys/dev/acpi/pcppi_acpi.c @@ -1,4 +1,4 @@ -/* $NetBSD: pcppi_acpi.c,v 1.7 2007/10/19 11:59:35 ad Exp $ */ +/* $NetBSD: pcppi_acpi.c,v 1.8 2007/12/09 20:27:53 jmcneill Exp $ */ /* * Copyright (c) 2002 Jared D. McNeill <jmcneill@invisible.ca> @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pcppi_acpi.c,v 1.7 2007/10/19 11:59:35 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pcppi_acpi.c,v 1.8 2007/12/09 20:27:53 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -121,6 +121,9 @@ pcppi_acpi_attach(struct device *parent, struct device *self, pcppi_attach(sc); + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); + out: acpi_resource_cleanup(&res); } diff --git a/sys/dev/apm/apm.c b/sys/dev/apm/apm.c index 8b4a8f9ce9f..a0dd710e288 100644 --- a/sys/dev/apm/apm.c +++ b/sys/dev/apm/apm.c @@ -1,4 +1,4 @@ -/* $NetBSD: apm.c,v 1.15 2007/12/05 17:19:48 pooka Exp $ */ +/* $NetBSD: apm.c,v 1.16 2007/12/09 20:27:54 jmcneill Exp $ */ /*- * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. @@ -40,7 +40,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: apm.c,v 1.15 2007/12/05 17:19:48 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: apm.c,v 1.16 2007/12/09 20:27:54 jmcneill Exp $"); #include "opt_apm.h" @@ -316,11 +316,8 @@ apm_suspend(struct apm_softc *sc) sc->sc_power_state = PWR_SUSPEND; if (!(sc->sc_hwflags & APM_F_DONT_RUN_HOOKS)) { - dopowerhooks(PWR_SOFTSUSPEND); - + pmf_system_suspend(); apm_spl = splhigh(); - - dopowerhooks(PWR_SUSPEND); } error = (*sc->sc_ops->aa_set_powstate)(sc->sc_cookie, APM_DEV_ALLDEVS, @@ -345,11 +342,8 @@ apm_standby(struct apm_softc *sc) sc->sc_power_state = PWR_STANDBY; if (!(sc->sc_hwflags & APM_F_DONT_RUN_HOOKS)) { - dopowerhooks(PWR_SOFTSTANDBY); - + pmf_system_suspend(); apm_spl = splhigh(); - - dopowerhooks(PWR_STANDBY); } error = (*sc->sc_ops->aa_set_powstate)(sc->sc_cookie, APM_DEV_ALLDEVS, APM_SYS_STANDBY); @@ -379,11 +373,8 @@ apm_resume(struct apm_softc *sc, u_int event_type, u_int event_info) inittodr(time_second); if (!(sc->sc_hwflags & APM_F_DONT_RUN_HOOKS)) { - dopowerhooks(PWR_RESUME); - splx(apm_spl); - - dopowerhooks(PWR_SOFTRESUME); + pmf_system_resume(); } apm_record_event(sc, event_type); @@ -694,6 +685,9 @@ apm_attach(struct apm_softc *sc) "kernel APM support disabled\n", sc->sc_dev.dv_xname); } + + if (!pmf_device_register(&sc->sc_dev, NULL, NULL)) + aprint_error_dev(&sc->sc_dev, "couldn't establish power handler\n"); } void diff --git a/sys/dev/ata/ata.c b/sys/dev/ata/ata.c index bd1f556f060..fa55e3929d8 100644 --- a/sys/dev/ata/ata.c +++ b/sys/dev/ata/ata.c @@ -1,4 +1,4 @@ -/* $NetBSD: ata.c,v 1.91 2007/10/19 11:59:36 ad Exp $ */ +/* $NetBSD: ata.c,v 1.92 2007/12/09 20:27:54 jmcneill Exp $ */ /* * Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.91 2007/10/19 11:59:36 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.92 2007/12/09 20:27:54 jmcneill Exp $"); #include "opt_ata.h" @@ -106,7 +106,8 @@ const struct cdevsw atabus_cdevsw = { extern struct cfdriver atabus_cd; -static void atabus_powerhook(int, void *); +static bool atabus_resume(device_t); +static bool atabus_suspend(device_t); /* * atabusprint: @@ -416,11 +417,8 @@ atabus_attach(struct device *parent, struct device *self, void *aux) aprint_error("%s: unable to create kernel thread: error %d\n", sc->sc_dev.dv_xname, error); - sc->sc_powerhook = powerhook_establish(sc->sc_dev.dv_xname, - atabus_powerhook, sc); - if (sc->sc_powerhook == NULL) - printf("%s: WARNING: unable to establish power hook\n", - sc->sc_dev.dv_xname); + if (!pmf_device_register(self, atabus_suspend, atabus_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } /* @@ -502,10 +500,6 @@ atabus_detach(struct device *self, int flags) while (chp->ch_thread != NULL) (void) tsleep(&chp->ch_flags, PRIBIO, "atadown", 0); - /* power hook */ - if (sc->sc_powerhook) - powerhook_disestablish(sc->sc_powerhook); - /* * Detach atapibus and its children. */ @@ -1475,33 +1469,38 @@ atabusioctl(dev_t dev, u_long cmd, void *addr, int flag, return (error); }; -static void -atabus_powerhook(int why, void *hdl) +static bool +atabus_suspend(device_t dv) { - struct atabus_softc *sc = (struct atabus_softc *)hdl; + struct atabus_softc *sc = device_private(dv); + struct ata_channel *chp = sc->sc_chan; + + ata_queue_idle(chp->ch_queue); + + return true; +} + +static bool +atabus_resume(device_t dv) +{ + struct atabus_softc *sc = device_private(dv); struct ata_channel *chp = sc->sc_chan; int s; - switch (why) { - case PWR_SOFTSUSPEND: - case PWR_SOFTSTANDBY: - /* freeze the queue and wait for the controller to be idle */ - ata_queue_idle(chp->ch_queue); - break; - case PWR_RESUME: - printf("%s: resuming...\n", sc->sc_dev.dv_xname); - s = splbio(); - KASSERT(chp->ch_queue->queue_freeze > 0); - /* unfreeze the queue and reset drives (to wake them up) */ - chp->ch_queue->queue_freeze--; - ata_reset_channel(chp, AT_WAIT); + /* + * XXX joerg: with wdc, the first channel unfreezes the controler. + * Move this the reset and queue idling into wdc. + */ + s = splbio(); + if (chp->ch_queue->queue_freeze == 0) { splx(s); - break; - case PWR_SUSPEND: - case PWR_STANDBY: - case PWR_SOFTRESUME: - break; + return true; } + KASSERT(chp->ch_queue->queue_freeze > 0); + /* unfreeze the queue and reset drives */ + chp->ch_queue->queue_freeze--; + ata_reset_channel(chp, AT_WAIT); + splx(s); - return; + return true; } diff --git a/sys/dev/ata/atavar.h b/sys/dev/ata/atavar.h index 3460505104a..b5e5bd0688b 100644 --- a/sys/dev/ata/atavar.h +++ b/sys/dev/ata/atavar.h @@ -1,4 +1,4 @@ -/* $NetBSD: atavar.h,v 1.74 2007/07/09 21:00:31 ad Exp $ */ +/* $NetBSD: atavar.h,v 1.75 2007/12/09 20:27:54 jmcneill Exp $ */ /* * Copyright (c) 1998, 2001 Manuel Bouyer. @@ -102,7 +102,6 @@ struct atabus_softc { struct ata_channel *sc_chan; int sc_flags; #define ATABUSCF_OPEN 0x01 - void *sc_powerhook; }; /* diff --git a/sys/dev/ata/wd.c b/sys/dev/ata/wd.c index 94358fb8622..8c87abc7b27 100644 --- a/sys/dev/ata/wd.c +++ b/sys/dev/ata/wd.c @@ -1,4 +1,4 @@ -/* $NetBSD: wd.c,v 1.350 2007/11/07 08:59:03 itohy Exp $ */ +/* $NetBSD: wd.c,v 1.351 2007/12/09 20:27:54 jmcneill Exp $ */ /* * Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved. @@ -66,7 +66,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.350 2007/11/07 08:59:03 itohy Exp $"); +__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.351 2007/12/09 20:27:54 jmcneill Exp $"); #include "opt_ata.h" @@ -139,6 +139,8 @@ int wdactivate(struct device *, enum devact); int wdprint(void *, char *); void wdperror(const struct wd_softc *); +static bool wd_suspend(device_t); + CFATTACH_DECL(wd, sizeof(struct wd_softc), wdprobe, wdattach, wddetach, wdactivate); @@ -189,9 +191,8 @@ void __wdstart(struct wd_softc*, struct buf *); void wdrestart(void *); void wddone(void *); int wd_get_params(struct wd_softc *, u_int8_t, struct ataparams *); -int wd_standby(struct wd_softc *, int); +static int wd_standby(struct wd_softc *, int); int wd_flushcache(struct wd_softc *, int); -void wd_shutdown(void *); int wd_getcache(struct wd_softc *, int *); int wd_setcache(struct wd_softc *, int); @@ -414,10 +415,6 @@ wdattach(struct device *parent, struct device *self, void *aux) disk_init(&wd->sc_dk, wd->sc_dev.dv_xname, &wddkdriver); disk_attach(&wd->sc_dk); wd->sc_wdc_bio.lp = wd->sc_dk.dk_label; - wd->sc_sdhook = shutdownhook_establish(wd_shutdown, wd); - if (wd->sc_sdhook == NULL) - aprint_error("%s: WARNING: unable to establish shutdown hook\n", - wd->sc_dev.dv_xname); #if NRND > 0 rnd_attach_source(&wd->rnd_source, wd->sc_dev.dv_xname, RND_TYPE_DISK, 0); @@ -425,6 +422,20 @@ wdattach(struct device *parent, struct device *self, void *aux) /* Discover wedges on this disk. */ dkwedge_discover(&wd->sc_dk); + + if (!pmf_device_register(self, wd_suspend, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); +} + +static bool +wd_suspend(device_t dv) +{ + struct wd_softc *sc = device_private(dv); + + wd_flushcache(sc, AT_WAIT | AT_POLL); + wd_standby(sc, AT_WAIT | AT_POLL); + + return true; } int @@ -489,9 +500,7 @@ wddetach(struct device *self, int flags) sc->sc_bscount = 0; #endif - /* Get rid of the shutdown hook. */ - if (sc->sc_sdhook != NULL) - shutdownhook_disestablish(sc->sc_sdhook); + pmf_device_deregister(self); #if NRND > 0 /* Unhook the entropy source. */ @@ -1857,7 +1866,7 @@ wd_setcache(struct wd_softc *wd, int bits) return 0; } -int +static int wd_standby(struct wd_softc *wd, int flags) { struct ata_command ata_c; @@ -1869,8 +1878,8 @@ wd_standby(struct wd_softc *wd, int flags) ata_c.flags = flags; ata_c.timeout = 30000; /* 30s timeout */ if (wd->atabus->ata_exec_command(wd->drvp, &ata_c) != ATACMD_COMPLETE) { - printf("%s: standby immediate command didn't complete\n", - wd->sc_dev.dv_xname); + aprint_error_dev(&wd->sc_dev, + "standby immediate command didn't complete\n"); return EIO; } if (ata_c.flags & AT_ERROR) { @@ -1880,8 +1889,7 @@ wd_standby(struct wd_softc *wd, int flags) if (ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) { char sbuf[sizeof(at_errbits) + 64]; bitmask_snprintf(ata_c.flags, at_errbits, sbuf, sizeof(sbuf)); - printf("%s: wd_standby: status=%s\n", wd->sc_dev.dv_xname, - sbuf); + aprint_error_dev(&wd->sc_dev, "wd_standby: status=%s\n", sbuf); return EIO; } return 0; @@ -1929,14 +1937,6 @@ wd_flushcache(struct wd_softc *wd, int flags) return 0; } -void -wd_shutdown(void *arg) -{ - - struct wd_softc *wd = arg; - wd_flushcache(wd, AT_POLL); -} - /* * Allocate space for a ioctl queue structure. Mostly taken from * scsipi_ioctl.c diff --git a/sys/dev/ata/wdvar.h b/sys/dev/ata/wdvar.h index 5bd337fda8b..f909abab5c0 100644 --- a/sys/dev/ata/wdvar.h +++ b/sys/dev/ata/wdvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: wdvar.h,v 1.32 2005/12/11 12:21:14 christos Exp $ */ +/* $NetBSD: wdvar.h,v 1.33 2007/12/09 20:27:55 jmcneill Exp $ */ /* * Copyright (c) 1998, 2001 Manuel Bouyer. @@ -66,8 +66,6 @@ struct wd_softc { int retries; /* number of xfer retry */ - void *sc_sdhook; /* our shutdown hook */ - #ifdef WD_SOFTBADSECT SLIST_HEAD(, disk_badsectors) sc_bslist; u_int sc_bscount; diff --git a/sys/dev/audio.c b/sys/dev/audio.c index f086955e929..dee292c5ab2 100644 --- a/sys/dev/audio.c +++ b/sys/dev/audio.c @@ -1,4 +1,4 @@ -/* $NetBSD: audio.c,v 1.226 2007/12/05 17:19:47 pooka Exp $ */ +/* $NetBSD: audio.c,v 1.227 2007/12/09 20:27:51 jmcneill Exp $ */ /* * Copyright (c) 1991-1993 Regents of the University of California. @@ -61,7 +61,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.226 2007/12/05 17:19:47 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.227 2007/12/09 20:27:51 jmcneill Exp $"); #include "audio.h" #if NAUDIO > 0 @@ -102,6 +102,7 @@ int audiodebug = AUDIO_DEBUG; #define SPECIFIED(x) (x != ~0) #define SPECIFIED_CH(x) (x != (u_char)~0) +int audio_idle_timeout = 30; int audio_blk_ms = AUDIO_BLK_MS; int audiosetinfo(struct audio_softc *, struct audio_info *); @@ -173,7 +174,17 @@ void audioattach(struct device *, struct device *, void *); int audiodetach(struct device *, int); int audioactivate(struct device *, enum devact); -void audio_powerhook(int, void *); +static void audio_idle(void *); +static void audio_activity(device_t, devactive_t); + +static bool audio_suspend(device_t dv); +static bool audio_resume(device_t dv); +static void audio_volume_down(device_t); +static void audio_volume_up(device_t); +static void audio_volume_toggle(device_t); + +static void audio_mixer_capture(struct audio_softc *); +static void audio_mixer_restore(struct audio_softc *); static void audio_softintr_rd(void *); static void audio_softintr_wr(void *); @@ -333,6 +344,8 @@ audioattach(struct device *parent, struct device *self, void *aux) return; } + sc->sc_lastgain = 128; + if ((error = audio_set_defaults(sc, 0))) { aprint_error("audioattach: audio_set_defaults() failed\n"); sc->hw_if = NULL; @@ -419,6 +432,9 @@ audioattach(struct device *parent, struct device *self, void *aux) au_setup_ports(sc, &sc->sc_inports, &mi, itable); } + if (strcmp(mi.label.name, AudioNdac) == 0 && + sc->sc_outports.master == -1) + sc->sc_outports.master = mi.index; } else if (mi.mixer_class == mclass) { if (strcmp(mi.label.name, AudioNmonitor) == 0) sc->sc_monitor_port = mi.index; @@ -467,11 +483,25 @@ audioattach(struct device *parent, struct device *self, void *aux) sc->sc_inports.allports, sc->sc_inports.master, sc->sc_outports.allports, sc->sc_outports.master)); - sc->sc_powerhook = powerhook_establish(sc->dev.dv_xname, - audio_powerhook, sc); - if (sc->sc_powerhook == NULL) - aprint_error("%s: can't establish powerhook\n", - sc->dev.dv_xname); + callout_init(&sc->sc_idle_counter, 0); + callout_setfunc(&sc->sc_idle_counter, audio_idle, self); + + if (!pmf_device_register(self, audio_suspend, audio_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); + if (!device_active_register(self, audio_activity)) + aprint_error_dev(self, "couldn't register activity handler\n"); + + if (!pmf_event_register(self, PMFE_AUDIO_VOLUME_DOWN, + audio_volume_down, true)) + aprint_error_dev(self, "couldn't add volume down handler\n"); + if (!pmf_event_register(self, PMFE_AUDIO_VOLUME_UP, + audio_volume_up, true)) + aprint_error_dev(self, "couldn't add volume up handler\n"); + if (!pmf_event_register(self, PMFE_AUDIO_VOLUME_TOGGLE, + audio_volume_toggle, true)) + aprint_error_dev(self, "couldn't add volume toggle handler\n"); + + callout_schedule(&sc->sc_idle_counter, audio_idle_timeout * hz); } int @@ -503,6 +533,17 @@ audiodetach(struct device *self, int flags) sc->sc_dying = true; + pmf_event_deregister(self, PMFE_AUDIO_VOLUME_DOWN, + audio_volume_down, true); + pmf_event_deregister(self, PMFE_AUDIO_VOLUME_UP, + audio_volume_up, true); + pmf_event_deregister(self, PMFE_AUDIO_VOLUME_TOGGLE, + audio_volume_toggle, true); + + callout_stop(&sc->sc_idle_counter); + + pmf_device_deregister(self); + wakeup(&sc->sc_wchan); wakeup(&sc->sc_rchan); s = splaudio(); @@ -529,10 +570,6 @@ audiodetach(struct device *self, int flags) vdevgone(maj, mn | AUDIOCTL_DEVICE, mn | AUDIOCTL_DEVICE, VCHR); vdevgone(maj, mn | MIXER_DEVICE, mn | MIXER_DEVICE, VCHR); - if (sc->sc_powerhook != NULL) { - powerhook_disestablish(sc->sc_powerhook); - sc->sc_powerhook = NULL; - } if (sc->sc_sih_rd) { softint_disestablish(sc->sc_sih_rd); sc->sc_sih_rd = NULL; @@ -542,6 +579,8 @@ audiodetach(struct device *self, int flags) sc->sc_sih_wr = NULL; } + callout_destroy(&sc->sc_idle_counter); + return 0; } @@ -949,8 +988,8 @@ audioopen(dev_t dev, int flags, int ifmt, struct lwp *l) if (sc->sc_dying) return EIO; - if (sc->hw_if->powerstate && sc->sc_opencnt <= 0) - sc->hw_if->powerstate(sc->hw_hdl, AUDIOPOWER_ON); + device_active(&sc->dev, DVA_SYSTEM); + sc->sc_opencnt++; sc->sc_refcnt++; @@ -983,6 +1022,9 @@ audioclose(dev_t dev, int flags, int ifmt, struct lwp *l) unit = AUDIOUNIT(dev); sc = audio_cd.cd_devs[unit]; + + device_active(&sc->dev, DVA_SYSTEM); + switch (AUDIODEV(dev)) { case SOUND_DEVICE: case AUDIO_DEVICE: @@ -1000,8 +1042,6 @@ audioclose(dev_t dev, int flags, int ifmt, struct lwp *l) } sc->sc_opencnt--; - if (sc->hw_if->powerstate && sc->sc_opencnt <= 0) - sc->hw_if->powerstate(sc->hw_hdl, AUDIOPOWER_OFF); return error; } @@ -1019,6 +1059,8 @@ audioread(dev_t dev, struct uio *uio, int ioflag) if (sc->sc_dying) return EIO; + device_active(&sc->dev, DVA_SYSTEM); + sc->sc_refcnt++; switch (AUDIODEV(dev)) { case SOUND_DEVICE: @@ -1051,6 +1093,8 @@ audiowrite(dev_t dev, struct uio *uio, int ioflag) if (sc->sc_dying) return EIO; + device_active(&sc->dev, DVA_SYSTEM); + sc->sc_refcnt++; switch (AUDIODEV(dev)) { case SOUND_DEVICE: @@ -1085,6 +1129,7 @@ audioioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l) case SOUND_DEVICE: case AUDIO_DEVICE: case AUDIOCTL_DEVICE: + device_active(&sc->dev, DVA_SYSTEM); error = audio_ioctl(sc, cmd, addr, flag, l); break; case MIXER_DEVICE: @@ -1109,6 +1154,8 @@ audiopoll(dev_t dev, int events, struct lwp *l) if (sc->sc_dying) return POLLHUP; + device_active(&sc->dev, DVA_SYSTEM); + sc->sc_refcnt++; switch (AUDIODEV(dev)) { case SOUND_DEVICE: @@ -1138,6 +1185,8 @@ audiokqfilter(dev_t dev, struct knote *kn) if (sc->sc_dying) return 1; + device_active(&sc->dev, DVA_SYSTEM); + sc->sc_refcnt++; switch (AUDIODEV(dev)) { case SOUND_DEVICE: @@ -1166,6 +1215,8 @@ audiommap(dev_t dev, off_t off, int prot) if (sc->sc_dying) return -1; + device_active(&sc->dev, DVA_SYSTEM); /* XXXJDM */ + sc->sc_refcnt++; switch (AUDIODEV(dev)) { case SOUND_DEVICE: @@ -3713,12 +3764,18 @@ mixer_ioctl(struct audio_softc *sc, u_long cmd, void *addr, int flag, struct lwp *l) { const struct audio_hw_if *hw; + mixer_ctrl_t *mc; int error; DPRINTF(("mixer_ioctl(%lu,'%c',%lu)\n", IOCPARM_LEN(cmd), (char)IOCGROUP(cmd), cmd&0xff)); hw = sc->hw_if; error = EINVAL; + + /* we can return cached values if we are sleeping */ + if (cmd != AUDIO_MIXER_READ) + device_active(&sc->dev, DVA_SYSTEM); + switch (cmd) { case FIOASYNC: mixer_remove(sc, l); /* remove old entry */ @@ -3746,7 +3803,19 @@ mixer_ioctl(struct audio_softc *sc, u_long cmd, void *addr, int flag, case AUDIO_MIXER_READ: DPRINTF(("AUDIO_MIXER_READ\n")); - error = hw->get_port(sc->hw_hdl, (mixer_ctrl_t *)addr); + mc = (mixer_ctrl_t *)addr; + + if (device_is_active(sc->sc_dev) || + sc->sc_mixer_state == NULL) + error = hw->get_port(sc->hw_hdl, mc); + else if (mc->dev >= sc->sc_nmixer_states) + error = ENXIO; + else { + int dev = mc->dev; + memcpy(mc, &sc->sc_mixer_state[dev], + sizeof(mixer_ctrl_t)); + error = 0; + } break; case AUDIO_MIXER_WRITE: @@ -3814,30 +3883,195 @@ audioprint(void *aux, const char *pnp) #endif /* NAUDIO > 0 || (NMIDI > 0 || NMIDIBUS > 0) */ #if NAUDIO > 0 -void -audio_powerhook(int why, void *aux) +static void +audio_mixer_capture(struct audio_softc *sc) { - struct audio_softc *sc; - const struct audio_hw_if *hwp; + mixer_devinfo_t mi; + mixer_ctrl_t *mc; - sc = (struct audio_softc *)aux; - hwp = sc->hw_if; + for (mi.index = 0; ; mi.index++) + if (sc->hw_if->query_devinfo(sc->hw_hdl, &mi) != 0) + break; - switch (why) { - case PWR_SOFTSUSPEND: - if (sc->sc_pbus == true) - hwp->halt_output(sc->hw_hdl); - if (sc->sc_rbus == true) - hwp->halt_input(sc->hw_hdl); - break; - case PWR_SOFTRESUME: - if (sc->sc_pbus == true) - audiostartp(sc); - if (sc->sc_rbus == true) - audiostartr(sc); - break; +#ifdef DIAGNOSTIC + if (sc->sc_mixer_state != NULL && sc->sc_nmixer_states != mi.index) { + free(sc->sc_mixer_state, M_DEVBUF); + sc->sc_mixer_state = NULL; + } +#endif + + sc->sc_nmixer_states = mi.index; + if (sc->sc_mixer_state == NULL) + sc->sc_mixer_state = malloc( + sizeof(mixer_ctrl_t) * sc->sc_nmixer_states, + M_DEVBUF, M_NOWAIT); + if (sc->sc_mixer_state == NULL) { + aprint_error("%s: couldn't allocate memory for mixer state\n", + device_xname(&sc->dev)); + return; + } + + for (mi.index = 0; ; mi.index++) { + if (sc->hw_if->query_devinfo(sc->hw_hdl, &mi) != 0) + break; + if (mi.type == AUDIO_MIXER_CLASS) + continue; + mc = &sc->sc_mixer_state[mi.index]; + mc->dev = mi.index; + mc->type = mi.type; + (void)sc->hw_if->get_port(sc->hw_hdl, mc); } return; } + +static void +audio_mixer_restore(struct audio_softc *sc) +{ + mixer_devinfo_t mi; + mixer_ctrl_t *mc; + + if (sc->sc_mixer_state == NULL) + return; + + for (mi.index = 0; ; mi.index++) { + if (sc->hw_if->query_devinfo(sc->hw_hdl, &mi) != 0) + break; + if (mi.type == AUDIO_MIXER_CLASS) + continue; + mc = &sc->sc_mixer_state[mi.index]; + (void)sc->hw_if->set_port(sc->hw_hdl, mc); + } + if (sc->hw_if->commit_settings) + sc->hw_if->commit_settings(sc->hw_hdl); + + return; +} + +static void +audio_idle(void *arg) +{ + device_t dv = arg; + struct audio_softc *sc = device_private(dv); + +#ifdef PNP_DEBUG + extern int pnp_debug_idle; + if (pnp_debug_idle) + printf("%s: idle handler called\n", device_xname(dv)); +#endif + + /* XXX joerg Make pmf_device_suspend handle children? */ + if (!pmf_device_suspend(dv)) + return; + + if (!pmf_device_suspend(sc->sc_dev)) + pmf_device_resume(dv); +} + +static void +audio_activity(device_t dv, devactive_t type) +{ + struct audio_softc *sc = device_private(dv); + + if (type != DVA_SYSTEM) + return; + + callout_schedule(&sc->sc_idle_counter, audio_idle_timeout * hz); + + if (!device_is_active(dv)) { + /* XXX joerg How to deal with a failing resume... */ + pmf_device_resume(sc->sc_dev); + pmf_device_resume(dv); + } +} + +static bool +audio_suspend(device_t dv) +{ + struct audio_softc *sc = device_private(dv); + const struct audio_hw_if *hwp = sc->hw_if; + int (s); + + s = splaudio(); + audio_mixer_capture(sc); + if (sc->sc_pbus == true) + hwp->halt_output(sc->hw_hdl); + if (sc->sc_rbus == true) + hwp->halt_input(sc->hw_hdl); + callout_stop(&sc->sc_idle_counter); + splx(s); + + return true; +} + +static bool +audio_resume(device_t dv) +{ + struct audio_softc *sc = device_private(dv); + int s; + + s = splaudio(); + audio_mixer_restore(sc); + if (sc->sc_pbus == true) + audiostartp(sc); + if (sc->sc_rbus == true) + audiostartr(sc); + splx(s); + + return true; +} + +static void +audio_volume_down(device_t dv) +{ + struct audio_softc *sc = device_private(dv); + u_int gain, newgain; + u_char balance; + int s; + + s = splaudio(); + au_get_gain(sc, &sc->sc_outports, &gain, &balance); + newgain = gain - 32; + if (newgain > 255) + newgain = 0; + au_set_gain(sc, &sc->sc_outports, newgain, balance); + splx(s); +} + +static void +audio_volume_up(device_t dv) +{ + struct audio_softc *sc = device_private(dv); + u_int gain, newgain; + u_char balance; + int s; + + s = splaudio(); + au_get_gain(sc, &sc->sc_outports, &gain, &balance); + newgain = gain + 32; + if (newgain > 255) + newgain = 255; + au_set_gain(sc, &sc->sc_outports, newgain, balance); + splx(s); +} + +static void +audio_volume_toggle(device_t dv) +{ + struct audio_softc *sc = device_private(dv); + u_int gain, newgain; + u_char balance; + int s; + + s = splaudio(); + au_get_gain(sc, &sc->sc_outports, &gain, &balance); + if (gain != 0) { + sc->sc_lastgain = gain; + newgain = sc->sc_lastgain; + } else + newgain = 0; + au_set_gain(sc, &sc->sc_outports, newgain, balance); + splx(s); +} + #endif /* NAUDIO > 0 */ diff --git a/sys/dev/audiovar.h b/sys/dev/audiovar.h index 40026d79e35..75fc2193d41 100644 --- a/sys/dev/audiovar.h +++ b/sys/dev/audiovar.h @@ -1,4 +1,4 @@ -/* $NetBSD: audiovar.h,v 1.39 2007/02/21 22:59:58 thorpej Exp $ */ +/* $NetBSD: audiovar.h,v 1.40 2007/12/09 20:27:52 jmcneill Exp $ */ /*- * Copyright (c) 2002 The NetBSD Foundation, Inc. @@ -225,7 +225,12 @@ struct audio_softc { long sc_rblktime; /* nominal time between interrupts */ #endif - void *sc_powerhook; + u_int sc_lastgain; + + mixer_ctrl_t *sc_mixer_state; + int sc_nmixer_states; + + callout_t sc_idle_counter; }; #endif /* _SYS_DEV_AUDIOVAR_H_ */ diff --git a/sys/dev/cardbus/cardbus.c b/sys/dev/cardbus/cardbus.c index f960ca48875..d52caf5f88a 100644 --- a/sys/dev/cardbus/cardbus.c +++ b/sys/dev/cardbus/cardbus.c @@ -1,4 +1,4 @@ -/* $NetBSD: cardbus.c,v 1.80 2007/12/01 17:56:59 jmcneill Exp $ */ +/* $NetBSD: cardbus.c,v 1.81 2007/12/09 20:27:55 jmcneill Exp $ */ /* * Copyright (c) 1997, 1998, 1999 and 2000 @@ -33,7 +33,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: cardbus.c,v 1.80 2007/12/01 17:56:59 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cardbus.c,v 1.81 2007/12/09 20:27:55 jmcneill Exp $"); #include "opt_cardbus.h" @@ -88,6 +88,8 @@ static int cardbus_read_tuples(struct cardbus_attach_args *, static void enable_function(struct cardbus_softc *, int, int); static void disable_function(struct cardbus_softc *, int); +static bool cardbus_child_register(device_t); + CFATTACH_DECL2(cardbus, sizeof(struct cardbus_softc), cardbusmatch, cardbusattach, NULL, NULL, cardbus_rescan, cardbus_childdetached); @@ -141,6 +143,9 @@ cardbusattach(struct device *parent, struct device *self, void *aux) sc->sc_rbus_iot = cba->cba_rbus_iot; sc->sc_rbus_memt = cba->cba_rbus_memt; #endif + + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); } static int @@ -403,6 +408,7 @@ cardbus_attach_card(struct cardbus_softc *sc) return (0); } + device_pmf_driver_set_child_register(&sc->sc_dev, cardbus_child_register); cardbus_rescan(&sc->sc_dev, "cardbus", wildcard); return (1); /* XXX */ } @@ -925,76 +931,92 @@ decode_tuple(u_int8_t *tuple, u_int8_t *end, /* * XXX: this is another reason why this code should be shared with PCI. */ -int -cardbus_powerstate(cardbus_devfunc_t ct, pcitag_t tag, const int *newstate, - int *oldstate) +static int +cardbus_get_powerstate_int(cardbus_devfunc_t ct, cardbustag_t tag, + cardbusreg_t *state, int offset) { + cardbusreg_t value, now; cardbus_chipset_tag_t cc = ct->ct_cc; cardbus_function_tag_t cf = ct->ct_cf; + value = cardbus_conf_read(cc, cf, tag, offset + PCI_PMCSR); + now = value & PCI_PMCSR_STATE_MASK; + switch (now) { + case PCI_PMCSR_STATE_D0: + case PCI_PMCSR_STATE_D1: + case PCI_PMCSR_STATE_D2: + case PCI_PMCSR_STATE_D3: + *state = now; + return 0; + default: + return EINVAL; + } +} + +int +cardbus_get_powerstate(cardbus_devfunc_t ct, cardbustag_t tag, + cardbusreg_t *state) +{ + cardbus_chipset_tag_t cc = ct->ct_cc; + cardbus_function_tag_t cf = ct->ct_cf; int offset; - pcireg_t value, cap, now; + cardbusreg_t value; - if (!cardbus_get_capability(cc, cf, tag, PCI_CAP_PWRMGMT, &offset, - &value)) + if (!cardbus_get_capability(cc, cf, tag, PCI_CAP_PWRMGMT, &offset, &value)) return EOPNOTSUPP; - cap = value >> 16; + return cardbus_get_powerstate_int(ct, tag, state, offset); +} + +static int +cardbus_set_powerstate_int(cardbus_devfunc_t ct, cardbustag_t tag, + cardbusreg_t state, int offset, cardbusreg_t cap_reg) +{ + cardbus_chipset_tag_t cc = ct->ct_cc; + cardbus_function_tag_t cf = ct->ct_cf; + + cardbusreg_t value, cap, now; + + cap = cap_reg >> PCI_PMCR_SHIFT; value = cardbus_conf_read(cc, cf, tag, offset + PCI_PMCSR); now = value & PCI_PMCSR_STATE_MASK; - value &= ~PCI_PMCSR_STATE_MASK; - if (oldstate) { - switch (now) { - case PCI_PMCSR_STATE_D0: - *oldstate = PCI_PWR_D0; - break; - case PCI_PMCSR_STATE_D1: - *oldstate = PCI_PWR_D1; - break; - case PCI_PMCSR_STATE_D2: - *oldstate = PCI_PWR_D2; - break; - case PCI_PMCSR_STATE_D3: - *oldstate = PCI_PWR_D3; - break; - default: - return EINVAL; - } - } - if (newstate == NULL) + value &= ~PCI_PMCSR_STATE_MASK; + + if (now == state) return 0; - switch (*newstate) { - case PCI_PWR_D0: - if (now == PCI_PMCSR_STATE_D0) - return 0; + switch (state) { + case PCI_PMCSR_STATE_D0: value |= PCI_PMCSR_STATE_D0; break; - case PCI_PWR_D1: - if (now == PCI_PMCSR_STATE_D1) - return 0; - if (now == PCI_PMCSR_STATE_D2 || now == PCI_PMCSR_STATE_D3) + case PCI_PMCSR_STATE_D1: + if (now == PCI_PMCSR_STATE_D2 || now == PCI_PMCSR_STATE_D3) { + printf("invalid transition from %d to D1\n", (int)now); return EINVAL; - if (!(cap & PCI_PMCR_D1SUPP)) + } + if (!(cap & PCI_PMCR_D1SUPP)) { + printf("D1 not supported\n"); return EOPNOTSUPP; + } value |= PCI_PMCSR_STATE_D1; break; - case PCI_PWR_D2: - if (now == PCI_PMCSR_STATE_D2) - return 0; - if (now == PCI_PMCSR_STATE_D3) + case PCI_PMCSR_STATE_D2: + if (now == PCI_PMCSR_STATE_D3) { + printf("invalid transition from %d to D2\n", (int)now); return EINVAL; - if (!(cap & PCI_PMCR_D2SUPP)) + } + if (!(cap & PCI_PMCR_D2SUPP)) { + printf("D2 not supported\n"); return EOPNOTSUPP; + } value |= PCI_PMCSR_STATE_D2; break; - case PCI_PWR_D3: - if (now == PCI_PMCSR_STATE_D3) - return 0; + case PCI_PMCSR_STATE_D3: value |= PCI_PMCSR_STATE_D3; break; default: return EINVAL; } + cardbus_conf_write(cc, cf, tag, offset + PCI_PMCSR, value); DELAY(1000); @@ -1002,41 +1024,20 @@ cardbus_powerstate(cardbus_devfunc_t ct, pcitag_t tag, const int *newstate, } int -cardbus_setpowerstate(const char *dvname, cardbus_devfunc_t ct, pcitag_t tag, - int newpwr) +cardbus_set_powerstate(cardbus_devfunc_t ct, cardbustag_t tag, cardbusreg_t state) { - int oldpwr, error; - - if ((error = cardbus_powerstate(ct, tag, &newpwr, &oldpwr)) != 0) - return error; - - if (oldpwr == newpwr) - return 0; + cardbus_chipset_tag_t cc = ct->ct_cc; + cardbus_function_tag_t cf = ct->ct_cf; + int offset; + cardbusreg_t value; - if (oldpwr > newpwr) { - printf("%s: sleeping to power state D%d\n", dvname, oldpwr); - return 0; - } + if (!cardbus_get_capability(cc, cf, tag, PCI_CAP_PWRMGMT, &offset, + &value)) + return EOPNOTSUPP; - /* oldpwr < newpwr */ - switch (oldpwr) { - case PCI_PWR_D3: - /* - * XXX: This is because none of the devices do - * the necessary song and dance for now to wakeup - * Once this - */ - printf("%s: cannot wake up from power state D%d\n", - dvname, oldpwr); - return EINVAL; - default: - printf("%s: waking up from power state D%d\n", - dvname, oldpwr); - return 0; - } + return cardbus_set_powerstate_int(ct, tag, state, offset, value); } - #ifdef CARDBUS_DEBUG static const char *tuple_name(int); static const char *tuple_names[] = { @@ -1095,3 +1096,137 @@ print_tuple(u_int8_t *tuple, int len, void *data) } } #endif + +void +cardbus_conf_capture(cardbus_chipset_tag_t cc, cardbus_function_tag_t cf, + cardbustag_t tag, struct cardbus_conf_state *pcs) +{ + int off; + + for (off = 0; off < 16; off++) + pcs->reg[off] = cardbus_conf_read(cc, cf, tag, (off * 4)); +} + +void +cardbus_conf_restore(cardbus_chipset_tag_t cc, cardbus_function_tag_t cf, + cardbustag_t tag, struct cardbus_conf_state *pcs) +{ + int off; + cardbusreg_t val; + + for (off = 15; off >= 0; off--) { + val = cardbus_conf_read(cc, cf, tag, (off * 4)); + if (val != pcs->reg[off]) + cardbus_conf_write(cc, cf,tag, (off * 4), pcs->reg[off]); + } +} + +void +cardbus_disable_retry(cardbus_chipset_tag_t cc, cardbus_function_tag_t cf, + cardbustag_t tag) +{ + cardbusreg_t retry; + + /* + * Disable retry timeout to keep PCI Tx retries from + * interfering with ACPI C3 CPU state. + */ + retry = cardbus_conf_read(cc, cf, tag, PCI_RETRY_TIMEOUT_REG); + retry &= ~PCI_RETRY_TIMEOUT_REG_MASK; + cardbus_conf_write(cc, cf, tag, PCI_RETRY_TIMEOUT_REG, retry); +} + +struct cardbus_child_power { + struct cardbus_conf_state p_cardbusconf; + cardbus_devfunc_t p_ct; + cardbustag_t p_tag; + cardbus_chipset_tag_t p_cc; + cardbus_function_tag_t p_cf; + cardbusreg_t p_pm_cap; + bool p_has_pm; + int p_pm_offset; +}; + +static bool +cardbus_child_suspend(device_t dv) +{ + struct cardbus_child_power *priv = device_pmf_bus_private(dv); + + cardbus_conf_capture(priv->p_cc, priv->p_cf, priv->p_tag, + &priv->p_cardbusconf); + + if (priv->p_has_pm && + cardbus_set_powerstate_int(priv->p_ct, priv->p_tag, + PCI_PMCSR_STATE_D3, priv->p_pm_offset, priv->p_pm_cap)) { + aprint_error_dev(dv, "unsupported state, continuing.\n"); + return false; + } + + Cardbus_function_disable(priv->p_ct); + + return true; +} + +static bool +cardbus_child_resume(device_t dv) +{ + struct cardbus_child_power *priv = device_pmf_bus_private(dv); + + Cardbus_function_enable(priv->p_ct); + + if (priv->p_has_pm && + cardbus_set_powerstate_int(priv->p_ct, priv->p_tag, + PCI_PMCSR_STATE_D0, priv->p_pm_offset, priv->p_pm_cap)) { + aprint_error_dev(dv, "unsupported state, continuing.\n"); + return false; + } + + cardbus_conf_restore(priv->p_cc, priv->p_cf, priv->p_tag, + &priv->p_cardbusconf); + + return true; +} + +static void +cardbus_child_deregister(device_t dv) +{ + struct cardbus_child_power *priv = device_pmf_bus_private(dv); + + free(priv, M_DEVBUF); +} + +static bool +cardbus_child_register(device_t child) +{ + device_t self = device_parent(child); + struct cardbus_softc *sc = device_private(self); + struct cardbus_devfunc *ct; + struct cardbus_child_power *priv; + int off; + cardbusreg_t reg; + + ct = sc->sc_funcs[device_locator(child, CARDBUSCF_FUNCTION)]; + + priv = malloc(sizeof(*priv), M_DEVBUF, M_WAITOK); + + priv->p_ct = ct; + priv->p_cc = ct->ct_cf; + priv->p_cf = ct->ct_cf; + priv->p_tag = cardbus_make_tag(priv->p_cc, priv->p_cf, ct->ct_bus, + ct->ct_func); + + if (cardbus_get_capability(priv->p_cc, priv->p_cf, priv->p_tag, + PCI_CAP_PWRMGMT, &off, ®)) { + priv->p_has_pm = true; + priv->p_pm_offset = off; + priv->p_pm_cap = reg; + } else { + priv->p_has_pm = false; + priv->p_pm_offset = -1; + } + + device_pmf_bus_register(child, priv, cardbus_child_suspend, + cardbus_child_resume, cardbus_child_deregister); + + return true; +} diff --git a/sys/dev/cardbus/cardbusvar.h b/sys/dev/cardbus/cardbusvar.h index 00e6b0e4986..5472db2ee4f 100644 --- a/sys/dev/cardbus/cardbusvar.h +++ b/sys/dev/cardbus/cardbusvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: cardbusvar.h,v 1.36 2007/11/16 18:36:53 dyoung Exp $ */ +/* $NetBSD: cardbusvar.h,v 1.37 2007/12/09 20:27:55 jmcneill Exp $ */ /* * Copyright (c) 1998, 1999 and 2000 @@ -199,6 +199,9 @@ struct cardbus_softc { struct cardbus_devfunc *sc_funcs[8]; /* list of cardbus device functions */ }; +struct cardbus_conf_state { + cardbusreg_t reg[16]; +}; /* * struct cardbus_devfunc: @@ -326,10 +329,18 @@ int cardbus_restore_bar(cardbus_devfunc_t); int cardbus_function_enable(struct cardbus_softc *, int); int cardbus_function_disable(struct cardbus_softc *, int); +void cardbus_disable_retry(cardbus_chipset_tag_t, cardbus_function_tag_t, + cardbustag_t); + int cardbus_get_capability(cardbus_chipset_tag_t, cardbus_function_tag_t, cardbustag_t, int, int *, cardbusreg_t *); -int cardbus_powerstate(cardbus_devfunc_t, pcitag_t, const int *, int *); -int cardbus_setpowerstate(const char *, cardbus_devfunc_t, pcitag_t, int); +int cardbus_get_powerstate(cardbus_devfunc_t, cardbustag_t, cardbusreg_t *); +int cardbus_set_powerstate(cardbus_devfunc_t, cardbustag_t, cardbusreg_t); + +void cardbus_conf_capture(cardbus_chipset_tag_t, cardbus_function_tag_t, + cardbustag_t, struct cardbus_conf_state *); +void cardbus_conf_restore(cardbus_chipset_tag_t, cardbus_function_tag_t, + cardbustag_t, struct cardbus_conf_state *); #define Cardbus_function_enable(ct) cardbus_function_enable((ct)->ct_sc, (ct)->ct_func) #define Cardbus_function_disable(ct) cardbus_function_disable((ct)->ct_sc, (ct)->ct_func) diff --git a/sys/dev/cardbus/cardslot.c b/sys/dev/cardbus/cardslot.c index 85bb8ab12ab..053e0d19d8b 100644 --- a/sys/dev/cardbus/cardslot.c +++ b/sys/dev/cardbus/cardslot.c @@ -1,4 +1,4 @@ -/* $NetBSD: cardslot.c,v 1.37 2007/12/01 05:51:16 jmcneill Exp $ */ +/* $NetBSD: cardslot.c,v 1.38 2007/12/09 20:27:55 jmcneill Exp $ */ /* * Copyright (c) 1999 and 2000 @@ -33,7 +33,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: cardslot.c,v 1.37 2007/12/01 05:51:16 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cardslot.c,v 1.38 2007/12/09 20:27:55 jmcneill Exp $"); #include "opt_cardslot.h" @@ -166,6 +166,9 @@ cardslotattach(struct device *parent, struct device *self, /* attach deferred */ cardslot_event_throw(sc, CARDSLOT_EVENT_INSERTION_16); } + + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); } diff --git a/sys/dev/cardbus/if_ath_cardbus.c b/sys/dev/cardbus/if_ath_cardbus.c index 53def036ac3..7ac2f0b28a2 100644 --- a/sys/dev/cardbus/if_ath_cardbus.c +++ b/sys/dev/cardbus/if_ath_cardbus.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_ath_cardbus.c,v 1.20 2007/11/21 02:10:45 dyoung Exp $ */ +/* $NetBSD: if_ath_cardbus.c,v 1.21 2007/12/09 20:27:55 jmcneill Exp $ */ /* * Copyright (c) 2003 * Ichiro FUKUHARA <ichiro@ichiro.org>. @@ -36,7 +36,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_ath_cardbus.c,v 1.20 2007/11/21 02:10:45 dyoung Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_ath_cardbus.c,v 1.21 2007/12/09 20:27:55 jmcneill Exp $"); #include "opt_inet.h" #include "bpfilter.h" @@ -107,13 +107,11 @@ struct ath_cardbus_softc { int sc_intrline; /* interrupt line */ bus_space_tag_t sc_iot; bus_space_handle_t sc_ioh; - void *sc_sdhook; }; int ath_cardbus_match(struct device *, struct cfdata *, void *); void ath_cardbus_attach(struct device *, struct device *, void *); int ath_cardbus_detach(struct device *, int); -void ath_cardbus_shutdown(void *arg); CFATTACH_DECL(ath_cardbus, sizeof(struct ath_cardbus_softc), ath_cardbus_match, ath_cardbus_attach, ath_cardbus_detach, ath_activate); @@ -122,7 +120,20 @@ void ath_cardbus_setup(struct ath_cardbus_softc *); int ath_cardbus_enable(struct ath_softc *); void ath_cardbus_disable(struct ath_softc *); -void ath_cardbus_power(struct ath_softc *, int); + +static bool +ath_cardbus_resume(device_t dv) +{ + struct ath_cardbus_softc *csc = device_private(dv); + cardbus_devfunc_t ct = csc->sc_ct; + cardbus_chipset_tag_t cc = ct->ct_cc; + cardbus_function_tag_t cf = ct->ct_cf; + + cardbus_disable_retry(cc, cf, csc->sc_tag); + ath_resume(&csc->sc_ath); + + return true; +} int ath_cardbus_match(struct device *parent, struct cfdata *match, @@ -161,13 +172,6 @@ ath_cardbus_attach(struct device *parent, struct device *self, */ sc->sc_enable = ath_cardbus_enable; sc->sc_disable = ath_cardbus_disable; - sc->sc_power = ath_cardbus_power; - - csc->sc_sdhook = shutdownhook_establish(ath_cardbus_shutdown, csc); - if (csc->sc_sdhook == NULL) { - aprint_error("couldn't establish shutdown hook\n"); - return; - } /* * Map the device. @@ -184,7 +188,6 @@ ath_cardbus_attach(struct device *parent, struct device *self, else { printf("%s: unable to map device registers\n", sc->sc_dev.dv_xname); - shutdownhook_disestablish(csc->sc_sdhook); return; } @@ -199,15 +202,15 @@ ath_cardbus_attach(struct device *parent, struct device *self, /* Remember which interrupt line. */ csc->sc_intrline = ca->ca_intrline; + if (!pmf_device_register(self, NULL, ath_cardbus_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); + else + pmf_class_network_register(self, &sc->sc_if); + /* * Finish off the attach. */ ath_attach(PCI_PRODUCT(ca->ca_id), sc); - - /* - * Power down the socket. - */ - Cardbus_function_disable(csc->sc_ct); } int @@ -223,12 +226,12 @@ ath_cardbus_detach(struct device *self, int flags) panic("%s: data structure lacks", sc->sc_dev.dv_xname); #endif - shutdownhook_disestablish(csc->sc_sdhook); - rv = ath_detach(sc); if (rv) return (rv); + pmf_device_deregister(self); + /* * Unhook the interrupt handler. */ @@ -245,16 +248,6 @@ ath_cardbus_detach(struct device *self, int flags) return (0); } -void -ath_cardbus_shutdown(void *arg) -{ - struct ath_cardbus_softc *csc; - - csc = arg; - - ath_shutdown(&csc->sc_ath); -} - int ath_cardbus_enable(struct ath_softc *sc) { @@ -301,44 +294,20 @@ ath_cardbus_disable(struct ath_softc *sc) /* Unhook the interrupt handler. */ cardbus_intr_disestablish(cc, cf, csc->sc_ih); csc->sc_ih = NULL; - - /* Power down the socket. */ - Cardbus_function_disable(ct); -} - -void -ath_cardbus_power(struct ath_softc *sc, int why) -{ - struct ath_cardbus_softc *csc = (void *) sc; - - printf("%s: ath_cardbus_power\n", sc->sc_dev.dv_xname); - - if (why == PWR_RESUME) { - /* - * Give the PCI configuration registers a kick - * in the head. - */ -#ifdef DIAGNOSTIC - if (ATH_IS_ENABLED(sc) == 0) - panic("ath_cardbus_power"); -#endif - ath_cardbus_setup(csc); - } } void ath_cardbus_setup(struct ath_cardbus_softc *csc) { - struct ath_softc *sc = &csc->sc_ath; cardbus_devfunc_t ct = csc->sc_ct; cardbus_chipset_tag_t cc = ct->ct_cc; cardbus_function_tag_t cf = ct->ct_cf; int error; pcireg_t reg; - if ((error = cardbus_setpowerstate(sc->sc_dev.dv_xname, ct, csc->sc_tag, + if ((error = cardbus_set_powerstate(ct, csc->sc_tag, PCI_PWR_D0)) != 0) - aprint_debug("%s: cardbus_setpowerstate %d\n", __func__, error); + aprint_debug("%s: cardbus_set_powerstate %d\n", __func__, error); /* Program the BAR. */ cardbus_conf_write(cc, cf, csc->sc_tag, ATH_PCI_MMBA, diff --git a/sys/dev/cardbus/if_atw_cardbus.c b/sys/dev/cardbus/if_atw_cardbus.c index 16f5338c082..c65bc2e4245 100644 --- a/sys/dev/cardbus/if_atw_cardbus.c +++ b/sys/dev/cardbus/if_atw_cardbus.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_atw_cardbus.c,v 1.18 2007/10/19 11:59:38 ad Exp $ */ +/* $NetBSD: if_atw_cardbus.c,v 1.19 2007/12/09 20:27:56 jmcneill Exp $ */ /*- * Copyright (c) 1999, 2000, 2003 The NetBSD Foundation, Inc. @@ -43,7 +43,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_atw_cardbus.c,v 1.18 2007/10/19 11:59:38 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_atw_cardbus.c,v 1.19 2007/12/09 20:27:56 jmcneill Exp $"); #include "opt_inet.h" #include "bpfilter.h" @@ -400,14 +400,12 @@ atw_cardbus_power(struct atw_softc *sc, int why) void atw_cardbus_setup(struct atw_cardbus_softc *csc) { - struct atw_softc *sc = &csc->sc_atw; cardbus_devfunc_t ct = csc->sc_ct; cardbus_chipset_tag_t cc = ct->ct_cc; cardbus_function_tag_t cf = ct->ct_cf; pcireg_t reg; - (void)cardbus_setpowerstate(sc->sc_dev.dv_xname, ct, csc->sc_tag, - PCI_PWR_D0); + (void)cardbus_set_powerstate(ct, csc->sc_tag, PCI_PWR_D0); /* Program the BAR. */ cardbus_conf_write(cc, cf, csc->sc_tag, csc->sc_bar_reg, diff --git a/sys/dev/cardbus/if_ex_cardbus.c b/sys/dev/cardbus/if_ex_cardbus.c index f9a7af5a51f..43ffbea5cbe 100644 --- a/sys/dev/cardbus/if_ex_cardbus.c +++ b/sys/dev/cardbus/if_ex_cardbus.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_ex_cardbus.c,v 1.40 2007/10/19 11:59:38 ad Exp $ */ +/* $NetBSD: if_ex_cardbus.c,v 1.41 2007/12/09 20:27:56 jmcneill Exp $ */ /* * CardBus specific routines for 3Com 3C575-family CardBus ethernet adapter @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_ex_cardbus.c,v 1.40 2007/10/19 11:59:38 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_ex_cardbus.c,v 1.41 2007/12/09 20:27:56 jmcneill Exp $"); /* #define EX_DEBUG 4 */ /* define to report information for debugging */ @@ -413,14 +413,12 @@ void ex_cardbus_setup(csc) struct ex_cardbus_softc *csc; { - struct ex_softc *sc = &csc->sc_softc; cardbus_devfunc_t ct = csc->sc_ct; cardbus_chipset_tag_t cc = ct->ct_cc; cardbus_function_tag_t cf = ct->ct_cf; cardbusreg_t reg; - (void)cardbus_setpowerstate(sc->sc_dev.dv_xname, ct, csc->sc_tag, - PCI_PWR_D0); + (void)cardbus_set_powerstate(ct, csc->sc_tag, PCI_PWR_D0); /* Program the BAR */ cardbus_conf_write(cc, cf, csc->sc_tag, diff --git a/sys/dev/cardbus/if_ral_cardbus.c b/sys/dev/cardbus/if_ral_cardbus.c index 1ed918966f9..adbb743b64a 100644 --- a/sys/dev/cardbus/if_ral_cardbus.c +++ b/sys/dev/cardbus/if_ral_cardbus.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_ral_cardbus.c,v 1.9 2007/10/19 11:59:39 ad Exp $ */ +/* $NetBSD: if_ral_cardbus.c,v 1.10 2007/12/09 20:27:56 jmcneill Exp $ */ /* $OpenBSD: if_ral_cardbus.c,v 1.6 2006/01/09 20:03:31 damien Exp $ */ /*- @@ -22,7 +22,7 @@ * CardBus front-end for the Ralink RT2560/RT2561/RT2561S/RT2661 driver. */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_ral_cardbus.c,v 1.9 2007/10/19 11:59:39 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_ral_cardbus.c,v 1.10 2007/12/09 20:27:56 jmcneill Exp $"); #include "bpfilter.h" @@ -148,7 +148,6 @@ ral_cardbus_attach(struct device *parent, struct device *self, /* power management hooks */ sc->sc_enable = ral_cardbus_enable; sc->sc_disable = ral_cardbus_disable; - sc->sc_power = ral_cardbus_power; /* map control/status registers */ error = Cardbus_mapreg_map(ct, CARDBUS_BASE0_REG, @@ -247,22 +246,6 @@ ral_cardbus_disable(struct rt2560_softc *sc) } void -ral_cardbus_power(struct rt2560_softc *sc, int why) -{ - - switch (why) { - case PWR_RESUME: - ral_cardbus_enable(sc); - break; - case PWR_SUSPEND: - ral_cardbus_disable(sc); - break; - } - - return; -} - -void ral_cardbus_setup(struct ral_cardbus_softc *csc) { cardbus_devfunc_t ct = csc->sc_ct; diff --git a/sys/dev/cardbus/if_re_cardbus.c b/sys/dev/cardbus/if_re_cardbus.c index 3b0724a50d4..9b1cdba24f0 100644 --- a/sys/dev/cardbus/if_re_cardbus.c +++ b/sys/dev/cardbus/if_re_cardbus.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_re_cardbus.c,v 1.14 2007/10/19 11:59:39 ad Exp $ */ +/* $NetBSD: if_re_cardbus.c,v 1.15 2007/12/09 20:27:56 jmcneill Exp $ */ /* * Copyright (c) 2004 Jonathan Stone @@ -36,7 +36,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_re_cardbus.c,v 1.14 2007/10/19 11:59:39 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_re_cardbus.c,v 1.15 2007/12/09 20:27:56 jmcneill Exp $"); #include "opt_inet.h" #include "bpfilter.h" @@ -133,7 +133,6 @@ void re_cardbus_setup(struct re_cardbus_softc *); int re_cardbus_enable(struct rtk_softc *); void re_cardbus_disable(struct rtk_softc *); -void re_cardbus_power(struct rtk_softc *, int); const struct rtk_type * re_cardbus_lookup(const struct cardbus_attach_args *ca) @@ -188,7 +187,6 @@ re_cardbus_attach(struct device *parent, struct device *self, void *aux) */ sc->sc_enable = re_cardbus_enable; sc->sc_disable = re_cardbus_disable; - sc->sc_power = re_cardbus_power; /* * Map control/status registers. @@ -233,6 +231,11 @@ re_cardbus_attach(struct device *parent, struct device *self, void *aux) sc->sc_dmat = ca->ca_dmat; re_attach(sc); + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); + else + pmf_class_network_register(self, &sc->ethercom.ec_if); + /* * Power down the socket. */ @@ -252,9 +255,13 @@ re_cardbus_detach(struct device *self, int flags) panic("%s: cardbus softc, cardbus_devfunc NULL", sc->sc_dev.dv_xname); #endif + rv = re_detach(sc); if (rv) return rv; + + pmf_device_deregister(self); + /* * Unhook the interrupt handler. */ @@ -394,21 +401,3 @@ re_cardbus_disable(struct rtk_softc *sc) /* Power down the socket. */ Cardbus_function_disable(ct); } - -void -re_cardbus_power(struct rtk_softc *sc, int why) -{ - struct re_cardbus_softc *csc = (void *) sc; - - if (why == PWR_RESUME) { - /* - * Give the PCI configuration registers a kick - * in the head. - */ -#ifdef DIAGNOSTIC - if (RTK_IS_ENABLED(sc) == 0) - panic("re_cardbus_power"); -#endif - re_cardbus_setup(csc); - } -} diff --git a/sys/dev/cardbus/if_rtk_cardbus.c b/sys/dev/cardbus/if_rtk_cardbus.c index 9e3f843a165..166e1390e60 100644 --- a/sys/dev/cardbus/if_rtk_cardbus.c +++ b/sys/dev/cardbus/if_rtk_cardbus.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_rtk_cardbus.c,v 1.33 2007/10/19 11:59:39 ad Exp $ */ +/* $NetBSD: if_rtk_cardbus.c,v 1.34 2007/12/09 20:27:56 jmcneill Exp $ */ /* * Copyright (c) 2000 Masanori Kanaoka @@ -36,7 +36,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_rtk_cardbus.c,v 1.33 2007/10/19 11:59:39 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_rtk_cardbus.c,v 1.34 2007/12/09 20:27:56 jmcneill Exp $"); #include "opt_inet.h" #include "bpfilter.h" @@ -206,7 +206,6 @@ rtk_cardbus_attach(struct device *parent, struct device *self, */ sc->sc_enable = rtk_cardbus_enable; sc->sc_disable = rtk_cardbus_disable; - sc->sc_power = rtk_cardbus_power; /* * Map control/status registers. @@ -250,6 +249,11 @@ rtk_cardbus_attach(struct device *parent, struct device *self, rtk_attach(sc); + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); + else + pmf_class_network_register(self, &sc->ethercom.ec_if); + /* * Power down the socket. */ @@ -413,23 +417,3 @@ rtk_cardbus_disable(sc) /* Power down the socket. */ Cardbus_function_disable(ct); } - -void -rtk_cardbus_power(sc, why) - struct rtk_softc *sc; - int why; -{ - struct rtk_cardbus_softc *csc = (void *) sc; - - if (why == PWR_RESUME) { - /* - * Give the PCI configuration registers a kick - * in the head. - */ -#ifdef DIAGNOSTIC - if (RTK_IS_ENABLED(sc) == 0) - panic("rtk_cardbus_power"); -#endif - rtk_cardbus_setup(csc); - } -} diff --git a/sys/dev/cardbus/if_rtw_cardbus.c b/sys/dev/cardbus/if_rtw_cardbus.c index cde48f8d9da..d23df1a05e3 100644 --- a/sys/dev/cardbus/if_rtw_cardbus.c +++ b/sys/dev/cardbus/if_rtw_cardbus.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_rtw_cardbus.c,v 1.18 2007/11/16 18:47:41 dyoung Exp $ */ +/* $NetBSD: if_rtw_cardbus.c,v 1.19 2007/12/09 20:27:56 jmcneill Exp $ */ /*- * Copyright (c) 2004, 2005 David Young. All rights reserved. @@ -74,7 +74,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_rtw_cardbus.c,v 1.18 2007/11/16 18:47:41 dyoung Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_rtw_cardbus.c,v 1.19 2007/12/09 20:27:56 jmcneill Exp $"); #include "opt_inet.h" #include "bpfilter.h" @@ -464,15 +464,13 @@ rtw_cardbus_power(struct rtw_softc *sc, int why) void rtw_cardbus_setup(struct rtw_cardbus_softc *csc) { - struct rtw_softc *sc = &csc->sc_rtw; cardbustag_t tag = csc->sc_tag; cardbus_devfunc_t ct = csc->sc_ct; cardbus_chipset_tag_t cc = ct->ct_cc; cardbusreg_t bhlc, csr, lattimer; cardbus_function_tag_t cf = ct->ct_cf; - (void)cardbus_setpowerstate(device_xname(&sc->sc_dev), ct, tag, - PCI_PWR_D0); + (void)cardbus_set_powerstate(ct, tag, PCI_PWR_D0); /* I believe the datasheet tries to warn us that the RTL8180 * wants for 16 (0x10) to divide the latency timer. diff --git a/sys/dev/cardbus/if_tlp_cardbus.c b/sys/dev/cardbus/if_tlp_cardbus.c index e388c8150b5..6d90b018999 100644 --- a/sys/dev/cardbus/if_tlp_cardbus.c +++ b/sys/dev/cardbus/if_tlp_cardbus.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_tlp_cardbus.c,v 1.54 2007/10/19 11:59:39 ad Exp $ */ +/* $NetBSD: if_tlp_cardbus.c,v 1.55 2007/12/09 20:27:56 jmcneill Exp $ */ /*- * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc. @@ -43,7 +43,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_tlp_cardbus.c,v 1.54 2007/10/19 11:59:39 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_tlp_cardbus.c,v 1.55 2007/12/09 20:27:56 jmcneill Exp $"); #include "opt_inet.h" #include "bpfilter.h" @@ -612,8 +612,7 @@ tlp_cardbus_setup(csc) break; } - (void)cardbus_setpowerstate(sc->sc_dev.dv_xname, ct, csc->sc_tag, - PCI_PWR_D0); + (void)cardbus_set_powerstate(ct, csc->sc_tag, PCI_PWR_D0); /* Program the BAR. */ cardbus_conf_write(cc, cf, csc->sc_tag, csc->sc_bar_reg, diff --git a/sys/dev/dkwedge/dk.c b/sys/dev/dkwedge/dk.c index 9c4fd442c99..932682a9b5d 100644 --- a/sys/dev/dkwedge/dk.c +++ b/sys/dev/dkwedge/dk.c @@ -1,4 +1,4 @@ -/* $NetBSD: dk.c,v 1.30 2007/11/26 19:01:37 pooka Exp $ */ +/* $NetBSD: dk.c,v 1.31 2007/12/09 20:27:56 jmcneill Exp $ */ /*- * Copyright (c) 2004, 2005, 2006, 2007 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: dk.c,v 1.30 2007/11/26 19:01:37 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: dk.c,v 1.31 2007/12/09 20:27:56 jmcneill Exp $"); #include "opt_dkwedge.h" @@ -150,7 +150,8 @@ dkwedge_attach(struct device *parent, struct device *self, void *aux) { - /* Nothing to do. */ + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); } /* @@ -162,6 +163,7 @@ static int dkwedge_detach(struct device *self, int flags) { + pmf_device_deregister(self); /* Always succeeds. */ return (0); } diff --git a/sys/dev/i2c/i2c.c b/sys/dev/i2c/i2c.c index bef090b4481..3c7dc60c8d6 100644 --- a/sys/dev/i2c/i2c.c +++ b/sys/dev/i2c/i2c.c @@ -1,4 +1,4 @@ -/* $NetBSD: i2c.c,v 1.16 2007/11/12 19:42:44 joerg Exp $ */ +/* $NetBSD: i2c.c,v 1.17 2007/12/09 20:27:57 jmcneill Exp $ */ /* * Copyright (c) 2003 Wasabi Systems, Inc. @@ -152,6 +152,9 @@ iic_attach(struct device *parent, struct device *self, void *aux) } #endif + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); + /* * Attach all i2c devices described in the kernel * configuration file. diff --git a/sys/dev/ic/an.c b/sys/dev/ic/an.c index 85274e44824..8c5da46371c 100644 --- a/sys/dev/ic/an.c +++ b/sys/dev/ic/an.c @@ -1,4 +1,4 @@ -/* $NetBSD: an.c,v 1.49 2007/10/19 11:59:47 ad Exp $ */ +/* $NetBSD: an.c,v 1.50 2007/12/09 20:27:57 jmcneill Exp $ */ /* * Copyright (c) 1997, 1998, 1999 * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. @@ -77,7 +77,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: an.c,v 1.49 2007/10/19 11:59:47 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: an.c,v 1.50 2007/12/09 20:27:57 jmcneill Exp $"); #include "bpfilter.h" @@ -448,41 +448,6 @@ an_activate(struct device *self, enum devact act) return error; } -void -an_power(int why, void *arg) -{ - int s; - struct an_softc *sc = arg; - struct ifnet *ifp = &sc->sc_if; - - s = splnet(); - switch (why) { - case PWR_SUSPEND: - case PWR_STANDBY: - an_stop(ifp, 1); - break; - case PWR_RESUME: - if (ifp->if_flags & IFF_UP) { - an_init(ifp); - (void)an_intr(sc); - } - break; - case PWR_SOFTSUSPEND: - case PWR_SOFTSTANDBY: - case PWR_SOFTRESUME: - break; - } - splx(s); -} - -void -an_shutdown(struct an_softc *sc) -{ - - if (sc->sc_attached) - an_stop(&sc->sc_if, 1); -} - int an_intr(void *arg) { diff --git a/sys/dev/ic/anvar.h b/sys/dev/ic/anvar.h index eb0be9d34f3..b0f931f0d3e 100644 --- a/sys/dev/ic/anvar.h +++ b/sys/dev/ic/anvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: anvar.h,v 1.14 2007/03/04 06:01:49 christos Exp $ */ +/* $NetBSD: anvar.h,v 1.15 2007/12/09 20:27:57 jmcneill Exp $ */ /* * Copyright (c) 1997, 1998, 1999 * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. @@ -165,8 +165,6 @@ struct an_softc { int an_attach(struct an_softc *); int an_detach(struct an_softc *); int an_activate(struct device *, enum devact); -void an_power(int, void *); -void an_shutdown(struct an_softc *); int an_intr(void *); #endif /* _DEV_IC_ANVAR_H */ diff --git a/sys/dev/ic/ath.c b/sys/dev/ic/ath.c index d5d8a15db92..57ff814bf43 100644 --- a/sys/dev/ic/ath.c +++ b/sys/dev/ic/ath.c @@ -1,4 +1,4 @@ -/* $NetBSD: ath.c,v 1.92 2007/11/27 00:07:42 dyoung Exp $ */ +/* $NetBSD: ath.c,v 1.93 2007/12/09 20:27:57 jmcneill Exp $ */ /*- * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting @@ -41,7 +41,7 @@ __FBSDID("$FreeBSD: src/sys/dev/ath/if_ath.c,v 1.104 2005/09/16 10:09:23 ru Exp $"); #endif #ifdef __NetBSD__ -__KERNEL_RCSID(0, "$NetBSD: ath.c,v 1.92 2007/11/27 00:07:42 dyoung Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ath.c,v 1.93 2007/12/09 20:27:57 jmcneill Exp $"); #endif /* @@ -203,7 +203,6 @@ static void ath_setcurmode(struct ath_softc *, enum ieee80211_phymode); #ifdef __NetBSD__ int ath_enable(struct ath_softc *); void ath_disable(struct ath_softc *); -void ath_power(int, void *); #endif #if NBPFILTER > 0 @@ -526,6 +525,7 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) ifp->if_softc = sc; ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST; ifp->if_start = ath_start; + ifp->if_stop = ath_stop; ifp->if_watchdog = ath_watchdog; ifp->if_ioctl = ath_ioctl; ifp->if_init = ath_ifinit; @@ -639,14 +639,7 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) ath_bpfattach(sc); #endif -#ifdef __NetBSD__ sc->sc_flags |= ATH_ATTACHED; - sc->sc_powerhook = powerhook_establish(sc->sc_dev.dv_xname, - ath_power, sc); - if (sc->sc_powerhook == NULL) - printf("%s: WARNING: unable to establish power hook\n", - sc->sc_dev.dv_xname); -#endif /* * Setup dynamic sysctl's now that country code and @@ -713,78 +706,15 @@ ath_detach(struct ath_softc *sc) return 0; } -#ifdef __NetBSD__ -void -ath_power(int why, void *arg) -{ - struct ath_softc *sc = arg; - int s; - - DPRINTF(sc, ATH_DEBUG_ANY, "ath_power(%d)\n", why); - - s = splnet(); - switch (why) { - case PWR_SUSPEND: - case PWR_STANDBY: - ath_suspend(sc, why); - break; - case PWR_RESUME: - ath_resume(sc, why); - break; - case PWR_SOFTSUSPEND: - case PWR_SOFTSTANDBY: - case PWR_SOFTRESUME: - break; - } - splx(s); -} -#endif - -void -ath_suspend(struct ath_softc *sc, int why) -{ - struct ifnet *ifp = &sc->sc_if; - - DPRINTF(sc, ATH_DEBUG_ANY, "%s: if_flags %x\n", - __func__, ifp->if_flags); - - ath_stop(ifp, 1); - if (sc->sc_power != NULL) - (*sc->sc_power)(sc, why); -} - void -ath_resume(struct ath_softc *sc, int why) +ath_resume(struct ath_softc *sc) { - struct ifnet *ifp = &sc->sc_if; - - DPRINTF(sc, ATH_DEBUG_ANY, "%s: if_flags %x\n", - __func__, ifp->if_flags); - - if (ifp->if_flags & IFF_UP) { - ath_init(sc); -#if 0 - (void)ath_intr(sc); -#endif - if (sc->sc_power != NULL) - (*sc->sc_power)(sc, why); - if (ifp->if_flags & IFF_RUNNING) - ath_start(ifp); - } if (sc->sc_softled) { ath_hal_gpioCfgOutput(sc->sc_ah, sc->sc_ledpin); ath_hal_gpioset(sc->sc_ah, sc->sc_ledpin, !sc->sc_ledon); } } -void -ath_shutdown(void *arg) -{ - struct ath_softc *sc = arg; - - ath_stop(&sc->sc_if, 1); -} - /* * Interrupt handler. Most of the actual processing is deferred. */ diff --git a/sys/dev/ic/athvar.h b/sys/dev/ic/athvar.h index 783387b0eb4..e34bf253896 100644 --- a/sys/dev/ic/athvar.h +++ b/sys/dev/ic/athvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: athvar.h,v 1.21 2007/07/17 01:26:17 dyoung Exp $ */ +/* $NetBSD: athvar.h,v 1.22 2007/12/09 20:27:57 jmcneill Exp $ */ /*- * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting @@ -306,11 +306,8 @@ struct ath_softc { int ath_attach(u_int16_t, struct ath_softc *); int ath_detach(struct ath_softc *); -void ath_resume(struct ath_softc *, int); -void ath_suspend(struct ath_softc *, int); int ath_activate(struct device *, enum devact); -void ath_power(int, void *); -void ath_shutdown(void *); +void ath_resume(struct ath_softc *); int ath_intr(void *); int ath_reset(struct ifnet *); void ath_sysctlattach(struct ath_softc *); diff --git a/sys/dev/ic/attimer.c b/sys/dev/ic/attimer.c index 413a09b3603..f78aade6e87 100644 --- a/sys/dev/ic/attimer.c +++ b/sys/dev/ic/attimer.c @@ -1,4 +1,4 @@ -/* $NetBSD: attimer.c,v 1.4 2007/10/19 11:59:48 ad Exp $ */ +/* $NetBSD: attimer.c,v 1.5 2007/12/09 20:27:58 jmcneill Exp $ */ /* * Copyright (c) 2005 The NetBSD Foundation. @@ -36,7 +36,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: attimer.c,v 1.4 2007/10/19 11:59:48 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: attimer.c,v 1.5 2007/12/09 20:27:58 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -56,6 +56,9 @@ void attimer_attach(struct attimer_softc *sc) { sc->sc_flags |= ATT_CONFIGURED; + + if (!pmf_device_register(&sc->sc_dev, NULL, NULL)) + aprint_error_dev(&sc->sc_dev, "couldn't establish power handler\n"); } /* diff --git a/sys/dev/ic/hpet.c b/sys/dev/ic/hpet.c index 0794eb1b974..9b22e4d0e75 100644 --- a/sys/dev/ic/hpet.c +++ b/sys/dev/ic/hpet.c @@ -1,4 +1,4 @@ -/* $NetBSD: hpet.c,v 1.3 2007/12/01 16:51:22 ad Exp $ */ +/* $NetBSD: hpet.c,v 1.4 2007/12/09 20:27:58 jmcneill Exp $ */ /* * Copyright (c) 2006 Nicolas Joly @@ -33,7 +33,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: hpet.c,v 1.3 2007/12/01 16:51:22 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: hpet.c,v 1.4 2007/12/09 20:27:58 jmcneill Exp $"); #include <sys/systm.h> #include <sys/device.h> @@ -48,6 +48,7 @@ __KERNEL_RCSID(0, "$NetBSD: hpet.c,v 1.3 2007/12/01 16:51:22 ad Exp $"); #include <dev/ic/hpetvar.h> static u_int hpet_get_timecount(struct timecounter *); +static bool hpet_resume(device_t); void hpet_attach_subr(struct hpet_softc *sc) { @@ -60,12 +61,6 @@ hpet_attach_subr(struct hpet_softc *sc) { tc->tc_get_timecount = hpet_get_timecount; tc->tc_quality = 2000; - /* XXX Only 32-bits supported for now */ - val = bus_space_read_4(sc->sc_memt, sc->sc_memh, HPET_INFO); - if ((val & HPET_INFO_64BITS) != 0) { - aprint_debug("%s: Found 64-bits HPET, will only use lowest" - " 32-bits\n", sc->sc_dev.dv_xname); - } tc->tc_counter_mask = 0xffffffff; /* Get frequency */ @@ -81,12 +76,27 @@ hpet_attach_subr(struct hpet_softc *sc) { tc->tc_priv = sc; tc_init(tc); + + if (!pmf_device_register(&sc->sc_dev, NULL, hpet_resume)) + aprint_error_dev(&sc->sc_dev, "couldn't establish power handler\n"); } static u_int hpet_get_timecount(struct timecounter *tc) { struct hpet_softc *sc = tc->tc_priv; - return bus_space_read_4(sc->sc_memt, sc->sc_memh, HPET_MCOUNT); + return bus_space_read_4(sc->sc_memt, sc->sc_memh, HPET_MCOUNT_LO); } +static bool +hpet_resume(device_t dv) +{ + struct hpet_softc *sc = device_private(dv); + uint32_t val; + + val = bus_space_read_4(sc->sc_memt, sc->sc_memh, HPET_CONFIG); + val |= HPET_CONFIG_ENABLE; + bus_space_write_4(sc->sc_memt, sc->sc_memh, HPET_CONFIG, val); + + return true; +} diff --git a/sys/dev/ic/hpetreg.h b/sys/dev/ic/hpetreg.h index 16648a20bf1..dcde6ee447a 100644 --- a/sys/dev/ic/hpetreg.h +++ b/sys/dev/ic/hpetreg.h @@ -1,4 +1,4 @@ -/* $NetBSD: hpetreg.h,v 1.1 2007/03/08 14:26:28 njoly Exp $ */ +/* $NetBSD: hpetreg.h,v 1.2 2007/12/09 20:27:58 jmcneill Exp $ */ /* * Copyright (c) 2006 Nicolas Joly @@ -31,11 +31,27 @@ #ifndef _DEV_IC_HPETREG_H_ #define _DEV_IC_HPETREG_H_ -#define HPET_INFO 0x00 -#define HPET_INFO_64BITS 0x2000 -#define HPET_PERIOD 0x04 -#define HPET_CONFIG 0x10 -#define HPET_CONFIG_ENABLE 0x0001 -#define HPET_MCOUNT 0xf0 +#define HPET_WINDOW_SIZE 0x400 + +#define HPET_INFO 0x00 +#define HPET_INFO_64BITS 0x2000 +#define HPET_PERIOD 0x04 +#define HPET_CONFIG 0x10 +#define HPET_CONFIG_ENABLE 0x0001 +#define HPET_MCOUNT_LO 0xf0 +#define HPET_MCOUNT_HI 0xf4 +#define HPET_INT_STATUS 0x20 +#define HPET_INT_STS_TIMER0 0x00000001 + +#define HPET_TIMER_USE_LEVEL_INTR 0x00000002 +#define HPET_TIMER_ENABLE_INTR 0x00000004 +#define HPET_TIMER_IS_PERIODIC_INTR 0x00000008 +#define HPET_TIMER_HAS_PERIODIC_INTR 0x00000010 +#define HPET_TIMER_INTR_SHIFT 9 + +#define HPET_TIMER0_CONFIG 0x0100 +#define HPET_TIMER0_INTCAP 0x0104 +#define HPET_TIMER0_CMPREG_LO 0x0108 +#define HPET_TIMER0_CMPREG_HI 0x010C #endif /* _DEV_IC_HPETREG_H_ */ diff --git a/sys/dev/ic/i82801lpcreg.h b/sys/dev/ic/i82801lpcreg.h index c2cfbe2f86c..ddddbc28418 100644 --- a/sys/dev/ic/i82801lpcreg.h +++ b/sys/dev/ic/i82801lpcreg.h @@ -1,4 +1,4 @@ -/* $NetBSD: i82801lpcreg.h,v 1.6 2007/08/26 18:39:43 xtraeme Exp $ */ +/* $NetBSD: i82801lpcreg.h,v 1.7 2007/12/09 20:27:58 jmcneill Exp $ */ /*- * Copyright (c) 2004 The NetBSD Foundation, Inc. @@ -78,6 +78,16 @@ #define LPCIB_PCI_MON7_TRP_RNG 0xc7 #define LPCIB_PCI_MON_TRP_MSK oxcc #define LPCIB_PCI_GEN_CNTL 0xd0 +#define LPCIB_ICH5_HPTC_EN 0x00020000 +#define LPCIB_ICH5_HPTC_WIN_MASK 0x0000c000 +#define LPCIB_ICH5_HPTC_0000 0x00000000 +#define LPCIB_ICH5_HPTC_0000_BASE 0xfed00000 +#define LPCIB_ICH5_HPTC_1000 0x00008000 +#define LPCIB_ICH5_HPTC_1000_BASE 0xfed01000 +#define LPCIB_ICH5_HPTC_2000 0x00010000 +#define LPCIB_ICH5_HPTC_2000_BASE 0xfed02000 +#define LPCIB_ICH5_HPTC_3000 0x00018000 +#define LPCIB_ICH5_HPTC_3000_BASE 0xfed03000 #define LPCIB_PCI_GEN_STA 0xd4 # define LPCIB_PCI_GEN_STA_SAFE_MODE (1 << 2) # define LPCIB_PCI_GEN_STA_NO_REBOOT (1 << 1) @@ -209,9 +219,21 @@ /* ICH Chipset Configuration Registers (ICH6 and newer) */ #define LPCIB_RCBA 0xf0 -#define LPCIB_GCS_OFFSET 0x3410 -#define LPCIB_GCS_SIZE 4 -#define LPCIB_GCS_NO_REBOOT 0x20 +#define LPCIB_RCBA_EN 0x00000001 +#define LPCIB_RCBA_SIZE 0x00004000 +#define LPCIB_GCS_OFFSET 0x3410 +#define LPCIB_GCS_NO_REBOOT 0x20 +#define LPCIB_RCBA_HPTC 0x00003404 +#define LPCIB_RCBA_HPTC_EN 0x00000080 +#define LPCIB_RCBA_HPTC_WIN_MASK 0x00000003 +#define LPCIB_RCBA_HPTC_0000 0x00000000 +#define LPCIB_RCBA_HPTC_0000_BASE 0xfed00000 +#define LPCIB_RCBA_HPTC_1000 0x00000001 +#define LPCIB_RCBA_HPTC_1000_BASE 0xfed01000 +#define LPCIB_RCBA_HPTC_2000 0x00000002 +#define LPCIB_RCBA_HPTC_2000_BASE 0xfed02000 +#define LPCIB_RCBA_HPTC_3000 0x00000003 +#define LPCIB_RCBA_HPTC_3000_BASE 0xfed03000 /* * System management TCO registers diff --git a/sys/dev/ic/pckbc.c b/sys/dev/ic/pckbc.c index bf1ce784220..ed39bd94af1 100644 --- a/sys/dev/ic/pckbc.c +++ b/sys/dev/ic/pckbc.c @@ -1,4 +1,4 @@ -/* $NetBSD: pckbc.c,v 1.38 2007/10/19 11:59:59 ad Exp $ */ +/* $NetBSD: pckbc.c,v 1.39 2007/12/09 20:27:58 jmcneill Exp $ */ /* * Copyright (c) 2004 Ben Harris. @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pckbc.c,v 1.38 2007/10/19 11:59:59 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pckbc.c,v 1.39 2007/12/09 20:27:58 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -714,3 +714,20 @@ pckbc_cnattach(iot, addr, cmd_offset, slot) return (res); } + +bool +pckbc_resume(device_t dv) +{ + struct pckbc_softc *sc = device_private(dv); + struct pckbc_internal *t; + + t = sc->id; + (void)pckbc_poll_data1(t, PCKBC_KBD_SLOT); + if (!pckbc_send_cmd(t->t_iot, t->t_ioh_c, KBC_SELFTEST)) + return false; + (void)pckbc_poll_data1(t, PCKBC_KBD_SLOT); + (void)pckbc_put8042cmd(t); + pckbcintr(t->t_sc); + + return true; +} diff --git a/sys/dev/ic/pckbcvar.h b/sys/dev/ic/pckbcvar.h index aac2d483393..0288621ed07 100644 --- a/sys/dev/ic/pckbcvar.h +++ b/sys/dev/ic/pckbcvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: pckbcvar.h,v 1.12 2005/12/11 12:21:28 christos Exp $ */ +/* $NetBSD: pckbcvar.h,v 1.13 2007/12/09 20:27:58 jmcneill Exp $ */ /* * Copyright (c) 1998 @@ -111,4 +111,7 @@ void pckbcintr_soft(void *); /* md hook for use without mi wscons */ int pckbc_machdep_cnattach(pckbc_tag_t, pckbc_slot_t); +/* power management */ +bool pckbc_resume(device_t); + #endif /* _DEV_IC_PCKBCVAR_H_ */ diff --git a/sys/dev/ic/rt2560.c b/sys/dev/ic/rt2560.c index 7cdca7ae351..a21b62ef31b 100644 --- a/sys/dev/ic/rt2560.c +++ b/sys/dev/ic/rt2560.c @@ -1,4 +1,4 @@ -/* $NetBSD: rt2560.c,v 1.14 2007/10/21 17:03:37 degroote Exp $ */ +/* $NetBSD: rt2560.c,v 1.15 2007/12/09 20:27:58 jmcneill Exp $ */ /* $OpenBSD: rt2560.c,v 1.15 2006/04/20 20:31:12 miod Exp $ */ /* $FreeBSD: rt2560.c,v 1.3 2006/03/21 21:15:43 damien Exp $*/ @@ -24,7 +24,7 @@ * http://www.ralinktech.com/ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rt2560.c,v 1.14 2007/10/21 17:03:37 degroote Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rt2560.c,v 1.15 2007/12/09 20:27:58 jmcneill Exp $"); #include "bpfilter.h" @@ -148,8 +148,7 @@ static const char *rt2560_get_rf(int); static void rt2560_read_eeprom(struct rt2560_softc *); static int rt2560_bbp_init(struct rt2560_softc *); static int rt2560_init(struct ifnet *); -static void rt2560_stop(void *); -static void rt2560_powerhook(int, void *); +static void rt2560_stop(struct ifnet *, int); /* * Supported rates for 802.11a/b/g modes (in 500Kbps unit). @@ -401,16 +400,10 @@ rt2560_attach(void *xsc, int id) goto fail5; } - sc->sc_powerhook = powerhook_establish(sc->sc_dev.dv_xname, - rt2560_powerhook, sc); - if (sc->sc_powerhook == NULL) - aprint_error("%s: can't establish powerhook\n", - sc->sc_dev.dv_xname); - sc->sc_suspend = PWR_RESUME; - ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_init = rt2560_init; + ifp->if_stop = rt2560_stop; ifp->if_ioctl = rt2560_ioctl; ifp->if_start = rt2560_start; ifp->if_watchdog = rt2560_watchdog; @@ -496,6 +489,11 @@ rt2560_attach(void *xsc, int id) ieee80211_announce(ic); + if (!pmf_device_register(&sc->sc_dev, NULL, NULL)) + aprint_error_dev(&sc->sc_dev, "couldn't establish power handler\n"); + else + pmf_class_network_register(&sc->sc_dev, ifp); + return 0; fail5: rt2560_free_tx_ring(sc, &sc->bcnq); @@ -516,10 +514,9 @@ rt2560_detach(void *xsc) callout_stop(&sc->scan_ch); callout_stop(&sc->rssadapt_ch); - if (sc->sc_powerhook != NULL) - powerhook_disestablish(sc->sc_powerhook); + pmf_device_deregister(&sc->sc_dev); - rt2560_stop(sc); + rt2560_stop(ifp, 1); ieee80211_ifdetach(&sc->sc_ic); /* free all nodes */ if_detach(ifp); @@ -1463,7 +1460,7 @@ rt2560_shutdown(void *xsc) { struct rt2560_softc *sc = xsc; - rt2560_stop(sc); + rt2560_stop(&sc->sc_if, 1); } void @@ -1471,7 +1468,7 @@ rt2560_suspend(void *xsc) { struct rt2560_softc *sc = xsc; - rt2560_stop(sc); + rt2560_stop(&sc->sc_if, 1); } void @@ -1534,6 +1531,9 @@ rt2560_intr(void *arg) struct ifnet *ifp = &sc->sc_if; uint32_t r; + if (!device_is_active(&sc->sc_dev)) + return 0; + /* disable interrupts */ RAL_WRITE(sc, RT2560_CSR8, 0xffffffff); @@ -1541,10 +1541,6 @@ rt2560_intr(void *arg) if (!(ifp->if_flags & IFF_RUNNING)) return 0; - /* if we're suspended, don't bother */ - if (sc->sc_suspend != PWR_RESUME) - return 0; - r = RAL_READ(sc, RT2560_CSR7); RAL_WRITE(sc, RT2560_CSR7, r); @@ -2257,7 +2253,7 @@ rt2560_ioctl(struct ifnet *ifp, u_long cmd, void *data) rt2560_init(ifp); } else { if (ifp->if_flags & IFF_RUNNING) - rt2560_stop(sc); + rt2560_stop(ifp, 1); } break; @@ -2819,7 +2815,7 @@ rt2560_init(struct ifnet *ifp) sc->sc_flags |= RT2560_ENABLED; } - rt2560_stop(sc); + rt2560_stop(ifp, 1); /* setup tx rings */ tmp = RT2560_PRIO_RING_COUNT << 24 | @@ -2860,7 +2856,7 @@ rt2560_init(struct ifnet *ifp) RAL_WRITE(sc, RT2560_CSR1, RT2560_HOST_READY); if (rt2560_bbp_init(sc) != 0) { - rt2560_stop(sc); + rt2560_stop(ifp, 1); return EIO; } @@ -2902,11 +2898,10 @@ rt2560_init(struct ifnet *ifp) } static void -rt2560_stop(void *priv) +rt2560_stop(struct ifnet *ifp, int disable) { - struct rt2560_softc *sc = priv; + struct rt2560_softc *sc = ifp->if_softc; struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = ic->ic_ifp; sc->sc_tx_timer = 0; ifp->if_timer = 0; @@ -2938,41 +2933,3 @@ rt2560_stop(void *priv) rt2560_reset_rx_ring(sc, &sc->rxq); } - -static void -rt2560_powerhook(int why, void *opaque) -{ - struct rt2560_softc *sc; - struct ifnet *ifp; - int s; - - sc = (struct rt2560_softc *)opaque; - ifp = &sc->sc_if; - - s = splnet(); - switch (why) { - case PWR_SUSPEND: - sc->sc_suspend = why; - rt2560_stop(sc); - if (sc->sc_power != NULL) - (*sc->sc_power)(sc, why); - break; - case PWR_RESUME: - sc->sc_suspend = why; - if (ifp->if_flags & IFF_UP) { - if (sc->sc_power != NULL) - (*sc->sc_power)(sc, why); - rt2560_init(ifp); - if (ifp->if_flags & IFF_RUNNING) - rt2560_start(ifp); - } - break; - case PWR_STANDBY: - case PWR_SOFTSUSPEND: - case PWR_SOFTRESUME: - break; - } - splx(s); - - return; -} diff --git a/sys/dev/ic/rt2560var.h b/sys/dev/ic/rt2560var.h index a4183608eab..23acf28d946 100644 --- a/sys/dev/ic/rt2560var.h +++ b/sys/dev/ic/rt2560var.h @@ -1,4 +1,4 @@ -/* $NetBSD: rt2560var.h,v 1.5 2007/03/04 06:02:00 christos Exp $ */ +/* $NetBSD: rt2560var.h,v 1.6 2007/12/09 20:27:58 jmcneill Exp $ */ /* $OpenBSD: rt2560var.h,v 1.2 2006/01/14 12:43:27 damien Exp $ */ /*- @@ -105,7 +105,6 @@ struct rt2560_softc { int (*sc_enable)(struct rt2560_softc *); void (*sc_disable)(struct rt2560_softc *); - void (*sc_power)(struct rt2560_softc *, int); bus_dma_tag_t sc_dmat; bus_space_tag_t sc_st; @@ -167,9 +166,6 @@ struct rt2560_softc { #define sc_txtap sc_txtapu.th int sc_txtap_len; #endif - - void *sc_powerhook; - int sc_suspend; }; #define sc_if sc_ec.ec_if diff --git a/sys/dev/ic/rt2661.c b/sys/dev/ic/rt2661.c index f5b0e2d2cbc..06caca4c4bc 100644 --- a/sys/dev/ic/rt2661.c +++ b/sys/dev/ic/rt2661.c @@ -1,4 +1,4 @@ -/* $NetBSD: rt2661.c,v 1.20 2007/10/21 17:03:37 degroote Exp $ */ +/* $NetBSD: rt2661.c,v 1.21 2007/12/09 20:27:58 jmcneill Exp $ */ /* $OpenBSD: rt2661.c,v 1.17 2006/05/01 08:41:11 damien Exp $ */ /* $FreeBSD: rt2560.c,v 1.5 2006/06/02 19:59:31 csjp Exp $ */ @@ -25,7 +25,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rt2661.c,v 1.20 2007/10/21 17:03:37 degroote Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rt2661.c,v 1.21 2007/12/09 20:27:58 jmcneill Exp $"); #include "bpfilter.h" @@ -427,6 +427,7 @@ rt2661_attach(void *xsc, int id) ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_init = rt2661_init; + ifp->if_stop = rt2661_stop; ifp->if_ioctl = rt2661_ioctl; ifp->if_start = rt2661_start; ifp->if_watchdog = rt2661_watchdog; @@ -509,6 +510,11 @@ rt2661_attach(void *xsc, int id) ieee80211_announce(ic); + if (!pmf_device_register(&sc->sc_dev, NULL, NULL)) + aprint_error_dev(&sc->sc_dev, "couldn't establish power handler\n"); + else + pmf_class_network_register(&sc->sc_dev, ifp); + return 0; fail6: rt2661_free_tx_ring(sc, &sc->mgtq); @@ -528,6 +534,8 @@ rt2661_detach(void *xsc) callout_stop(&sc->scan_ch); callout_stop(&sc->rssadapt_ch); + pmf_device_deregister(&sc->sc_dev); + ieee80211_ifdetach(&sc->sc_ic); if_detach(ifp); diff --git a/sys/dev/ic/rt2661var.h b/sys/dev/ic/rt2661var.h index 0e7221432f6..e754bbd72ec 100644 --- a/sys/dev/ic/rt2661var.h +++ b/sys/dev/ic/rt2661var.h @@ -1,4 +1,4 @@ -/* $NetBSD: rt2661var.h,v 1.6 2007/03/04 06:02:00 christos Exp $ */ +/* $NetBSD: rt2661var.h,v 1.7 2007/12/09 20:27:59 jmcneill Exp $ */ /* $OpenBSD: rt2661var.h,v 1.4 2006/02/25 12:56:47 damien Exp $ */ /*- @@ -98,7 +98,6 @@ struct rt2661_softc { int (*sc_enable)(struct rt2661_softc *); void (*sc_disable)(struct rt2661_softc *); - void (*sc_power)(struct rt2661_softc *, int); bus_dma_tag_t sc_dmat; bus_space_tag_t sc_st; diff --git a/sys/dev/ic/rtl8169.c b/sys/dev/ic/rtl8169.c index 1b6286e83b7..5459da14f8b 100644 --- a/sys/dev/ic/rtl8169.c +++ b/sys/dev/ic/rtl8169.c @@ -1,4 +1,4 @@ -/* $NetBSD: rtl8169.c,v 1.89 2007/10/19 11:59:59 ad Exp $ */ +/* $NetBSD: rtl8169.c,v 1.90 2007/12/09 20:27:59 jmcneill Exp $ */ /* * Copyright (c) 1997, 1998-2003 @@ -162,10 +162,8 @@ static int re_init(struct ifnet *); static void re_stop(struct ifnet *, int); static void re_watchdog(struct ifnet *); -static void re_shutdown(void *); static int re_enable(struct rtk_softc *); static void re_disable(struct rtk_softc *); -static void re_power(int, void *); static int re_ifmedia_upd(struct ifnet *); static void re_ifmedia_sts(struct ifnet *, struct ifmediareq *); @@ -794,25 +792,6 @@ re_attach(struct rtk_softc *sc) if_attach(ifp); ether_ifattach(ifp, eaddr); - - /* - * Make sure the interface is shutdown during reboot. - */ - sc->sc_sdhook = shutdownhook_establish(re_shutdown, sc); - if (sc->sc_sdhook == NULL) - aprint_error("%s: WARNING: unable to establish shutdown hook\n", - sc->sc_dev.dv_xname); - /* - * Add a suspend hook to make sure we come back up after a - * resume. - */ - sc->sc_powerhook = powerhook_establish(sc->sc_dev.dv_xname, - re_power, sc); - if (sc->sc_powerhook == NULL) - aprint_error("%s: WARNING: unable to establish power hook\n", - sc->sc_dev.dv_xname); - - return; fail_8: @@ -936,10 +915,6 @@ re_detach(struct rtk_softc *sc) bus_dmamem_free(sc->sc_dmat, &sc->re_ldata.re_tx_listseg, sc->re_ldata.re_tx_listnseg); - - shutdownhook_disestablish(sc->sc_sdhook); - powerhook_disestablish(sc->sc_powerhook); - return 0; } @@ -976,41 +951,6 @@ re_disable(struct rtk_softc *sc) } } -/* - * re_power: - * Power management (suspend/resume) hook. - */ -void -re_power(int why, void *arg) -{ - struct rtk_softc *sc = (void *)arg; - struct ifnet *ifp = &sc->ethercom.ec_if; - int s; - - s = splnet(); - switch (why) { - case PWR_SUSPEND: - case PWR_STANDBY: - re_stop(ifp, 0); - if (sc->sc_power != NULL) - (*sc->sc_power)(sc, why); - break; - case PWR_RESUME: - if (ifp->if_flags & IFF_UP) { - if (sc->sc_power != NULL) - (*sc->sc_power)(sc, why); - re_init(ifp); - } - break; - case PWR_SOFTSUSPEND: - case PWR_SOFTSTANDBY: - case PWR_SOFTRESUME: - break; - } - splx(s); -} - - static int re_newbuf(struct rtk_softc *sc, int idx, struct mbuf *m) { @@ -1376,20 +1316,6 @@ re_txeof(struct rtk_softc *sc) ifp->if_timer = 0; } -/* - * Stop all chip I/O so that the kernel's probe routines don't - * get confused by errant DMAs when rebooting. - */ -static void -re_shutdown(void *vsc) - -{ - struct rtk_softc *sc = vsc; - - re_stop(&sc->ethercom.ec_if, 0); -} - - static void re_tick(void *xsc) { diff --git a/sys/dev/ic/rtl81x9.c b/sys/dev/ic/rtl81x9.c index 524b1ec3a78..f38755c8e44 100644 --- a/sys/dev/ic/rtl81x9.c +++ b/sys/dev/ic/rtl81x9.c @@ -1,4 +1,4 @@ -/* $NetBSD: rtl81x9.c,v 1.78 2007/11/06 02:29:20 uwe Exp $ */ +/* $NetBSD: rtl81x9.c,v 1.79 2007/12/09 20:27:59 jmcneill Exp $ */ /* * Copyright (c) 1997, 1998 @@ -86,7 +86,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rtl81x9.c,v 1.78 2007/11/06 02:29:20 uwe Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rtl81x9.c,v 1.79 2007/12/09 20:27:59 jmcneill Exp $"); #include "bpfilter.h" #include "rnd.h" @@ -140,7 +140,6 @@ STATIC int rtk_init(struct ifnet *); STATIC void rtk_stop(struct ifnet *, int); STATIC void rtk_watchdog(struct ifnet *); -STATIC void rtk_shutdown(void *); STATIC int rtk_ifmedia_upd(struct ifnet *); STATIC void rtk_ifmedia_sts(struct ifnet *, struct ifmediareq *); @@ -157,7 +156,6 @@ STATIC void rtk_tick(void *); STATIC int rtk_enable(struct rtk_softc *); STATIC void rtk_disable(struct rtk_softc *); -STATIC void rtk_power(int, void *); STATIC void rtk_list_tx_init(struct rtk_softc *); @@ -755,24 +753,6 @@ rtk_attach(struct rtk_softc *sc) if_attach(ifp); ether_ifattach(ifp, eaddr); - /* - * Make sure the interface is shutdown during reboot. - */ - sc->sc_sdhook = shutdownhook_establish(rtk_shutdown, sc); - if (sc->sc_sdhook == NULL) - aprint_error_dev(self, - "WARNING: unable to establish shutdown hook\n"); - /* - * Add a suspend hook to make sure we come back up after a - * resume. - */ - sc->sc_powerhook = powerhook_establish(device_xname(self), - rtk_power, sc); - if (sc->sc_powerhook == NULL) - aprint_error_dev(self, - "WARNING: unable to establish power hook\n"); - - #if NRND > 0 rnd_attach_source(&sc->rnd_source, device_xname(self), RND_TYPE_NET, 0); @@ -886,9 +866,6 @@ rtk_detach(struct rtk_softc *sc) RTK_RXBUFLEN + 16); bus_dmamem_free(sc->sc_dmat, &sc->sc_dmaseg, sc->sc_dmanseg); - shutdownhook_disestablish(sc->sc_sdhook); - powerhook_disestablish(sc->sc_powerhook); - return 0; } @@ -926,40 +903,6 @@ rtk_disable(struct rtk_softc *sc) } /* - * rtk_power: - * Power management (suspend/resume) hook. - */ -void -rtk_power(int why, void *arg) -{ - struct rtk_softc *sc = (void *)arg; - struct ifnet *ifp = &sc->ethercom.ec_if; - int s; - - s = splnet(); - switch (why) { - case PWR_SUSPEND: - case PWR_STANDBY: - rtk_stop(ifp, 0); - if (sc->sc_power != NULL) - (*sc->sc_power)(sc, why); - break; - case PWR_RESUME: - if (ifp->if_flags & IFF_UP) { - if (sc->sc_power != NULL) - (*sc->sc_power)(sc, why); - rtk_init(ifp); - } - break; - case PWR_SOFTSUSPEND: - case PWR_SOFTSTANDBY: - case PWR_SOFTRESUME: - break; - } - splx(s); -} - -/* * A frame has been uploaded: pass the resulting mbuf chain up to * the higher level protocols. * @@ -1619,18 +1562,6 @@ rtk_stop(struct ifnet *ifp, int disable) ifp->if_timer = 0; } -/* - * Stop all chip I/O so that the kernel's probe routines don't - * get confused by errant DMAs when rebooting. - */ -STATIC void -rtk_shutdown(void *arg) -{ - struct rtk_softc *sc = (struct rtk_softc *)arg; - - rtk_stop(&sc->ethercom.ec_if, 0); -} - STATIC void rtk_tick(void *arg) { diff --git a/sys/dev/ic/rtl81x9var.h b/sys/dev/ic/rtl81x9var.h index e1bb8b955d3..c35edd47750 100644 --- a/sys/dev/ic/rtl81x9var.h +++ b/sys/dev/ic/rtl81x9var.h @@ -1,4 +1,4 @@ -/* $NetBSD: rtl81x9var.h,v 1.39 2007/03/21 12:17:31 tsutsui Exp $ */ +/* $NetBSD: rtl81x9var.h,v 1.40 2007/12/09 20:27:59 jmcneill Exp $ */ /* * Copyright (c) 1997, 1998 @@ -215,13 +215,9 @@ struct rtk_softc { int sc_txthresh; /* Early tx threshold */ int sc_rev; /* MII revision */ - void *sc_sdhook; /* shutdown hook */ - void *sc_powerhook; /* power management hook */ - /* Power management hooks. */ int (*sc_enable) (struct rtk_softc *); void (*sc_disable) (struct rtk_softc *); - void (*sc_power) (struct rtk_softc *, int); #if NRND > 0 rndsource_element_t rnd_source; #endif diff --git a/sys/dev/ic/spic.c b/sys/dev/ic/spic.c index f169291355c..a9732c0f33c 100644 --- a/sys/dev/ic/spic.c +++ b/sys/dev/ic/spic.c @@ -1,4 +1,4 @@ -/* $NetBSD: spic.c,v 1.9 2007/10/19 12:00:02 ad Exp $ */ +/* $NetBSD: spic.c,v 1.10 2007/12/09 20:28:00 jmcneill Exp $ */ /* * Copyright (c) 2002 The NetBSD Foundation, Inc. @@ -56,7 +56,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: spic.c,v 1.9 2007/10/19 12:00:02 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: spic.c,v 1.10 2007/12/09 20:28:00 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -74,6 +74,9 @@ __KERNEL_RCSID(0, "$NetBSD: spic.c,v 1.9 2007/10/19 12:00:02 ad Exp $"); #include <dev/wscons/wsconsio.h> #include <dev/wscons/wsmousevar.h> +#define SPIC_EVENT_BRIGHTNESS_DOWN 0x15 +#define SPIC_EVENT_BRIGHTNESS_UP 0x16 + #define POLLRATE (hz/30) /* Some hardware constants */ @@ -205,6 +208,12 @@ spic_intr(void *v) { case 0x1d: dz -= 0x20; break; + case SPIC_EVENT_BRIGHTNESS_UP: + pmf_event_inject(&sc->sc_dev, PMFE_DISPLAY_BRIGHTNESS_UP); + break; + case SPIC_EVENT_BRIGHTNESS_DOWN: + pmf_event_inject(&sc->sc_dev, PMFE_DISPLAY_BRIGHTNESS_DOWN); + break; default: printf("spic0: v1=0x%02x v2=0x%02x\n", v1, v2); goto skip; diff --git a/sys/dev/ic/vga.c b/sys/dev/ic/vga.c index 2fe1cef7466..5a08014a6ef 100644 --- a/sys/dev/ic/vga.c +++ b/sys/dev/ic/vga.c @@ -1,4 +1,4 @@ -/* $NetBSD: vga.c,v 1.96 2007/10/19 12:00:04 ad Exp $ */ +/* $NetBSD: vga.c,v 1.97 2007/12/09 20:28:00 jmcneill Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -28,7 +28,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: vga.c,v 1.96 2007/10/19 12:00:04 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vga.c,v 1.97 2007/12/09 20:28:00 jmcneill Exp $"); /* for WSCONS_SUPPORT_PCVTFONTS */ #include "opt_wsdisplay_compat.h" @@ -1488,3 +1488,11 @@ vga_setborder(struct vga_config *vc, u_int value) return (0); } #endif /* WSDISPLAY_CUSTOM_BORDER */ + +void +vga_resume(struct vga_softc *sc) +{ +#ifdef VGA_RESET_ON_RESUME + vga_initregs(&sc->sc_vc->hdl); +#endif +} diff --git a/sys/dev/ic/vga_subr.c b/sys/dev/ic/vga_subr.c index 45f4b4e5807..ca951eeb3a3 100644 --- a/sys/dev/ic/vga_subr.c +++ b/sys/dev/ic/vga_subr.c @@ -1,4 +1,4 @@ -/* $NetBSD: vga_subr.c,v 1.22 2007/10/19 12:00:04 ad Exp $ */ +/* $NetBSD: vga_subr.c,v 1.23 2007/12/09 20:28:00 jmcneill Exp $ */ /* * Copyright (c) 1998 @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: vga_subr.c,v 1.22 2007/10/19 12:00:04 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vga_subr.c,v 1.23 2007/12/09 20:28:00 jmcneill Exp $"); /* for WSDISPLAY_BORDER_COLOR */ #include "opt_wsdisplay_border.h" @@ -48,9 +48,6 @@ __KERNEL_RCSID(0, "$NetBSD: vga_subr.c,v 1.22 2007/10/19 12:00:04 ad Exp $"); static void fontram(struct vga_handle *); static void textram(struct vga_handle *); -#ifdef VGA_RESET -static void vga_initregs(struct vga_handle *); -#endif static void fontram(struct vga_handle *vh) @@ -214,7 +211,6 @@ vga_load_builtinfont(struct vga_handle *vh, u_int8_t *font, int firstchar, } #endif /* !VGA_RASTERCONSOLE */ -#ifdef VGA_RESET /* * vga_reset(): * Reset VGA registers to put it into 80x25 text mode. (mode 3) @@ -375,7 +371,7 @@ static const u_int8_t vga_dacpal[] = { 0x3f, 0x3f, 0x3f /* WHITE */ }; -static void +void vga_initregs(vh) struct vga_handle *vh; { @@ -427,4 +423,3 @@ vga_initregs(vh) /* reenable video */ vga_ts_write(vh, mode, vga_ts[1] & ~VGA_TS_MODE_BLANK); } -#endif /* VGA_RESET */ diff --git a/sys/dev/ic/vgavar.h b/sys/dev/ic/vgavar.h index 83552d6e7a8..20575f84f61 100644 --- a/sys/dev/ic/vgavar.h +++ b/sys/dev/ic/vgavar.h @@ -1,4 +1,4 @@ -/* $NetBSD: vgavar.h,v 1.26 2007/03/04 06:02:03 christos Exp $ */ +/* $NetBSD: vgavar.h,v 1.27 2007/12/09 20:28:00 jmcneill Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -192,6 +192,8 @@ int vga_is_console(bus_space_tag_t, int); int vga_cnattach(bus_space_tag_t, bus_space_tag_t, int, int); int vga_cndetach(void); +void vga_resume(struct vga_softc *); + #ifndef VGA_RASTERCONSOLE struct wsscreen_descr; void vga_loadchars(struct vga_handle *, int, int, int, int, const char *); @@ -204,8 +206,7 @@ void vga_setscreentype(struct vga_handle *, const struct wsscreen_descr *); #else /* !VGA_RASTERCONSOLE */ void vga_load_builtinfont(struct vga_handle *, u_int8_t *, int, int); #endif /* !VGA_RASTERCONSOLE */ -#ifdef VGA_RESET void vga_reset(struct vga_handle *, void (*)(struct vga_handle *)); -#endif +void vga_initregs(struct vga_handle *); extern int vga_no_builtinfont; diff --git a/sys/dev/ic/wi.c b/sys/dev/ic/wi.c index 23c90e2ab32..af4ca44a71a 100644 --- a/sys/dev/ic/wi.c +++ b/sys/dev/ic/wi.c @@ -1,4 +1,4 @@ -/* $NetBSD: wi.c,v 1.222 2007/10/19 12:00:05 ad Exp $ */ +/* $NetBSD: wi.c,v 1.223 2007/12/09 20:28:00 jmcneill Exp $ */ /*- * Copyright (c) 2004 The NetBSD Foundation, Inc. @@ -106,7 +106,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: wi.c,v 1.222 2007/10/19 12:00:05 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: wi.c,v 1.223 2007/12/09 20:28:00 jmcneill Exp $"); #define WI_HERMES_AUTOINC_WAR /* Work around data write autoinc bug. */ #define WI_HERMES_STATS_WAR /* Work around stats counter bug. */ @@ -630,43 +630,8 @@ wi_activate(struct device *self, enum devact act) splx(s); return rv; } - -void -wi_power(struct wi_softc *sc, int why) -{ - struct ifnet *ifp = &sc->sc_if; - int s; - - s = splnet(); - switch (why) { - case PWR_SUSPEND: - case PWR_STANDBY: - wi_stop(ifp, 1); - break; - case PWR_RESUME: - if (ifp->if_flags & IFF_UP) { - wi_init(ifp); - (void)wi_intr(sc); - } - break; - case PWR_SOFTSUSPEND: - case PWR_SOFTSTANDBY: - case PWR_SOFTRESUME: - break; - } - splx(s); -} #endif /* __NetBSD__ */ -void -wi_shutdown(struct wi_softc *sc) -{ - struct ifnet *ifp = &sc->sc_if; - - if (sc->sc_attached) - wi_stop(ifp, 1); -} - int wi_intr(void *arg) { diff --git a/sys/dev/ic/wivar.h b/sys/dev/ic/wivar.h index d63ae1cdb39..e6e288be062 100644 --- a/sys/dev/ic/wivar.h +++ b/sys/dev/ic/wivar.h @@ -1,4 +1,4 @@ -/* $NetBSD: wivar.h,v 1.59 2007/03/04 06:02:04 christos Exp $ */ +/* $NetBSD: wivar.h,v 1.60 2007/12/09 20:28:00 jmcneill Exp $ */ /* * Copyright (c) 1997, 1998, 1999 @@ -285,5 +285,3 @@ int wi_attach(struct wi_softc *, const u_int8_t *); int wi_detach(struct wi_softc *); int wi_activate(struct device *, enum devact); int wi_intr(void *arg); -void wi_power(struct wi_softc *, int); -void wi_shutdown(struct wi_softc *); diff --git a/sys/dev/ieee1394/firewire.c b/sys/dev/ieee1394/firewire.c index fe7c10d1b44..bd7bb26375b 100644 --- a/sys/dev/ieee1394/firewire.c +++ b/sys/dev/ieee1394/firewire.c @@ -1,4 +1,4 @@ -/* $NetBSD: firewire.c,v 1.16 2007/11/05 19:08:56 kiyohara Exp $ */ +/* $NetBSD: firewire.c,v 1.17 2007/12/09 20:28:01 jmcneill Exp $ */ /*- * Copyright (c) 2003 Hidetoshi Shimokawa * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa @@ -563,6 +563,11 @@ FW_ATTACH(firewire) fw_busreset(fc, FWBUSNOTREADY); fc->ibr(fc); +#ifdef __NetBSD__ + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); +#endif + FW_ATTACH_RETURN(0); } diff --git a/sys/dev/ieee1394/fwohci.c b/sys/dev/ieee1394/fwohci.c index 4fc0eb99351..8e8b8784e45 100644 --- a/sys/dev/ieee1394/fwohci.c +++ b/sys/dev/ieee1394/fwohci.c @@ -1,4 +1,4 @@ -/* $NetBSD: fwohci.c,v 1.112 2007/11/06 15:24:11 kiyohara Exp $ */ +/* $NetBSD: fwohci.c,v 1.113 2007/12/09 20:28:01 jmcneill Exp $ */ /*- * Copyright (c) 2003 Hidetoshi Shimokawa @@ -37,7 +37,7 @@ * */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: fwohci.c,v 1.112 2007/11/06 15:24:11 kiyohara Exp $"); +__KERNEL_RCSID(0, "$NetBSD: fwohci.c,v 1.113 2007/12/09 20:28:01 jmcneill Exp $"); #define ATRQ_CH 0 #define ATRS_CH 1 @@ -2208,6 +2208,11 @@ fwohci_filt(void *arg) { struct fwohci_softc *sc = (struct fwohci_softc *)arg; +#if defined(__NetBSD__) + if (!device_is_active(sc->fc.dev)) + return (FILTER_STRAY); +#endif + if (!(sc->intmask & OHCI_INT_EN)) { /* polling mode */ return (FILTER_STRAY); diff --git a/sys/dev/ieee1394/if_fwip.c b/sys/dev/ieee1394/if_fwip.c index 20e2b177f26..be6a1f7a8d7 100644 --- a/sys/dev/ieee1394/if_fwip.c +++ b/sys/dev/ieee1394/if_fwip.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_fwip.c,v 1.10 2007/11/05 19:08:57 kiyohara Exp $ */ +/* $NetBSD: if_fwip.c,v 1.11 2007/12/09 20:28:01 jmcneill Exp $ */ /*- * Copyright (c) 2004 * Doug Rabson @@ -313,6 +313,13 @@ FW_ATTACH(fwip) FIREWIRE_IFATTACH(ifp, hwaddr); splx(s); +#if defined(__NetBSD__) + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); + else + pmf_class_network_register(self, ifp); +#endif + FWIPDEBUG(ifp, "interface created\n"); FW_ATTACH_RETURN(0); } diff --git a/sys/dev/isa/aps.c b/sys/dev/isa/aps.c index 7d6227f1e2b..d3d6036704f 100644 --- a/sys/dev/isa/aps.c +++ b/sys/dev/isa/aps.c @@ -1,4 +1,4 @@ -/* $NetBSD: aps.c,v 1.4 2007/11/17 08:30:35 kefren Exp $ */ +/* $NetBSD: aps.c,v 1.5 2007/12/09 20:28:01 jmcneill Exp $ */ /* $OpenBSD: aps.c,v 1.15 2007/05/19 19:14:11 tedu Exp $ */ /* @@ -23,7 +23,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: aps.c,v 1.4 2007/11/17 08:30:35 kefren Exp $"); +__KERNEL_RCSID(0, "$NetBSD: aps.c,v 1.5 2007/12/09 20:28:01 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -103,7 +103,6 @@ struct aps_softc { struct callout sc_callout; struct sensor_rec aps_data; - void *sc_powerhook; }; static int aps_match(struct device *, struct cfdata *, void *); @@ -115,7 +114,8 @@ static uint8_t aps_mem_read_1(bus_space_tag_t, bus_space_handle_t, int, uint8_t); static void aps_refresh_sensor_data(struct aps_softc *sc); static void aps_refresh(void *); -static void aps_power(int, void *); +static bool aps_suspend(device_t); +static bool aps_resume(device_t); CFATTACH_DECL(aps, sizeof(struct aps_softc), aps_match, aps_attach, aps_detach, NULL); @@ -251,12 +251,8 @@ aps_attach(struct device *parent, struct device *self, void *aux) return; } - sc->sc_powerhook = powerhook_establish(sc->sc_dev.dv_xname, - aps_power, - sc); - if (sc->sc_powerhook == NULL) - aprint_error("%s: can't establish powerhook\n", - device_xname(&sc->sc_dev)); + if (!pmf_device_register(self, aps_suspend, aps_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); /* Refresh sensor data every 0.5 seconds */ callout_init(&sc->sc_callout, 0); @@ -404,28 +400,36 @@ aps_refresh(void *arg) callout_schedule(&sc->sc_callout, (hz) / 2); } -static void -aps_power(int why, void *arg) +static bool +aps_suspend(device_t dv) { - struct aps_softc *sc = (struct aps_softc *)arg; + struct aps_softc *sc = device_private(dv); - if (why != PWR_RESUME) { - callout_stop(&sc->sc_callout); - } else { - /* - * Redo the init sequence on resume, because APS is - * as forgetful as it is deaf. - */ - bus_space_write_1(sc->sc_iot, sc->sc_ioh, APS_INIT, 0x13); - bus_space_write_1(sc->sc_iot, sc->sc_ioh, APS_CMD, 0x01); - bus_space_read_1(sc->sc_iot, sc->sc_ioh, APS_CMD); - bus_space_write_1(sc->sc_iot, sc->sc_ioh, APS_INIT, 0x13); - bus_space_write_1(sc->sc_iot, sc->sc_ioh, APS_CMD, 0x01); - - if (aps_mem_read_1(sc->sc_iot, sc->sc_ioh, APS_CMD, 0x00) && - aps_init(sc)) - callout_schedule(&sc->sc_callout, (hz) / 2); - else - printf("aps: failed to wake up\n"); - } + callout_stop(&sc->sc_callout); + + return true; +} + +static bool +aps_resume(device_t dv) +{ + struct aps_softc *sc = device_private(dv); + + /* + * Redo the init sequence on resume, because APS is + * as forgetful as it is deaf. + */ + bus_space_write_1(sc->sc_iot, sc->sc_ioh, APS_INIT, 0x13); + bus_space_write_1(sc->sc_iot, sc->sc_ioh, APS_CMD, 0x01); + bus_space_read_1(sc->sc_iot, sc->sc_ioh, APS_CMD); + bus_space_write_1(sc->sc_iot, sc->sc_ioh, APS_INIT, 0x13); + bus_space_write_1(sc->sc_iot, sc->sc_ioh, APS_CMD, 0x01); + + if (aps_mem_read_1(sc->sc_iot, sc->sc_ioh, APS_CMD, 0x00) && + aps_init(sc)) + callout_schedule(&sc->sc_callout, (hz) / 2); + else + aprint_error_dev(dv, "failed to wake up\n"); + + return true; } diff --git a/sys/dev/isa/isa.c b/sys/dev/isa/isa.c index 08a81d0dcbc..dbe2640d4ce 100644 --- a/sys/dev/isa/isa.c +++ b/sys/dev/isa/isa.c @@ -1,4 +1,4 @@ -/* $NetBSD: isa.c,v 1.130 2007/12/01 04:50:23 jmcneill Exp $ */ +/* $NetBSD: isa.c,v 1.131 2007/12/09 20:28:01 jmcneill Exp $ */ /*- * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: isa.c,v 1.130 2007/12/01 04:50:23 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: isa.c,v 1.131 2007/12/09 20:28:01 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -136,6 +136,9 @@ isaattach(struct device *parent, struct device *self, void *aux) /* Attach all indrect-config children. */ isarescan(self, "isa", wildcard); + + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); } int diff --git a/sys/dev/isapnp/isapnp.c b/sys/dev/isapnp/isapnp.c index 6e431927d1a..ffe98d8004a 100644 --- a/sys/dev/isapnp/isapnp.c +++ b/sys/dev/isapnp/isapnp.c @@ -1,4 +1,4 @@ -/* $NetBSD: isapnp.c,v 1.54 2007/12/01 16:58:36 ad Exp $ */ +/* $NetBSD: isapnp.c,v 1.55 2007/12/09 20:28:02 jmcneill Exp $ */ /*- * Copyright (c) 1996 The NetBSD Foundation, Inc. @@ -41,7 +41,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: isapnp.c,v 1.54 2007/12/01 16:58:36 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: isapnp.c,v 1.55 2007/12/09 20:28:02 jmcneill Exp $"); #include "isadma.h" @@ -960,6 +960,9 @@ isapnp_attach(struct device *parent, struct device *self, void *aux) #else isapnp_callback(self); #endif + + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); } /* isapnp_callback diff --git a/sys/dev/mii/acphy.c b/sys/dev/mii/acphy.c index 804fa205ae4..8e2f6997e14 100644 --- a/sys/dev/mii/acphy.c +++ b/sys/dev/mii/acphy.c @@ -1,4 +1,4 @@ -/* $NetBSD: acphy.c,v 1.19 2006/11/16 21:24:06 christos Exp $ */ +/* $NetBSD: acphy.c,v 1.20 2007/12/09 20:28:02 jmcneill Exp $ */ /* * Copyright 2001 Wasabi Systems, Inc. @@ -40,7 +40,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: acphy.c,v 1.19 2006/11/16 21:24:06 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acphy.c,v 1.20 2007/12/09 20:28:02 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -146,6 +146,9 @@ acphyattach(struct device *parent, struct device *self, void *aux) else mii_phy_add_media(sc); aprint_normal("\n"); + + if (!pmf_device_register(self, NULL, mii_phy_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } static int diff --git a/sys/dev/mii/amhphy.c b/sys/dev/mii/amhphy.c index 80403732903..0ad58bc13c2 100644 --- a/sys/dev/mii/amhphy.c +++ b/sys/dev/mii/amhphy.c @@ -1,4 +1,4 @@ -/* $NetBSD: amhphy.c,v 1.15 2006/11/16 21:24:06 christos Exp $ */ +/* $NetBSD: amhphy.c,v 1.16 2007/12/09 20:28:02 jmcneill Exp $ */ /* * Copyright 2001 Wasabi Systems, Inc. @@ -40,7 +40,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: amhphy.c,v 1.15 2006/11/16 21:24:06 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: amhphy.c,v 1.16 2007/12/09 20:28:02 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -120,6 +120,9 @@ amhphyattach(struct device *parent, struct device *self, void *aux) else mii_phy_add_media(sc); aprint_normal("\n"); + + if (!pmf_device_register(self, NULL, mii_phy_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } static int diff --git a/sys/dev/mii/bmtphy.c b/sys/dev/mii/bmtphy.c index 948a851bb80..b892f7dc3f9 100644 --- a/sys/dev/mii/bmtphy.c +++ b/sys/dev/mii/bmtphy.c @@ -1,4 +1,4 @@ -/* $NetBSD: bmtphy.c,v 1.22 2006/11/16 21:24:07 christos Exp $ */ +/* $NetBSD: bmtphy.c,v 1.23 2007/12/09 20:28:02 jmcneill Exp $ */ /*- * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc. @@ -73,7 +73,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: bmtphy.c,v 1.22 2006/11/16 21:24:07 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: bmtphy.c,v 1.23 2007/12/09 20:28:02 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -169,6 +169,9 @@ bmtphyattach(struct device *parent, struct device *self, void *aux) else mii_phy_add_media(sc); aprint_normal("\n"); + + if (!pmf_device_register(self, NULL, mii_phy_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } static int diff --git a/sys/dev/mii/brgphy.c b/sys/dev/mii/brgphy.c index 5eed9bd2a90..ee85941be5e 100644 --- a/sys/dev/mii/brgphy.c +++ b/sys/dev/mii/brgphy.c @@ -1,4 +1,4 @@ -/* $NetBSD: brgphy.c,v 1.34 2007/08/06 12:16:33 markd Exp $ */ +/* $NetBSD: brgphy.c,v 1.35 2007/12/09 20:28:02 jmcneill Exp $ */ /*- * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc. @@ -74,7 +74,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: brgphy.c,v 1.34 2007/08/06 12:16:33 markd Exp $"); +__KERNEL_RCSID(0, "$NetBSD: brgphy.c,v 1.35 2007/12/09 20:28:02 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -300,6 +300,9 @@ brgphyattach(struct device *parent, struct device *self, void *aux) else mii_phy_add_media(sc); aprint_normal("\n"); + + if (!pmf_device_register(self, NULL, mii_phy_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } static int diff --git a/sys/dev/mii/ciphy.c b/sys/dev/mii/ciphy.c index 38e4a3610a5..4b09c5a32e4 100644 --- a/sys/dev/mii/ciphy.c +++ b/sys/dev/mii/ciphy.c @@ -1,4 +1,4 @@ -/* $NetBSD: ciphy.c,v 1.12 2007/10/19 12:00:35 ad Exp $ */ +/* $NetBSD: ciphy.c,v 1.13 2007/12/09 20:28:02 jmcneill Exp $ */ /*- * Copyright (c) 2004 @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ciphy.c,v 1.12 2007/10/19 12:00:35 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ciphy.c,v 1.13 2007/12/09 20:28:02 jmcneill Exp $"); /* * Driver for the Cicada CS8201 10/100/1000 copper PHY. @@ -141,6 +141,9 @@ ciphyattach(struct device *parent, struct device *self, void *aux) else mii_phy_add_media(sc); aprint_normal("\n"); + + if (!pmf_device_register(self, NULL, mii_phy_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } static int diff --git a/sys/dev/mii/dmphy.c b/sys/dev/mii/dmphy.c index 81a7a0f7a0f..54533cfeaf4 100644 --- a/sys/dev/mii/dmphy.c +++ b/sys/dev/mii/dmphy.c @@ -1,4 +1,4 @@ -/* $NetBSD: dmphy.c,v 1.27 2006/11/16 21:24:07 christos Exp $ */ +/* $NetBSD: dmphy.c,v 1.28 2007/12/09 20:28:02 jmcneill Exp $ */ /*- * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc. @@ -72,7 +72,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: dmphy.c,v 1.27 2006/11/16 21:24:07 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: dmphy.c,v 1.28 2007/12/09 20:28:02 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -158,6 +158,9 @@ dmphyattach(struct device *parent, struct device *self, void *aux) else mii_phy_add_media(sc); aprint_normal("\n"); + + if (!pmf_device_register(self, NULL, mii_phy_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } static int diff --git a/sys/dev/mii/exphy.c b/sys/dev/mii/exphy.c index 851534c053b..f6c114fc28d 100644 --- a/sys/dev/mii/exphy.c +++ b/sys/dev/mii/exphy.c @@ -1,4 +1,4 @@ -/* $NetBSD: exphy.c,v 1.44 2006/11/16 21:24:07 christos Exp $ */ +/* $NetBSD: exphy.c,v 1.45 2007/12/09 20:28:02 jmcneill Exp $ */ /*- * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc. @@ -71,7 +71,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: exphy.c,v 1.44 2006/11/16 21:24:07 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: exphy.c,v 1.45 2007/12/09 20:28:02 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -158,6 +158,9 @@ exphyattach(struct device *parent, struct device *self, void *aux) else mii_phy_add_media(sc); aprint_normal("\n"); + + if (!pmf_device_register(self, NULL, mii_phy_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } static int diff --git a/sys/dev/mii/gentbi.c b/sys/dev/mii/gentbi.c index ea6cbc30fc3..70f1afecaf1 100644 --- a/sys/dev/mii/gentbi.c +++ b/sys/dev/mii/gentbi.c @@ -1,4 +1,4 @@ -/* $NetBSD: gentbi.c,v 1.18 2006/11/16 21:24:07 christos Exp $ */ +/* $NetBSD: gentbi.c,v 1.19 2007/12/09 20:28:02 jmcneill Exp $ */ /*- * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc. @@ -74,7 +74,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: gentbi.c,v 1.18 2006/11/16 21:24:07 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: gentbi.c,v 1.19 2007/12/09 20:28:02 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -172,6 +172,9 @@ gentbiattach(struct device *parent, struct device *self, void *aux) else mii_phy_add_media(sc); aprint_normal("\n"); + + if (!pmf_device_register(self, NULL, mii_phy_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } static int diff --git a/sys/dev/mii/glxtphy.c b/sys/dev/mii/glxtphy.c index 572a32ae893..089f71443c9 100644 --- a/sys/dev/mii/glxtphy.c +++ b/sys/dev/mii/glxtphy.c @@ -1,4 +1,4 @@ -/* $NetBSD: glxtphy.c,v 1.17 2006/11/16 21:24:07 christos Exp $ */ +/* $NetBSD: glxtphy.c,v 1.18 2007/12/09 20:28:02 jmcneill Exp $ */ /*- * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc. @@ -71,7 +71,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: glxtphy.c,v 1.17 2006/11/16 21:24:07 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: glxtphy.c,v 1.18 2007/12/09 20:28:02 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -158,6 +158,9 @@ glxtphyattach(struct device *parent, struct device *self, void *aux) else mii_phy_add_media(sc); aprint_normal("\n"); + + if (!pmf_device_register(self, NULL, mii_phy_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } static int diff --git a/sys/dev/mii/gphyter.c b/sys/dev/mii/gphyter.c index 79d038d085e..121702801d2 100644 --- a/sys/dev/mii/gphyter.c +++ b/sys/dev/mii/gphyter.c @@ -1,4 +1,4 @@ -/* $NetBSD: gphyter.c,v 1.19 2006/11/16 21:24:07 christos Exp $ */ +/* $NetBSD: gphyter.c,v 1.20 2007/12/09 20:28:03 jmcneill Exp $ */ /*- * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc. @@ -75,7 +75,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: gphyter.c,v 1.19 2006/11/16 21:24:07 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: gphyter.c,v 1.20 2007/12/09 20:28:03 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -183,6 +183,9 @@ gphyterattach(struct device *parent, struct device *self, void *aux) if (strap & STRAP_NC_MODE) aprint_normal(", pre-C5 BCM5400 compat enabled"); aprint_normal("\n"); + + if (!pmf_device_register(self, NULL, mii_phy_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } static int diff --git a/sys/dev/mii/icsphy.c b/sys/dev/mii/icsphy.c index 73598a58c9b..189790a5899 100644 --- a/sys/dev/mii/icsphy.c +++ b/sys/dev/mii/icsphy.c @@ -1,4 +1,4 @@ -/* $NetBSD: icsphy.c,v 1.41 2006/11/16 21:24:07 christos Exp $ */ +/* $NetBSD: icsphy.c,v 1.42 2007/12/09 20:28:03 jmcneill Exp $ */ /*- * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc. @@ -72,7 +72,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: icsphy.c,v 1.41 2006/11/16 21:24:07 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: icsphy.c,v 1.42 2007/12/09 20:28:03 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -162,6 +162,9 @@ icsphyattach(struct device *parent, struct device *self, void *aux) else mii_phy_add_media(sc); aprint_normal("\n"); + + if (!pmf_device_register(self, NULL, mii_phy_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } static int diff --git a/sys/dev/mii/igphy.c b/sys/dev/mii/igphy.c index db95a44a086..83e223187c1 100644 --- a/sys/dev/mii/igphy.c +++ b/sys/dev/mii/igphy.c @@ -1,4 +1,4 @@ -/* $NetBSD: igphy.c,v 1.12 2007/08/28 01:11:50 msaitoh Exp $ */ +/* $NetBSD: igphy.c,v 1.13 2007/12/09 20:28:03 jmcneill Exp $ */ /* * The Intel copyright applies to the analog register setup, and the @@ -77,7 +77,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: igphy.c,v 1.12 2007/08/28 01:11:50 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: igphy.c,v 1.13 2007/12/09 20:28:03 jmcneill Exp $"); #include "opt_mii.h" @@ -174,6 +174,9 @@ igphyattach(struct device *parent, struct device *self, void *aux) else mii_phy_add_media(sc); aprint_normal("\n"); + + if (!pmf_device_register(self, NULL, mii_phy_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } static void diff --git a/sys/dev/mii/ikphy.c b/sys/dev/mii/ikphy.c index 2185b9af9a9..3c9ab3ce748 100644 --- a/sys/dev/mii/ikphy.c +++ b/sys/dev/mii/ikphy.c @@ -1,4 +1,4 @@ -/* $NetBSD: ikphy.c,v 1.3 2006/11/16 21:24:07 christos Exp $ */ +/* $NetBSD: ikphy.c,v 1.4 2007/12/09 20:28:03 jmcneill Exp $ */ /******************************************************************************* Copyright (c) 2001-2005, Intel Corporation @@ -64,7 +64,7 @@ POSSIBILITY OF SUCH DAMAGE. */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ikphy.c,v 1.3 2006/11/16 21:24:07 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ikphy.c,v 1.4 2007/12/09 20:28:03 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -148,6 +148,9 @@ ikphyattach(struct device *parent, struct device *self, void *aux) else mii_phy_add_media(sc); aprint_normal("\n"); + + if (!pmf_device_register(self, NULL, mii_phy_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } static int diff --git a/sys/dev/mii/inphy.c b/sys/dev/mii/inphy.c index 1d8e19fbafd..b6e1e0be5f6 100644 --- a/sys/dev/mii/inphy.c +++ b/sys/dev/mii/inphy.c @@ -1,4 +1,4 @@ -/* $NetBSD: inphy.c,v 1.43 2006/11/16 21:24:07 christos Exp $ */ +/* $NetBSD: inphy.c,v 1.44 2007/12/09 20:28:03 jmcneill Exp $ */ /*- * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc. @@ -72,7 +72,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: inphy.c,v 1.43 2006/11/16 21:24:07 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: inphy.c,v 1.44 2007/12/09 20:28:03 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -164,6 +164,9 @@ inphyattach(struct device *parent, struct device *self, void *aux) else mii_phy_add_media(sc); aprint_normal("\n"); + + if (!pmf_device_register(self, NULL, mii_phy_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } static int diff --git a/sys/dev/mii/iophy.c b/sys/dev/mii/iophy.c index f819445aad0..d3848235796 100644 --- a/sys/dev/mii/iophy.c +++ b/sys/dev/mii/iophy.c @@ -1,4 +1,4 @@ -/* $NetBSD: iophy.c,v 1.28 2006/11/16 21:24:07 christos Exp $ */ +/* $NetBSD: iophy.c,v 1.29 2007/12/09 20:28:03 jmcneill Exp $ */ /* * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc. @@ -71,7 +71,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: iophy.c,v 1.28 2006/11/16 21:24:07 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: iophy.c,v 1.29 2007/12/09 20:28:03 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -153,6 +153,9 @@ iophyattach(struct device *parent, struct device *self, void *aux) else mii_phy_add_media(sc); aprint_normal("\n"); + + if (!pmf_device_register(self, NULL, mii_phy_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } static int diff --git a/sys/dev/mii/lxtphy.c b/sys/dev/mii/lxtphy.c index 4d9fc9f3825..a4aa2a7d6dc 100644 --- a/sys/dev/mii/lxtphy.c +++ b/sys/dev/mii/lxtphy.c @@ -1,4 +1,4 @@ -/* $NetBSD: lxtphy.c,v 1.41 2006/11/16 21:24:07 christos Exp $ */ +/* $NetBSD: lxtphy.c,v 1.42 2007/12/09 20:28:03 jmcneill Exp $ */ /*- * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc. @@ -72,7 +72,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: lxtphy.c,v 1.41 2006/11/16 21:24:07 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: lxtphy.c,v 1.42 2007/12/09 20:28:03 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -178,6 +178,9 @@ lxtphyattach(struct device *parent, struct device *self, void *aux) else mii_phy_add_media(sc); aprint_normal("\n"); + + if (!pmf_device_register(self, NULL, mii_phy_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } static int diff --git a/sys/dev/mii/makphy.c b/sys/dev/mii/makphy.c index e9d2be069a6..a92ba99a1fd 100644 --- a/sys/dev/mii/makphy.c +++ b/sys/dev/mii/makphy.c @@ -1,4 +1,4 @@ -/* $NetBSD: makphy.c,v 1.23 2007/02/23 03:03:10 msaitoh Exp $ */ +/* $NetBSD: makphy.c,v 1.24 2007/12/09 20:28:03 jmcneill Exp $ */ /*- * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc. @@ -71,7 +71,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: makphy.c,v 1.23 2007/02/23 03:03:10 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: makphy.c,v 1.24 2007/12/09 20:28:03 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -165,6 +165,9 @@ makphyattach(struct device *parent, struct device *self, void *aux) else mii_phy_add_media(sc); aprint_normal("\n"); + + if (!pmf_device_register(self, NULL, mii_phy_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } static void diff --git a/sys/dev/mii/mii_physubr.c b/sys/dev/mii/mii_physubr.c index d891a148c4b..3fd1ed65249 100644 --- a/sys/dev/mii/mii_physubr.c +++ b/sys/dev/mii/mii_physubr.c @@ -1,4 +1,4 @@ -/* $NetBSD: mii_physubr.c,v 1.53 2006/11/16 21:24:07 christos Exp $ */ +/* $NetBSD: mii_physubr.c,v 1.54 2007/12/09 20:28:03 jmcneill Exp $ */ /*- * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc. @@ -42,7 +42,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: mii_physubr.c,v 1.53 2006/11/16 21:24:07 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: mii_physubr.c,v 1.54 2007/12/09 20:28:03 jmcneill Exp $"); #include <sys/param.h> #include <sys/device.h> @@ -633,3 +633,12 @@ mii_phy_flowstatus(struct mii_softc *sc) } /* NOTREACHED */ } + +bool +mii_phy_resume(device_t dv) +{ + struct mii_softc *sc = device_private(dv); + + PHY_RESET(sc); + return true; +} diff --git a/sys/dev/mii/miivar.h b/sys/dev/mii/miivar.h index e9c37b2fd94..17cac6a965d 100644 --- a/sys/dev/mii/miivar.h +++ b/sys/dev/mii/miivar.h @@ -1,4 +1,4 @@ -/* $NetBSD: miivar.h,v 1.47 2006/11/16 21:24:07 christos Exp $ */ +/* $NetBSD: miivar.h,v 1.48 2007/12/09 20:28:03 jmcneill Exp $ */ /*- * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc. @@ -233,6 +233,7 @@ void mii_attach(struct device *, struct mii_data *, int, int, int, int); void mii_activate(struct mii_data *, enum devact, int, int); void mii_detach(struct mii_data *, int, int); +bool mii_phy_resume(device_t); int mii_mediachg(struct mii_data *); void mii_tick(struct mii_data *); diff --git a/sys/dev/mii/mvphy.c b/sys/dev/mii/mvphy.c index f9ec87904bb..420fb5a3af3 100644 --- a/sys/dev/mii/mvphy.c +++ b/sys/dev/mii/mvphy.c @@ -1,4 +1,4 @@ -/* $NetBSD: mvphy.c,v 1.3 2007/02/17 23:23:38 jmcneill Exp $ */ +/* $NetBSD: mvphy.c,v 1.4 2007/12/09 20:28:03 jmcneill Exp $ */ /*- * Copyright (c) 2006 Sam Leffler, Errno Consulting @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: mvphy.c,v 1.3 2007/02/17 23:23:38 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: mvphy.c,v 1.4 2007/12/09 20:28:03 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -212,6 +212,9 @@ mvphyattach(struct device *parent, struct device *self, void *aux) else mii_phy_add_media(sc); aprint_normal("\n"); + + if (!pmf_device_register(self, NULL, mii_phy_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } static int diff --git a/sys/dev/mii/nsphy.c b/sys/dev/mii/nsphy.c index c51753b8bb4..0f6f38773a8 100644 --- a/sys/dev/mii/nsphy.c +++ b/sys/dev/mii/nsphy.c @@ -1,4 +1,4 @@ -/* $NetBSD: nsphy.c,v 1.49 2006/11/16 21:24:07 christos Exp $ */ +/* $NetBSD: nsphy.c,v 1.50 2007/12/09 20:28:04 jmcneill Exp $ */ /*- * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc. @@ -72,7 +72,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: nsphy.c,v 1.49 2006/11/16 21:24:07 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: nsphy.c,v 1.50 2007/12/09 20:28:04 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -153,6 +153,9 @@ nsphyattach(struct device *parent, struct device *self, void *aux) else mii_phy_add_media(sc); aprint_normal("\n"); + + if (!pmf_device_register(self, NULL, mii_phy_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } static int diff --git a/sys/dev/mii/nsphyter.c b/sys/dev/mii/nsphyter.c index f647a689bee..274fcc5075a 100644 --- a/sys/dev/mii/nsphyter.c +++ b/sys/dev/mii/nsphyter.c @@ -1,4 +1,4 @@ -/* $NetBSD: nsphyter.c,v 1.26 2006/11/16 21:24:07 christos Exp $ */ +/* $NetBSD: nsphyter.c,v 1.27 2007/12/09 20:28:04 jmcneill Exp $ */ /*- * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc. @@ -75,7 +75,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: nsphyter.c,v 1.26 2006/11/16 21:24:07 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: nsphyter.c,v 1.27 2007/12/09 20:28:04 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -161,6 +161,9 @@ nsphyterattach(struct device *parent, struct device *self, void *aux) else mii_phy_add_media(sc); aprint_normal("\n"); + + if (!pmf_device_register(self, NULL, mii_phy_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } static int diff --git a/sys/dev/mii/pnaphy.c b/sys/dev/mii/pnaphy.c index 0d065408908..c23ba94abdc 100644 --- a/sys/dev/mii/pnaphy.c +++ b/sys/dev/mii/pnaphy.c @@ -1,4 +1,4 @@ -/* $NetBSD: pnaphy.c,v 1.16 2006/11/16 21:24:07 christos Exp $ */ +/* $NetBSD: pnaphy.c,v 1.17 2007/12/09 20:28:04 jmcneill Exp $ */ /* * Copyright 2001 Wasabi Systems, Inc. @@ -47,7 +47,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pnaphy.c,v 1.16 2006/11/16 21:24:07 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pnaphy.c,v 1.17 2007/12/09 20:28:04 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -130,6 +130,9 @@ pnaphyattach(struct device *parent, struct device *self, void *aux) else mii_phy_add_media(sc); aprint_normal("\n"); + + if (!pmf_device_register(self, NULL, mii_phy_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } static int diff --git a/sys/dev/mii/qsphy.c b/sys/dev/mii/qsphy.c index 8e6bf5a1334..529b31e4724 100644 --- a/sys/dev/mii/qsphy.c +++ b/sys/dev/mii/qsphy.c @@ -1,4 +1,4 @@ -/* $NetBSD: qsphy.c,v 1.40 2006/11/16 21:24:07 christos Exp $ */ +/* $NetBSD: qsphy.c,v 1.41 2007/12/09 20:28:04 jmcneill Exp $ */ /*- * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc. @@ -72,7 +72,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: qsphy.c,v 1.40 2006/11/16 21:24:07 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: qsphy.c,v 1.41 2007/12/09 20:28:04 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -152,6 +152,9 @@ qsphyattach(struct device *parent, struct device *self, void *aux) else mii_phy_add_media(sc); aprint_normal("\n"); + + if (!pmf_device_register(self, NULL, mii_phy_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } static int diff --git a/sys/dev/mii/rgephy.c b/sys/dev/mii/rgephy.c index b66b119be99..56a28aca2b7 100644 --- a/sys/dev/mii/rgephy.c +++ b/sys/dev/mii/rgephy.c @@ -1,4 +1,4 @@ -/* $NetBSD: rgephy.c,v 1.16 2006/12/03 03:16:48 tsutsui Exp $ */ +/* $NetBSD: rgephy.c,v 1.17 2007/12/09 20:28:04 jmcneill Exp $ */ /* * Copyright (c) 2003 @@ -33,7 +33,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rgephy.c,v 1.16 2006/12/03 03:16:48 tsutsui Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rgephy.c,v 1.17 2007/12/09 20:28:04 jmcneill Exp $"); /* @@ -153,6 +153,9 @@ rgephy_attach(struct device *parent, struct device *self, void *aux) PHY_RESET(sc); aprint_normal("\n"); + + if (!pmf_device_register(self, NULL, mii_phy_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } static int diff --git a/sys/dev/mii/rlphy.c b/sys/dev/mii/rlphy.c index 28359af8313..3daf968022f 100644 --- a/sys/dev/mii/rlphy.c +++ b/sys/dev/mii/rlphy.c @@ -1,4 +1,4 @@ -/* $NetBSD: rlphy.c,v 1.18 2007/11/06 00:58:32 uwe Exp $ */ +/* $NetBSD: rlphy.c,v 1.19 2007/12/09 20:28:04 jmcneill Exp $ */ /* $OpenBSD: rlphy.c,v 1.20 2005/07/31 05:27:30 pvalchev Exp $ */ /* @@ -38,7 +38,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rlphy.c,v 1.18 2007/11/06 00:58:32 uwe Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rlphy.c,v 1.19 2007/12/09 20:28:04 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -140,6 +140,9 @@ rlphyattach(struct device *parent, struct device *self, void *aux) if (sc->mii_capabilities & BMSR_MEDIAMASK) mii_phy_add_media(sc); aprint_normal("\n"); + + if (!pmf_device_register(self, NULL, mii_phy_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } int diff --git a/sys/dev/mii/sqphy.c b/sys/dev/mii/sqphy.c index 56c1fb175a0..1298f0b43ce 100644 --- a/sys/dev/mii/sqphy.c +++ b/sys/dev/mii/sqphy.c @@ -1,4 +1,4 @@ -/* $NetBSD: sqphy.c,v 1.42 2006/11/16 21:24:07 christos Exp $ */ +/* $NetBSD: sqphy.c,v 1.43 2007/12/09 20:28:04 jmcneill Exp $ */ /*- * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc. @@ -72,7 +72,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sqphy.c,v 1.42 2006/11/16 21:24:07 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sqphy.c,v 1.43 2007/12/09 20:28:04 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -173,6 +173,9 @@ sqphyattach(struct device *parent, struct device *self, void *aux) else mii_phy_add_media(sc); aprint_normal("\n"); + + if (!pmf_device_register(self, NULL, mii_phy_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } static int diff --git a/sys/dev/mii/tlphy.c b/sys/dev/mii/tlphy.c index de7229de166..ca2940d71ba 100644 --- a/sys/dev/mii/tlphy.c +++ b/sys/dev/mii/tlphy.c @@ -1,4 +1,4 @@ -/* $NetBSD: tlphy.c,v 1.51 2007/10/19 12:00:36 ad Exp $ */ +/* $NetBSD: tlphy.c,v 1.52 2007/12/09 20:28:04 jmcneill Exp $ */ /*- * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc. @@ -71,7 +71,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: tlphy.c,v 1.51 2007/10/19 12:00:36 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tlphy.c,v 1.52 2007/12/09 20:28:04 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -200,6 +200,9 @@ tlphyattach(struct device *parent, struct device *self, void *aux) aprint_normal("\n"); #undef ADD #undef PRINT + + if (!pmf_device_register(self, NULL, mii_phy_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } static int diff --git a/sys/dev/mii/tqphy.c b/sys/dev/mii/tqphy.c index 9f5e63d2748..442f9c2932a 100644 --- a/sys/dev/mii/tqphy.c +++ b/sys/dev/mii/tqphy.c @@ -1,4 +1,4 @@ -/* $NetBSD: tqphy.c,v 1.31 2006/11/16 21:24:07 christos Exp $ */ +/* $NetBSD: tqphy.c,v 1.32 2007/12/09 20:28:04 jmcneill Exp $ */ /* * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc. @@ -73,7 +73,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: tqphy.c,v 1.31 2006/11/16 21:24:07 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tqphy.c,v 1.32 2007/12/09 20:28:04 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -165,6 +165,9 @@ tqphyattach(struct device *parent, struct device *self, void *aux) else mii_phy_add_media(sc); aprint_normal("\n"); + + if (!pmf_device_register(self, NULL, mii_phy_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } static int diff --git a/sys/dev/mii/ukphy.c b/sys/dev/mii/ukphy.c index b868d5e89c8..5d8fe3e535b 100644 --- a/sys/dev/mii/ukphy.c +++ b/sys/dev/mii/ukphy.c @@ -1,4 +1,4 @@ -/* $NetBSD: ukphy.c,v 1.30 2006/11/16 21:24:07 christos Exp $ */ +/* $NetBSD: ukphy.c,v 1.31 2007/12/09 20:28:04 jmcneill Exp $ */ /*- * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc. @@ -71,7 +71,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ukphy.c,v 1.30 2006/11/16 21:24:07 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ukphy.c,v 1.31 2007/12/09 20:28:04 jmcneill Exp $"); #include "opt_mii.h" @@ -175,6 +175,9 @@ ukphyattach(struct device *parent, struct device *self, void *aux) else mii_phy_add_media(sc); aprint_normal("\n"); + + if (!pmf_device_register(self, NULL, mii_phy_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } static int diff --git a/sys/dev/mii/urlphy.c b/sys/dev/mii/urlphy.c index 5b34f138e08..87e61fd138b 100644 --- a/sys/dev/mii/urlphy.c +++ b/sys/dev/mii/urlphy.c @@ -1,4 +1,4 @@ -/* $NetBSD: urlphy.c,v 1.18 2006/11/16 21:24:07 christos Exp $ */ +/* $NetBSD: urlphy.c,v 1.19 2007/12/09 20:28:04 jmcneill Exp $ */ /* * Copyright (c) 2001, 2002 * Shingo WATANABE <nabe@nabechan.org>. All rights reserved. @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: urlphy.c,v 1.18 2006/11/16 21:24:07 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: urlphy.c,v 1.19 2007/12/09 20:28:04 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -131,6 +131,9 @@ urlphy_attach(struct device *parent, struct device *self, void *aux) else mii_phy_add_media(sc); aprint_normal("\n"); + + if (!pmf_device_register(self, NULL, mii_phy_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } static int diff --git a/sys/dev/pad/pad.c b/sys/dev/pad/pad.c index 8c6f91e678e..84564631508 100644 --- a/sys/dev/pad/pad.c +++ b/sys/dev/pad/pad.c @@ -1,4 +1,4 @@ -/* $NetBSD: pad.c,v 1.3 2007/12/05 07:06:52 ad Exp $ */ +/* $NetBSD: pad.c,v 1.4 2007/12/09 20:28:04 jmcneill Exp $ */ /*- * Copyright (c) 2007 Jared D. McNeill <jmcneill@invisible.ca> @@ -33,7 +33,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pad.c,v 1.3 2007/12/05 07:06:52 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pad.c,v 1.4 2007/12/09 20:28:04 jmcneill Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -254,7 +254,6 @@ pad_attach(struct device *parent, struct device *self, void *opaque) sc = (pad_softc_t *)self; - aprint_normal_dev(self, "Pseudo Audio Device\n"); aprint_normal_dev(self, "outputs: 44100Hz, 16-bit, stereo\n"); sc->sc_open = 0; @@ -272,6 +271,9 @@ pad_attach(struct device *parent, struct device *self, void *opaque) sc->sc_rpos = sc->sc_wpos = 0; sc->sc_audiodev = (void *)audio_attach_mi(&pad_hw_if, sc, &sc->sc_dev); + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); + return; } diff --git a/sys/dev/pci/agp.c b/sys/dev/pci/agp.c index 8bcece80232..dadf6b5f536 100644 --- a/sys/dev/pci/agp.c +++ b/sys/dev/pci/agp.c @@ -1,4 +1,4 @@ -/* $NetBSD: agp.c,v 1.53 2007/12/05 07:06:52 ad Exp $ */ +/* $NetBSD: agp.c,v 1.54 2007/12/09 20:28:05 jmcneill Exp $ */ /*- * Copyright (c) 2000 Doug Rabson @@ -65,7 +65,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: agp.c,v 1.53 2007/12/05 07:06:52 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: agp.c,v 1.54 2007/12/09 20:28:05 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -103,6 +103,7 @@ static int agp_deallocate_user(struct agp_softc *, int); static int agp_bind_user(struct agp_softc *, agp_bind *); static int agp_unbind_user(struct agp_softc *, agp_unbind *); static int agpdev_match(struct pci_attach_args *); +static bool agp_resume(device_t); #include "agp_ali.h" #include "agp_amd.h" @@ -334,6 +335,11 @@ agpattach(struct device *parent, struct device *self, void *aux) (unsigned long)AGP_GET_APERTURE(sc)); else sc->as_chipc = NULL; + + if (!device_pmf_is_registered(self)) { + if (!pmf_device_register(self, NULL, agp_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); + } } CFATTACH_DECL(agp, sizeof(struct agp_softc), @@ -1082,3 +1088,11 @@ agp_free_dmamem(bus_dma_tag_t tag, size_t size, bus_dmamap_t map, bus_dmamem_unmap(tag, vaddr, size); bus_dmamem_free(tag, seg, nseg); } + +static bool +agp_resume(device_t dv) +{ + agp_flush_cache(); + + return true; +} diff --git a/sys/dev/pci/agp_i810.c b/sys/dev/pci/agp_i810.c index c3aff255fd3..0b141f8d186 100644 --- a/sys/dev/pci/agp_i810.c +++ b/sys/dev/pci/agp_i810.c @@ -1,4 +1,4 @@ -/* $NetBSD: agp_i810.c,v 1.46 2007/11/24 02:19:37 markd Exp $ */ +/* $NetBSD: agp_i810.c,v 1.47 2007/12/09 20:28:05 jmcneill Exp $ */ /*- * Copyright (c) 2000 Doug Rabson @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: agp_i810.c,v 1.46 2007/11/24 02:19:37 markd Exp $"); +__KERNEL_RCSID(0, "$NetBSD: agp_i810.c,v 1.47 2007/12/09 20:28:05 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -95,8 +95,7 @@ struct agp_i810_softc { bus_space_handle_t gtt_bsh; /* GTT bus_space handle */ struct pci_attach_args vga_pa; - void *sc_powerhook; - struct pci_conf_state sc_pciconf; + u_int32_t pgtblctl; }; static u_int32_t agp_i810_get_aperture(struct agp_softc *); @@ -110,7 +109,9 @@ static struct agp_memory *agp_i810_alloc_memory(struct agp_softc *, int, static int agp_i810_free_memory(struct agp_softc *, struct agp_memory *); static int agp_i810_bind_memory(struct agp_softc *, struct agp_memory *, off_t); static int agp_i810_unbind_memory(struct agp_softc *, struct agp_memory *); -static void agp_i810_powerhook(int, void *); + +static bool agp_i810_resume(device_t); +static int agp_i810_init(struct agp_softc *); static int agp_i810_init(struct agp_softc *); @@ -331,6 +332,9 @@ agp_i810_attach(struct device *parent, struct device *self, void *aux) gatt->ag_entries = AGP_GET_APERTURE(sc) >> AGP_PAGE_SHIFT; + if (!pmf_device_register(self, NULL, agp_i810_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); + return agp_i810_init(sc); } @@ -500,12 +504,6 @@ static int agp_i810_init(struct agp_softc *sc) */ agp_flush_cache(); - isc->sc_powerhook = powerhook_establish(sc->as_dev.dv_xname, - agp_i810_powerhook, sc); - if (isc->sc_powerhook == NULL) - printf("%s: WARNING: unable to establish PCI power hook\n", - sc->as_dev.dv_xname); - #if 0 /* * another device (drm) may need access to this region @@ -888,17 +886,14 @@ agp_i810_unbind_memory(struct agp_softc *sc, struct agp_memory *mem) return 0; } -static void -agp_i810_powerhook(int why, void *arg) +static bool +agp_i810_resume(device_t dv) { - struct agp_softc *sc = (struct agp_softc *)arg; + struct agp_softc *sc = device_private(dv); struct agp_i810_softc *isc = sc->as_chipc; - if (why == PWR_RESUME) { - pci_conf_restore(sc->as_pc, sc->as_tag, &isc->sc_pciconf); - agp_flush_cache(); - } else if ((why == PWR_STANDBY) || (why == PWR_SUSPEND)) - pci_conf_capture(sc->as_pc, sc->as_tag, &isc->sc_pciconf); + isc->pgtblctl = READ4(AGP_I810_PGTBL_CTL); + agp_flush_cache(); - return; + return true; } diff --git a/sys/dev/pci/agp_intel.c b/sys/dev/pci/agp_intel.c index c83fc2ddad4..46c56ccb104 100644 --- a/sys/dev/pci/agp_intel.c +++ b/sys/dev/pci/agp_intel.c @@ -1,4 +1,4 @@ -/* $NetBSD: agp_intel.c,v 1.24 2007/11/12 20:00:17 joerg Exp $ */ +/* $NetBSD: agp_intel.c,v 1.25 2007/12/09 20:28:05 jmcneill Exp $ */ /*- * Copyright (c) 2000 Doug Rabson @@ -29,7 +29,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: agp_intel.c,v 1.24 2007/11/12 20:00:17 joerg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: agp_intel.c,v 1.25 2007/12/09 20:28:05 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -64,8 +64,6 @@ struct agp_intel_softc { #define CHIP_I850 0x4 #define CHIP_I865 0x5 - void *sc_powerhook; - struct pci_conf_state sc_pciconf; }; static u_int32_t agp_intel_get_aperture(struct agp_softc *); @@ -73,8 +71,8 @@ static int agp_intel_set_aperture(struct agp_softc *, u_int32_t); static int agp_intel_bind_page(struct agp_softc *, off_t, bus_addr_t); static int agp_intel_unbind_page(struct agp_softc *, off_t); static void agp_intel_flush_tlb(struct agp_softc *); -static void agp_intel_powerhook(int, void *); static int agp_intel_init(struct agp_softc *); +static bool agp_intel_resume(device_t); static struct agp_methods agp_intel_methods = { agp_intel_get_aperture, @@ -190,6 +188,9 @@ agp_intel_attach(struct device *parent, struct device *self, void *aux) } isc->gatt = gatt; + if (!pmf_device_register(self, NULL, agp_intel_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); + return agp_intel_init(sc); } @@ -267,12 +268,6 @@ agp_intel_init(struct agp_softc *sc) AGP_INTEL_ERRSTS, 0x70); } - isc->sc_powerhook = powerhook_establish(sc->as_dev.dv_xname, - agp_intel_powerhook, sc); - if (isc->sc_powerhook == NULL) - aprint_error("%s: couldn't establish powerhook\n", - sc->as_dev.dv_xname); - return (0); } @@ -284,9 +279,6 @@ agp_intel_detach(struct agp_softc *sc) pcireg_t reg; struct agp_intel_softc *isc = sc->as_chipc; - if (isc->sc_powerhook) - powerhook_disestablish(isc->sc_powerhook); - error = agp_generic_detach(sc); if (error) return error; @@ -402,29 +394,13 @@ agp_intel_flush_tlb(struct agp_softc *sc) } } -static void -agp_intel_powerhook(int why, void *opaque) +static bool +agp_intel_resume(device_t dv) { - struct agp_softc *sc; - struct agp_intel_softc *isc; + struct agp_softc *sc = device_private(dv); - sc = (struct agp_softc *)opaque; - isc = (struct agp_intel_softc *)sc->as_chipc; - - switch (why) { - case PWR_SUSPEND: - case PWR_STANDBY: - pci_conf_capture(sc->as_pc, sc->as_tag, &isc->sc_pciconf); - break; - case PWR_RESUME: - pci_conf_restore(sc->as_pc, sc->as_tag, &isc->sc_pciconf); - agp_flush_cache(); - break; - case PWR_SOFTSUSPEND: - case PWR_SOFTSTANDBY: - case PWR_SOFTRESUME: - break; - } + agp_intel_init(sc); + agp_flush_cache(); - return; + return true; } diff --git a/sys/dev/pci/ahcisata_pci.c b/sys/dev/pci/ahcisata_pci.c index 30088a929ef..0f861877325 100644 --- a/sys/dev/pci/ahcisata_pci.c +++ b/sys/dev/pci/ahcisata_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: ahcisata_pci.c,v 1.1 2007/05/12 11:04:59 bouyer Exp $ */ +/* $NetBSD: ahcisata_pci.c,v 1.2 2007/12/09 20:28:05 jmcneill Exp $ */ /* * Copyright (c) 2006 Manuel Bouyer. @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ahcisata_pci.c,v 1.1 2007/05/12 11:04:59 bouyer Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ahcisata_pci.c,v 1.2 2007/12/09 20:28:05 jmcneill Exp $"); #include <sys/types.h> #include <sys/malloc.h> @@ -39,6 +39,7 @@ __KERNEL_RCSID(0, "$NetBSD: ahcisata_pci.c,v 1.1 2007/05/12 11:04:59 bouyer Exp #include <sys/kernel.h> #include <sys/systm.h> #include <sys/disklabel.h> +#include <sys/pmf.h> #include <uvm/uvm_extern.h> @@ -48,10 +49,19 @@ __KERNEL_RCSID(0, "$NetBSD: ahcisata_pci.c,v 1.1 2007/05/12 11:04:59 bouyer Exp #include <dev/pci/pciidevar.h> #include <dev/ic/ahcisatavar.h> +struct ahci_pci_softc { + struct ahci_softc ah_sc; /* must come first, struct device */ + pci_chipset_tag_t sc_pc; + pcitag_t sc_pcitag; +}; + + static int ahci_pci_match(struct device *, struct cfdata *, void *); static void ahci_pci_attach(struct device *, struct device *, void *); +static bool ahci_pci_resume(device_t); + -CFATTACH_DECL(ahcisata_pci, sizeof(struct ahci_softc), +CFATTACH_DECL(ahcisata_pci, sizeof(struct ahci_pci_softc), ahci_pci_match, ahci_pci_attach, NULL, NULL); static int @@ -85,7 +95,8 @@ static void ahci_pci_attach(struct device *parent, struct device *self, void *aux) { struct pci_attach_args *pa = aux; - struct ahci_softc *sc = (struct ahci_softc *)self; + struct ahci_pci_softc *psc = (struct ahci_pci_softc *)self; + struct ahci_softc *sc = &psc->ah_sc; bus_size_t size; char devinfo[256]; const char *intrstr; @@ -98,6 +109,9 @@ ahci_pci_attach(struct device *parent, struct device *self, void *aux) aprint_error("%s: can't map ahci registers\n", AHCINAME(sc)); return; } + psc->sc_pc = pa->pa_pc; + psc->sc_pcitag = pa->pa_tag; + pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo)); aprint_naive(": AHCI disk controller\n"); aprint_normal(": %s\n", devinfo); @@ -116,4 +130,24 @@ ahci_pci_attach(struct device *parent, struct device *self, void *aux) intrstr ? intrstr : "unknown interrupt"); sc->sc_dmat = pa->pa_dmat; ahci_attach(sc); + + if (!pmf_device_register(self, NULL, ahci_pci_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); +} + +static bool +ahci_pci_resume(device_t dv) +{ + struct ahci_pci_softc *psc = device_private(dv); + struct ahci_softc *sc = &psc->ah_sc; + int s; + + s = splbio(); + ahci_reset(sc); + ahci_setup_ports(sc); + ahci_reprobe_drives(sc); + ahci_enable_intrs(sc); + splx(s); + + return true; } diff --git a/sys/dev/pci/auacer.c b/sys/dev/pci/auacer.c index e49c72079b9..e9ebbdc5a87 100644 --- a/sys/dev/pci/auacer.c +++ b/sys/dev/pci/auacer.c @@ -1,4 +1,4 @@ -/* $NetBSD: auacer.c,v 1.17 2007/10/19 12:00:40 ad Exp $ */ +/* $NetBSD: auacer.c,v 1.18 2007/12/09 20:28:05 jmcneill Exp $ */ /*- * Copyright (c) 2004 The NetBSD Foundation, Inc. @@ -51,7 +51,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: auacer.c,v 1.17 2007/10/19 12:00:40 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: auacer.c,v 1.18 2007/12/09 20:28:05 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -133,10 +133,6 @@ struct auacer_softc { int sc_dmamap_flags; - /* Power Management */ - void *sc_powerhook; - int sc_suspend; - #define AUACER_NFORMATS 3 struct audio_format sc_formats[AUACER_NFORMATS]; struct audio_encoding_set *sc_encodings; @@ -194,7 +190,7 @@ static int auacer_allocmem(struct auacer_softc *, size_t, size_t, struct auacer_dma *); static int auacer_freemem(struct auacer_softc *, struct auacer_dma *); -static void auacer_powerhook(int, void *); +static bool auacer_resume(device_t); static int auacer_set_rate(struct auacer_softc *, int, u_int); static void auacer_reset(struct auacer_softc *sc); @@ -350,14 +346,12 @@ auacer_attach(struct device *parent, struct device *self, void *aux) return; } - /* Watch for power change */ - sc->sc_suspend = PWR_RESUME; - sc->sc_powerhook = powerhook_establish(sc->sc_dev.dv_xname, - auacer_powerhook, sc); - audio_attach_mi(&auacer_hw_if, sc, &sc->sc_dev); auacer_reset(sc); + + if (!pmf_device_register(self, NULL, auacer_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } CFATTACH_DECL(auacer, sizeof(struct auacer_softc), @@ -1030,38 +1024,14 @@ auacer_alloc_cdata(struct auacer_softc *sc) return error; } -static void -auacer_powerhook(int why, void *addr) +static bool +auacer_resume(device_t dv) { - struct auacer_softc *sc; + struct auacer_softc *sc = device_private(dv); - sc = (struct auacer_softc *)addr; - switch (why) { - case PWR_SUSPEND: - case PWR_STANDBY: - /* Power down */ - DPRINTF(1, ("%s: power down\n", sc->sc_dev.dv_xname)); - sc->sc_suspend = why; - break; - - case PWR_RESUME: - /* Wake up */ - DPRINTF(1, ("%s: power resume\n", sc->sc_dev.dv_xname)); - if (sc->sc_suspend == PWR_RESUME) { - printf("%s: resume without suspend.\n", - sc->sc_dev.dv_xname); - sc->sc_suspend = why; - return; - } - sc->sc_suspend = why; - auacer_reset_codec(sc); - delay(1000); - sc->codec_if->vtbl->restore_ports(sc->codec_if); - break; - - case PWR_SOFTSUSPEND: - case PWR_SOFTSTANDBY: - case PWR_SOFTRESUME: - break; - } + auacer_reset_codec(sc); + delay(1000); + sc->codec_if->vtbl->restore_ports(sc->codec_if); + + return true; } diff --git a/sys/dev/pci/auich.c b/sys/dev/pci/auich.c index 924947dbdc0..624f379bd4d 100644 --- a/sys/dev/pci/auich.c +++ b/sys/dev/pci/auich.c @@ -1,4 +1,4 @@ -/* $NetBSD: auich.c,v 1.119 2007/10/19 12:00:40 ad Exp $ */ +/* $NetBSD: auich.c,v 1.120 2007/12/09 20:28:05 jmcneill Exp $ */ /*- * Copyright (c) 2000, 2004, 2005 The NetBSD Foundation, Inc. @@ -118,7 +118,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: auich.c,v 1.119 2007/10/19 12:00:40 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: auich.c,v 1.120 2007/12/09 20:28:05 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -217,12 +217,6 @@ struct auich_softc { /* 440MX workaround */ int sc_dmamap_flags; - /* Power Management */ - void *sc_powerhook; - int sc_suspend; - int sc_powerstate; - struct pci_conf_state sc_pciconf; - /* sysctl */ struct sysctllog *sc_log; uint32_t sc_ac97_clock; @@ -291,7 +285,7 @@ static int auich_allocmem(struct auich_softc *, size_t, size_t, struct auich_dma *); static int auich_freemem(struct auich_softc *, struct auich_dma *); -static void auich_powerhook(int, void *); +static bool auich_resume(device_t); static int auich_set_rate(struct auich_softc *, int, u_long); static int auich_sysctl_verify(SYSCTLFN_ARGS); static void auich_finish_attach(struct device *); @@ -645,11 +639,9 @@ auich_attach(struct device *parent, struct device *self, void *aux) return; } - /* Watch for power change */ - sc->sc_suspend = PWR_RESUME; - sc->sc_powerhook = powerhook_establish(sc->sc_dev.dv_xname, - auich_powerhook, sc); + if (!pmf_device_register(self, NULL, auich_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); config_interrupts(self, auich_finish_attach); @@ -777,10 +769,6 @@ auich_finish_attach(struct device *self) sc->sc_audiodev = audio_attach_mi(&auich_hw_if, sc, &sc->sc_dev); -#if notyet - auich_powerhook(PWR_SUSPEND, sc); -#endif - return; } @@ -1245,6 +1233,10 @@ auich_intr(void *v) #endif sc = v; + + if (!device_has_power(&sc->sc_dev)) + return (0); + ret = 0; #ifdef DIAGNOSTIC csts = pci_conf_read(sc->sc_pc, sc->sc_pt, PCI_COMMAND_STATUS_REG); @@ -1479,31 +1471,7 @@ auich_trigger_input(void *v, void *start, void *end, int blksize, static int auich_powerstate(void *v, int state) { -#if notyet - struct auich_softc *sc; - int rv; - - sc = (struct auich_softc *)v; - rv = 0; - - switch (state) { - case AUDIOPOWER_OFF: - auich_powerhook(PWR_SUSPEND, sc); - break; - case AUDIOPOWER_ON: - auich_powerhook(PWR_RESUME, sc); - break; - default: - aprint_error("%s: unknown power state %d\n", - sc->sc_dev.dv_xname, state); - rv = 1; - break; - } - - return rv; -#else return 0; -#endif } static int @@ -1615,62 +1583,15 @@ auich_alloc_cdata(struct auich_softc *sc) return error; } -static void -auich_powerhook(int why, void *addr) +static bool +auich_resume(device_t dv) { - struct auich_softc *sc; - - sc = (struct auich_softc *)addr; - switch (why) { - case PWR_SUSPEND: - case PWR_STANDBY: - /* Power down */ - DPRINTF(1, ("%s: power down\n", sc->sc_dev.dv_xname)); - - /* if we're already asleep, don't try to sleep again */ - if (sc->sc_suspend == PWR_SUSPEND || - sc->sc_suspend == PWR_STANDBY) - break; - sc->sc_suspend = why; - - DELAY(1000); - pci_conf_capture(sc->sc_pc, sc->sc_pt, &sc->sc_pciconf); - - if (sc->sc_ih != NULL) - pci_intr_disestablish(sc->sc_pc, sc->sc_ih); - - break; + struct auich_softc *sc = device_private(dv); - case PWR_RESUME: - /* Wake up */ - DPRINTF(1, ("%s: power resume\n", sc->sc_dev.dv_xname)); - if (sc->sc_suspend == PWR_RESUME) { - printf("%s: resume without suspend.\n", - sc->sc_dev.dv_xname); - sc->sc_suspend = why; - return; - } - - sc->sc_ih = pci_intr_establish(sc->sc_pc, sc->intrh, IPL_AUDIO, - auich_intr, sc); - if (sc->sc_ih == NULL) { - aprint_error("%s: can't establish interrupt", - sc->sc_dev.dv_xname); - /* XXX jmcneill what should we do here? */ - return; - } - pci_conf_restore(sc->sc_pc, sc->sc_pt, &sc->sc_pciconf); - sc->sc_suspend = why; - auich_reset_codec(sc); - DELAY(1000); - (sc->codec_if->vtbl->restore_ports)(sc->codec_if); - break; - - case PWR_SOFTSUSPEND: - case PWR_SOFTSTANDBY: - case PWR_SOFTRESUME: - break; - } + auich_reset_codec(sc); + DELAY(1000); + (sc->codec_if->vtbl->restore_ports)(sc->codec_if); + return true; } /* diff --git a/sys/dev/pci/auixp.c b/sys/dev/pci/auixp.c index 06702904ec0..f4aabc8ffa2 100644 --- a/sys/dev/pci/auixp.c +++ b/sys/dev/pci/auixp.c @@ -1,4 +1,4 @@ -/* $NetBSD: auixp.c,v 1.24 2007/10/19 12:00:40 ad Exp $ */ +/* $NetBSD: auixp.c,v 1.25 2007/12/09 20:28:05 jmcneill Exp $ */ /* * Copyright (c) 2004, 2005 Reinoud Zandijk <reinoud@netbsd.org> @@ -50,7 +50,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: auixp.c,v 1.24 2007/10/19 12:00:40 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: auixp.c,v 1.25 2007/12/09 20:28:05 jmcneill Exp $"); #include <sys/types.h> #include <sys/errno.h> @@ -164,15 +164,6 @@ static int auixp_allocmem(struct auixp_softc *, size_t, size_t, static int auixp_freemem(struct auixp_softc *, struct auixp_dma *); static paddr_t auixp_mappage(void *, void *, off_t, int); - -/* power management (do we support that already?) */ -#if 0 -static void auixp_powerhook(int, void *); -static int auixp_suspend(struct auixp_softc *); -static int auixp_resume(struct auixp_softc *); -#endif - - /* Supporting subroutines */ static int auixp_init(struct auixp_softc *); static void auixp_autodetect_codecs(struct auixp_softc *); @@ -203,6 +194,8 @@ static void auixp_program_dma_chain(struct auixp_softc *, static void auixp_dma_update(struct auixp_softc *, struct auixp_dma *); static void auixp_update_busbusy(struct auixp_softc *); +static bool auixp_resume(device_t); + #ifdef DEBUG_AUIXP static struct auixp_softc *static_sc; @@ -1107,7 +1100,7 @@ auixp_attach(struct device *parent, struct device *self, void *aux) const char *intrstr; uint32_t data; char devinfo[256]; - int revision, len, error; + int revision, error; sc = (struct auixp_softc *)self; pa = (struct pci_attach_args *)aux; @@ -1202,27 +1195,8 @@ auixp_attach(struct device *parent, struct device *self, void *aux) return; } - /* XXX set up power hooks; not implemented yet XXX */ - - len = 1; /* shut up gcc */ -#ifdef notyet - /* create suspend save area */ - len = sizeof(uint16_t) * (ESA_REV_B_CODE_MEMORY_LENGTH - + ESA_REV_B_DATA_MEMORY_LENGTH + 1); - sc->savemem = (uint16_t *)malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO); - if (sc->savemem == NULL) { - aprint_error("%s: unable to allocate suspend buffer\n", - sc->sc_dev.dv_xname); - return; - } - - sc->powerhook = powerhook_establish(sc->sc_dev.dv_xname, - auixp_powerhook, sc); - if (sc->powerhook == NULL) - aprint_error("%s: WARNING: unable to establish powerhook\n", - sc->sc_dev.dv_xname); - -#endif + if (!pmf_device_register(self, NULL, auixp_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); /* * delay further configuration of codecs and audio after interrupts @@ -1393,8 +1367,7 @@ auixp_detach(struct device *self, int flags) if (sc->sc_ios) bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios); - if (sc->savemem) - free(sc->savemem, M_DEVBUF); + pmf_device_deregister(self); return 0; } @@ -1785,52 +1758,17 @@ auixp_init(struct auixp_softc *sc) return 0; } - -/* - * TODO power saving and suspend / resume support - * - */ - -#if 0 -static void -auixp_powerhook(int why, void *hdl) -{ - struct auixp_softc *sc; - - sc = (struct auixp_softc *)hdl; - switch (why) { - case PWR_SUSPEND: - case PWR_STANDBY: - auixp_suspend(sc); - break; - case PWR_RESUME: - auixp_resume(sc); -#if notyet - /* XXX fix me XXX */ - (sc->codec_if->vtbl->restore_ports)(sc->codec_if); -#endif - break; - } -} - - -static int -auixp_suspend(struct auixp_softc *sc) +static bool +auixp_resume(device_t dv) { + struct auixp_softc *sc = device_private(dv); - /* XXX no power functions yet XXX */ - return 0; -} - + auixp_reset_codec(sc); + delay(1000); + (sc->sc_codec[0].codec_if->vtbl->restore_ports)(sc->sc_codec[0].codec_if); -static int -auixp_resume(struct auixp_softc *sc) -{ - - /* XXX no power functions yet XXX */ - return 0; + return true; } -#endif /* 0 */ #ifdef DEBUG_AUIXP diff --git a/sys/dev/pci/auixpvar.h b/sys/dev/pci/auixpvar.h index 00c4843f0d4..8ab76770088 100644 --- a/sys/dev/pci/auixpvar.h +++ b/sys/dev/pci/auixpvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: auixpvar.h,v 1.5 2007/03/04 06:02:16 christos Exp $*/ +/* $NetBSD: auixpvar.h,v 1.6 2007/12/09 20:28:06 jmcneill Exp $*/ /* * Copyright (c) 2004, 2005 Reinoud Zandijk <reinoud@netbsd.org> @@ -138,10 +138,6 @@ struct auixp_softc { /* last set audio parameters */ struct audio_params sc_play_params; struct audio_params sc_rec_params; - - /* suspend/resume */ - void *powerhook; - uint16_t *savemem; }; diff --git a/sys/dev/pci/autri.c b/sys/dev/pci/autri.c index 75ba1cb1c22..c7a105e3a48 100644 --- a/sys/dev/pci/autri.c +++ b/sys/dev/pci/autri.c @@ -1,4 +1,4 @@ -/* $NetBSD: autri.c,v 1.35 2007/10/19 12:00:40 ad Exp $ */ +/* $NetBSD: autri.c,v 1.36 2007/12/09 20:28:06 jmcneill Exp $ */ /* * Copyright (c) 2001 SOMEYA Yoshihiko and KUROSAWA Takahiro. @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: autri.c,v 1.35 2007/10/19 12:00:40 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: autri.c,v 1.36 2007/12/09 20:28:06 jmcneill Exp $"); #include "midi.h" @@ -97,7 +97,7 @@ static int autri_write_codec(void *, uint8_t, uint16_t); static int autri_reset_codec(void *); static enum ac97_host_flags autri_flags_codec(void *); -static void autri_powerhook(int, void *); +static bool autri_resume(device_t); static int autri_init(void *); static struct autri_dma *autri_find_dma(struct autri_softc *, void *); static void autri_setup_channel(struct autri_softc *, int, @@ -592,32 +592,28 @@ autri_attach(struct device *parent, struct device *self, void *aux) return; } + if (!pmf_device_register(self, NULL, autri_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); + audio_attach_mi(&autri_hw_if, sc, &sc->sc_dev); #if NMIDI > 0 midi_attach_mi(&autri_midi_hw_if, sc, &sc->sc_dev); #endif - - sc->sc_old_power = PWR_RESUME; - powerhook_establish(sc->sc_dev.dv_xname, autri_powerhook, sc); } CFATTACH_DECL(autri, sizeof(struct autri_softc), autri_match, autri_attach, NULL, NULL); -static void -autri_powerhook(int why, void *addr) +static bool +autri_resume(device_t dv) { - struct autri_softc *sc; + struct autri_softc *sc = device_private(dv); - sc = addr; - if (why == PWR_RESUME && sc->sc_old_power == PWR_SUSPEND) { - DPRINTF(("PWR_RESUME\n")); - autri_init(sc); - /*autri_reset_codec(&sc->sc_codec);*/ - (sc->sc_codec.codec_if->vtbl->restore_ports)(sc->sc_codec.codec_if); - } - sc->sc_old_power = why; + autri_init(sc); + (sc->sc_codec.codec_if->vtbl->restore_ports)(sc->sc_codec.codec_if); + + return true; } static int diff --git a/sys/dev/pci/autrivar.h b/sys/dev/pci/autrivar.h index 87b2e5d90f4..3ea4da811c1 100644 --- a/sys/dev/pci/autrivar.h +++ b/sys/dev/pci/autrivar.h @@ -1,4 +1,4 @@ -/* $NetBSD: autrivar.h,v 1.3 2007/03/04 06:02:16 christos Exp $ */ +/* $NetBSD: autrivar.h,v 1.4 2007/12/09 20:28:06 jmcneill Exp $ */ /* * Copyright (c) 2001 SOMEYA Yoshihiko and KUROSAWA Takahiro. @@ -86,8 +86,6 @@ struct autri_softc { u_int32_t sc_class; int sc_revision; - int sc_old_power; - /* * Play/record status */ diff --git a/sys/dev/pci/auvia.c b/sys/dev/pci/auvia.c index bad34ff3308..8f7fd927f7e 100644 --- a/sys/dev/pci/auvia.c +++ b/sys/dev/pci/auvia.c @@ -1,4 +1,4 @@ -/* $NetBSD: auvia.c,v 1.60 2007/03/04 06:02:16 christos Exp $ */ +/* $NetBSD: auvia.c,v 1.61 2007/12/09 20:28:06 jmcneill Exp $ */ /*- * Copyright (c) 2000 The NetBSD Foundation, Inc. @@ -47,7 +47,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: auvia.c,v 1.60 2007/03/04 06:02:16 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: auvia.c,v 1.61 2007/12/09 20:28:06 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -118,7 +118,7 @@ static int auvia_trigger_output(void *, void *, void *, int, static int auvia_trigger_input(void *, void *, void *, int, void (*)(void *), void *, const audio_params_t *); -static void auvia_powerhook(int, void *); +static bool auvia_resume(device_t); static int auvia_intr(void *); static int auvia_attach_codec(void *, struct ac97_codec_if *); @@ -453,10 +453,8 @@ auvia_attach(struct device *parent, struct device *self, void *aux) return; } - /* Watch for power change */ - sc->sc_suspend = PWR_RESUME; - sc->sc_powerhook = powerhook_establish(sc->sc_dev.dv_xname, - auvia_powerhook, sc); + if (!pmf_device_register(self, NULL, auvia_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); audio_attach_mi(&auvia_hw_if, sc, &sc->sc_dev); sc->codec_if->vtbl->unlock(sc->codec_if); @@ -1113,36 +1111,14 @@ auvia_intr(void *arg) return rval; } -static void -auvia_powerhook(int why, void *addr) +static bool +auvia_resume(device_t dv) { - struct auvia_softc *sc; - - sc = addr; - switch (why) { - case PWR_SUSPEND: - case PWR_STANDBY: - /* Power down */ - sc->sc_suspend = why; - break; + struct auvia_softc *sc = device_private(dv); - case PWR_RESUME: - /* Wake up */ - if (sc->sc_suspend == PWR_RESUME) { - printf("%s: resume without suspend.\n", - sc->sc_dev.dv_xname); - sc->sc_suspend = why; - return; - } - sc->sc_suspend = why; - auvia_reset_codec(sc); - DELAY(1000); - (sc->codec_if->vtbl->restore_ports)(sc->codec_if); - break; + auvia_reset_codec(sc); + DELAY(1000); + (sc->codec_if->vtbl->restore_ports)(sc->codec_if); - case PWR_SOFTSUSPEND: - case PWR_SOFTSTANDBY: - case PWR_SOFTRESUME: - break; - } + return true; } diff --git a/sys/dev/pci/auviavar.h b/sys/dev/pci/auviavar.h index 8df24181c84..cb583372d66 100644 --- a/sys/dev/pci/auviavar.h +++ b/sys/dev/pci/auviavar.h @@ -1,4 +1,4 @@ -/* $NetBSD: auviavar.h,v 1.11 2007/02/21 23:00:00 thorpej Exp $ */ +/* $NetBSD: auviavar.h,v 1.12 2007/12/09 20:28:06 jmcneill Exp $ */ /*- * Copyright (c) 2000 The NetBSD Foundation, Inc. @@ -75,10 +75,6 @@ struct auvia_softc { struct auvia_softc_chan sc_play, sc_record; - /* Power Management */ - void *sc_powerhook; - int sc_suspend; - #define AUVIA_NFORMATS 8 struct audio_format sc_formats[AUVIA_NFORMATS]; struct audio_encoding_set *sc_encodings; diff --git a/sys/dev/pci/azalia.c b/sys/dev/pci/azalia.c index a4a4ecabe91..44d17a12d94 100644 --- a/sys/dev/pci/azalia.c +++ b/sys/dev/pci/azalia.c @@ -1,4 +1,4 @@ -/* $NetBSD: azalia.c,v 1.51 2007/08/14 13:57:56 kent Exp $ */ +/* $NetBSD: azalia.c,v 1.52 2007/12/09 20:28:06 jmcneill Exp $ */ /*- * Copyright (c) 2005 The NetBSD Foundation, Inc. @@ -48,7 +48,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: azalia.c,v 1.51 2007/08/14 13:57:56 kent Exp $"); +__KERNEL_RCSID(0, "$NetBSD: azalia.c,v 1.52 2007/12/09 20:28:06 jmcneill Exp $"); #include <sys/param.h> #include <sys/device.h> @@ -115,6 +115,7 @@ typedef struct azalia_t { struct device *audiodev; pci_chipset_tag_t pc; + pcitag_t tag; void *ih; bus_space_tag_t iot; bus_space_handle_t ioh; @@ -142,6 +143,7 @@ typedef struct azalia_t { int nistreams, nostreams, nbstreams; stream_t pstream; stream_t rstream; + int mode_cap; } azalia_t; #define XNAME(sc) ((sc)->dev.dv_xname) @@ -158,12 +160,13 @@ static int azalia_pci_match(struct device *, struct cfdata *, void *); static void azalia_pci_attach(struct device *, struct device *, void *); static int azalia_pci_activate(struct device *, enum devact); static int azalia_pci_detach(struct device *, int); +static bool azalia_pci_resume(device_t); static int azalia_intr(void *); static int azalia_attach(azalia_t *); static void azalia_attach_intr(struct device *); -static int azalia_init_corb(azalia_t *); +static int azalia_init_corb(azalia_t *, int); static int azalia_delete_corb(azalia_t *); -static int azalia_init_rirb(azalia_t *); +static int azalia_init_rirb(azalia_t *, int); static int azalia_delete_rirb(azalia_t *); static int azalia_set_command(const azalia_t *, nid_t, int, uint32_t, uint32_t); @@ -173,7 +176,7 @@ static void azalia_rirb_intr(azalia_t *); static int azalia_alloc_dmamem(azalia_t *, size_t, size_t, azalia_dma_t *); static int azalia_free_dmamem(const azalia_t *, azalia_dma_t*); -static int azalia_codec_init(codec_t *); +static int azalia_codec_init(codec_t *, int); static int azalia_codec_delete(codec_t *); static void azalia_codec_add_bits(codec_t *, int, uint32_t, int); static void azalia_codec_add_format(codec_t *, int, int, int, uint32_t, @@ -185,7 +188,9 @@ static int azalia_codec_disconnect_stream(codec_t *, int); static int azalia_widget_init(widget_t *, const codec_t *, int, const char *); static int azalia_widget_init_audio(widget_t *, const codec_t *, const char *); +#ifdef AZALIA_DEBUG static int azalia_widget_print_audio(const widget_t *, const char *, int); +#endif static int azalia_widget_init_pin(widget_t *, const codec_t *); static int azalia_widget_print_pin(const widget_t *, const char *); static int azalia_widget_init_connection(widget_t *, const codec_t *, const char *); @@ -327,6 +332,7 @@ azalia_pci_attach(struct device *parent, struct device *self, return; } sc->pc = pa->pa_pc; + sc->tag = pa->pa_tag; intrrupt_str = pci_intr_string(pa->pa_pc, ih); sc->ih = pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO, azalia_intr, sc); if (sc->ih == NULL) { @@ -338,6 +344,9 @@ azalia_pci_attach(struct device *parent, struct device *self, } aprint_normal("%s: interrupting at %s\n", XNAME(sc), intrrupt_str); + if (!pmf_device_register(self, NULL, azalia_pci_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); + sc->pciid = pa->pa_id; vendor = pci_findvendor(pa->pa_id); name = pci_findproduct(pa->pa_id); @@ -418,6 +427,21 @@ azalia_pci_detach(struct device *self, int flags) return 0; } +static bool +azalia_pci_resume(device_t dv) +{ + azalia_t *az = device_private(dv); + int s; + + s = splaudio(); + azalia_attach(az); + splx(s); + + azalia_attach_intr(&az->dev); + + return true; +} + static int azalia_intr(void *v) { @@ -429,6 +453,9 @@ azalia_intr(void *v) az = v; ret = 0; + if (!device_has_power(&az->dev)) + return 0; + intsts = AZ_READ_4(az, INTSTS); if (intsts == 0) return ret; @@ -463,8 +490,10 @@ azalia_attach(azalia_t *az) uint16_t gcap; uint16_t statests; - aprint_normal("%s: host: High Definition Audio rev. %d.%d\n", - XNAME(az), AZ_READ_1(az, VMAJ), AZ_READ_1(az, VMIN)); + if (az->audiodev == NULL) + aprint_normal("%s: host: High Definition Audio rev. %d.%d\n", + XNAME(az), AZ_READ_1(az, VMAJ), AZ_READ_1(az, VMIN)); + gcap = AZ_READ_2(az, GCAP); az->nistreams = HDA_GCAP_ISS(gcap); az->nostreams = HDA_GCAP_OSS(gcap); @@ -531,9 +560,10 @@ static void azalia_attach_intr(struct device *self) { azalia_t *az; - int err, i, c; + int err, i, c, reinit; az = (azalia_t*)self; + reinit = az->audiodev == NULL ? 0 : 1; AZ_WRITE_2(az, STATESTS, HDA_STATESTS_SDIWAKE); AZ_WRITE_1(az, RIRBSTS, HDA_RIRBSTS_RINTFL | HDA_RIRBSTS_RIRBOIS); @@ -542,10 +572,10 @@ azalia_attach_intr(struct device *self) AZ_WRITE_4(az, DPUBASE, 0); /* 4.4.1 Command Outbound Ring Buffer */ - if (azalia_init_corb(az)) + if (azalia_init_corb(az, reinit)) goto err_exit; /* 4.4.2 Response Inbound Ring Buffer */ - if (azalia_init_rirb(az)) + if (azalia_init_rirb(az, reinit)) goto err_exit; AZ_WRITE_4(az, INTCTL, @@ -553,7 +583,7 @@ azalia_attach_intr(struct device *self) c = -1; for (i = 0; i < az->ncodecs; i++) { - err = azalia_codec_init(&az->codecs[i]); + err = azalia_codec_init(&az->codecs[i], reinit); if (!err && c < 0) c = i; } @@ -568,15 +598,15 @@ azalia_attach_intr(struct device *self) az->mode_cap &= ~AUMODE_RECORD; /* Use stream#1 and #2. Don't use stream#0. */ - if (az->nostreams > 0 && - azalia_stream_init(&az->pstream, az, az->nistreams + 0, - 1, AUMODE_PLAY)) - goto err_exit; - if (az->nistreams > 0 && - azalia_stream_init(&az->rstream, az, 0, 2, AUMODE_RECORD)) - goto err_exit; + if (reinit == 0) { + if (azalia_stream_init(&az->pstream, az, az->nistreams + 0, + 1, AUMODE_PLAY)) + goto err_exit; + if (azalia_stream_init(&az->rstream, az, 0, 2, AUMODE_RECORD)) + goto err_exit; - az->audiodev = audio_attach_mi(&azalia_hw_if, az, &az->dev); + az->audiodev = audio_attach_mi(&azalia_hw_if, az, &az->dev); + } return; err_exit: azalia_pci_detach(self, 0); @@ -584,7 +614,7 @@ err_exit: } static int -azalia_init_corb(azalia_t *az) +azalia_init_corb(azalia_t *az, int reinit) { int entries, err, i; uint16_t corbrp, corbwp; @@ -624,11 +654,14 @@ azalia_init_corb(azalia_t *az) return -1; } - err = azalia_alloc_dmamem(az, entries * sizeof(corb_entry_t), - 128, &az->corb_dma); - if (err) { - aprint_error("%s: can't allocate CORB buffer\n", XNAME(az)); - return err; + if (reinit == 0) { + err = azalia_alloc_dmamem(az, entries * sizeof(corb_entry_t), + 128, &az->corb_dma); + if (err) { + aprint_error("%s: can't allocate CORB buffer\n", + XNAME(az)); + return err; + } } AZ_WRITE_4(az, CORBLBASE, (uint32_t)AZALIA_DMA_DMAADDR(&az->corb_dma)); AZ_WRITE_4(az, CORBUBASE, PTR_UPPER32(AZALIA_DMA_DMAADDR(&az->corb_dma))); @@ -686,7 +719,7 @@ azalia_delete_corb(azalia_t *az) } static int -azalia_init_rirb(azalia_t *az) +azalia_init_rirb(azalia_t *az, int reinit) { int entries, err, i; uint16_t rirbwp; @@ -726,11 +759,14 @@ azalia_init_rirb(azalia_t *az) return -1; } - err = azalia_alloc_dmamem(az, entries * sizeof(rirb_entry_t), - 128, &az->rirb_dma); - if (err) { - aprint_error("%s: can't allocate RIRB buffer\n", XNAME(az)); - return err; + if (reinit == 0) { + err = azalia_alloc_dmamem(az, entries * sizeof(rirb_entry_t), + 128, &az->rirb_dma); + if (err) { + aprint_error("%s: can't allocate RIRB buffer\n", + XNAME(az)); + return err; + } } AZ_WRITE_4(az, RIRBLBASE, (uint32_t)AZALIA_DMA_DMAADDR(&az->rirb_dma)); AZ_WRITE_4(az, RIRBUBASE, PTR_UPPER32(AZALIA_DMA_DMAADDR(&az->rirb_dma))); @@ -743,8 +779,12 @@ azalia_init_rirb(azalia_t *az) az->unsolq_rp = 0; az->unsolq_wp = 0; az->unsolq_kick = FALSE; - az->unsolq = malloc(sizeof(rirb_entry_t) * UNSOLQ_SIZE, - M_DEVBUF, M_ZERO | M_NOWAIT); + if (reinit == 0) { + az->unsolq = malloc(sizeof(rirb_entry_t) * UNSOLQ_SIZE, + M_DEVBUF, M_ZERO | M_NOWAIT); + } else { + memset(az->unsolq, 0, sizeof(rirb_entry_t) * UNSOLQ_SIZE); + } if (az->unsolq == NULL) { aprint_error("%s: can't allocate unsolicited response queue.\n", XNAME(az)); @@ -984,7 +1024,7 @@ azalia_free_dmamem(const azalia_t *az, azalia_dma_t* d) * ================================================================ */ static int -azalia_codec_init(codec_t *this) +azalia_codec_init(codec_t *this, int reinit) { #define LEAD_LEN 100 char lead[LEAD_LEN]; @@ -1006,21 +1046,26 @@ azalia_codec_init(codec_t *this) return err; this->vid = id; this->subid = this->az->subid; - err = azalia_codec_init_vtbl(this); - if (err) - return err; - aprint_normal("%s: codec[%d]: ", XNAME(this->az), addr); - if (this->name == NULL) { - aprint_normal("0x%4.4x/0x%4.4x (rev. %u.%u)\n", - id >> 16, id & 0xffff, - COP_RID_REVISION(rev), COP_RID_STEPPING(rev)); - } else { - aprint_normal("%s (rev. %u.%u)\n", this->name, - COP_RID_REVISION(rev), COP_RID_STEPPING(rev)); + if (!reinit) { + err = azalia_codec_init_vtbl(this); + if (err) + return err; + } + + if (!reinit) { + aprint_normal("%s: codec[%d]: ", XNAME(this->az), addr); + if (this->name == NULL) { + aprint_normal("0x%4.4x/0x%4.4x (rev. %u.%u)\n", + id >> 16, id & 0xffff, + COP_RID_REVISION(rev), COP_RID_STEPPING(rev)); + } else { + aprint_normal("%s (rev. %u.%u)\n", this->name, + COP_RID_REVISION(rev), COP_RID_STEPPING(rev)); + } + aprint_normal("%s: codec[%d]: High Definition Audio rev. %u.%u\n", + XNAME(this->az), addr, COP_RID_MAJ(rev), COP_RID_MIN(rev)); } - aprint_normal("%s: codec[%d]: High Definition Audio rev. %u.%u\n", - XNAME(this->az), addr, COP_RID_MAJ(rev), COP_RID_MIN(rev)); /* identify function nodes */ err = this->comresp(this, CORB_NID_ROOT, CORB_GET_PARAMETER, @@ -1046,12 +1091,12 @@ azalia_codec_init(codec_t *this) if (COP_FTYPE(result) == COP_FTYPE_AUDIO) { this->audiofunc = n + i; break; /* XXX multiple audio functions? */ - } else if (COP_FTYPE(result) == COP_FTYPE_MODEM) { + } else if (COP_FTYPE(result) == COP_FTYPE_MODEM && !reinit) { aprint_normal("%s: codec[%d]: No support for modem function groups\n", XNAME(this->az), addr); } } - if (this->audiofunc < 0) { + if (this->audiofunc < 0 && !reinit) { aprint_error("%s: codec[%d] has no audio function groups\n", XNAME(this->az), addr); return -1; @@ -1070,16 +1115,21 @@ azalia_codec_init(codec_t *this) __func__, COP_NSUBNODES(result))); this->wstart = COP_START_NID(result); if (this->wstart < 2) { - aprint_error("%s: invalid node structure\n", XNAME(this->az)); + if (!reinit) + aprint_error("%s: invalid node structure\n", + XNAME(this->az)); return -1; } this->wend = this->wstart + COP_NSUBNODES(result); - this->w = malloc(sizeof(widget_t) * this->wend, M_DEVBUF, - M_ZERO | M_NOWAIT); - if (this->w == NULL) { - aprint_error("%s: out of memory\n", XNAME(this->az)); - return ENOMEM; - } + if (!reinit) { + this->w = malloc(sizeof(widget_t) * this->wend, M_DEVBUF, + M_ZERO | M_NOWAIT); + if (this->w == NULL) { + aprint_error("%s: out of memory\n", XNAME(this->az)); + return ENOMEM; + } + } else + memset(this->w, 0, sizeof(widget_t) * this->wend); /* query the base parameters */ this->comresp(this, this->audiofunc, CORB_GET_PARAMETER, @@ -1245,7 +1295,9 @@ azalia_codec_delete(codec_t *this) int azalia_codec_construct_format(codec_t *this, int newdac, int newadc) { +#ifdef AZALIA_DEBUG char flagbuf[FLAGBUFLEN]; +#endif const convgroup_t *group; uint32_t bits_rates; int prev_dac, prev_adc; @@ -1329,6 +1381,7 @@ azalia_codec_construct_format(codec_t *this, int newdac, int newadc) azalia_codec_add_bits(this, chan, bits_rates, AUMODE_PLAY); } +#ifdef AZALIA_DEBUG /* print playback capability */ if (prev_dac != this->dacs.cur) { snprintf(flagbuf, FLAGBUFLEN, "%s: playback: ", @@ -1336,6 +1389,7 @@ azalia_codec_construct_format(codec_t *this, int newdac, int newadc) azalia_widget_print_audio(&this->w[group->conv[0]], flagbuf, chan); } +#endif } /* register formats for recording */ @@ -1352,6 +1406,7 @@ azalia_codec_construct_format(codec_t *this, int newdac, int newadc) azalia_codec_add_bits(this, chan, bits_rates, AUMODE_RECORD); } +#ifdef AZALIA_DEBUG /* print recording capability */ if (prev_adc != this->adcs.cur) { snprintf(flagbuf, FLAGBUFLEN, "%s: recording: ", @@ -1359,6 +1414,7 @@ azalia_codec_construct_format(codec_t *this, int newdac, int newadc) azalia_widget_print_audio(&this->w[group->conv[0]], flagbuf, chan); } +#endif } #ifdef DIAGNOSTIC @@ -1706,6 +1762,7 @@ azalia_widget_init_audio(widget_t *this, const codec_t *codec, const char *lead) return 0; } +#ifdef AZALIA_DEBUG static int azalia_widget_print_audio(const widget_t *this, const char *lead, int channels) { @@ -1730,6 +1787,7 @@ azalia_widget_print_audio(const widget_t *this, const char *lead, int channels) aprint_normal("%sPCM formats=%s\n", lead, flagbuf); return 0; } +#endif static int azalia_widget_init_pin(widget_t *this, const codec_t *codec) diff --git a/sys/dev/pci/azalia_codec.c b/sys/dev/pci/azalia_codec.c index c04fabb2fb2..4a7a69661fa 100644 --- a/sys/dev/pci/azalia_codec.c +++ b/sys/dev/pci/azalia_codec.c @@ -1,4 +1,4 @@ -/* $NetBSD: azalia_codec.c,v 1.49 2007/11/26 15:47:36 christos Exp $ */ +/* $NetBSD: azalia_codec.c,v 1.50 2007/12/09 20:28:06 jmcneill Exp $ */ /*- * Copyright (c) 2005 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: azalia_codec.c,v 1.49 2007/11/26 15:47:36 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: azalia_codec.c,v 1.50 2007/12/09 20:28:06 jmcneill Exp $"); #include <sys/param.h> #include <sys/device.h> @@ -111,6 +111,7 @@ static int alc260_mixer_init(codec_t *); static int alc260_set_port(codec_t *, mixer_ctrl_t *); static int alc260_get_port(codec_t *, mixer_ctrl_t *); static int alc260_unsol_event(codec_t *, int); +static int alc262_init_widget(const codec_t *, widget_t *, nid_t); static int alc861_init_dacgroup(codec_t *); static int alc861vdgr_init_dacgroup(codec_t *); static int alc880_init_dacgroup(codec_t *); @@ -167,6 +168,7 @@ azalia_codec_init_vtbl(codec_t *this) break; case 0x10ec0262: this->name = "Realtek ALC262"; + this->init_widget = alc262_init_widget; break; case 0x10ec0268: this->name = "Realtek ALC268"; @@ -1998,6 +2000,22 @@ alc260_unsol_event(codec_t *this, int tag) * ---------------------------------------------------------------- */ static int +alc262_init_widget(const codec_t *this, widget_t *w, nid_t nid) +{ + switch (nid) { + case 0x0c: + strlcpy(w->name, AudioNmaster, sizeof(w->name)); + break; + } + + return 0; +} + +/* ---------------------------------------------------------------- + * Realtek ALC861 + * ---------------------------------------------------------------- */ + +static int alc861_init_dacgroup(codec_t *this) { static const convgroupset_t dacs = { diff --git a/sys/dev/pci/cs4280.c b/sys/dev/pci/cs4280.c index 96df6aa8b39..26eb558f9cb 100644 --- a/sys/dev/pci/cs4280.c +++ b/sys/dev/pci/cs4280.c @@ -1,4 +1,4 @@ -/* $NetBSD: cs4280.c,v 1.47 2007/10/19 12:00:41 ad Exp $ */ +/* $NetBSD: cs4280.c,v 1.48 2007/12/09 20:28:07 jmcneill Exp $ */ /* * Copyright (c) 1999, 2000 Tatoku Ogaito. All rights reserved. @@ -52,7 +52,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: cs4280.c,v 1.47 2007/10/19 12:00:41 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cs4280.c,v 1.48 2007/12/09 20:28:07 jmcneill Exp $"); #include "midi.h" @@ -110,8 +110,8 @@ static int cs4280_reset_codec(void *); #endif static enum ac97_host_flags cs4280_flags_codec(void *); -/* For PowerHook */ -static void cs4280_power(int, void *); +static bool cs4280_resume(device_t); +static bool cs4280_suspend(device_t); /* Internal functions */ static const struct cs4280_card_t * cs4280_identify_card(struct pci_attach_args *); @@ -365,9 +365,8 @@ cs4280_attach(struct device *parent, struct device *self, void *aux) midi_attach_mi(&cs4280_midi_hw_if, sc, &sc->sc_dev); #endif - sc->sc_suspend = PWR_RESUME; - sc->sc_powerhook = powerhook_establish(sc->sc_dev.dv_xname, - cs4280_power, sc); + if (!pmf_device_register(self, cs4280_suspend, cs4280_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } /* Interrupt handling function */ @@ -912,99 +911,79 @@ cs4280_trigger_input(void *addr, void *start, void *end, int blksize, return 0; } -/* Power Hook */ -static void -cs4280_power(int why, void *v) +static bool +cs4280_suspend(device_t dv) { - static uint32_t pctl = 0, pba = 0, pfie = 0, pdtc = 0; - static uint32_t cctl = 0, cba = 0, cie = 0; - struct cs428x_softc *sc; - - sc = (struct cs428x_softc *)v; - DPRINTF(("%s: cs4280_power why=%d\n", sc->sc_dev.dv_xname, why)); - switch (why) { - case PWR_SUSPEND: - case PWR_STANDBY: - sc->sc_suspend = why; - - /* save current playback status */ - if (sc->sc_prun) { - pctl = BA1READ4(sc, CS4280_PCTL); - pfie = BA1READ4(sc, CS4280_PFIE); - pba = BA1READ4(sc, CS4280_PBA); - pdtc = BA1READ4(sc, CS4280_PDTC); - DPRINTF(("pctl=0x%08x pfie=0x%08x pba=0x%08x pdtc=0x%08x\n", - pctl, pfie, pba, pdtc)); - } - - /* save current capture status */ - if (sc->sc_rrun) { - cctl = BA1READ4(sc, CS4280_CCTL); - cie = BA1READ4(sc, CS4280_CIE); - cba = BA1READ4(sc, CS4280_CBA); - DPRINTF(("cctl=0x%08x cie=0x%08x cba=0x%08x\n", - cctl, cie, cba)); - } + struct cs428x_softc *sc = device_private(dv); + + if (sc->sc_prun) { + sc->sc_suspend_state.cs4280.pctl = BA1READ4(sc, CS4280_PCTL); + sc->sc_suspend_state.cs4280.pfie = BA1READ4(sc, CS4280_PFIE); + sc->sc_suspend_state.cs4280.pba = BA1READ4(sc, CS4280_PBA); + sc->sc_suspend_state.cs4280.pdtc = BA1READ4(sc, CS4280_PDTC); + DPRINTF(("pctl=0x%08x pfie=0x%08x pba=0x%08x pdtc=0x%08x\n", + sc->sc_suspend_state.cs4280.pctl, + sc->sc_suspend_state.cs4280.pfie, + sc->sc_suspend_state.cs4280.pba, + sc->sc_suspend_state.cs4280.pdtc)); + } - /* Stop DMA */ - BA1WRITE4(sc, CS4280_PCTL, pctl & ~PCTL_MASK); - BA1WRITE4(sc, CS4280_CCTL, BA1READ4(sc, CS4280_CCTL) & ~CCTL_MASK); + /* save current capture status */ + if (sc->sc_rrun) { + sc->sc_suspend_state.cs4280.cctl = BA1READ4(sc, CS4280_CCTL); + sc->sc_suspend_state.cs4280.cie = BA1READ4(sc, CS4280_CIE); + sc->sc_suspend_state.cs4280.cba = BA1READ4(sc, CS4280_CBA); + DPRINTF(("cctl=0x%08x cie=0x%08x cba=0x%08x\n", + sc->sc_suspend_state.cs4280.cctl, + sc->sc_suspend_state.cs4280.cie, + sc->sc_suspend_state.cs4280.cba)); + } - pci_conf_capture(sc->sc_pc, sc->sc_pt, &sc->sc_pciconf); - if (sc->sc_ih != NULL) - pci_intr_disestablish(sc->sc_pc, sc->sc_ih); + /* Stop DMA */ + BA1WRITE4(sc, CS4280_PCTL, sc->sc_suspend_state.cs4280.pctl & ~PCTL_MASK); + BA1WRITE4(sc, CS4280_CCTL, BA1READ4(sc, CS4280_CCTL) & ~CCTL_MASK); - break; - case PWR_RESUME: - if (sc->sc_suspend == PWR_RESUME) { - printf("cs4280_power: odd, resume without suspend.\n"); - sc->sc_suspend = why; - return; - } + return true; +} - sc->sc_ih = pci_intr_establish(sc->sc_pc, sc->intrh, - IPL_AUDIO, cs4280_intr, sc); - if (sc->sc_ih == NULL) { - aprint_error("%s: can't establish interrupt", - sc->sc_dev.dv_xname); - /* XXX jmcneill what should we do here? */ - return; - } - pci_conf_restore(sc->sc_pc, sc->sc_pt, &sc->sc_pciconf); +static bool +cs4280_resume(device_t dv) +{ + struct cs428x_softc *sc = device_private(dv); - sc->sc_suspend = why; - cs4280_init(sc, 0); + cs4280_init(sc, 0); #if 0 - cs4280_reset_codec(sc); + cs4280_reset_codec(sc); #endif - /* restore ac97 registers */ - (*sc->codec_if->vtbl->restore_ports)(sc->codec_if); - - /* restore DMA related status */ - if(sc->sc_prun) { - DPRINTF(("pctl=0x%08x pfie=0x%08x pba=0x%08x pdtc=0x%08x\n", - pctl, pfie, pba, pdtc)); - cs4280_set_dac_rate(sc, sc->sc_prate); - BA1WRITE4(sc, CS4280_PDTC, pdtc); - BA1WRITE4(sc, CS4280_PBA, pba); - BA1WRITE4(sc, CS4280_PFIE, pfie); - BA1WRITE4(sc, CS4280_PCTL, pctl); - } + /* restore ac97 registers */ + (*sc->codec_if->vtbl->restore_ports)(sc->codec_if); + + /* restore DMA related status */ + if(sc->sc_prun) { + DPRINTF(("pctl=0x%08x pfie=0x%08x pba=0x%08x pdtc=0x%08x\n", + sc->sc_suspend_state.cs4280.pctl, + sc->sc_suspend_state.cs4280.pfie, + sc->sc_suspend_state.cs4280.pba, + sc->sc_suspend_state.cs4280.pdtc)); + cs4280_set_dac_rate(sc, sc->sc_prate); + BA1WRITE4(sc, CS4280_PDTC, sc->sc_suspend_state.cs4280.pdtc); + BA1WRITE4(sc, CS4280_PBA, sc->sc_suspend_state.cs4280.pba); + BA1WRITE4(sc, CS4280_PFIE, sc->sc_suspend_state.cs4280.pfie); + BA1WRITE4(sc, CS4280_PCTL, sc->sc_suspend_state.cs4280.pctl); + } - if (sc->sc_rrun) { - DPRINTF(("cctl=0x%08x cie=0x%08x cba=0x%08x\n", - cctl, cie, cba)); - cs4280_set_adc_rate(sc, sc->sc_rrate); - BA1WRITE4(sc, CS4280_CBA, cba); - BA1WRITE4(sc, CS4280_CIE, cie); - BA1WRITE4(sc, CS4280_CCTL, cctl); - } - break; - case PWR_SOFTSUSPEND: - case PWR_SOFTSTANDBY: - case PWR_SOFTRESUME: - break; + if (sc->sc_rrun) { + DPRINTF(("cctl=0x%08x cie=0x%08x cba=0x%08x\n", + sc->sc_suspend_state.cs4280.cctl, + sc->sc_suspend_state.cs4280.cie, + sc->sc_suspend_state.cs4280.cba)); + cs4280_set_adc_rate(sc, sc->sc_rrate); + BA1WRITE4(sc, CS4280_CBA, sc->sc_suspend_state.cs4280.cba); + BA1WRITE4(sc, CS4280_CIE, sc->sc_suspend_state.cs4280.cie); + BA1WRITE4(sc, CS4280_CCTL, sc->sc_suspend_state.cs4280.cctl); } + + return true; } static int diff --git a/sys/dev/pci/cs4281.c b/sys/dev/pci/cs4281.c index bf4e8ec5713..3e32a67213b 100644 --- a/sys/dev/pci/cs4281.c +++ b/sys/dev/pci/cs4281.c @@ -1,4 +1,4 @@ -/* $NetBSD: cs4281.c,v 1.35 2007/10/19 12:00:41 ad Exp $ */ +/* $NetBSD: cs4281.c,v 1.36 2007/12/09 20:28:07 jmcneill Exp $ */ /* * Copyright (c) 2000 Tatoku Ogaito. All rights reserved. @@ -43,7 +43,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: cs4281.c,v 1.35 2007/10/19 12:00:41 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cs4281.c,v 1.36 2007/12/09 20:28:07 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -106,7 +106,8 @@ static void cs4281_set_adc_rate(struct cs428x_softc *, int); static int cs4281_init(struct cs428x_softc *, int); /* Power Management */ -static void cs4281_power(int, void *); +static bool cs4281_suspend(device_t); +static bool cs4281_resume(device_t); static const struct audio_hw_if cs4281_hw_if = { NULL, /* open */ @@ -292,9 +293,8 @@ cs4281_attach(struct device *parent, struct device *self, void *aux) midi_attach_mi(&cs4281_midi_hw_if, sc, &sc->sc_dev); #endif - sc->sc_suspend = PWR_RESUME; - sc->sc_powerhook = powerhook_establish(sc->sc_dev.dv_xname, - cs4281_power, sc); + if (!pmf_device_register(self, cs4281_suspend, cs4281_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } static int @@ -721,93 +721,64 @@ cs4281_trigger_input(void *addr, void *start, void *end, int blksize, return 0; } -/* Power Hook */ -static void -cs4281_power(int why, void *v) +static bool +cs4281_suspend(device_t dv) { - static uint32_t dba0 = 0, dbc0 = 0, dmr0 = 0, dcr0 = 0; - static uint32_t dba1 = 0, dbc1 = 0, dmr1 = 0, dcr1 = 0; - struct cs428x_softc *sc; - - sc = (struct cs428x_softc *)v; - DPRINTF(("%s: cs4281_power why=%d\n", sc->sc_dev.dv_xname, why)); - switch (why) { - case PWR_SUSPEND: - case PWR_STANDBY: - sc->sc_suspend = why; - - /* save current playback status */ - if (sc->sc_prun) { - dcr0 = BA0READ4(sc, CS4281_DCR0); - dmr0 = BA0READ4(sc, CS4281_DMR0); - dbc0 = BA0READ4(sc, CS4281_DBC0); - dba0 = BA0READ4(sc, CS4281_DBA0); - } - - /* save current capture status */ - if (sc->sc_rrun) { - dcr1 = BA0READ4(sc, CS4281_DCR1); - dmr1 = BA0READ4(sc, CS4281_DMR1); - dbc1 = BA0READ4(sc, CS4281_DBC1); - dba1 = BA0READ4(sc, CS4281_DBA1); - } - /* Stop DMA */ - BA0WRITE4(sc, CS4281_DCR0, BA0READ4(sc, CS4281_DCR0) | DCRn_MSK); - BA0WRITE4(sc, CS4281_DCR1, BA0READ4(sc, CS4281_DCR1) | DCRn_MSK); + struct cs428x_softc *sc = device_private(dv); + + /* save current playback status */ + if (sc->sc_prun) { + sc->sc_suspend_state.cs4281.dcr0 = BA0READ4(sc, CS4281_DCR0); + sc->sc_suspend_state.cs4281.dmr0 = BA0READ4(sc, CS4281_DMR0); + sc->sc_suspend_state.cs4281.dbc0 = BA0READ4(sc, CS4281_DBC0); + sc->sc_suspend_state.cs4281.dba0 = BA0READ4(sc, CS4281_DBA0); + } - pci_conf_capture(sc->sc_pc, sc->sc_pt, &sc->sc_pciconf); - if (sc->sc_ih != NULL) - pci_intr_disestablish(sc->sc_pc, sc->sc_ih); + /* save current capture status */ + if (sc->sc_rrun) { + sc->sc_suspend_state.cs4281.dcr1 = BA0READ4(sc, CS4281_DCR1); + sc->sc_suspend_state.cs4281.dmr1 = BA0READ4(sc, CS4281_DMR1); + sc->sc_suspend_state.cs4281.dbc1 = BA0READ4(sc, CS4281_DBC1); + sc->sc_suspend_state.cs4281.dba1 = BA0READ4(sc, CS4281_DBA1); + } + /* Stop DMA */ + BA0WRITE4(sc, CS4281_DCR0, BA0READ4(sc, CS4281_DCR0) | DCRn_MSK); + BA0WRITE4(sc, CS4281_DCR1, BA0READ4(sc, CS4281_DCR1) | DCRn_MSK); - break; - case PWR_RESUME: - if (sc->sc_suspend == PWR_RESUME) { - printf("cs4281_power: odd, resume without suspend.\n"); - sc->sc_suspend = why; - return; - } + return true; +} - sc->sc_ih = pci_intr_establish(sc->sc_pc, sc->intrh, - IPL_AUDIO, cs4281_intr, sc); - if (sc->sc_ih == NULL) { - aprint_error("%s: can't establish interrupt", - sc->sc_dev.dv_xname); - /* XXX jmcneill what should we do here? */ - return; - } - pci_conf_restore(sc->sc_pc, sc->sc_pt, &sc->sc_pciconf); +static bool +cs4281_resume(device_t dv) +{ + struct cs428x_softc *sc = device_private(dv); - sc->sc_suspend = why; - cs4281_init(sc, 0); - cs4281_reset_codec(sc); + cs4281_init(sc, 0); + cs4281_reset_codec(sc); - /* restore ac97 registers */ - (*sc->codec_if->vtbl->restore_ports)(sc->codec_if); + /* restore ac97 registers */ + (*sc->codec_if->vtbl->restore_ports)(sc->codec_if); - /* restore DMA related status */ - if (sc->sc_prun) { - cs4281_set_dac_rate(sc, sc->sc_prate); - BA0WRITE4(sc, CS4281_DBA0, dba0); - BA0WRITE4(sc, CS4281_DBC0, dbc0); - BA0WRITE4(sc, CS4281_DMR0, dmr0); - BA0WRITE4(sc, CS4281_DCR0, dcr0); - } - if (sc->sc_rrun) { - cs4281_set_adc_rate(sc, sc->sc_rrate); - BA0WRITE4(sc, CS4281_DBA1, dba1); - BA0WRITE4(sc, CS4281_DBC1, dbc1); - BA0WRITE4(sc, CS4281_DMR1, dmr1); - BA0WRITE4(sc, CS4281_DCR1, dcr1); - } - /* enable intterupts */ - if (sc->sc_prun || sc->sc_rrun) - BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM); - break; - case PWR_SOFTSUSPEND: - case PWR_SOFTSTANDBY: - case PWR_SOFTRESUME: - break; + /* restore DMA related status */ + if (sc->sc_prun) { + cs4281_set_dac_rate(sc, sc->sc_prate); + BA0WRITE4(sc, CS4281_DBA0, sc->sc_suspend_state.cs4281.dba0); + BA0WRITE4(sc, CS4281_DBC0, sc->sc_suspend_state.cs4281.dbc0); + BA0WRITE4(sc, CS4281_DMR0, sc->sc_suspend_state.cs4281.dmr0); + BA0WRITE4(sc, CS4281_DCR0, sc->sc_suspend_state.cs4281.dcr0); + } + if (sc->sc_rrun) { + cs4281_set_adc_rate(sc, sc->sc_rrate); + BA0WRITE4(sc, CS4281_DBA1, sc->sc_suspend_state.cs4281.dba1); + BA0WRITE4(sc, CS4281_DBC1, sc->sc_suspend_state.cs4281.dbc1); + BA0WRITE4(sc, CS4281_DMR1, sc->sc_suspend_state.cs4281.dmr1); + BA0WRITE4(sc, CS4281_DCR1, sc->sc_suspend_state.cs4281.dcr1); } + /* enable intterupts */ + if (sc->sc_prun || sc->sc_rrun) + BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM); + + return true; } /* control AC97 codec */ diff --git a/sys/dev/pci/cs428x.h b/sys/dev/pci/cs428x.h index ef5e180e667..97cffe2a79b 100644 --- a/sys/dev/pci/cs428x.h +++ b/sys/dev/pci/cs428x.h @@ -1,4 +1,4 @@ -/* $NetBSD: cs428x.h,v 1.13 2007/06/15 13:26:57 joerg Exp $ */ +/* $NetBSD: cs428x.h,v 1.14 2007/12/09 20:28:07 jmcneill Exp $ */ /* * Copyright (c) 2000 Tatoku Ogaito. All rights reserved. @@ -141,9 +141,27 @@ struct cs428x_softc { struct ac97_host_if host_if; /* Power Management */ - char sc_suspend; - void *sc_powerhook; /* Power Hook */ - struct pci_conf_state sc_pciconf; + union { + struct { + uint32_t pctl; + uint32_t pba; + uint32_t pfie; + uint32_t pdtc; + uint32_t cctl; + uint32_t cba; + uint32_t cie; + } cs4280; + struct { + uint32_t dba0; + uint32_t dbc0; + uint32_t dmr0; + uint32_t dcr0; + uint32_t dba1; + uint32_t dbc1; + uint32_t dmr1; + uint32_t dcr1; + } cs4281; + } sc_suspend_state; /* CLKRUN hack (CS428X_FLAG_CLKRUN), only for CS4280 */ int sc_active; diff --git a/sys/dev/pci/ehci_pci.c b/sys/dev/pci/ehci_pci.c index 9d8d06cbdb9..943144bf4a2 100644 --- a/sys/dev/pci/ehci_pci.c +++ b/sys/dev/pci/ehci_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: ehci_pci.c,v 1.31 2007/10/19 12:00:43 ad Exp $ */ +/* $NetBSD: ehci_pci.c,v 1.32 2007/12/09 20:28:07 jmcneill Exp $ */ /* * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ehci_pci.c,v 1.31 2007/10/19 12:00:43 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ehci_pci.c,v 1.32 2007/12/09 20:28:07 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -69,16 +69,13 @@ extern int ehcidebug; static void ehci_get_ownership(ehci_softc_t *sc, pci_chipset_tag_t pc, pcitag_t tag); -static void ehci_pci_powerhook(int, void *); +static bool ehci_pci_resume(device_t); struct ehci_pci_softc { ehci_softc_t sc; pci_chipset_tag_t sc_pc; pcitag_t sc_tag; void *sc_ih; /* interrupt vectoring */ - - void *sc_powerhook; - struct pci_conf_state sc_pciconf; }; #define EHCI_MAX_BIOS_WAIT 1000 /* ms */ @@ -210,21 +207,15 @@ ehci_pci_attach(struct device *parent, struct device *self, void *aux) ehci_get_ownership(&sc->sc, pc, tag); - /* - * Establish our powerhook before ehci_init() does its powerhook. - */ - sc->sc_powerhook = powerhook_establish( - USBDEVNAME(sc->sc.sc_bus.bdev) , ehci_pci_powerhook, sc); - if (sc->sc_powerhook == NULL) - aprint_error("%s: couldn't establish powerhook\n", - devname); - r = ehci_init(&sc->sc); if (r != USBD_NORMAL_COMPLETION) { aprint_error("%s: init failed, error=%d\n", devname, r); return; } + if (!pmf_device_register(self, ehci_suspend, ehci_pci_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); + /* Attach usb device. */ sc->sc.sc_child = config_found((void *)sc, &sc->sc.sc_bus, usbctlprint); @@ -236,9 +227,7 @@ ehci_pci_detach(device_ptr_t self, int flags) struct ehci_pci_softc *sc = (struct ehci_pci_softc *)self; int rv; - if (sc->sc_powerhook != NULL) - powerhook_disestablish(sc->sc_powerhook); - + pmf_device_deregister(self); rv = ehci_detach(&sc->sc, flags); if (rv) return (rv); @@ -336,27 +325,11 @@ ehci_get_ownership(ehci_softc_t *sc, pci_chipset_tag_t pc, pcitag_t tag) } } -static void -ehci_pci_powerhook(int why, void *opaque) +static bool +ehci_pci_resume(device_t dv) { - struct ehci_pci_softc *sc; - pci_chipset_tag_t pc; - pcitag_t tag; - - sc = (struct ehci_pci_softc *)opaque; - pc = sc->sc_pc; - tag = sc->sc_tag; - - switch (why) { - case PWR_STANDBY: - case PWR_SUSPEND: - pci_conf_capture(pc, tag, &sc->sc_pciconf); - break; - case PWR_RESUME: - pci_conf_restore(pc, tag, &sc->sc_pciconf); - ehci_get_ownership(&sc->sc, pc, tag); - break; - } + struct ehci_pci_softc *sc = device_private(dv); - return; + ehci_get_ownership(&sc->sc, sc->sc_pc, sc->sc_tag); + return ehci_resume(dv); } diff --git a/sys/dev/pci/esa.c b/sys/dev/pci/esa.c index 396a56bd2e4..33ba3304cad 100644 --- a/sys/dev/pci/esa.c +++ b/sys/dev/pci/esa.c @@ -1,4 +1,4 @@ -/* $NetBSD: esa.c,v 1.42 2007/10/19 12:00:43 ad Exp $ */ +/* $NetBSD: esa.c,v 1.43 2007/12/09 20:28:07 jmcneill Exp $ */ /* * Copyright (c) 2001, 2002, 2006 Jared D. McNeill <jmcneill@invisible.ca> @@ -39,7 +39,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: esa.c,v 1.42 2007/10/19 12:00:43 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: esa.c,v 1.43 2007/12/09 20:28:07 jmcneill Exp $"); #include <sys/types.h> #include <sys/errno.h> @@ -162,9 +162,8 @@ static void esa_remove_list(struct esa_voice *, struct esa_list *, int); /* power management */ -static void esa_powerhook(int, void *); -static int esa_suspend(struct esa_softc *); -static int esa_resume(struct esa_softc *); +static bool esa_suspend(device_t); +static bool esa_resume(device_t); #define ESA_NENCODINGS 8 @@ -1136,11 +1135,8 @@ esa_attach(struct device *parent, struct device *self, void *aux) audio_attach_mi(&esa_hw_if, &sc->voice[i], &sc->sc_dev); } - sc->powerhook = powerhook_establish(sc->sc_dev.dv_xname, - esa_powerhook, sc); - if (sc->powerhook == NULL) - aprint_error("%s: WARNING: unable to establish powerhook\n", - sc->sc_dev.dv_xname); + if (!pmf_device_register(self, esa_suspend, esa_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); return; } @@ -1637,33 +1633,14 @@ esa_remove_list(struct esa_voice *vc, struct esa_list *el, int index) return; } -static void -esa_powerhook(int why, void *hdl) -{ - struct esa_softc *sc; - - sc = (struct esa_softc *)hdl; - switch (why) { - case PWR_SUSPEND: - case PWR_STANDBY: - esa_suspend(sc); - break; - case PWR_RESUME: - esa_resume(sc); - sc->codec_if->vtbl->restore_ports(sc->codec_if); - break; - } -} - -static int -esa_suspend(struct esa_softc *sc) +static bool +esa_suspend(device_t dv) { - bus_space_tag_t iot; - bus_space_handle_t ioh; + struct esa_softc *sc = device_private(dv); + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; int i, index; - iot = sc->sc_iot; - ioh = sc->sc_ioh; index = 0; bus_space_write_2(iot, ioh, ESA_HOST_INT_CTRL, 0); @@ -1681,19 +1658,18 @@ esa_suspend(struct esa_softc *sc) sc->savemem[index++] = esa_read_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, i); - return 0; + return true; } -static int -esa_resume(struct esa_softc *sc) +static bool +esa_resume(device_t dv) { - bus_space_tag_t iot; - bus_space_handle_t ioh; + struct esa_softc *sc = device_private(dv); + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; int i, index; uint8_t reset_state; - iot = sc->sc_iot; - ioh = sc->sc_ioh; index = 0; delay(10000); @@ -1721,7 +1697,7 @@ esa_resume(struct esa_softc *sc) esa_enable_interrupts(sc); esa_amp_enable(sc); - return 0; + return true; } static uint32_t diff --git a/sys/dev/pci/esavar.h b/sys/dev/pci/esavar.h index bc725c238e3..6e065c14cc8 100644 --- a/sys/dev/pci/esavar.h +++ b/sys/dev/pci/esavar.h @@ -1,4 +1,4 @@ -/* $NetBSD: esavar.h,v 1.8 2007/03/04 06:02:18 christos Exp $ */ +/* $NetBSD: esavar.h,v 1.9 2007/12/09 20:28:07 jmcneill Exp $ */ /* * Copyright (c) 2001, 2002 Jared D. McNeill <jmcneill@invisible.ca> @@ -132,6 +132,5 @@ struct esa_softc int type; /* Allegro-1 or Maestro 3? */ int delay1, delay2; - void *powerhook; uint16_t *savemem; }; diff --git a/sys/dev/pci/esm.c b/sys/dev/pci/esm.c index af6f11e37fa..25d90204b00 100644 --- a/sys/dev/pci/esm.c +++ b/sys/dev/pci/esm.c @@ -1,4 +1,4 @@ -/* $NetBSD: esm.c,v 1.43 2007/10/19 12:00:43 ad Exp $ */ +/* $NetBSD: esm.c,v 1.44 2007/12/09 20:28:07 jmcneill Exp $ */ /*- * Copyright (c) 2002, 2003 Matt Fredette @@ -66,7 +66,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: esm.c,v 1.43 2007/10/19 12:00:43 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: esm.c,v 1.44 2007/12/09 20:28:07 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -146,8 +146,8 @@ static void esmch_set_format(struct esm_chinfo *, static void esmch_combine_input(struct esm_softc *, struct esm_chinfo *); -/* Power Management */ -void esm_powerhook(int, void *); +static bool esm_suspend(device_t); +static bool esm_resume(device_t); CFATTACH_DECL(esm, sizeof(struct esm_softc), esm_match, esm_attach, NULL, NULL); @@ -1700,39 +1700,14 @@ esm_attach(struct device *parent, struct device *self, void *aux) audio_attach_mi(&esm_hw_if, self, &ess->sc_dev); - ess->esm_suspend = PWR_RESUME; - ess->esm_powerhook = powerhook_establish(ess->sc_dev.dv_xname, - esm_powerhook, ess); + if (!pmf_device_register(self, esm_suspend, esm_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } -/* Power Hook */ -void -esm_powerhook(int why, void *v) -{ - struct esm_softc *ess; - - ess = (struct esm_softc *)v; - DPRINTF(ESM_DEBUG_PARAM, - ("%s: ESS maestro 2E why=%d\n", ess->sc_dev.dv_xname, why)); - switch (why) { - case PWR_SUSPEND: - case PWR_STANDBY: - ess->esm_suspend = why; - esm_suspend(ess); - DPRINTF(ESM_DEBUG_RESUME, ("esm_suspend\n")); - break; - - case PWR_RESUME: - ess->esm_suspend = why; - esm_resume(ess); - DPRINTF(ESM_DEBUG_RESUME, ("esm_resumed\n")); - break; - } -} - -int -esm_suspend(struct esm_softc *ess) +static bool +esm_suspend(device_t dv) { + struct esm_softc *ess = device_private(dv); int x; x = splaudio(); @@ -1749,12 +1724,13 @@ esm_suspend(struct esm_softc *ess) bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 0); delay(1); - return 0; + return true; } -int -esm_resume(struct esm_softc *ess) +static bool +esm_resume(device_t dv) { + struct esm_softc *ess = device_private(dv); int x; uint16_t pcmbar; @@ -1787,21 +1763,6 @@ esm_resume(struct esm_softc *ess) wp_starttimer(ess); } splx(x); - return 0; -} - -#if 0 -int -esm_shutdown(struct esm_softc *ess) -{ - int i; - - wp_stoptimer(ess); - bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL, 0); - esm_halt_output(ess); - esm_halt_input(ess); - - return 0; + return true; } -#endif diff --git a/sys/dev/pci/esmvar.h b/sys/dev/pci/esmvar.h index 38ce882e0ce..188e1488b39 100644 --- a/sys/dev/pci/esmvar.h +++ b/sys/dev/pci/esmvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: esmvar.h,v 1.14 2007/03/04 06:02:18 christos Exp $ */ +/* $NetBSD: esmvar.h,v 1.15 2007/12/09 20:28:08 jmcneill Exp $ */ /*- * Copyright (c) 2002, 2003 Matt Fredette @@ -178,10 +178,6 @@ struct esm_softc { void (*sc_rintr)(void *); void *sc_rarg; - - /* Power Management */ - char esm_suspend; - void *esm_powerhook; }; enum esm_quirk_flags { @@ -202,7 +198,6 @@ int esm_attach_codec(void *, struct ac97_codec_if *); int esm_reset_codec(void *); enum ac97_host_flags esm_flags_codec(void *); -void esm_power(struct esm_softc *, int); void esm_init(struct esm_softc *); void esm_initcodec(struct esm_softc *); @@ -235,8 +230,4 @@ int esm_intr(void *); int esm_allocmem(struct esm_softc *, size_t, size_t, struct esm_dma *); -int esm_suspend(struct esm_softc *); -int esm_resume(struct esm_softc *); -int esm_shutdown(struct esm_softc *); - enum esm_quirk_flags esm_get_quirks(pcireg_t); diff --git a/sys/dev/pci/fwohci_pci.c b/sys/dev/pci/fwohci_pci.c index 9703d4e76aa..1c7c9719626 100644 --- a/sys/dev/pci/fwohci_pci.c +++ b/sys/dev/pci/fwohci_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: fwohci_pci.c,v 1.27 2007/11/06 15:24:10 kiyohara Exp $ */ +/* $NetBSD: fwohci_pci.c,v 1.28 2007/12/09 20:28:08 jmcneill Exp $ */ /*- * Copyright (c) 2000 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: fwohci_pci.c,v 1.27 2007/11/06 15:24:10 kiyohara Exp $"); +__KERNEL_RCSID(0, "$NetBSD: fwohci_pci.c,v 1.28 2007/12/09 20:28:08 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -62,17 +62,15 @@ struct fwohci_pci_softc { pci_chipset_tag_t psc_pc; pcitag_t psc_tag; - struct pci_conf_state psc_pciconf; void *psc_ih; - void *psc_shutdownhook; - void *psc_powerhook; }; static int fwohci_pci_match(struct device *, struct cfdata *, void *); static void fwohci_pci_attach(struct device *, struct device *, void *); -static void fwohci_pci_shutdown(void *); -static void fwohci_pci_power(int, void *); + +static bool fwohci_pci_suspend(device_t); +static bool fwohci_pci_resume(device_t); CFATTACH_DECL(fwohci_pci, sizeof(struct fwohci_pci_softc), fwohci_pci_match, fwohci_pci_attach, NULL, NULL); @@ -118,7 +116,7 @@ fwohci_pci_attach(struct device *parent, struct device *self, NULL, &psc->psc_sc.bssize)) { aprint_error("%s: can't map OHCI register space\n", self->dv_xname); - return; + goto fail; } /* Disable interrupts, so we don't get any spurious ones. */ @@ -132,7 +130,7 @@ fwohci_pci_attach(struct device *parent, struct device *self, /* Map and establish the interrupt. */ if (pci_intr_map(pa, &ih)) { aprint_error("%s: couldn't map interrupt\n", self->dv_xname); - return; + goto fail; } intrstr = pci_intr_string(pa->pa_pc, ih); psc->psc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, fwohci_filt, @@ -143,57 +141,51 @@ fwohci_pci_attach(struct device *parent, struct device *self, if (intrstr != NULL) aprint_normal(" at %s", intrstr); aprint_normal("\n"); - return; + goto fail; } aprint_normal("%s: interrupting at %s\n", self->dv_xname, intrstr); - psc->psc_shutdownhook = - shutdownhook_establish(fwohci_pci_shutdown, psc); - psc->psc_powerhook = - powerhook_establish(self->dv_xname, fwohci_pci_power, psc); + if (!pmf_device_register(self, fwohci_pci_suspend, fwohci_pci_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); if (fwohci_init(&(psc->psc_sc), &(psc->psc_sc.fc._dev)) != 0) { pci_intr_disestablish(pa->pa_pc, psc->psc_ih); bus_space_unmap(psc->psc_sc.bst, psc->psc_sc.bsh, psc->psc_sc.bssize); } + + return; + +fail: + /* In the event that we fail to attach, register a null pnp handler */ + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); + + return; } -static void -fwohci_pci_shutdown(void *arg) +static bool +fwohci_pci_suspend(device_t dv) { - struct fwohci_pci_softc *psc = arg; + struct fwohci_pci_softc *psc = device_private(dv); + int s; + s = splbio(); fwohci_stop(&psc->psc_sc, psc->psc_sc.fc.dev); + splx(s); + + return true; } -static void -fwohci_pci_power(int why, void *arg) +static bool +fwohci_pci_resume(device_t dv) { - struct fwohci_pci_softc *psc = arg; + struct fwohci_pci_softc *psc = device_private(dv); int s; s = splbio(); - switch (why) { - case PWR_SUSPEND: - case PWR_STANDBY: - printf("%s: suspending...\n", psc->psc_sc.fc._dev.dv_xname); - - pci_conf_capture(psc->psc_pc, psc->psc_tag, &psc->psc_pciconf); - fwohci_stop(&psc->psc_sc, psc->psc_sc.fc.dev); - break; - - case PWR_RESUME: - printf("%s: resuming...\n", psc->psc_sc.fc._dev.dv_xname); - - pci_conf_restore(psc->psc_pc, psc->psc_tag, &psc->psc_pciconf); - fwohci_resume(&psc->psc_sc, psc->psc_sc.fc.dev); - break; - - case PWR_SOFTSUSPEND: - case PWR_SOFTSTANDBY: - case PWR_SOFTRESUME: - break; - } + fwohci_resume(&psc->psc_sc, psc->psc_sc.fc.dev); splx(s); + + return true; } diff --git a/sys/dev/pci/ichsmb.c b/sys/dev/pci/ichsmb.c index bcd13d04aef..7f210d61693 100644 --- a/sys/dev/pci/ichsmb.c +++ b/sys/dev/pci/ichsmb.c @@ -1,4 +1,4 @@ -/* $NetBSD: ichsmb.c,v 1.10 2007/10/19 12:00:44 ad Exp $ */ +/* $NetBSD: ichsmb.c,v 1.11 2007/12/09 20:28:08 jmcneill Exp $ */ /* $OpenBSD: ichiic.c,v 1.18 2007/05/03 09:36:26 dlg Exp $ */ /* @@ -22,7 +22,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ichsmb.c,v 1.10 2007/10/19 12:00:44 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ichsmb.c,v 1.11 2007/12/09 20:28:08 jmcneill Exp $"); #include <sys/param.h> #include <sys/device.h> @@ -175,7 +175,8 @@ ichsmb_attach(struct device *parent, struct device *self, void *aux) iba.iba_tag = &sc->sc_i2c_tag; config_found(self, &iba, iicbus_print); - return; + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); } static int diff --git a/sys/dev/pci/if_an_pci.c b/sys/dev/pci/if_an_pci.c index 083974a0525..41ddad4aa46 100644 --- a/sys/dev/pci/if_an_pci.c +++ b/sys/dev/pci/if_an_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_an_pci.c,v 1.23 2007/10/19 12:00:44 ad Exp $ */ +/* $NetBSD: if_an_pci.c,v 1.24 2007/12/09 20:28:08 jmcneill Exp $ */ /* * Copyright (c) 2000 The NetBSD Foundation, Inc. @@ -43,7 +43,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_an_pci.c,v 1.23 2007/10/19 12:00:44 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_an_pci.c,v 1.24 2007/12/09 20:28:08 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -81,6 +81,8 @@ __KERNEL_RCSID(0, "$NetBSD: if_an_pci.c,v 1.23 2007/10/19 12:00:44 ad Exp $"); struct an_pci_softc { struct an_softc sc_an; /* real "an" softc */ + pci_chipset_tag_t sc_pct; + pcitag_t sc_pcitag; /* PCI-specific goo. */ void *sc_ih; /* interrupt handle */ @@ -130,6 +132,9 @@ an_pci_attach(struct device *parent, struct device *self, void *aux) bus_size_t iosize; u_int32_t csr; + psc->sc_pct = pa->pa_pc; + psc->sc_pcitag = pa->pa_tag; + aprint_naive(": 802.11 controller\n"); pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo)); @@ -171,4 +176,9 @@ an_pci_attach(struct device *parent, struct device *self, void *aux) pci_intr_disestablish(pa->pa_pc, psc->sc_ih); bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize); } + + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); + else + pmf_class_network_register(self, &sc->sc_if); } diff --git a/sys/dev/pci/if_ath_pci.c b/sys/dev/pci/if_ath_pci.c index 3516ee7056c..2445df619f0 100644 --- a/sys/dev/pci/if_ath_pci.c +++ b/sys/dev/pci/if_ath_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_ath_pci.c,v 1.21 2007/04/17 21:50:31 dyoung Exp $ */ +/* $NetBSD: if_ath_pci.c,v 1.22 2007/12/09 20:28:08 jmcneill Exp $ */ /*- * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting @@ -41,7 +41,7 @@ __FBSDID("$FreeBSD: src/sys/dev/ath/if_ath_pci.c,v 1.11 2005/01/18 18:08:16 sam Exp $"); #endif #ifdef __NetBSD__ -__KERNEL_RCSID(0, "$NetBSD: if_ath_pci.c,v 1.21 2007/04/17 21:50:31 dyoung Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_ath_pci.c,v 1.22 2007/12/09 20:28:08 jmcneill Exp $"); #endif /* @@ -84,22 +84,16 @@ struct ath_pci_softc { struct ath_softc sc_sc; pci_chipset_tag_t sc_pc; pcitag_t sc_pcitag; - struct pci_conf_state sc_pciconf; void *sc_ih; /* interrupt handler */ bus_space_tag_t sc_iot; bus_space_handle_t sc_ioh; - void *sc_sdhook; }; #define BS_BAR 0x10 -#define PCIR_RETRY_TIMEOUT_REG 0x40 -#define PCIR_RETRY_TIMEOUT_MASK __BITS(15,8) static void ath_pci_attach(struct device *, struct device *, void *); static int ath_pci_detach(struct device *, int); static int ath_pci_match(struct device *, struct cfdata *, void *); -static void ath_pci_shutdown(void *); -static void ath_pci_powerhook(int, void *); static int ath_pci_detach(struct device *, int); CFATTACH_DECL(ath_pci, @@ -109,8 +103,6 @@ CFATTACH_DECL(ath_pci, ath_pci_detach, NULL); -static int ath_pci_setup(struct pci_attach_args *); - static int ath_pci_match(struct device *parent, struct cfdata *match, void *aux) { @@ -123,34 +115,28 @@ ath_pci_match(struct device *parent, struct cfdata *match, void *aux) return 0; } -static void -ath_disable_retry(pci_chipset_tag_t pc, pcitag_t tag) +static bool +ath_pci_resume(device_t dv) { -#if 0 - pcireg_t retry; + struct ath_pci_softc *sc = device_private(dv); - /* - * Disable retry timeout to keep PCI Tx retries from - * interfering with ACPI C3 CPU state. - */ - retry = pci_conf_read(pc, tag, PCIR_RETRY_TIMEOUT_REG); - pci_conf_write(pc, tag, PCIR_RETRY_TIMEOUT_REG, - retry & ~PCIR_RETRY_TIMEOUT_MASK); -#endif + pci_disable_retry(sc->sc_pc, sc->sc_pcitag); + ath_resume(&sc->sc_sc); + + return true; } static int -ath_pci_setup(struct pci_attach_args *pa) +ath_pci_setup(struct ath_pci_softc *sc) { - pci_chipset_tag_t pc = pa->pa_pc; pcireg_t bhlc, csr, icr, lattimer; /* * Enable memory mapping and bus mastering. */ - pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, - pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG) | - PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_MEM_ENABLE); - csr = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); + csr = pci_conf_read(sc->sc_pc, sc->sc_pcitag, PCI_COMMAND_STATUS_REG); + csr |= PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_MEM_ENABLE; + pci_conf_write(sc->sc_pc, sc->sc_pcitag, PCI_COMMAND_STATUS_REG, csr); + csr = pci_conf_read(sc->sc_pc, sc->sc_pcitag, PCI_COMMAND_STATUS_REG); if ((csr & PCI_COMMAND_MEM_ENABLE) == 0) { aprint_error("couldn't enable memory mapping\n"); @@ -161,7 +147,7 @@ ath_pci_setup(struct pci_attach_args *pa) return 0; } - ath_disable_retry(pc, pa->pa_tag); + pci_disable_retry(sc->sc_pc, sc->sc_pcitag); /* * XXX Both this comment and code are replicated in @@ -184,13 +170,13 @@ ath_pci_setup(struct pci_attach_args *pa) * I never set a Latency Timer less than 0x10, since that * is what the old code did. */ - bhlc = pci_conf_read(pc, pa->pa_tag, PCI_BHLC_REG); - icr = pci_conf_read(pc, pa->pa_tag, PCI_INTERRUPT_REG); + bhlc = pci_conf_read(sc->sc_pc, sc->sc_pcitag, PCI_BHLC_REG); + icr = pci_conf_read(sc->sc_pc, sc->sc_pcitag, PCI_INTERRUPT_REG); lattimer = MAX(0x10, MIN(0xf8, 8 * PCI_MIN_GNT(icr))); if (PCI_LATTIMER(bhlc) < lattimer) { bhlc &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT); bhlc |= (lattimer << PCI_LATTIMER_SHIFT); - pci_conf_write(pc, pa->pa_tag, PCI_BHLC_REG, bhlc); + pci_conf_write(sc->sc_pc, sc->sc_pcitag, PCI_BHLC_REG, bhlc); } return 1; } @@ -204,15 +190,14 @@ ath_pci_attach(struct device *parent, struct device *self, void *aux) pci_chipset_tag_t pc = pa->pa_pc; pci_intr_handle_t ih; pcireg_t mem_type; - void *phook; const char *intrstr = NULL; psc->sc_pc = pc; psc->sc_pcitag = pa->pa_tag; - if (!ath_pci_setup(pa)) - goto bad; + if (!ath_pci_setup(psc)) + goto bad; /* * Setup memory-mapping of PCI registers. @@ -254,26 +239,15 @@ ath_pci_attach(struct device *parent, struct device *self, void *aux) sc->sc_dmat = pa->pa_dmat; - psc->sc_sdhook = shutdownhook_establish(ath_pci_shutdown, psc); - if (psc->sc_sdhook == NULL) { - aprint_error("couldn't make shutdown hook\n"); - goto bad3; - } - - phook = powerhook_establish(sc->sc_dev.dv_xname, - ath_pci_powerhook, psc); - if (phook == NULL) { - aprint_error("couldn't make power hook\n"); - goto bad3; - } + if (!pmf_device_register(self, NULL, ath_pci_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); + else + pmf_class_network_register(self, &sc->sc_if); if (ath_attach(PCI_PRODUCT(pa->pa_id), sc) == 0) return; - shutdownhook_disestablish(psc->sc_sdhook); - powerhook_disestablish(phook); - -bad3: pci_intr_disestablish(pc, psc->sc_ih); + pci_intr_disestablish(pc, psc->sc_ih); bad2: /* XXX */ bad1: /* XXX */ bad: @@ -285,40 +259,9 @@ ath_pci_detach(struct device *self, int flags) { struct ath_pci_softc *psc = (struct ath_pci_softc *)self; - shutdownhook_disestablish(psc->sc_sdhook); ath_detach(&psc->sc_sc); + pmf_device_deregister(self); pci_intr_disestablish(psc->sc_pc, psc->sc_ih); return (0); } - -static void -ath_pci_shutdown(void *self) -{ - struct ath_pci_softc *psc = (struct ath_pci_softc *)self; - - ath_shutdown(&psc->sc_sc); -} - -static void -ath_pci_powerhook(int why, void *arg) -{ - struct ath_pci_softc *sc = arg; - pci_chipset_tag_t pc = sc->sc_pc; - pcitag_t tag = sc->sc_pcitag; - - switch (why) { - case PWR_SOFTSUSPEND: - ath_pci_shutdown(sc); - break; - case PWR_SUSPEND: - pci_conf_capture(pc, tag, &sc->sc_pciconf); - break; - case PWR_RESUME: - pci_conf_restore(pc, tag, &sc->sc_pciconf); - ath_disable_retry(pc, tag); - break; - } - - return; -} diff --git a/sys/dev/pci/if_bge.c b/sys/dev/pci/if_bge.c index 1f3b28a99db..e5c3d228af4 100644 --- a/sys/dev/pci/if_bge.c +++ b/sys/dev/pci/if_bge.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_bge.c,v 1.140 2007/11/07 00:23:18 ad Exp $ */ +/* $NetBSD: if_bge.c,v 1.141 2007/12/09 20:28:08 jmcneill Exp $ */ /* * Copyright (c) 2001 Wind River Systems @@ -79,7 +79,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_bge.c,v 1.140 2007/11/07 00:23:18 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_bge.c,v 1.141 2007/12/09 20:28:08 jmcneill Exp $"); #include "bpfilter.h" #include "vlan.h" @@ -183,7 +183,6 @@ static int bge_rxthresh_nodenum; static int bge_probe(device_t, cfdata_t, void *); static void bge_attach(device_t, device_t, void *); -static void bge_powerhook(int, void *); static void bge_release_resources(struct bge_softc *); static void bge_txeof(struct bge_softc *); static void bge_rxeof(struct bge_softc *); @@ -196,9 +195,8 @@ static int bge_intr(void *); static void bge_start(struct ifnet *); static int bge_ioctl(struct ifnet *, u_long, void *); static int bge_init(struct ifnet *); -static void bge_stop(struct bge_softc *); +static void bge_stop(struct ifnet *, int); static void bge_watchdog(struct ifnet *); -static void bge_shutdown(void *); static int bge_ifmedia_upd(struct ifnet *); static void bge_ifmedia_sts(struct ifnet *, struct ifmediareq *); @@ -296,41 +294,34 @@ CFATTACH_DECL_NEW(bge, sizeof(struct bge_softc), static u_int32_t bge_readmem_ind(struct bge_softc *sc, int off) { - struct pci_attach_args *pa = &(sc->bge_pa); pcireg_t val; - pci_conf_write(pa->pa_pc, pa->pa_tag, BGE_PCI_MEMWIN_BASEADDR, off); - val = pci_conf_read(pa->pa_pc, pa->pa_tag, BGE_PCI_MEMWIN_DATA); + pci_conf_write(sc->sc_pc, sc->sc_pcitag, BGE_PCI_MEMWIN_BASEADDR, off); + val = pci_conf_read(sc->sc_pc, sc->sc_pcitag, BGE_PCI_MEMWIN_DATA); return val; } static void bge_writemem_ind(struct bge_softc *sc, int off, int val) { - struct pci_attach_args *pa = &(sc->bge_pa); - - pci_conf_write(pa->pa_pc, pa->pa_tag, BGE_PCI_MEMWIN_BASEADDR, off); - pci_conf_write(pa->pa_pc, pa->pa_tag, BGE_PCI_MEMWIN_DATA, val); + pci_conf_write(sc->sc_pc, sc->sc_pcitag, BGE_PCI_MEMWIN_BASEADDR, off); + pci_conf_write(sc->sc_pc, sc->sc_pcitag, BGE_PCI_MEMWIN_DATA, val); } #ifdef notdef static u_int32_t bge_readreg_ind(struct bge_softc *sc, int off) { - struct pci_attach_args *pa = &(sc->bge_pa); - - pci_conf_write(pa->pa_pc, pa->pa_tag, BGE_PCI_REG_BASEADDR, off); - return(pci_conf_read(pa->pa_pc, pa->pa_tag, BGE_PCI_REG_DATA)); + pci_conf_write(sc->sc_pc, sc->sc_pcitag, BGE_PCI_REG_BASEADDR, off); + return(pci_conf_read(sc->sc_pc, sc->sc_pcitag, BGE_PCI_REG_DATA)); } #endif static void bge_writereg_ind(struct bge_softc *sc, int off, int val) { - struct pci_attach_args *pa = &(sc->bge_pa); - - pci_conf_write(pa->pa_pc, pa->pa_tag, BGE_PCI_REG_BASEADDR, off); - pci_conf_write(pa->pa_pc, pa->pa_tag, BGE_PCI_REG_DATA, val); + pci_conf_write(sc->sc_pc, sc->sc_pcitag, BGE_PCI_REG_BASEADDR, off); + pci_conf_write(sc->sc_pc, sc->sc_pcitag, BGE_PCI_REG_DATA, val); } #ifdef notdef @@ -339,12 +330,11 @@ bge_vpd_readbyte(struct bge_softc *sc, int addr) { int i; u_int32_t val; - struct pci_attach_args *pa = &(sc->bge_pa); - pci_conf_write(pa->pa_pc, pa->pa_tag, BGE_PCI_VPD_ADDR, addr); + pci_conf_write(sc->sc_pc, sc->sc_pcitag, BGE_PCI_VPD_ADDR, addr); for (i = 0; i < BGE_TIMEOUT * 10; i++) { DELAY(10); - if (pci_conf_read(pa->pa_pc, pa->pa_tag, BGE_PCI_VPD_ADDR) & + if (pci_conf_read(sc->sc_pc, sc->sc_pcitag, BGE_PCI_VPD_ADDR) & BGE_VPD_FLAG) break; } @@ -354,7 +344,7 @@ bge_vpd_readbyte(struct bge_softc *sc, int addr) return(0); } - val = pci_conf_read(pa->pa_pc, pa->pa_tag, BGE_PCI_VPD_DATA); + val = pci_conf_read(sc->sc_pc, sc->sca_pcitag, BGE_PCI_VPD_DATA); return((val >> ((addr % 4) * 8)) & 0xFF); } @@ -1220,11 +1210,10 @@ bge_chipinit(struct bge_softc *sc) u_int32_t cachesize; int i; u_int32_t dma_rw_ctl; - struct pci_attach_args *pa = &(sc->bge_pa); /* Set endianness before we access any non-PCI registers. */ - pci_conf_write(pa->pa_pc, pa->pa_tag, BGE_PCI_MISC_CTL, + pci_conf_write(sc->sc_pc, sc->sc_pcitag, BGE_PCI_MISC_CTL, BGE_INIT); /* Set power state to D0. */ @@ -1249,11 +1238,11 @@ bge_chipinit(struct bge_softc *sc) */ for (i = BGE_STATS_BLOCK; i < BGE_STATS_BLOCK_END + 1; i += sizeof(u_int32_t)) - BGE_MEMWIN_WRITE(pa->pa_pc, pa->pa_tag, i, 0); + BGE_MEMWIN_WRITE(sc->sc_pc, sc->sc_pcitag, i, 0); for (i = BGE_STATUS_BLOCK; i < BGE_STATUS_BLOCK_END + 1; i += sizeof(u_int32_t)) - BGE_MEMWIN_WRITE(pa->pa_pc, pa->pa_tag, i, 0); + BGE_MEMWIN_WRITE(sc->sc_pc, sc->sc_pcitag, i, 0); /* Set up the PCI DMA control register. */ if (sc->bge_pcie) { @@ -1271,7 +1260,7 @@ bge_chipinit(struct bge_softc *sc) #define DMA_CTRL_WRITE_PCIE_H20MARK_256 0x00380000 dma_rw_ctl = 0x76000000; /* XXX XXX XXX */; - device_ctl = pci_conf_read(pa->pa_pc, pa->pa_tag, + device_ctl = pci_conf_read(sc->sc_pc, sc->sc_pcitag, BGE_PCI_CONF_DEV_CTRL); aprint_debug_dev(sc->bge_dev, "pcie mode=0x%x\n", device_ctl); @@ -1287,7 +1276,7 @@ bge_chipinit(struct bge_softc *sc) } else { dma_rw_ctl |= BGE_PCIDMA_RWCTL_PCIE_WRITE_WATRMARK_128; } - } else if (pci_conf_read(pa->pa_pc, pa->pa_tag,BGE_PCI_PCISTATE) & + } else if (pci_conf_read(sc->sc_pc, sc->sc_pcitag,BGE_PCI_PCISTATE) & BGE_PCISTATE_PCI_BUSMODE) { /* Conventional PCI bus */ DPRINTFN(4, ("(%s: PCI 2.2 DMA setting)\n", @@ -1335,7 +1324,7 @@ bge_chipinit(struct bge_softc *sc) } } - pci_conf_write(pa->pa_pc, pa->pa_tag, BGE_PCI_DMA_RW_CTL, dma_rw_ctl); + pci_conf_write(sc->sc_pc, sc->sc_pcitag, BGE_PCI_DMA_RW_CTL, dma_rw_ctl); /* * Set up general mode register. @@ -1345,40 +1334,40 @@ bge_chipinit(struct bge_softc *sc) BGE_MODECTL_TX_NO_PHDR_CSUM|BGE_MODECTL_RX_NO_PHDR_CSUM); /* Get cache line size. */ - cachesize = pci_conf_read(pa->pa_pc, pa->pa_tag, BGE_PCI_CACHESZ); + cachesize = pci_conf_read(sc->sc_pc, sc->sc_pcitag, BGE_PCI_CACHESZ); /* * Avoid violating PCI spec on certain chip revs. */ - if (pci_conf_read(pa->pa_pc, pa->pa_tag, BGE_PCI_CMD) & + if (pci_conf_read(sc->sc_pc, sc->sc_pcitag, BGE_PCI_CMD) & PCIM_CMD_MWIEN) { switch(cachesize) { case 1: - PCI_SETBIT(pa->pa_pc, pa->pa_tag, BGE_PCI_DMA_RW_CTL, + PCI_SETBIT(sc->sc_pc, sc->sc_pcitag, BGE_PCI_DMA_RW_CTL, BGE_PCI_WRITE_BNDRY_16BYTES); break; case 2: - PCI_SETBIT(pa->pa_pc, pa->pa_tag, BGE_PCI_DMA_RW_CTL, + PCI_SETBIT(sc->sc_pc, sc->sc_pcitag, BGE_PCI_DMA_RW_CTL, BGE_PCI_WRITE_BNDRY_32BYTES); break; case 4: - PCI_SETBIT(pa->pa_pc, pa->pa_tag, BGE_PCI_DMA_RW_CTL, + PCI_SETBIT(sc->sc_pc, sc->sc_pcitag, BGE_PCI_DMA_RW_CTL, BGE_PCI_WRITE_BNDRY_64BYTES); break; case 8: - PCI_SETBIT(pa->pa_pc, pa->pa_tag, BGE_PCI_DMA_RW_CTL, + PCI_SETBIT(sc->sc_pc, sc->sc_pcitag, BGE_PCI_DMA_RW_CTL, BGE_PCI_WRITE_BNDRY_128BYTES); break; case 16: - PCI_SETBIT(pa->pa_pc, pa->pa_tag, BGE_PCI_DMA_RW_CTL, + PCI_SETBIT(sc->sc_pc, sc->sc_pcitag, BGE_PCI_DMA_RW_CTL, BGE_PCI_WRITE_BNDRY_256BYTES); break; case 32: - PCI_SETBIT(pa->pa_pc, pa->pa_tag, BGE_PCI_DMA_RW_CTL, + PCI_SETBIT(sc->sc_pc, sc->sc_pcitag, BGE_PCI_DMA_RW_CTL, BGE_PCI_WRITE_BNDRY_512BYTES); break; case 64: - PCI_SETBIT(pa->pa_pc, pa->pa_tag, BGE_PCI_DMA_RW_CTL, + PCI_SETBIT(sc->sc_pc, sc->sc_pcitag, BGE_PCI_DMA_RW_CTL, BGE_PCI_WRITE_BNDRY_1024BYTES); break; default: @@ -1389,7 +1378,7 @@ bge_chipinit(struct bge_softc *sc) "cache line size %d not supported " "disabling PCI MWI\n", #endif - PCI_CLRBIT(pa->pa_pc, pa->pa_tag, BGE_PCI_CMD, + PCI_CLRBIT(sc->sc_pc, sc->sc_pcitag, BGE_PCI_CMD, PCIM_CMD_MWIEN); break; } @@ -1399,7 +1388,7 @@ bge_chipinit(struct bge_softc *sc) * Disable memory write invalidate. Apparently it is not supported * properly by these devices. */ - PCI_CLRBIT(pa->pa_pc, pa->pa_tag, BGE_PCI_CMD, PCIM_CMD_MWIEN); + PCI_CLRBIT(sc->sc_pc, sc->sc_pcitag, BGE_PCI_CMD, PCIM_CMD_MWIEN); #ifdef __brokenalpha__ @@ -1434,8 +1423,7 @@ bge_blockinit(struct bge_softc *sc) * ring RCBs, plus other things which live in NIC memory. */ - pci_conf_write(sc->bge_pa.pa_pc, sc->bge_pa.pa_tag, - BGE_PCI_MEMWIN_BASEADDR, 0); + pci_conf_write(sc->sc_pc, sc->sc_pcitag, BGE_PCI_MEMWIN_BASEADDR, 0); /* Configure mbuf memory pool */ if ((sc->bge_quirks & BGE_QUIRK_5705_CORE) == 0) { @@ -2424,7 +2412,7 @@ bge_attach(device_t parent, device_t self, void *aux) struct pci_attach_args *pa = aux; const struct bge_product *bp; const struct bge_revision *br; - pci_chipset_tag_t pc = pa->pa_pc; + pci_chipset_tag_t pc = sc->sc_pc; pci_intr_handle_t ih; const char *intrstr = NULL; bus_dma_segment_t seg; @@ -2443,8 +2431,9 @@ bge_attach(device_t parent, device_t self, void *aux) bp = bge_lookup(pa); KASSERT(bp != NULL); + sc->sc_pc = pa->pa_pc; + sc->sc_pcitag = pa->pa_tag; sc->bge_dev = self; - sc->bge_pa = *pa; aprint_naive(": Ethernet controller\n"); aprint_normal(": %s\n", bp->bp_name); @@ -2453,10 +2442,10 @@ bge_attach(device_t parent, device_t self, void *aux) * Map control/status registers. */ DPRINTFN(5, ("Map control/status regs\n")); - command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); + command = pci_conf_read(pc, sc->sc_pcitag, PCI_COMMAND_STATUS_REG); command |= PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE; - pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, command); - command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); + pci_conf_write(pc, sc->sc_pcitag, PCI_COMMAND_STATUS_REG, command); + command = pci_conf_read(pc, sc->sc_pcitag, PCI_COMMAND_STATUS_REG); if (!(command & PCI_COMMAND_MEM_ENABLE)) { aprint_error_dev(sc->bge_dev, @@ -2465,7 +2454,7 @@ bge_attach(device_t parent, device_t self, void *aux) } DPRINTFN(5, ("pci_mem_find\n")); - memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, BGE_PCI_BAR0); + memtype = pci_mapreg_type(sc->sc_pc, sc->sc_pcitag, BGE_PCI_BAR0); switch (memtype) { case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT: case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT: @@ -2505,10 +2494,10 @@ bge_attach(device_t parent, device_t self, void *aux) * We do not have memory-mapped registers in this state, * so force device into D0 state before starting initialization. */ - pm_ctl = pci_conf_read(pc, pa->pa_tag, BGE_PCI_PWRMGMT_CMD); + pm_ctl = pci_conf_read(pc, sc->sc_pcitag, BGE_PCI_PWRMGMT_CMD); pm_ctl &= ~(PCI_PWR_D0|PCI_PWR_D1|PCI_PWR_D2|PCI_PWR_D3); pm_ctl |= (1 << 8) | PCI_PWR_D0 ; /* D0 state */ - pci_conf_write(pc, pa->pa_tag, BGE_PCI_PWRMGMT_CMD, pm_ctl); + pci_conf_write(pc, sc->sc_pcitag, BGE_PCI_PWRMGMT_CMD, pm_ctl); DELAY(1000); /* 27 usec is allegedly sufficent */ /* @@ -2516,14 +2505,14 @@ bge_attach(device_t parent, device_t self, void *aux) * ASIC. */ sc->bge_chipid = - pci_conf_read(pa->pa_pc, pa->pa_tag, BGE_PCI_MISC_CTL) & + pci_conf_read(sc->sc_pc, sc->sc_pcitag, BGE_PCI_MISC_CTL) & BGE_PCIMISCCTL_ASICREV; /* * Detect PCI-Express devices * XXX: guessed from Linux/FreeBSD; no documentation */ - if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_PCIEXPRESS, + if (pci_get_capability(sc->sc_pc, sc->sc_pcitag, PCI_CAP_PCIEXPRESS, NULL, NULL) != 0) sc->bge_pcie = 1; else @@ -2651,6 +2640,7 @@ bge_attach(device_t parent, device_t self, void *aux) ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = bge_ioctl; + ifp->if_stop = bge_stop; ifp->if_start = bge_start; ifp->if_init = bge_init; ifp->if_watchdog = bge_watchdog; @@ -2698,7 +2688,7 @@ bge_attach(device_t parent, device_t self, void *aux) sc->bge_tbi = 1; /* The SysKonnect SK-9D41 is a 1000baseSX card. */ - if ((pci_conf_read(pa->pa_pc, pa->pa_tag, BGE_PCI_SUBSYS) >> 16) == + if ((pci_conf_read(sc->sc_pc, sc->sc_pcitag, BGE_PCI_SUBSYS) >> 16) == SK_SUBSYSID_9D41) sc->bge_tbi = 1; @@ -2741,7 +2731,7 @@ bge_attach(device_t parent, device_t self, void *aux) */ if (sc->bge_quirks & BGE_QUIRK_PCIX_DMA_ALIGN_BUG) { /* If in PCI-X mode, work around the alignment bug. */ - if ((pci_conf_read(pa->pa_pc, pa->pa_tag, BGE_PCI_PCISTATE) & + if ((pci_conf_read(sc->sc_pc, sc->sc_pcitag, BGE_PCI_PCISTATE) & (BGE_PCISTATE_PCI_BUSMODE | BGE_PCISTATE_PCI_BUSSPEED)) == BGE_PCISTATE_PCI_BUSSPEED) sc->bge_rx_alignment_bug = 1; @@ -2776,11 +2766,10 @@ bge_attach(device_t parent, device_t self, void *aux) DPRINTFN(5, ("callout_init\n")); callout_init(&sc->bge_timeout, 0); - sc->bge_powerhook = powerhook_establish(device_xname(sc->bge_dev), - bge_powerhook, sc); - if (sc->bge_powerhook == NULL) - aprint_error_dev(sc->bge_dev, - "unable to establish PCI power hook\n"); + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); + else + pmf_class_network_register(self, ifp); } static void @@ -2796,16 +2785,15 @@ bge_release_resources(struct bge_softc *sc) static void bge_reset(struct bge_softc *sc) { - struct pci_attach_args *pa = &sc->bge_pa; u_int32_t cachesize, command, pcistate, new_pcistate; int i, val; /* Save some important PCI state. */ - cachesize = pci_conf_read(pa->pa_pc, pa->pa_tag, BGE_PCI_CACHESZ); - command = pci_conf_read(pa->pa_pc, pa->pa_tag, BGE_PCI_CMD); - pcistate = pci_conf_read(pa->pa_pc, pa->pa_tag, BGE_PCI_PCISTATE); + cachesize = pci_conf_read(sc->sc_pc, sc->sc_pcitag, BGE_PCI_CACHESZ); + command = pci_conf_read(sc->sc_pc, sc->sc_pcitag, BGE_PCI_CMD); + pcistate = pci_conf_read(sc->sc_pc, sc->sc_pcitag, BGE_PCI_PCISTATE); - pci_conf_write(pa->pa_pc, pa->pa_tag, BGE_PCI_MISC_CTL, + pci_conf_write(sc->sc_pc, sc->sc_pcitag, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_INDIRECT_ACCESS|BGE_PCIMISCCTL_MASK_PCI_INTR| BGE_HIF_SWAP_OPTIONS|BGE_PCIMISCCTL_PCISTATE_RW); @@ -2846,8 +2834,8 @@ bge_reset(struct bge_softc *sc) DELAY(500000); /* XXX: Magic Numbers */ - reg = pci_conf_read(pa->pa_pc, pa->pa_tag, BGE_PCI_UNKNOWN0); - pci_conf_write(pa->pa_pc, pa->pa_tag, BGE_PCI_UNKNOWN0, + reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, BGE_PCI_UNKNOWN0); + pci_conf_write(sc->sc_pc, sc->sc_pcitag, BGE_PCI_UNKNOWN0, reg | (1 << 15)); } /* @@ -2856,17 +2844,17 @@ bge_reset(struct bge_softc *sc) * Should be replaced with references to PCI config-space * capability block for PCI-Express. */ - pci_conf_write(pa->pa_pc, pa->pa_tag, + pci_conf_write(sc->sc_pc, sc->sc_pcitag, BGE_PCI_CONF_DEV_CTRL, 0xf5000); } /* Reset some of the PCI state that got zapped by reset */ - pci_conf_write(pa->pa_pc, pa->pa_tag, BGE_PCI_MISC_CTL, + pci_conf_write(sc->sc_pc, sc->sc_pcitag, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_INDIRECT_ACCESS|BGE_PCIMISCCTL_MASK_PCI_INTR| BGE_HIF_SWAP_OPTIONS|BGE_PCIMISCCTL_PCISTATE_RW); - pci_conf_write(pa->pa_pc, pa->pa_tag, BGE_PCI_CMD, command); - pci_conf_write(pa->pa_pc, pa->pa_tag, BGE_PCI_CACHESZ, cachesize); + pci_conf_write(sc->sc_pc, sc->sc_pcitag, BGE_PCI_CMD, command); + pci_conf_write(sc->sc_pc, sc->sc_pcitag, BGE_PCI_CACHESZ, cachesize); bge_writereg_ind(sc, BGE_MISC_CFG, (65 << 1)); /* Enable memory arbiter. */ @@ -2918,7 +2906,7 @@ bge_reset(struct bge_softc *sc) * results. */ for (i = 0; i < 10000; i++) { - new_pcistate = pci_conf_read(pa->pa_pc, pa->pa_tag, + new_pcistate = pci_conf_read(sc->sc_pc, sc->sc_pcitag, BGE_PCI_PCISTATE); if ((new_pcistate & ~BGE_PCISTATE_RESERVED) == (pcistate & ~BGE_PCISTATE_RESERVED)) @@ -3943,7 +3931,7 @@ bge_init(struct ifnet *ifp) ifp = &sc->ethercom.ec_if; /* Cancel pending I/O and flush buffers. */ - bge_stop(sc); + bge_stop(ifp, 0); bge_reset(sc); bge_chipinit(sc); @@ -4123,9 +4111,8 @@ bge_ioctl(struct ifnet *ifp, u_long command, void *data) } else if (!(sc->bge_if_flags & IFF_UP)) bge_init(ifp); } else { - if (ifp->if_flags & IFF_RUNNING) { - bge_stop(sc); - } + if (ifp->if_flags & IFF_RUNNING) + bge_stop(ifp, 1); } sc->bge_if_flags = ifp->if_flags; error = 0; @@ -4215,9 +4202,9 @@ bge_stop_block(struct bge_softc *sc, bus_addr_t reg, uint32_t bit) * RX and TX lists. */ static void -bge_stop(struct bge_softc *sc) +bge_stop(struct ifnet *ifp, int disable) { - struct ifnet *ifp = &sc->ethercom.ec_if; + struct bge_softc *sc = ifp->if_softc; callout_stop(&sc->bge_timeout); @@ -4296,20 +4283,6 @@ bge_stop(struct bge_softc *sc) ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); } -/* - * Stop all chip I/O so that the kernel's probe routines don't - * get confused by errant DMAs when rebooting. - */ -static void -bge_shutdown(void *xsc) -{ - struct bge_softc *sc = (struct bge_softc *)xsc; - - bge_stop(sc); - bge_reset(sc); -} - - static int sysctl_bge_verify(SYSCTLFN_ARGS) { @@ -4384,35 +4357,3 @@ SYSCTL_SETUP(sysctl_bge, "sysctl bge subtree setup") err: aprint_error("%s: sysctl_createv failed (rc = %d)\n", __func__, rc); } - -static void -bge_powerhook(int why, void *hdl) -{ - struct bge_softc *sc = (struct bge_softc *)hdl; - struct ifnet *ifp = &sc->ethercom.ec_if; - struct pci_attach_args *pa = &(sc->bge_pa); - pci_chipset_tag_t pc = pa->pa_pc; - pcitag_t tag = pa->pa_tag; - - switch (why) { - case PWR_SOFTSUSPEND: - case PWR_SOFTSTANDBY: - bge_shutdown(sc); - break; - case PWR_SOFTRESUME: - if (ifp->if_flags & IFF_UP) { - ifp->if_flags &= ~IFF_RUNNING; - bge_init(ifp); - } - break; - case PWR_SUSPEND: - case PWR_STANDBY: - pci_conf_capture(pc, tag, &sc->bge_pciconf); - break; - case PWR_RESUME: - pci_conf_restore(pc, tag, &sc->bge_pciconf); - break; - } - - return; -} diff --git a/sys/dev/pci/if_bgereg.h b/sys/dev/pci/if_bgereg.h index a643ca3bb8a..edc459bcbc1 100644 --- a/sys/dev/pci/if_bgereg.h +++ b/sys/dev/pci/if_bgereg.h @@ -1,4 +1,4 @@ -/* $NetBSD: if_bgereg.h,v 1.44 2007/09/24 21:25:45 joerg Exp $ */ +/* $NetBSD: if_bgereg.h,v 1.45 2007/12/09 20:28:08 jmcneill Exp $ */ /* * Copyright (c) 2001 Wind River Systems * Copyright (c) 1997, 1998, 1999, 2001 @@ -2385,7 +2385,9 @@ struct bge_softc { bus_space_handle_t bge_bhandle; bus_space_tag_t bge_btag; void *bge_intrhand; - struct pci_attach_args bge_pa; + pci_chipset_tag_t sc_pc; + pcitag_t sc_pcitag; + struct mii_data bge_mii; struct ifmedia bge_ifmedia; /* media info */ u_int8_t bge_extram; /* has external SSRAM */ @@ -2437,6 +2439,4 @@ struct bge_softc { int bge_pending_rxintr_change; SLIST_HEAD(, txdmamap_pool_entry) txdma_list; struct txdmamap_pool_entry *txdma[BGE_TX_RING_CNT]; - void *bge_powerhook; - struct pci_conf_state bge_pciconf; }; diff --git a/sys/dev/pci/if_ipw.c b/sys/dev/pci/if_ipw.c index 9c28578fe4b..5595a48fabc 100644 --- a/sys/dev/pci/if_ipw.c +++ b/sys/dev/pci/if_ipw.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_ipw.c,v 1.34 2007/10/19 12:00:45 ad Exp $ */ +/* $NetBSD: if_ipw.c,v 1.35 2007/12/09 20:28:09 jmcneill Exp $ */ /* FreeBSD: src/sys/dev/ipw/if_ipw.c,v 1.15 2005/11/13 17:17:40 damien Exp */ /*- @@ -29,7 +29,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_ipw.c,v 1.34 2007/10/19 12:00:45 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_ipw.c,v 1.35 2007/12/09 20:28:09 jmcneill Exp $"); /*- * Intel(R) PRO/Wireless 2100 MiniPCI driver @@ -94,10 +94,7 @@ static int ipw_match(struct device *, struct cfdata *, void *); static void ipw_attach(struct device *, struct device *, void *); static int ipw_detach(struct device *, int); -static void ipw_shutdown(void *); -static int ipw_suspend(struct ipw_softc *); -static int ipw_resume(struct ipw_softc *); -static void ipw_powerhook(int, void *); +static bool ipw_resume(device_t); static int ipw_media_change(struct ifnet *); static void ipw_media_status(struct ifnet *, struct ifmediareq *); @@ -204,10 +201,7 @@ ipw_attach(struct device *parent, struct device *self, void *aux) data |= PCI_COMMAND_MASTER_ENABLE; pci_conf_write(sc->sc_pct, pa->pa_tag, PCI_COMMAND_STATUS_REG, data); - /* clear device specific PCI configuration register 0x41 */ - data = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40); - data &= ~0x0000ff00; - pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, data); + pci_disable_retry(sc->sc_pct, sc->sc_pcitag); /* map the register window */ error = pci_mapreg_map(pa, IPW_PCI_BAR0, PCI_MAPREG_TYPE_MEM | @@ -340,18 +334,10 @@ ipw_attach(struct device *parent, struct device *self, void *aux) */ sc->dwelltime = 100; - /* - * Make sure the interface is shutdown during reboot. - */ - sc->sc_sdhook = shutdownhook_establish(ipw_shutdown, sc); - if (sc->sc_sdhook == NULL) - aprint_error("%s: WARNING: unable to establish shutdown hook\n", - sc->sc_dev.dv_xname); - sc->sc_powerhook = powerhook_establish(sc->sc_dev.dv_xname, - ipw_powerhook, sc); - if (sc->sc_powerhook == NULL) - printf("%s: WARNING: unable to establish power hook\n", - sc->sc_dev.dv_xname); + if (!pmf_device_register(self, NULL, ipw_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); + else + pmf_class_network_register(self, ifp); ieee80211_announce(ic); @@ -756,67 +742,14 @@ ipw_release(struct ipw_softc *sc) } -static void -ipw_shutdown(void *arg) +static bool +ipw_resume(device_t dv) { - struct ipw_softc *sc = (struct ipw_softc *)arg; - struct ifnet *ifp = sc->sc_ic.ic_ifp; + struct ipw_softc *sc = device_private(dv); - ipw_stop(ifp, 1); -} + pci_disable_retry(sc->sc_pct, sc->sc_pcitag); - -static int -ipw_suspend(struct ipw_softc *sc) -{ - struct ifnet *ifp = sc->sc_ic.ic_ifp; - - ipw_stop(ifp, 1); - - return 0; -} - -static int -ipw_resume(struct ipw_softc *sc) -{ - struct ifnet *ifp = sc->sc_ic.ic_ifp; - pcireg_t data; - - /* clear device specific PCI configuration register 0x41 */ - data = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40); - data &= ~0x0000ff00; - pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, data); - - if (ifp->if_flags & IFF_UP) { - ipw_init(ifp); - if (ifp->if_flags & IFF_RUNNING) - ipw_start(ifp); - } - - return 0; -} - -static void -ipw_powerhook(int why, void *arg) -{ - struct ipw_softc *sc = arg; - int s; - - s = splnet(); - switch (why) { - case PWR_SUSPEND: - case PWR_STANDBY: - ipw_suspend(sc); - break; - case PWR_RESUME: - ipw_resume(sc); - break; - case PWR_SOFTSUSPEND: - case PWR_SOFTSTANDBY: - case PWR_SOFTRESUME: - break; - } - splx(s); + return true; } static int diff --git a/sys/dev/pci/if_ipwvar.h b/sys/dev/pci/if_ipwvar.h index 53afc561a4c..a71c4a07c85 100644 --- a/sys/dev/pci/if_ipwvar.h +++ b/sys/dev/pci/if_ipwvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: if_ipwvar.h,v 1.11 2006/04/17 20:57:24 rpaulo Exp $ */ +/* $NetBSD: if_ipwvar.h,v 1.12 2007/12/09 20:28:09 jmcneill Exp $ */ /*- * Copyright (c) 2004 @@ -109,9 +109,6 @@ struct ipw_softc { pcitag_t sc_pcitag; bus_size_t sc_sz; - void *sc_sdhook; /* shutdown hook */ - void *sc_powerhook; /* power management hook */ - int sc_tx_timer; bus_dma_tag_t sc_dmat; diff --git a/sys/dev/pci/if_iwi.c b/sys/dev/pci/if_iwi.c index 9c7365af277..906360e800b 100644 --- a/sys/dev/pci/if_iwi.c +++ b/sys/dev/pci/if_iwi.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_iwi.c,v 1.67 2007/10/22 15:31:46 joerg Exp $ */ +/* $NetBSD: if_iwi.c,v 1.68 2007/12/09 20:28:09 jmcneill Exp $ */ /*- * Copyright (c) 2004, 2005 @@ -28,7 +28,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_iwi.c,v 1.67 2007/10/22 15:31:46 joerg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_iwi.c,v 1.68 2007/12/09 20:28:09 jmcneill Exp $"); /*- * Intel(R) PRO/Wireless 2200BG/2225BG/2915ABG driver @@ -94,11 +94,6 @@ static int iwi_match(device_t, struct cfdata *, void *); static void iwi_attach(device_t, device_t, void *); static int iwi_detach(device_t, int); -static void iwi_shutdown(void *); -static int iwi_suspend(struct iwi_softc *); -static int iwi_resume(struct iwi_softc *); -static void iwi_powerhook(int, void *); - static int iwi_alloc_cmd_ring(struct iwi_softc *, struct iwi_cmd_ring *, int); static void iwi_reset_cmd_ring(struct iwi_softc *, struct iwi_cmd_ring *); @@ -206,6 +201,16 @@ iwi_match(device_t parent, struct cfdata *match, void *aux) return 0; } +static bool +iwi_pci_resume(device_t dv) +{ + struct iwi_softc *sc = device_private(dv); + + pci_disable_retry(sc->sc_pct, sc->sc_pcitag); + + return true; +} + /* Base Address Register */ #define IWI_PCI_BAR0 0x10 @@ -233,10 +238,7 @@ iwi_attach(device_t parent, device_t self, void *aux) revision = PCI_REVISION(pa->pa_class); aprint_normal(": %s (rev. 0x%02x)\n", devinfo, revision); - /* clear device specific PCI configuration register 0x41 */ - data = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40); - data &= ~0x0000ff00; - pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, data); + pci_disable_retry(sc->sc_pct, sc->sc_pcitag); /* clear unit numbers allocated to IBSS */ sc->sc_unr = 0; @@ -435,18 +437,10 @@ iwi_attach(device_t parent, device_t self, void *aux) iwi_sysctlattach(sc); - /* - * Make sure the interface is shutdown during reboot. - */ - sc->sc_sdhook = shutdownhook_establish(iwi_shutdown, sc); - if (sc->sc_sdhook == NULL) - aprint_error_dev(self, - "WARNING: unable to establish shutdown hook\n"); - sc->sc_powerhook = powerhook_establish(device_xname(self), - iwi_powerhook, sc); - if (sc->sc_powerhook == NULL) - aprint_error_dev(self, - "WARNING: unable to establish power hook\n"); + if (!pmf_device_register(self, NULL, iwi_pci_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); + else + pmf_class_network_register(self, ifp); ieee80211_announce(ic); @@ -461,6 +455,8 @@ iwi_detach(device_t self, int flags) struct iwi_softc *sc = device_private(self); struct ifnet *ifp = &sc->sc_if; + pmf_device_deregister(self); + if (ifp != NULL) iwi_stop(ifp, 1); @@ -484,9 +480,6 @@ iwi_detach(device_t self, int flags) bus_space_unmap(sc->sc_st, sc->sc_sh, sc->sc_sz); - powerhook_disestablish(sc->sc_powerhook); - shutdownhook_disestablish(sc->sc_sdhook); - return 0; } @@ -784,73 +777,6 @@ iwi_free_rx_ring(struct iwi_softc *sc, struct iwi_rx_ring *ring) } } -static void -iwi_shutdown(void *arg) -{ - struct iwi_softc *sc = (struct iwi_softc *)arg; - struct ifnet *ifp = sc->sc_ic.ic_ifp; - - iwi_stop(ifp, 1); -} - -static int -iwi_suspend(struct iwi_softc *sc) -{ - struct ifnet *ifp = sc->sc_ic.ic_ifp; - - iwi_stop(ifp, 1); - - return 0; -} - -static int -iwi_resume(struct iwi_softc *sc) -{ - struct ifnet *ifp = sc->sc_ic.ic_ifp; - pcireg_t data; - - /* clear device specific PCI configuration register 0x41 */ - data = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40); - data &= ~0x0000ff00; - pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, data); - - if (ifp->if_flags & IFF_UP) { - iwi_init(ifp); - if (ifp->if_flags & IFF_RUNNING) - iwi_start(ifp); - } - - return 0; -} - -static void -iwi_powerhook(int why, void *arg) -{ - struct iwi_softc *sc = arg; - pci_chipset_tag_t pc = sc->sc_pct; - pcitag_t tag = sc->sc_pcitag; - int s; - - s = splnet(); - switch (why) { - case PWR_SUSPEND: - case PWR_STANDBY: - pci_conf_capture(pc, tag, &sc->sc_pciconf); - break; - case PWR_RESUME: - pci_conf_restore(pc, tag, &sc->sc_pciconf); - break; - case PWR_SOFTSUSPEND: - case PWR_SOFTSTANDBY: - iwi_suspend(sc); - break; - case PWR_SOFTRESUME: - iwi_resume(sc); - break; - } - splx(s); -} - static struct ieee80211_node * iwi_node_alloc(struct ieee80211_node_table *nt) { diff --git a/sys/dev/pci/if_iwivar.h b/sys/dev/pci/if_iwivar.h index 0ada21412d8..ea55920d05d 100644 --- a/sys/dev/pci/if_iwivar.h +++ b/sys/dev/pci/if_iwivar.h @@ -1,4 +1,4 @@ -/* $NetBSD: if_iwivar.h,v 1.14 2007/10/22 15:28:48 joerg Exp $ */ +/* $NetBSD: if_iwivar.h,v 1.15 2007/12/09 20:28:09 jmcneill Exp $ */ /*- * Copyright (c) 2004, 2005 @@ -144,10 +144,6 @@ struct iwi_softc { pcitag_t sc_pcitag; bus_size_t sc_sz; - void *sc_sdhook; /* shutdown hook */ - void *sc_powerhook; /* power management hook */ - struct pci_conf_state sc_pciconf; - struct sysctllog *sc_sysctllog; int antenna; diff --git a/sys/dev/pci/if_nfe.c b/sys/dev/pci/if_nfe.c index 8a003b97c6f..f58201e3e5d 100644 --- a/sys/dev/pci/if_nfe.c +++ b/sys/dev/pci/if_nfe.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_nfe.c,v 1.23 2007/11/14 14:59:50 xtraeme Exp $ */ +/* $NetBSD: if_nfe.c,v 1.24 2007/12/09 20:28:09 jmcneill Exp $ */ /* $OpenBSD: if_nfe.c,v 1.52 2006/03/02 09:04:00 jsg Exp $ */ /*- @@ -21,7 +21,7 @@ /* Driver for NVIDIA nForce MCP Fast Ethernet and Gigabit Ethernet */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_nfe.c,v 1.23 2007/11/14 14:59:50 xtraeme Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_nfe.c,v 1.24 2007/12/09 20:28:09 jmcneill Exp $"); #include "opt_inet.h" #include "bpfilter.h" @@ -323,6 +323,7 @@ nfe_attach(struct device *parent, struct device *self, void *aux) ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = nfe_ioctl; ifp->if_start = nfe_start; + ifp->if_stop = nfe_stop; ifp->if_watchdog = nfe_watchdog; ifp->if_init = nfe_init; ifp->if_baudrate = IF_Gbps(1); @@ -365,25 +366,10 @@ nfe_attach(struct device *parent, struct device *self, void *aux) callout_init(&sc->sc_tick_ch, 0); callout_setfunc(&sc->sc_tick_ch, nfe_tick, sc); - sc->sc_powerhook = powerhook_establish(sc->sc_dev.dv_xname, - nfe_power, sc); -} - -void -nfe_power(int why, void *arg) -{ - struct nfe_softc *sc = arg; - struct ifnet *ifp; - - if (why == PWR_RESUME) { - ifp = &sc->sc_ethercom.ec_if; - if (ifp->if_flags & IFF_UP) { - ifp->if_flags &= ~IFF_RUNNING; - nfe_init(ifp); - if (ifp->if_flags & IFF_RUNNING) - nfe_start(ifp); - } - } + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); + else + pmf_class_network_register(self, ifp); } void diff --git a/sys/dev/pci/if_nfevar.h b/sys/dev/pci/if_nfevar.h index 368cedf5964..f4c2137e03b 100644 --- a/sys/dev/pci/if_nfevar.h +++ b/sys/dev/pci/if_nfevar.h @@ -1,4 +1,4 @@ -/* $NetBSD: if_nfevar.h,v 1.3 2007/09/24 13:17:54 cube Exp $ */ +/* $NetBSD: if_nfevar.h,v 1.4 2007/12/09 20:28:09 jmcneill Exp $ */ /* $OpenBSD: if_nfevar.h,v 1.11 2006/02/19 13:57:02 damien Exp $ */ /*- @@ -76,7 +76,6 @@ struct nfe_softc { bus_dma_tag_t sc_dmat; struct mii_data sc_mii; struct callout sc_tick_ch; - void *sc_powerhook; int sc_if_flags; u_int sc_flags; diff --git a/sys/dev/pci/if_re_pci.c b/sys/dev/pci/if_re_pci.c index 3d1c610432b..10100ab8d83 100644 --- a/sys/dev/pci/if_re_pci.c +++ b/sys/dev/pci/if_re_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_re_pci.c,v 1.30 2007/10/19 12:00:47 ad Exp $ */ +/* $NetBSD: if_re_pci.c,v 1.31 2007/12/09 20:28:09 jmcneill Exp $ */ /* * Copyright (c) 1997, 1998-2003 @@ -183,43 +183,13 @@ re_pci_attach(struct device *parent, struct device *self, void *aux) const struct rtk_type *t; uint32_t hwrev; int error = 0; - pcireg_t pmreg, memtype; + pcireg_t memtype; bool ioh_valid, memh_valid; pcireg_t command; bus_space_tag_t iot, memt; bus_space_handle_t ioh, memh; bus_size_t iosize, memsize, bsize; - - /* - * Handle power management nonsense. - */ - if (pci_get_capability(pc, pa->pa_tag, PCI_CAP_PWRMGMT, &pmreg, 0)) { - command = pci_conf_read(pc, pa->pa_tag, pmreg + PCI_PMCSR); - if (command & PCI_PMCSR_STATE_MASK) { - u_int32_t iobase, membase, irq; - - /* Save important PCI config data. */ - iobase = pci_conf_read(pc, pa->pa_tag, RTK_PCI_LOIO); - membase = pci_conf_read(pc, pa->pa_tag, RTK_PCI_LOMEM); - irq = pci_conf_read(pc, pa->pa_tag, PCI_INTERRUPT_REG); - - /* Reset the power state. */ - aprint_normal("%s: chip is is in D%d power mode " - "-- setting to D0\n", sc->sc_dev.dv_xname, - command & PCI_PMCSR_STATE_MASK); - - command &= ~PCI_PMCSR_STATE_MASK; - pci_conf_write(pc, pa->pa_tag, - pmreg + PCI_PMCSR, command); - - /* Restore PCI config data. */ - pci_conf_write(pc, pa->pa_tag, RTK_PCI_LOIO, iobase); - pci_conf_write(pc, pa->pa_tag, RTK_PCI_LOMEM, membase); - pci_conf_write(pc, pa->pa_tag, PCI_INTERRUPT_REG, irq); - } - } - /* * Map control/status registers. */ @@ -329,4 +299,9 @@ re_pci_attach(struct device *parent, struct device *self, void *aux) bus_space_unmap(memt, memh, memsize); } } + + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); + else + pmf_class_network_register(self, &sc->ethercom.ec_if); } diff --git a/sys/dev/pci/if_rtk_pci.c b/sys/dev/pci/if_rtk_pci.c index c9422141883..de7fa68de56 100644 --- a/sys/dev/pci/if_rtk_pci.c +++ b/sys/dev/pci/if_rtk_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_rtk_pci.c,v 1.34 2007/11/06 02:29:19 uwe Exp $ */ +/* $NetBSD: if_rtk_pci.c,v 1.35 2007/12/09 20:28:10 jmcneill Exp $ */ /* * Copyright (c) 1997, 1998 @@ -47,7 +47,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_rtk_pci.c,v 1.34 2007/11/06 02:29:19 uwe Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_rtk_pci.c,v 1.35 2007/12/09 20:28:10 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -82,11 +82,6 @@ struct rtk_pci_softc { /* PCI-specific goo.*/ void *sc_ih; - pci_chipset_tag_t sc_pc; /* PCI chipset */ - pcitag_t sc_pcitag; /* PCI tag */ - - void *sc_powerhook; /* powerhook ctxt. */ - struct pci_conf_state sc_pciconf; }; static const struct rtk_type rtk_pci_devs[] = { @@ -111,7 +106,6 @@ static const struct rtk_type rtk_pci_devs[] = { static int rtk_pci_match(device_t, struct cfdata *, void *); static void rtk_pci_attach(device_t, device_t, void *); -static void rtk_pci_powerhook(int, void *); CFATTACH_DECL(rtk_pci, sizeof(struct rtk_pci_softc), rtk_pci_match, rtk_pci_attach, NULL, NULL); @@ -151,7 +145,6 @@ rtk_pci_attach(device_t parent, device_t self, void *aux) { struct rtk_pci_softc *psc = device_private(self); struct rtk_softc *sc = &psc->sc_rtk; - pcireg_t command; struct pci_attach_args *pa = aux; pci_chipset_tag_t pc = pa->pa_pc; pci_intr_handle_t ih; @@ -159,12 +152,8 @@ rtk_pci_attach(device_t parent, device_t self, void *aux) bus_space_handle_t ioh, memh; const char *intrstr = NULL; const struct rtk_type *t; - int pmreg; int ioh_valid, memh_valid; - psc->sc_pc = pa->pa_pc; - psc->sc_pcitag = pa->pa_tag; - t = rtk_pci_lookup(pa); if (t == NULL) { printf("\n"); @@ -176,35 +165,6 @@ rtk_pci_attach(device_t parent, device_t self, void *aux) t->rtk_name, PCI_REVISION(pa->pa_class)); /* - * Handle power management nonsense. - */ - - if (pci_get_capability(pc, pa->pa_tag, PCI_CAP_PWRMGMT, &pmreg, 0)) { - command = pci_conf_read(pc, pa->pa_tag, pmreg + PCI_PMCSR); - if (command & PCI_PMCSR_STATE_MASK) { - pcireg_t iobase, membase, irq; - - /* Save important PCI config data. */ - iobase = pci_conf_read(pc, pa->pa_tag, RTK_PCI_LOIO); - membase = pci_conf_read(pc, pa->pa_tag, RTK_PCI_LOMEM); - irq = pci_conf_read(pc, pa->pa_tag, PCI_INTERRUPT_REG); - - /* Reset the power state. */ - aprint_normal_dev(self, - "chip is in D%d power mode -- setting to D0\n", - command & PCI_PMCSR_STATE_MASK); - command &= ~PCI_PMCSR_STATE_MASK; - pci_conf_write(pc, pa->pa_tag, - pmreg + PCI_PMCSR, command); - - /* Restore PCI config data. */ - pci_conf_write(pc, pa->pa_tag, RTK_PCI_LOIO, iobase); - pci_conf_write(pc, pa->pa_tag, RTK_PCI_LOMEM, membase); - pci_conf_write(pc, pa->pa_tag, PCI_INTERRUPT_REG, irq); - } - } - - /* * Map control/status registers. * * The original FreeBSD's driver has the following comment: @@ -258,34 +218,10 @@ rtk_pci_attach(device_t parent, device_t self, void *aux) sc->sc_dmat = pa->pa_dmat; sc->sc_flags |= RTK_ENABLED; - psc->sc_powerhook = powerhook_establish(device_xname(self), - rtk_pci_powerhook, psc); - if (psc->sc_powerhook == NULL) - aprint_error_dev(self, - "WARNING: unable to establish pci power hook\n"); + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); + else + pmf_class_network_register(self, &sc->ethercom.ec_if); rtk_attach(sc); } - -static void -rtk_pci_powerhook(int why, void *arg) -{ - struct rtk_pci_softc *sc = (struct rtk_pci_softc *)arg; - int s; - - s = splnet(); - switch (why) { - case PWR_SUSPEND: - case PWR_STANDBY: - pci_conf_capture(sc->sc_pc, sc->sc_pcitag, &sc->sc_pciconf); - break; - case PWR_RESUME: - pci_conf_restore(sc->sc_pc, sc->sc_pcitag, &sc->sc_pciconf); - break; - case PWR_SOFTSUSPEND: - case PWR_SOFTSTANDBY: - case PWR_SOFTRESUME: - break; - } - splx(s); -} diff --git a/sys/dev/pci/if_wi_pci.c b/sys/dev/pci/if_wi_pci.c index d113cda1900..78e7db292ae 100644 --- a/sys/dev/pci/if_wi_pci.c +++ b/sys/dev/pci/if_wi_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_wi_pci.c,v 1.42 2007/10/19 12:00:49 ad Exp $ */ +/* $NetBSD: if_wi_pci.c,v 1.43 2007/12/09 20:28:10 jmcneill Exp $ */ /*- * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -43,7 +43,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_wi_pci.c,v 1.42 2007/10/19 12:00:49 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_wi_pci.c,v 1.43 2007/12/09 20:28:10 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -92,8 +92,7 @@ struct wi_pci_softc { /* PCI-specific goo */ pci_intr_handle_t psc_ih; pci_chipset_tag_t psc_pc; - - void *sc_powerhook; /* power hook descriptor */ + pcitag_t psc_pcitag; }; static int wi_pci_match(struct device *, struct cfdata *, void *); @@ -101,7 +100,6 @@ static void wi_pci_attach(struct device *, struct device *, void *); static int wi_pci_enable(struct wi_softc *); static void wi_pci_disable(struct wi_softc *); static void wi_pci_reset(struct wi_softc *); -static void wi_pci_powerhook(int, void *); static const struct wi_pci_product *wi_pci_lookup(struct pci_attach_args *); @@ -236,6 +234,7 @@ wi_pci_attach(struct device *parent, struct device *self, void *aux) bus_space_handle_t memh, ioh, plxh, tmdh; psc->psc_pc = pc; + psc->psc_pcitag = pa->pa_tag; wpp = wi_pci_lookup(pa); #ifdef DIAGNOSTIC @@ -383,19 +382,8 @@ wi_pci_attach(struct device *parent, struct device *self, void *aux) if (!wpp->wpp_chip) sc->sc_reset = wi_pci_reset; - /* Add a suspend hook to restore PCI config state */ - psc->sc_powerhook = powerhook_establish(self->dv_xname, - wi_pci_powerhook, psc); - if (psc->sc_powerhook == NULL) - printf("%s: WARNING: unable to establish pci power hook\n", - self->dv_xname); -} - -static void -wi_pci_powerhook(int why, void *arg) -{ - struct wi_pci_softc *psc = arg; - struct wi_softc *sc = &psc->psc_wi; - - wi_power(sc, why); + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); + else + pmf_class_network_register(self, &sc->sc_if); } diff --git a/sys/dev/pci/if_wm.c b/sys/dev/pci/if_wm.c index 40722b613f2..9819385cf28 100644 --- a/sys/dev/pci/if_wm.c +++ b/sys/dev/pci/if_wm.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_wm.c,v 1.148 2007/10/30 07:49:40 simonb Exp $ */ +/* $NetBSD: if_wm.c,v 1.149 2007/12/09 20:28:10 jmcneill Exp $ */ /* * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc. @@ -79,7 +79,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.148 2007/10/30 07:49:40 simonb Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.149 2007/12/09 20:28:10 jmcneill Exp $"); #include "bpfilter.h" #include "rnd.h" @@ -268,11 +268,8 @@ struct wm_softc { bus_space_handle_t sc_flashh; /* flash registers space handle */ bus_dma_tag_t sc_dmat; /* bus DMA tag */ struct ethercom sc_ethercom; /* ethernet common data */ - void *sc_sdhook; /* shutdown hook */ - void *sc_powerhook; /* power hook */ pci_chipset_tag_t sc_pc; pcitag_t sc_pcitag; - struct pci_conf_state sc_pciconf; wm_chip_type sc_type; /* chip type */ int sc_flags; /* flags; see below */ @@ -523,9 +520,6 @@ static int wm_ioctl(struct ifnet *, u_long, void *); static int wm_init(struct ifnet *); static void wm_stop(struct ifnet *, int); -static void wm_shutdown(void *); -static void wm_powerhook(int, void *); - static void wm_reset(struct wm_softc *); static void wm_rxdrain(struct wm_softc *); static int wm_add_rxbuf(struct wm_softc *, int); @@ -1617,19 +1611,11 @@ wm_attach(struct device *parent, struct device *self, void *aux) NULL, sc->sc_dev.dv_xname, "rx_macctl"); #endif /* WM_EVENT_COUNTERS */ - /* - * Make sure the interface is shutdown during reboot. - */ - sc->sc_sdhook = shutdownhook_establish(wm_shutdown, sc); - if (sc->sc_sdhook == NULL) - aprint_error("%s: WARNING: unable to establish shutdown hook\n", - sc->sc_dev.dv_xname); + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); + else + pmf_class_network_register(self, ifp); - sc->sc_powerhook = powerhook_establish(sc->sc_dev.dv_xname, - wm_powerhook, sc); - if (sc->sc_powerhook == NULL) - aprint_error("%s: can't establish powerhook\n", - sc->sc_dev.dv_xname); return; /* @@ -1661,48 +1647,6 @@ wm_attach(struct device *parent, struct device *self, void *aux) } /* - * wm_shutdown: - * - * Make sure the interface is stopped at reboot time. - */ -static void -wm_shutdown(void *arg) -{ - struct wm_softc *sc = arg; - - wm_stop(&sc->sc_ethercom.ec_if, 1); -} - -static void -wm_powerhook(int why, void *arg) -{ - struct wm_softc *sc = arg; - struct ifnet *ifp = &sc->sc_ethercom.ec_if; - pci_chipset_tag_t pc = sc->sc_pc; - pcitag_t tag = sc->sc_pcitag; - - switch (why) { - case PWR_SOFTSUSPEND: - wm_shutdown(sc); - break; - case PWR_SOFTRESUME: - ifp->if_flags &= ~IFF_RUNNING; - wm_init(ifp); - if (ifp->if_flags & IFF_RUNNING) - wm_start(ifp); - break; - case PWR_SUSPEND: - pci_conf_capture(pc, tag, &sc->sc_pciconf); - break; - case PWR_RESUME: - pci_conf_restore(pc, tag, &sc->sc_pciconf); - break; - } - - return; -} - -/* * wm_tx_offload: * * Set up TCP/IP checksumming parameters for the diff --git a/sys/dev/pci/if_wpi.c b/sys/dev/pci/if_wpi.c index 7b945dcdd09..f92a32791b8 100644 --- a/sys/dev/pci/if_wpi.c +++ b/sys/dev/pci/if_wpi.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_wpi.c,v 1.32 2007/12/01 18:02:42 jmcneill Exp $ */ +/* $NetBSD: if_wpi.c,v 1.33 2007/12/09 20:28:10 jmcneill Exp $ */ /*- * Copyright (c) 2006, 2007 @@ -18,7 +18,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_wpi.c,v 1.32 2007/12/01 18:02:42 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_wpi.c,v 1.33 2007/12/09 20:28:10 jmcneill Exp $"); /* * Driver for Intel PRO/Wireless 3945ABG 802.11 network adapters. @@ -94,7 +94,6 @@ static const struct ieee80211_rateset wpi_rateset_11g = static int wpi_match(device_t, struct cfdata *, void *); static void wpi_attach(device_t, device_t, void *); static int wpi_detach(device_t , int); -static void wpi_power(int, void *); static int wpi_dma_contig_alloc(bus_dma_tag_t, struct wpi_dma_info *, void **, bus_size_t, bus_size_t, int); static void wpi_dma_contig_free(struct wpi_dma_info *); @@ -164,6 +163,7 @@ static int wpi_reset(struct wpi_softc *); static void wpi_hw_config(struct wpi_softc *); static int wpi_init(struct ifnet *); static void wpi_stop(struct ifnet *, int); +static bool wpi_resume(device_t); CFATTACH_DECL_NEW(wpi, sizeof (struct wpi_softc), wpi_match, wpi_attach, wpi_detach, NULL); @@ -212,10 +212,7 @@ wpi_attach(device_t parent __unused, device_t self, void *aux) revision = PCI_REVISION(pa->pa_class); aprint_normal(": %s (rev. 0x%02x)\n", devinfo, revision); - /* clear device specific PCI configuration register 0x41 */ - data = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40); - data &= ~0x0000ff00; - pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, data); + pci_disable_retry(pa->pa_pc, pa->pa_tag); /* enable bus-mastering */ data = pci_conf_read(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG); @@ -343,8 +340,10 @@ wpi_attach(device_t parent __unused, device_t self, void *aux) sc->amrr.amrr_min_success_threshold = 1; sc->amrr.amrr_max_success_threshold = 15; - /* set powerhook */ - sc->powerhook = powerhook_establish(device_xname(self), wpi_power, sc); + if (!pmf_device_register(self, NULL, wpi_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); + else + pmf_class_network_register(self, ifp); #if NBPFILTER > 0 bpfattach2(ifp, DLT_IEEE802_11_RADIO, @@ -406,32 +405,6 @@ wpi_detach(device_t self, int flags __unused) return 0; } -static void -wpi_power(int why, void *arg) -{ - struct wpi_softc *sc = arg; - struct ifnet *ifp; - pcireg_t data; - int s; - - if (why != PWR_RESUME) - return; - - /* clear device specific PCI configuration register 0x41 */ - data = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40); - data &= ~0x0000ff00; - pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, data); - - s = splnet(); - ifp = sc->sc_ic.ic_ifp; - if (ifp->if_flags & IFF_UP) { - ifp->if_init(ifp); - if (ifp->if_flags & IFF_RUNNING) - ifp->if_start(ifp); - } - splx(s); -} - static int wpi_dma_contig_alloc(bus_dma_tag_t tag, struct wpi_dma_info *dma, void **kvap, bus_size_t size, bus_size_t alignment, int flags) @@ -3153,3 +3126,14 @@ wpi_stop(struct ifnet *ifp, int disable) tmp = WPI_READ(sc, WPI_RESET); WPI_WRITE(sc, WPI_RESET, tmp | WPI_SW_RESET); } + +static bool +wpi_resume(device_t dv) +{ + struct wpi_softc *sc = device_private(dv); + + pci_disable_retry(sc->sc_pct, sc->sc_pcitag); + (void)wpi_reset(sc); + + return true; +} diff --git a/sys/dev/pci/if_wpivar.h b/sys/dev/pci/if_wpivar.h index 84657505c9f..b8e34fdff79 100644 --- a/sys/dev/pci/if_wpivar.h +++ b/sys/dev/pci/if_wpivar.h @@ -1,4 +1,4 @@ -/* $NetBSD: if_wpivar.h,v 1.9 2007/11/16 00:13:32 degroote Exp $ */ +/* $NetBSD: if_wpivar.h,v 1.10 2007/12/09 20:28:11 jmcneill Exp $ */ /*- * Copyright (c) 2006 @@ -166,7 +166,6 @@ struct wpi_softc { int8_t maxpwr[IEEE80211_CHAN_MAX]; int sc_tx_timer; - void *powerhook; #if NBPFILTER > 0 void * sc_drvbpf; diff --git a/sys/dev/pci/neo.c b/sys/dev/pci/neo.c index 7b02a93e142..c4b2a84ecc8 100644 --- a/sys/dev/pci/neo.c +++ b/sys/dev/pci/neo.c @@ -1,4 +1,4 @@ -/* $NetBSD: neo.c,v 1.36 2007/10/19 12:00:52 ad Exp $ */ +/* $NetBSD: neo.c,v 1.37 2007/12/09 20:28:11 jmcneill Exp $ */ /* * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk> @@ -32,7 +32,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: neo.c,v 1.36 2007/10/19 12:00:52 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: neo.c,v 1.37 2007/12/09 20:28:11 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -162,8 +162,6 @@ struct neo_softc { struct ac97_codec_if *codec_if; struct ac97_host_if host_if; - - void *powerhook; }; /* -------------------------------------------------------------------- */ @@ -207,7 +205,6 @@ static void neo_free(void *, void *, struct malloc_type *); static size_t neo_round_buffersize(void *, int, size_t); static paddr_t neo_mappage(void *, void *, off_t, int); static int neo_get_props(void *); -static void neo_power(int, void *); CFATTACH_DECL(neo, sizeof(struct neo_softc), neo_match, neo_attach, NULL, NULL); @@ -552,16 +549,15 @@ neo_match(struct device *parent, struct cfdata *match, return 0; } -static void -neo_power(int why, void *addr) +static bool +neo_resume(device_t dv) { - struct neo_softc *sc; + struct neo_softc *sc = device_private(dv); - sc = (struct neo_softc *)addr; - if (why == PWR_RESUME) { - nm_init(sc); - sc->codec_if->vtbl->restore_ports(sc->codec_if); - } + nm_init(sc); + sc->codec_if->vtbl->restore_ports(sc->codec_if); + + return true; } static void @@ -634,7 +630,8 @@ neo_attach(struct device *parent, struct device *self, void *aux) if (ac97_attach(&sc->host_if, self) != 0) return; - sc->powerhook = powerhook_establish(sc->dev.dv_xname, neo_power, sc); + if (!pmf_device_register(self, NULL, neo_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); audio_attach_mi(&neo_hw_if, sc, &sc->dev); } diff --git a/sys/dev/pci/ohci_pci.c b/sys/dev/pci/ohci_pci.c index e96804ae48d..2468a6daa55 100644 --- a/sys/dev/pci/ohci_pci.c +++ b/sys/dev/pci/ohci_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: ohci_pci.c,v 1.32 2007/10/19 12:00:53 ad Exp $ */ +/* $NetBSD: ohci_pci.c,v 1.33 2007/12/09 20:28:11 jmcneill Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -38,7 +38,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ohci_pci.c,v 1.32 2007/10/19 12:00:53 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ohci_pci.c,v 1.33 2007/12/09 20:28:11 jmcneill Exp $"); #include "ehci.h" @@ -68,6 +68,7 @@ struct ohci_pci_softc { struct usb_pci sc_pci; #endif pci_chipset_tag_t sc_pc; + pcitag_t sc_tag; void *sc_ih; /* interrupt vectoring */ }; @@ -115,6 +116,7 @@ ohci_pci_attach(struct device *parent, struct device *self, void *aux) OHCI_ALL_INTRS); sc->sc_pc = pc; + sc->sc_tag = tag; sc->sc.sc_bus.dmatag = pa->pa_dmat; /* Enable the device. */ @@ -157,6 +159,9 @@ ohci_pci_attach(struct device *parent, struct device *self, void *aux) usb_pci_add(&sc->sc_pci, pa, &sc->sc.sc_bus); #endif + if (!pmf_device_register(self, ohci_suspend, ohci_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); + /* Attach usb device. */ sc->sc.sc_child = config_found((void *)sc, &sc->sc.sc_bus, usbctlprint); diff --git a/sys/dev/pci/pccbb.c b/sys/dev/pci/pccbb.c index d9c08f22f7d..e9e34d43dc2 100644 --- a/sys/dev/pci/pccbb.c +++ b/sys/dev/pci/pccbb.c @@ -1,4 +1,4 @@ -/* $NetBSD: pccbb.c,v 1.155 2007/12/01 05:41:53 jmcneill Exp $ */ +/* $NetBSD: pccbb.c,v 1.156 2007/12/09 20:28:11 jmcneill Exp $ */ /* * Copyright (c) 1998, 1999 and 2000 @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pccbb.c,v 1.155 2007/12/01 05:41:53 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pccbb.c,v 1.156 2007/12/09 20:28:11 jmcneill Exp $"); /* #define CBB_DEBUG @@ -185,7 +185,6 @@ static void pccbb_pcmcia_delay(struct pcic_handle *, int, const char *); static void pccbb_pcmcia_do_io_map(struct pcic_handle *, int); static void pccbb_pcmcia_do_mem_map(struct pcic_handle *, int); -static void pccbb_powerhook(int, void *); /* bus-space allocation and deallocation functions */ #if rbus @@ -217,6 +216,9 @@ void pccbb_winlist_show(struct pccbb_win_chain *); /* for config_defer */ static void pccbb_pci_callback(struct device *); +static bool pccbb_suspend(device_t); +static bool pccbb_resume(device_t); + #if defined SHOW_REGS static void cb_show_regs(pci_chipset_tag_t pc, pcitag_t tag, bus_space_tag_t memt, bus_space_handle_t memh); @@ -378,36 +380,6 @@ cb_chipset(u_int32_t pci_id, int *flagp) return (yc->yc_chiptype); } -static void -pccbb_shutdown(void *arg) -{ - struct pccbb_softc *sc = arg; - pcireg_t command; - - DPRINTF(("%s: shutdown\n", sc->sc_dev.dv_xname)); - - /* - * turn off power - * - * XXX - do not turn off power if chipset is TI 113X because - * only TI 1130 with PowerMac 2400 hangs in pccbb_power(). - */ - if (sc->sc_chipset != CB_TI113X) { - pccbb_power((cardbus_chipset_tag_t)sc, - CARDBUS_VCC_0V | CARDBUS_VPP_0V); - } - - bus_space_write_4(sc->sc_base_memt, sc->sc_base_memh, CB_SOCKET_MASK, - 0); - - command = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_COMMAND_STATUS_REG); - - command &= ~(PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE | - PCI_COMMAND_MASTER_ENABLE); - pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_COMMAND_STATUS_REG, command); - -} - void pccbbattach(struct device *parent, struct device *self, void *aux) { @@ -418,7 +390,6 @@ pccbbattach(struct device *parent, struct device *self, void *aux) bus_addr_t sockbase; char devinfo[256]; int flags; - int pwrmgt_offs; #ifdef __HAVE_PCCBB_ATTACH_HOOK pccbb_attach_hook(parent, self, pa); @@ -452,23 +423,6 @@ pccbbattach(struct device *parent, struct device *self, void *aux) sc->sc_flags &= ~CBB_MEMHMAPPED; - /* power management: set D0 state */ - sc->sc_pwrmgt_offs = 0; - if (pci_get_capability(pc, pa->pa_tag, PCI_CAP_PWRMGMT, - &pwrmgt_offs, 0)) { - reg = pci_conf_read(pc, pa->pa_tag, pwrmgt_offs + PCI_PMCSR); - if ((reg & PCI_PMCSR_STATE_MASK) != PCI_PMCSR_STATE_D0 || - reg & 0x100 /* PCI_PMCSR_PME_EN */) { - reg &= ~PCI_PMCSR_STATE_MASK; - reg |= PCI_PMCSR_STATE_D0; - reg &= ~(0x100 /* PCI_PMCSR_PME_EN */); - pci_conf_write(pc, pa->pa_tag, - pwrmgt_offs + PCI_PMCSR, reg); - } - - sc->sc_pwrmgt_offs = pwrmgt_offs; - } - /* * MAP socket registers and ExCA registers on memory-space * When no valid address is set on socket base registers (on pci @@ -526,15 +480,11 @@ pccbbattach(struct device *parent, struct device *self, void *aux) sc->sc_dmat = pa->pa_dmat; sc->sc_tag = pa->pa_tag; sc->sc_function = pa->pa_function; - sc->sc_sockbase = sock_base; - sc->sc_busnum = busreg; memcpy(&sc->sc_pa, pa, sizeof(*pa)); sc->sc_pcmcia_flags = flags; /* set PCMCIA facility */ - shutdownhook_establish(pccbb_shutdown, sc); - /* Disable legacy register mapping. */ switch (sc->sc_chipset) { case CB_RX5C46X: /* fallthrough */ @@ -559,6 +509,9 @@ pccbbattach(struct device *parent, struct device *self, void *aux) break; } + if (!pmf_device_register(self, pccbb_suspend, pccbb_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); + config_defer(self, pccbb_pci_callback); } @@ -618,7 +571,6 @@ pccbb_pci_callback(struct device *self) sc->sc_dev.dv_xname, (unsigned long)sock_base, (unsigned long)pci_conf_read(pc, sc->sc_tag, PCI_SOCKBASE))); - sc->sc_sockbase = sockbase; #endif sc->sc_flags |= CBB_MEMHMAPPED; } @@ -655,7 +607,6 @@ pccbb_pci_callback(struct device *self) } aprint_normal("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr); - powerhook_establish(sc->sc_dev.dv_xname, pccbb_powerhook, sc); { u_int32_t sockstat; @@ -3274,97 +3225,64 @@ pccbb_winset(bus_addr_t align, struct pccbb_softc *sc, bus_space_tag_t bst) #endif /* rbus */ -static void -pccbb_powerhook(int why, void *arg) +static bool +pccbb_suspend(device_t dv) { - struct pccbb_softc *sc = arg; - pcireg_t reg; + struct pccbb_softc *sc = device_private(dv); bus_space_tag_t base_memt = sc->sc_base_memt; /* socket regs memory */ bus_space_handle_t base_memh = sc->sc_base_memh; + pcireg_t reg; - DPRINTF(("%s: power: why %d\n", sc->sc_dev.dv_xname, why)); - - if (why == PWR_SUSPEND || why == PWR_STANDBY) { - DPRINTF(("%s: power: why %d stopping intr\n", - sc->sc_dev.dv_xname, why)); - if (sc->sc_pil_intr_enable) { - (void)pccbbintr_function(sc); - } - sc->sc_pil_intr_enable = 0; - - pci_conf_capture(sc->sc_pc, sc->sc_tag, &sc->sc_pciconf); - - if (sc->sc_chipset == CB_RX5C47X) - sc->sc_ricoh_misc_ctrl = pci_conf_read(sc->sc_pc, - sc->sc_tag, - RICOH_PCI_MISC_CTRL); + if (sc->sc_pil_intr_enable) + (void)pccbbintr_function(sc); + sc->sc_pil_intr_enable = 0; - /* ToDo: deactivate or suspend child devices */ - } + reg = bus_space_read_4(base_memt, base_memh, CB_SOCKET_MASK); + /* Disable interrupts. */ + reg &= ~(CB_SOCKET_MASK_CSTS | CB_SOCKET_MASK_CD | CB_SOCKET_MASK_POWER); + bus_space_write_4(base_memt, base_memh, CB_SOCKET_MASK, reg); + /* XXX joerg Disable power to the socket? */ - if (why == PWR_RESUME) { - if (sc->sc_pwrmgt_offs != 0) { - reg = pci_conf_read(sc->sc_pc, sc->sc_tag, - sc->sc_pwrmgt_offs + PCI_PMCSR); - if ((reg & PCI_PMCSR_STATE_MASK) != PCI_PMCSR_STATE_D0 || - reg & PCI_PMCSR_PME_EN) { - /* powrstate != D0 */ + if (sc->sc_chipset == CB_RX5C47X) + sc->sc_ricoh_misc_ctrl = pci_conf_read(sc->sc_pc, + sc->sc_tag, RICOH_PCI_MISC_CTRL); - printf("%s going back to D0 mode\n", - sc->sc_dev.dv_xname); - reg &= ~PCI_PMCSR_STATE_MASK; - reg |= PCI_PMCSR_STATE_D0; - reg &= ~PCI_PMCSR_PME_EN; - pci_conf_write(sc->sc_pc, sc->sc_tag, - sc->sc_pwrmgt_offs + PCI_PMCSR, reg); - - pci_conf_write(sc->sc_pc, sc->sc_tag, - PCI_SOCKBASE, sc->sc_sockbase); - pci_conf_write(sc->sc_pc, sc->sc_tag, - PCI_BUSNUM, sc->sc_busnum); - pccbb_chipinit(sc); - /* setup memory and io space window for CB */ - pccbb_winset(0x1000, sc, sc->sc_memt); - pccbb_winset(0x04, sc, sc->sc_iot); - goto norestore; - } - } + return true; +} -norestore: - pci_conf_restore(sc->sc_pc, sc->sc_tag, &sc->sc_pciconf); - if (sc->sc_chipset == CB_RX5C47X) { - pci_conf_write(sc->sc_pc, sc->sc_tag, - RICOH_PCI_MISC_CTRL, sc->sc_ricoh_misc_ctrl); - } +static bool +pccbb_resume(device_t dv) +{ + struct pccbb_softc *sc = device_private(dv); + bus_space_tag_t base_memt = sc->sc_base_memt; /* socket regs memory */ + bus_space_handle_t base_memh = sc->sc_base_memh; + pcireg_t reg; - if (pci_conf_read (sc->sc_pc, sc->sc_tag, PCI_SOCKBASE) == 0) - /* BIOS did not recover this register */ - pci_conf_write (sc->sc_pc, sc->sc_tag, - PCI_SOCKBASE, sc->sc_sockbase); - if (pci_conf_read (sc->sc_pc, sc->sc_tag, PCI_BUSNUM) == 0) - /* BIOS did not recover this register */ - pci_conf_write (sc->sc_pc, sc->sc_tag, - PCI_BUSNUM, sc->sc_busnum); - /* CSC Interrupt: Card detect interrupt on */ - reg = bus_space_read_4(base_memt, base_memh, CB_SOCKET_MASK); - /* Card detect intr is turned on. */ - reg |= CB_SOCKET_MASK_CD | CB_SOCKET_MASK_POWER; - bus_space_write_4(base_memt, base_memh, CB_SOCKET_MASK, reg); - /* reset interrupt */ - reg = bus_space_read_4(base_memt, base_memh, CB_SOCKET_EVENT); - bus_space_write_4(base_memt, base_memh, CB_SOCKET_EVENT, reg); + pccbb_chipinit(sc); + /* setup memory and io space window for CB */ + pccbb_winset(0x1000, sc, sc->sc_memt); + pccbb_winset(0x04, sc, sc->sc_iot); + if (sc->sc_chipset == CB_RX5C47X) + pci_conf_write(sc->sc_pc, sc->sc_tag, + RICOH_PCI_MISC_CTRL, sc->sc_ricoh_misc_ctrl); + + /* CSC Interrupt: Card detect interrupt on */ + reg = bus_space_read_4(base_memt, base_memh, CB_SOCKET_MASK); + /* Card detect intr is turned on. */ + reg |= CB_SOCKET_MASK_CD | CB_SOCKET_MASK_POWER; + bus_space_write_4(base_memt, base_memh, CB_SOCKET_MASK, reg); + /* reset interrupt */ + reg = bus_space_read_4(base_memt, base_memh, CB_SOCKET_EVENT); + bus_space_write_4(base_memt, base_memh, CB_SOCKET_EVENT, reg); - /* - * check for card insertion or removal during suspend period. - * XXX: the code can't cope with card swap (remove then - * insert). how can we detect such situation? - */ - (void)pccbbintr(sc); + /* + * check for card insertion or removal during suspend period. + * XXX: the code can't cope with card swap (remove then + * insert). how can we detect such situation? + */ + (void)pccbbintr(sc); - sc->sc_pil_intr_enable = 1; - DPRINTF(("%s: power: RESUME enabling intr\n", - sc->sc_dev.dv_xname)); + sc->sc_pil_intr_enable = 1; - /* ToDo: activate or wakeup child devices */ - } + return true; } diff --git a/sys/dev/pci/pccbbvar.h b/sys/dev/pci/pccbbvar.h index 5dcfe285a89..2a26c932293 100644 --- a/sys/dev/pci/pccbbvar.h +++ b/sys/dev/pci/pccbbvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: pccbbvar.h,v 1.29 2007/08/10 22:57:54 dyoung Exp $ */ +/* $NetBSD: pccbbvar.h,v 1.30 2007/12/09 20:28:11 jmcneill Exp $ */ /* * Copyright (c) 1999 HAYAKAWA Koichi. All rights reserved. * @@ -132,9 +132,6 @@ struct pccbb_softc { bus_addr_t sc_io_start; /* CardBus/PCMCIA io start */ bus_addr_t sc_io_end; /* CardBus/PCMCIA io end */ - pcireg_t sc_sockbase; /* Socket base register */ - pcireg_t sc_busnum; /* bus number */ - /* CardBus stuff */ struct cardslot_softc *sc_csc; @@ -156,8 +153,6 @@ struct pccbb_softc { LIST_HEAD(, pccbb_intrhand_list) sc_pil; int sc_pil_intr_enable; /* can i call intr handler for child device? */ - int sc_pwrmgt_offs; /* Offset for power management capability */ - struct pci_conf_state sc_pciconf; pcireg_t sc_ricoh_misc_ctrl; }; diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index 7b06067b205..87211c3708d 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: pci.c,v 1.106 2007/12/01 16:46:18 ad Exp $ */ +/* $NetBSD: pci.c,v 1.107 2007/12/09 20:28:11 jmcneill Exp $ */ /* * Copyright (c) 1995, 1996, 1997, 1998 @@ -36,11 +36,12 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pci.c,v 1.106 2007/12/01 16:46:18 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pci.c,v 1.107 2007/12/09 20:28:11 jmcneill Exp $"); #include "opt_pci.h" #include <sys/param.h> +#include <sys/malloc.h> #include <sys/systm.h> #include <sys/device.h> @@ -50,8 +51,12 @@ __KERNEL_RCSID(0, "$NetBSD: pci.c,v 1.106 2007/12/01 16:46:18 ad Exp $"); #include <uvm/uvm_extern.h> +#include <net/if.h> + #include "locators.h" +static bool pci_child_register(device_t); + #ifdef PCI_CONFIG_DUMP int pci_config_dump = 1; #else @@ -126,86 +131,6 @@ pcimatch(struct device *parent, struct cfdata *cf, void *aux) } static void -pci_power_devices(struct pci_softc *sc, int why) -{ - pci_chipset_tag_t pc; - int device, function, nfunctions; - pcitag_t tag; - pcireg_t bhlcr, id; - pcireg_t state; -#ifdef __PCI_BUS_DEVORDER - char devs[32]; - int i; -#endif - - pc = sc->sc_pc; - switch (why) { - case PWR_STANDBY: - state = PCI_PMCSR_STATE_D1; - break; - case PWR_SUSPEND: - state = PCI_PMCSR_STATE_D3; - break; - case PWR_RESUME: - state = PCI_PMCSR_STATE_D0; - break; - default: - /* we should never be called here */ -#ifdef DIAGNOSTIC - panic("pci_power_devices called with invalid reason %d\n", - why); - /* NOTREACHED */ -#endif - return; - } - -#ifdef __PCI_BUS_DEVORDER - pci_bus_devorder(sc->sc_pc, sc->sc_bus, devs); - for (i = 0; (device = devs[i]) < 32 && device >= 0; i++) -#else - for (device = 0; device < sc->sc_maxndevs; device++) -#endif - { - tag = pci_make_tag(pc, sc->sc_bus, device, 0); - bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG); - if (PCI_HDRTYPE_TYPE(bhlcr) > 2) - continue; - id = pci_conf_read(pc, tag, PCI_ID_REG); - if (PCI_VENDOR(id) == PCI_VENDOR_INVALID || - PCI_VENDOR(id) == 0x0000) - continue; - nfunctions = PCI_HDRTYPE_MULTIFN(bhlcr) ? 8 : 1; - - for (function = 0; function < nfunctions; function++) { - tag = pci_make_tag(pc, sc->sc_bus, device, function); - if (sc->PCI_SC_DEVICESC(device, function) != NULL) - continue; - (void)pci_set_powerstate(pc, tag, state); - } - } - - return; -} - -static void -pci_powerhook(int why, void *aux) -{ - struct pci_softc *sc; - - sc = (struct pci_softc *)aux; - - switch (why) { - case PWR_SUSPEND: - case PWR_STANDBY: - case PWR_RESUME: - pci_power_devices(sc, why); - break; - } - - return; -} - -static void pciattach(struct device *parent, struct device *self, void *aux) { struct pcibus_attach_args *pba = aux; @@ -229,7 +154,7 @@ pciattach(struct device *parent, struct device *self, void *aux) if (io_enabled == 0 && mem_enabled == 0) { aprint_error("%s: no spaces enabled!\n", self->dv_xname); - return; + goto fail; } #define PRINT(str) \ @@ -272,13 +197,20 @@ do { \ sc->sc_intrtag = pba->pba_intrtag; sc->sc_flags = pba->pba_flags; - sc->sc_powerhook = powerhook_establish(sc->sc_dev.dv_xname, - pci_powerhook, sc); - if (sc->sc_powerhook == NULL) - aprint_error("%s: can't establish powerhook\n", - sc->sc_dev.dv_xname); + device_pmf_driver_set_child_register(&sc->sc_dev, pci_child_register); pcirescan(&sc->sc_dev, "pci", wildcard); + +fail: + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); +} + +static int +pcidetach(struct device *self, int flags) +{ + pmf_device_deregister(self); + return 0; } int @@ -447,6 +379,9 @@ pcidevdetached(struct device *sc, struct device *dev) psc->PCI_SC_DEVICESC(d, f) = 0; } +CFATTACH_DECL2(pci, sizeof(struct pci_softc), + pcimatch, pciattach, pcidetach, NULL, pcirescan, pcidevdetached); + int pci_get_capability(pci_chipset_tag_t pc, pcitag_t tag, int capid, int *offset, pcireg_t *value) @@ -694,9 +629,13 @@ pci_conf_restore(pci_chipset_tag_t pc, pcitag_t tag, struct pci_conf_state *pcs) { int off; + pcireg_t val; - for (off = 0; off < 16; off++) - pci_conf_write(pc, tag, (off * 4), pcs->reg[off]); + for (off = 15; off >= 0; off--) { + val = pci_conf_read(pc, tag, (off * 4)); + if (val != pcs->reg[off]) + pci_conf_write(pc, tag, (off * 4), pcs->reg[off]); + } return; } @@ -704,16 +643,12 @@ pci_conf_restore(pci_chipset_tag_t pc, pcitag_t tag, /* * Power Management Capability (Rev 2.2) */ -int -pci_get_powerstate(pci_chipset_tag_t pc, pcitag_t tag , pcireg_t *state) +static int +pci_get_powerstate_int(pci_chipset_tag_t pc, pcitag_t tag , pcireg_t *state, + int offset) { - int offset; - pcireg_t value, cap, now; + pcireg_t value, now; - if (!pci_get_capability(pc, tag, PCI_CAP_PWRMGMT, &offset, &value)) - return EOPNOTSUPP; - - cap = value >> PCI_PMCR_SHIFT; value = pci_conf_read(pc, tag, offset + PCI_PMCSR); now = value & PCI_PMCSR_STATE_MASK; switch (now) { @@ -729,15 +664,24 @@ pci_get_powerstate(pci_chipset_tag_t pc, pcitag_t tag , pcireg_t *state) } int -pci_set_powerstate(pci_chipset_tag_t pc, pcitag_t tag, pcireg_t state) +pci_get_powerstate(pci_chipset_tag_t pc, pcitag_t tag , pcireg_t *state) { int offset; - pcireg_t value, cap, now; + pcireg_t value; if (!pci_get_capability(pc, tag, PCI_CAP_PWRMGMT, &offset, &value)) return EOPNOTSUPP; - cap = value >> PCI_PMCR_SHIFT; + return pci_get_powerstate_int(pc, tag, state, offset); +} + +static int +pci_set_powerstate_int(pci_chipset_tag_t pc, pcitag_t tag, pcireg_t state, + int offset, pcireg_t cap_reg) +{ + pcireg_t value, cap, now; + + cap = cap_reg >> PCI_PMCR_SHIFT; value = pci_conf_read(pc, tag, offset + PCI_PMCSR); now = value & PCI_PMCSR_STATE_MASK; value &= ~PCI_PMCSR_STATE_MASK; @@ -749,22 +693,28 @@ pci_set_powerstate(pci_chipset_tag_t pc, pcitag_t tag, pcireg_t state) value |= PCI_PMCSR_STATE_D0; break; case PCI_PMCSR_STATE_D1: - if (now == PCI_PMCSR_STATE_D2 || now == PCI_PMCSR_STATE_D3) + if (now == PCI_PMCSR_STATE_D2 || now == PCI_PMCSR_STATE_D3) { + printf("invalid transition from %d to D1\n", (int)now); return EINVAL; - if (!(cap & PCI_PMCR_D1SUPP)) + } + if (!(cap & PCI_PMCR_D1SUPP)) { + printf("D1 not supported\n"); return EOPNOTSUPP; + } value |= PCI_PMCSR_STATE_D1; break; case PCI_PMCSR_STATE_D2: - if (now == PCI_PMCSR_STATE_D3) + if (now == PCI_PMCSR_STATE_D3) { + printf("invalid transition from %d to D2\n", (int)now); return EINVAL; - if (!(cap & PCI_PMCR_D2SUPP)) + } + if (!(cap & PCI_PMCR_D2SUPP)) { + printf("D2 not supported\n"); return EOPNOTSUPP; + } value |= PCI_PMCSR_STATE_D2; break; case PCI_PMCSR_STATE_D3: - if (now == PCI_PMCSR_STATE_D3) - return 0; value |= PCI_PMCSR_STATE_D3; break; default: @@ -776,6 +726,20 @@ pci_set_powerstate(pci_chipset_tag_t pc, pcitag_t tag, pcireg_t state) } int +pci_set_powerstate(pci_chipset_tag_t pc, pcitag_t tag, pcireg_t state) +{ + int offset; + pcireg_t value; + + if (!pci_get_capability(pc, tag, PCI_CAP_PWRMGMT, &offset, &value)) { + printf("pci_set_powerstate not supported\n"); + return EOPNOTSUPP; + } + + return pci_set_powerstate_int(pc, tag, state, offset, value); +} + +int pci_activate(pci_chipset_tag_t pc, pcitag_t tag, void *sc, int (*wakefun)(pci_chipset_tag_t, pcitag_t, void *, pcireg_t)) { @@ -822,9 +786,6 @@ pci_activate_null(pci_chipset_tag_t pc, pcitag_t tag, return 0; } -CFATTACH_DECL2(pci, sizeof(struct pci_softc), - pcimatch, pciattach, NULL, NULL, pcirescan, pcidevdetached); - void pci_disable_retry(pci_chipset_tag_t pc, pcitag_t tag) { @@ -838,3 +799,90 @@ pci_disable_retry(pci_chipset_tag_t pc, pcitag_t tag) retry &= ~PCI_RETRY_TIMEOUT_REG_MASK; pci_conf_write(pc, tag, PCI_RETRY_TIMEOUT_REG, retry); } + +struct pci_child_power { + struct pci_conf_state p_pciconf; + pci_chipset_tag_t p_pc; + pcitag_t p_tag; + bool p_has_pm; + int p_pm_offset; + pcireg_t p_pm_cap; + pcireg_t p_class; +}; + +static bool +pci_child_suspend(device_t dv) +{ + struct pci_child_power *priv = device_pmf_bus_private(dv); + + pci_conf_capture(priv->p_pc, priv->p_tag, &priv->p_pciconf); + + if (priv->p_has_pm && + PCI_CLASS(priv->p_class) != PCI_CLASS_DISPLAY && + pci_set_powerstate_int(priv->p_pc, priv->p_tag, + PCI_PMCSR_STATE_D3, priv->p_pm_offset, priv->p_pm_cap)) { + aprint_error_dev(dv, "unsupported state, continuing.\n"); + return false; + } + return true; +} + +static bool +pci_child_resume(device_t dv) +{ + struct pci_child_power *priv = device_pmf_bus_private(dv); + + if (priv->p_has_pm && + pci_set_powerstate_int(priv->p_pc, priv->p_tag, + PCI_PMCSR_STATE_D0, priv->p_pm_offset, priv->p_pm_cap)) { + aprint_error_dev(dv, "unsupported state, continuing.\n"); + return false; + } + + pci_conf_restore(priv->p_pc, priv->p_tag, &priv->p_pciconf); + + return true; +} + +static void +pci_child_deregister(device_t dv) +{ + struct pci_child_power *priv = device_pmf_bus_private(dv); + + free(priv, M_DEVBUF); +} + +static bool +pci_child_register(device_t child) +{ + device_t self = device_parent(child); + struct pci_softc *sc = device_private(self); + struct pci_child_power *priv; + int device, function, off; + pcireg_t reg; + + priv = malloc(sizeof(*priv), M_DEVBUF, M_WAITOK); + + device = device_locator(child, PCICF_DEV); + function = device_locator(child, PCICF_FUNCTION); + + priv->p_pc = sc->sc_pc; + priv->p_tag = pci_make_tag(priv->p_pc, sc->sc_bus, device, + function); + priv->p_class = pci_conf_read(priv->p_pc, priv->p_tag, PCI_CLASS_REG); + + if (pci_get_capability(priv->p_pc, priv->p_tag, + PCI_CAP_PWRMGMT, &off, ®)) { + priv->p_has_pm = true; + priv->p_pm_offset = off; + priv->p_pm_cap = reg; + } else { + priv->p_has_pm = false; + priv->p_pm_offset = -1; + } + + device_pmf_bus_register(child, priv, pci_child_suspend, + pci_child_resume, pci_child_deregister); + + return true; +} diff --git a/sys/dev/pci/pcidevs.h b/sys/dev/pci/pcidevs.h index 723ada15ef0..a32e0d507e5 100644 --- a/sys/dev/pci/pcidevs.h +++ b/sys/dev/pci/pcidevs.h @@ -1,10 +1,10 @@ -/* $NetBSD: pcidevs.h,v 1.920 2007/11/26 09:36:29 bjs Exp $ */ +/* $NetBSD: pcidevs.h,v 1.921 2007/12/09 20:28:12 jmcneill Exp $ */ /* * THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT. * * generated from: - * NetBSD: pcidevs,v 1.919 2007/11/24 01:44:55 markd Exp + * NetBSD: pcidevs,v 1.885.6.10 2007/10/31 23:14:07 joerg Exp */ /* diff --git a/sys/dev/pci/pcidevs_data.h b/sys/dev/pci/pcidevs_data.h index 1268e2692f0..3e4a873da5a 100644 --- a/sys/dev/pci/pcidevs_data.h +++ b/sys/dev/pci/pcidevs_data.h @@ -1,10 +1,10 @@ -/* $NetBSD: pcidevs_data.h,v 1.919 2007/11/26 09:36:29 bjs Exp $ */ +/* $NetBSD: pcidevs_data.h,v 1.920 2007/12/09 20:28:12 jmcneill Exp $ */ /* * THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT. * * generated from: - * NetBSD: pcidevs,v 1.919 2007/11/24 01:44:55 markd Exp + * NetBSD: pcidevs,v 1.885.6.10 2007/10/31 23:14:07 joerg Exp */ /* diff --git a/sys/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h index 27b39cfd334..69900d1601f 100644 --- a/sys/dev/pci/pcivar.h +++ b/sys/dev/pci/pcivar.h @@ -1,4 +1,4 @@ -/* $NetBSD: pcivar.h,v 1.76 2007/11/12 19:54:36 joerg Exp $ */ +/* $NetBSD: pcivar.h,v 1.77 2007/12/09 20:28:12 jmcneill Exp $ */ /* * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. @@ -42,6 +42,7 @@ */ #include <sys/device.h> +#include <sys/pmf.h> #include <sys/bus.h> #include <dev/pci/pcireg.h> @@ -169,7 +170,6 @@ struct pci_softc { /* accounting of child devices */ struct device *sc_devices[32*8]; #define PCI_SC_DEVICESC(d, f) sc_devices[(d) * 8 + (f)] - void *sc_powerhook; }; struct pci_conf_state { diff --git a/sys/dev/pci/piixide.c b/sys/dev/pci/piixide.c index edb236ad8fe..3c449b8185c 100644 --- a/sys/dev/pci/piixide.c +++ b/sys/dev/pci/piixide.c @@ -1,4 +1,4 @@ -/* $NetBSD: piixide.c,v 1.41 2007/09/09 01:09:02 xtraeme Exp $ */ +/* $NetBSD: piixide.c,v 1.42 2007/12/09 20:28:12 jmcneill Exp $ */ /* * Copyright (c) 1999, 2000, 2001 Manuel Bouyer. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: piixide.c,v 1.41 2007/09/09 01:09:02 xtraeme Exp $"); +__KERNEL_RCSID(0, "$NetBSD: piixide.c,v 1.42 2007/12/09 20:28:12 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -50,7 +50,8 @@ static u_int32_t piix_setup_sidetim_timings(u_int8_t, u_int8_t, u_int8_t); static void piixsata_chip_map(struct pciide_softc*, struct pci_attach_args *); static int piix_dma_init(void *, int, int, void *, size_t, int); -static void piixide_powerhook(int, void *); +static bool piixide_resume(device_t); +static bool piixide_suspend(device_t); static int piixide_match(struct device *, struct cfdata *, void *); static void piixide_attach(struct device *, struct device *, void *); @@ -277,42 +278,34 @@ piixide_attach(struct device *parent, struct device *self, void *aux) pciide_common_attach(sc, pa, pciide_lookup_product(pa->pa_id, pciide_intel_products)); - /* Setup our powerhook */ - sc->sc_powerhook = powerhook_establish( - sc->sc_wdcdev.sc_atac.atac_dev.dv_xname, piixide_powerhook, sc); - if (sc->sc_powerhook == NULL) - printf("%s: WARNING: unable to establish PCI power hook\n", - sc->sc_wdcdev.sc_atac.atac_dev.dv_xname); + if (!pmf_device_register(self, piixide_suspend, piixide_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } -static void -piixide_powerhook(int why, void *hdl) +static bool +piixide_resume(device_t dv) { - struct pciide_softc *sc = (struct pciide_softc *)hdl; - - switch (why) { - case PWR_SUSPEND: - case PWR_STANDBY: - pci_conf_capture(sc->sc_pc, sc->sc_tag, &sc->sc_pciconf); - sc->sc_idetim = pci_conf_read(sc->sc_pc, sc->sc_tag, - PIIX_IDETIM); - sc->sc_udmatim = pci_conf_read(sc->sc_pc, sc->sc_tag, - PIIX_UDMATIM); - break; - case PWR_RESUME: - pci_conf_restore(sc->sc_pc, sc->sc_tag, &sc->sc_pciconf); - pci_conf_write(sc->sc_pc, sc->sc_tag, PIIX_IDETIM, - sc->sc_idetim); - pci_conf_write(sc->sc_pc, sc->sc_tag, PIIX_UDMATIM, - sc->sc_udmatim); - break; - case PWR_SOFTSUSPEND: - case PWR_SOFTSTANDBY: - case PWR_SOFTRESUME: - break; - } + struct pciide_softc *sc = device_private(dv); + + pci_conf_write(sc->sc_pc, sc->sc_tag, PIIX_IDETIM, + sc->sc_idetim); + pci_conf_write(sc->sc_pc, sc->sc_tag, PIIX_UDMATIM, + sc->sc_udmatim); + + return true; +} + +static bool +piixide_suspend(device_t dv) +{ + struct pciide_softc *sc = device_private(dv); + + sc->sc_idetim = pci_conf_read(sc->sc_pc, sc->sc_tag, + PIIX_IDETIM); + sc->sc_udmatim = pci_conf_read(sc->sc_pc, sc->sc_tag, + PIIX_UDMATIM); - return; + return true; } static void diff --git a/sys/dev/pci/piixpm.c b/sys/dev/pci/piixpm.c index 01e316c7cc9..019a997c733 100644 --- a/sys/dev/pci/piixpm.c +++ b/sys/dev/pci/piixpm.c @@ -1,4 +1,4 @@ -/* $NetBSD: piixpm.c,v 1.17 2007/10/19 12:00:54 ad Exp $ */ +/* $NetBSD: piixpm.c,v 1.18 2007/12/09 20:28:13 jmcneill Exp $ */ /* $OpenBSD: piixpm.c,v 1.20 2006/02/27 08:25:02 grange Exp $ */ /* @@ -73,15 +73,14 @@ struct piixpm_softc { volatile int error; } sc_i2c_xfer; - void * sc_powerhook; - struct pci_conf_state sc_pciconf; pcireg_t sc_devact[2]; }; int piixpm_match(struct device *, struct cfdata *, void *); void piixpm_attach(struct device *, struct device *, void *); -void piixpm_powerhook(int, void *); +static bool piixpm_suspend(device_t); +static bool piixpm_resume(device_t); int piixpm_i2c_acquire_bus(void *, int); void piixpm_i2c_release_bus(void *, int); @@ -150,11 +149,8 @@ piixpm_attach(struct device *parent, struct device *self, void *aux) aprint_normal("\n%s: %s (rev. 0x%02x)\n", device_xname(self), devinfo, PCI_REVISION(pa->pa_class)); - sc->sc_powerhook = powerhook_establish(sc->sc_dev.dv_xname, - piixpm_powerhook, sc); - if (sc->sc_powerhook == NULL) - aprint_error("%s: can't establish powerhook\n", - sc->sc_dev.dv_xname); + if (!pmf_device_register(self, piixpm_suspend, piixpm_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); /* Read configuration */ conf = pci_conf_read(pa->pa_pc, pa->pa_tag, PIIX_SMB_HOSTC); @@ -240,27 +236,30 @@ nopowermanagement: return; } -void -piixpm_powerhook(int why, void *cookie) +static bool +piixpm_suspend(device_t dv) { - struct piixpm_softc *sc = cookie; - pci_chipset_tag_t pc = sc->sc_pc; - pcitag_t tag = sc->sc_pcitag; - - switch (why) { - case PWR_SUSPEND: - pci_conf_capture(pc, tag, &sc->sc_pciconf); - sc->sc_devact[0] = pci_conf_read(pc, tag, PIIX_DEVACTA); - sc->sc_devact[1] = pci_conf_read(pc, tag, PIIX_DEVACTB); - break; - case PWR_RESUME: - pci_conf_restore(pc, tag, &sc->sc_pciconf); - pci_conf_write(pc, tag, PIIX_DEVACTA, sc->sc_devact[0]); - pci_conf_write(pc, tag, PIIX_DEVACTB, sc->sc_devact[1]); - break; - } + struct piixpm_softc *sc = device_private(dv); - return; + sc->sc_devact[0] = pci_conf_read(sc->sc_pc, sc->sc_pcitag, + PIIX_DEVACTA); + sc->sc_devact[1] = pci_conf_read(sc->sc_pc, sc->sc_pcitag, + PIIX_DEVACTB); + + return true; +} + +static bool +piixpm_resume(device_t dv) +{ + struct piixpm_softc *sc = device_private(dv); + + pci_conf_write(sc->sc_pc, sc->sc_pcitag, PIIX_DEVACTA, + sc->sc_devact[0]); + pci_conf_write(sc->sc_pc, sc->sc_pcitag, PIIX_DEVACTB, + sc->sc_devact[1]); + + return true; } int diff --git a/sys/dev/pci/ppb.c b/sys/dev/pci/ppb.c index be881da2510..ce4e4e5bbe6 100644 --- a/sys/dev/pci/ppb.c +++ b/sys/dev/pci/ppb.c @@ -1,4 +1,4 @@ -/* $NetBSD: ppb.c,v 1.35 2007/10/16 18:27:00 joerg Exp $ */ +/* $NetBSD: ppb.c,v 1.36 2007/12/09 20:28:13 jmcneill Exp $ */ /* * Copyright (c) 1996, 1998 Christopher G. Demetriou. All rights reserved. @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ppb.c,v 1.35 2007/10/16 18:27:00 joerg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ppb.c,v 1.36 2007/12/09 20:28:13 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -41,13 +41,19 @@ __KERNEL_RCSID(0, "$NetBSD: ppb.c,v 1.35 2007/10/16 18:27:00 joerg Exp $"); #include <dev/pci/pcireg.h> #include <dev/pci/pcivar.h> #include <dev/pci/ppbreg.h> +#include <dev/pci/pcidevs.h> struct ppb_softc { struct device sc_dev; /* generic device glue */ pci_chipset_tag_t sc_pc; /* our PCI chipset... */ pcitag_t sc_tag; /* ...and tag. */ + + pcireg_t sc_pciconfext[48]; }; +static bool ppb_resume(device_t); +static bool ppb_suspend(device_t); + static int ppbmatch(struct device *parent, struct cfdata *match, void *aux) @@ -67,12 +73,13 @@ ppbmatch(struct device *parent, struct cfdata *match, } static void -ppb_fix_pcix(device_t self, struct pci_attach_args *pa) +ppb_fix_pcix(device_t self) { + struct ppb_softc *sc = device_private(self); pcireg_t reg; int off; - if (!pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_PCIEXPRESS, + if (!pci_get_capability(sc->sc_pc, sc->sc_tag, PCI_CAP_PCIEXPRESS, &off, ®)) return; /* Not a PCIe device */ @@ -80,11 +87,11 @@ ppb_fix_pcix(device_t self, struct pci_attach_args *pa) aprint_normal_dev(self, "unuspported PCI Express version\n"); return; } - reg = pci_conf_read(pa->pa_pc, pa->pa_tag, off + 0x18); + reg = pci_conf_read(sc->sc_pc, sc->sc_tag, off + 0x18); if (reg & 0x003f) { aprint_normal_dev(self, "disabling notification events\n"); reg &= ~0x003f; - pci_conf_write(pa->pa_pc, pa->pa_tag, off + 0x18, reg); + pci_conf_write(sc->sc_pc, sc->sc_tag, off + 0x18, reg); } } @@ -114,7 +121,7 @@ ppbattach(struct device *parent, struct device *self, void *aux) return; } - ppb_fix_pcix(self, pa); + ppb_fix_pcix(self); #if 0 /* @@ -128,6 +135,9 @@ ppbattach(struct device *parent, struct device *self, void *aux) pa->pa_bus, PPB_BUSINFO_PRIMARY(busdata)); #endif + if (!pmf_device_register(self, ppb_suspend, ppb_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); + /* * Attach the PCI bus than hangs off of it. * @@ -148,5 +158,37 @@ ppbattach(struct device *parent, struct device *self, void *aux) config_found_ia(self, "pcibus", &pba, pcibusprint); } +static bool +ppb_resume(device_t dv) +{ + struct ppb_softc *sc = device_private(dv); + int off; + pcireg_t val; + + for (off = 0x40; off <= 0xff; off += 4) { + val = pci_conf_read(sc->sc_pc, sc->sc_tag, off); + if (val != sc->sc_pciconfext[(off - 0x40) / 4]) + pci_conf_write(sc->sc_pc, sc->sc_tag, off, + sc->sc_pciconfext[(off - 0x40)/4]); + } + + ppb_fix_pcix(dv); + + return true; +} + +static bool +ppb_suspend(device_t dv) +{ + struct ppb_softc *sc = device_private(dv); + int off; + + for (off = 0x40; off <= 0xff; off += 4) + sc->sc_pciconfext[(off - 0x40) / 4] = + pci_conf_read(sc->sc_pc, sc->sc_tag, off); + + return true; +} + CFATTACH_DECL(ppb, sizeof(struct ppb_softc), ppbmatch, ppbattach, NULL, NULL); diff --git a/sys/dev/pci/uhci_pci.c b/sys/dev/pci/uhci_pci.c index 5487e82e980..da4b535d296 100644 --- a/sys/dev/pci/uhci_pci.c +++ b/sys/dev/pci/uhci_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: uhci_pci.c,v 1.39 2007/11/25 02:46:54 dsainty Exp $ */ +/* $NetBSD: uhci_pci.c,v 1.40 2007/12/09 20:28:13 jmcneill Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -38,7 +38,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uhci_pci.c,v 1.39 2007/11/25 02:46:54 dsainty Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uhci_pci.c,v 1.40 2007/12/09 20:28:13 jmcneill Exp $"); #include "ehci.h" @@ -62,7 +62,7 @@ __KERNEL_RCSID(0, "$NetBSD: uhci_pci.c,v 1.39 2007/11/25 02:46:54 dsainty Exp $" #include <dev/usb/uhcireg.h> #include <dev/usb/uhcivar.h> -static void uhci_pci_powerhook(int, void *); +static bool uhci_pci_resume(device_t); struct uhci_pci_softc { uhci_softc_t sc; @@ -72,9 +72,6 @@ struct uhci_pci_softc { pci_chipset_tag_t sc_pc; pcitag_t sc_tag; void *sc_ih; /* interrupt vectoring */ - - void *sc_powerhook; - struct pci_conf_state sc_pciconf; }; static int @@ -189,15 +186,6 @@ uhci_pci_attach(struct device *parent, struct device *self, void *aux) snprintf(sc->sc.sc_vendor, sizeof(sc->sc.sc_vendor), "vendor 0x%04x", PCI_VENDOR(pa->pa_id)); - /* - * Establish our powerhook before uhci_init() does its powerhook. - */ - sc->sc_powerhook = powerhook_establish(USBDEVNAME(sc->sc.sc_bus.bdev), - uhci_pci_powerhook, sc); - if (sc->sc_powerhook == NULL) - aprint_error("%s: couldn't establish powerhook\n", - devname); - r = uhci_init(&sc->sc); if (r != USBD_NORMAL_COMPLETION) { aprint_error("%s: init failed, error=%d\n", devname, r); @@ -208,6 +196,9 @@ uhci_pci_attach(struct device *parent, struct device *self, void *aux) usb_pci_add(&sc->sc_pci, pa, &sc->sc.sc_bus); #endif + if (!pmf_device_register(self, uhci_suspend, uhci_pci_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); + /* Attach usb device. */ sc->sc.sc_child = config_found((void *)sc, &sc->sc.sc_bus, usbctlprint); @@ -219,8 +210,7 @@ uhci_pci_detach(device_ptr_t self, int flags) struct uhci_pci_softc *sc = (struct uhci_pci_softc *)self; int rv; - if (sc->sc_powerhook != NULL) - powerhook_disestablish(sc->sc_powerhook); + pmf_device_deregister(self); rv = uhci_detach(&sc->sc, flags); if (rv) @@ -239,34 +229,16 @@ uhci_pci_detach(device_ptr_t self, int flags) return (0); } -static void -uhci_pci_powerhook(int why, void *opaque) +static bool +uhci_pci_resume(device_t dv) { - struct uhci_pci_softc *sc; - pci_chipset_tag_t pc; - pcitag_t tag; - pcireg_t reg; - - sc = (struct uhci_pci_softc *)opaque; - pc = sc->sc_pc; - tag = sc->sc_tag; - - switch (why) { - case PWR_SUSPEND: - case PWR_STANDBY: - pci_conf_capture(pc, tag, &sc->sc_pciconf); - break; - case PWR_RESUME: - pci_conf_restore(pc, tag, &sc->sc_pciconf); - /* the BIOS might change this on us */ - reg = pci_conf_read(pc, tag, PCI_LEGSUP); - reg |= PCI_LEGSUP_USBPIRQDEN; - reg &= ~PCI_LEGSUP_USBSMIEN; - pci_conf_write(pc, tag, PCI_LEGSUP, reg); - break; - } + struct uhci_pci_softc *sc = device_private(dv); + + /* Set LEGSUP register to its default value. */ + pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_LEGSUP, + PCI_LEGSUP_USBPIRQDEN); - return; + return uhci_resume(dv); } CFATTACH_DECL(uhci_pci, sizeof(struct uhci_pci_softc), diff --git a/sys/dev/pci/vga_pci.c b/sys/dev/pci/vga_pci.c index 17f9714dfdb..f45ddf9274a 100644 --- a/sys/dev/pci/vga_pci.c +++ b/sys/dev/pci/vga_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: vga_pci.c,v 1.36 2007/12/01 17:00:41 ad Exp $ */ +/* $NetBSD: vga_pci.c,v 1.37 2007/12/09 20:28:13 jmcneill Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -28,7 +28,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: vga_pci.c,v 1.36 2007/12/01 17:00:41 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vga_pci.c,v 1.37 2007/12/09 20:28:13 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -69,11 +69,14 @@ struct vga_pci_softc { struct vga_bar sc_bars[NBARS]; struct vga_bar sc_rom; + + struct pci_conf_state sc_pciconf; }; static int vga_pci_match(struct device *, struct cfdata *, void *); static void vga_pci_attach(struct device *, struct device *, void *); static int vga_pci_lookup_quirks(struct pci_attach_args *); +static bool vga_pci_resume(device_t dv); CFATTACH_DECL(vga_pci, sizeof(struct vga_pci_softc), vga_pci_match, vga_pci_attach, NULL, NULL); @@ -218,9 +221,26 @@ vga_pci_attach(struct device *parent, struct device *self, void *aux) vga_common_attach(sc, pa->pa_iot, pa->pa_memt, WSDISPLAY_TYPE_PCIVGA, vga_pci_lookup_quirks(pa), &vga_pci_funcs); + /* + * XXX Do not use the generic PCI framework for now as + * XXX it would power down the device when the console + * XXX is still using it. + */ + if (!pmf_device_register(self, NULL, vga_pci_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); config_found_ia(self, "drm", aux, vga_drm_print); } +static bool +vga_pci_resume(device_t dv) +{ + struct vga_pci_softc *sc = device_private(dv); + + vga_resume(&sc->sc_vga); + + return true; +} + int vga_pci_cnattach(bus_space_tag_t iot, bus_space_tag_t memt, pci_chipset_tag_t pc, int bus, int device, diff --git a/sys/dev/pci/yds.c b/sys/dev/pci/yds.c index 08cb974906e..cac1c10ffa4 100644 --- a/sys/dev/pci/yds.c +++ b/sys/dev/pci/yds.c @@ -1,4 +1,4 @@ -/* $NetBSD: yds.c,v 1.38 2007/10/19 12:00:56 ad Exp $ */ +/* $NetBSD: yds.c,v 1.39 2007/12/09 20:28:13 jmcneill Exp $ */ /* * Copyright (c) 2000, 2001 Kazuki Sakamoto and Minoura Makoto. @@ -39,7 +39,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: yds.c,v 1.38 2007/10/19 12:00:56 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: yds.c,v 1.39 2007/12/09 20:28:13 jmcneill Exp $"); #include "mpu.h" @@ -192,7 +192,6 @@ static uint32_t yds_get_lpfk(u_int); static struct yds_dma *yds_find_dma(struct yds_softc *, void *); static int yds_init(struct yds_softc *); -static void yds_powerhook(int, void *); #ifdef AUDIO_DEBUG static void yds_dump_play_slot(struct yds_softc *, int); @@ -679,64 +678,48 @@ yds_init(struct yds_softc *sc) return 0; } -static void -yds_powerhook(int why, void *addr) +static bool +yds_suspend(device_t dv) { - struct yds_softc *sc; - pci_chipset_tag_t pc; - pcitag_t tag; - pcireg_t reg; - int s; + struct yds_softc *sc = device_private(dv); + pci_chipset_tag_t pc = sc->sc_pc; + pcitag_t tag = sc->sc_pcitag; - sc = (struct yds_softc *)addr; - pc = sc->sc_pc; - tag = sc->sc_pcitag; + sc->sc_dsctrl = pci_conf_read(pc, tag, YDS_PCI_DSCTRL); + sc->sc_legacy = pci_conf_read(pc, tag, YDS_PCI_LEGACY); + sc->sc_ba[0] = pci_conf_read(pc, tag, YDS_PCI_FM_BA); + sc->sc_ba[1] = pci_conf_read(pc, tag, YDS_PCI_MPU_BA); - s = splaudio(); - switch (why) { - case PWR_SUSPEND: - pci_conf_capture(pc, tag, &sc->sc_pciconf); + return true; +} - sc->sc_dsctrl = pci_conf_read(pc, tag, YDS_PCI_DSCTRL); - sc->sc_legacy = pci_conf_read(pc, tag, YDS_PCI_LEGACY); - sc->sc_ba[0] = pci_conf_read(pc, tag, YDS_PCI_FM_BA); - sc->sc_ba[1] = pci_conf_read(pc, tag, YDS_PCI_MPU_BA); - break; - case PWR_RESUME: - pci_conf_restore(pc, tag, &sc->sc_pciconf); - - /* Disable legacy mode */ - reg = pci_conf_read(pc, tag, YDS_PCI_LEGACY); - pci_conf_write(pc, tag, YDS_PCI_LEGACY, - reg & YDS_PCI_LEGACY_LAD); - - /* Enable the device. */ - reg = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); - reg |= (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE | - PCI_COMMAND_MASTER_ENABLE); - pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, reg); - reg = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); - if (yds_init(sc)) { - printf("%s: reinitialize failed\n", - sc->sc_dev.dv_xname); - splx(s); - return; - } - pci_conf_write(pc, tag, YDS_PCI_DSCTRL, sc->sc_dsctrl); - sc->sc_codec[0].codec_if->vtbl->restore_ports(sc->sc_codec[0].codec_if); - break; - case PWR_SOFTRESUME: - pci_conf_write(pc, tag, YDS_PCI_LEGACY, sc->sc_legacy); - pci_conf_write(pc, tag, YDS_PCI_FM_BA, sc->sc_ba[0]); - pci_conf_write(pc, tag, YDS_PCI_MPU_BA, sc->sc_ba[1]); -#if notyet - yds_configure_legacy(addr); -#endif - break; +static bool +yds_resume(device_t dv) +{ + struct yds_softc *sc = device_private(dv); + pci_chipset_tag_t pc = sc->sc_pc; + pcitag_t tag = sc->sc_pcitag; + pcireg_t reg; + + /* Disable legacy mode */ + reg = pci_conf_read(pc, tag, YDS_PCI_LEGACY); + pci_conf_write(pc, tag, YDS_PCI_LEGACY, reg & YDS_PCI_LEGACY_LAD); + + /* Enable the device. */ + reg = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); + reg |= (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE | + PCI_COMMAND_MASTER_ENABLE); + pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, reg); + reg = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); + if (yds_init(sc)) { + aprint_error_dev(dv, "reinitialize failed\n"); + return false; } - splx(s); - return; + pci_conf_write(pc, tag, YDS_PCI_DSCTRL, sc->sc_dsctrl); + sc->sc_codec[0].codec_if->vtbl->restore_ports(sc->sc_codec[0].codec_if); + + return true; } static void @@ -929,7 +912,8 @@ detected: sc->sc_legacy_iot = pa->pa_iot; config_defer((struct device*) sc, yds_configure_legacy); - powerhook_establish(sc->sc_dev.dv_xname, yds_powerhook, sc); + if (!pmf_device_register(self, yds_suspend, yds_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } static int diff --git a/sys/dev/pckbport/pckbd.c b/sys/dev/pckbport/pckbd.c index 46ab38c12d4..5ccccc32739 100644 --- a/sys/dev/pckbport/pckbd.c +++ b/sys/dev/pckbport/pckbd.c @@ -1,4 +1,4 @@ -/* $NetBSD: pckbd.c,v 1.17 2007/12/01 14:36:15 jmcneill Exp $ */ +/* $NetBSD: pckbd.c,v 1.18 2007/12/09 20:28:13 jmcneill Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -75,7 +75,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pckbd.c,v 1.17 2007/12/01 14:36:15 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pckbd.c,v 1.18 2007/12/09 20:28:13 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -126,12 +126,9 @@ struct pckbd_softc { #ifdef WSDISPLAY_COMPAT_RAWKBD int rawkbd; #endif - - void *sc_powerhook; }; static int pckbd_is_console(pckbport_tag_t, pckbport_slot_t); -static void pckbd_powerhook(int, void *); int pckbdprobe(struct device *, struct cfdata *, void *); void pckbdattach(struct device *, struct device *, void *); @@ -249,55 +246,55 @@ pckbd_is_console(pckbport_tag_t tag, pckbport_slot_t slot) tag == pckbd_consdata.t_kbctag && slot == pckbd_consdata.t_kbcslot; } -static void -pckbd_powerhook(int why, void *opaque) +static bool +pckbd_suspend(device_t dv) { - struct pckbd_softc *sc; + struct pckbd_softc *sc = device_private(dv); + u_char cmd[1]; int res; - u_char cmd[1], resp[1]; - sc = (struct pckbd_softc *)opaque; + /* XXX duped from pckbd_enable, but we want to disable + * it even if it's the console kbd + */ + cmd[0] = KBC_DISABLE; + res = pckbport_enqueue_cmd(sc->id->t_kbctag, + sc->id->t_kbcslot, cmd, 1, 0, 1, 0); + if (res) + return false; - switch (why) { - case PWR_STANDBY: - case PWR_SUSPEND: - printf("%s: suspending...\n", sc->sc_dev.dv_xname); - /* XXX duped from pckbd_enable, but we want to disable it - * even if it's the console kbd - */ - cmd[0] = KBC_DISABLE; - res = pckbport_enqueue_cmd(sc->id->t_kbctag, sc->id->t_kbcslot, - cmd, 1, 0, 1, 0); - if (res) - printf("pckbd_disable: command error\n"); + pckbport_slot_enable(sc->id->t_kbctag, + sc->id->t_kbcslot, 0); - pckbport_slot_enable(sc->id->t_kbctag, sc->id->t_kbcslot, 0); + sc->sc_enabled = 0; + return true; +} - sc->sc_enabled = 0; - break; - case PWR_RESUME: - printf("%s: resuming...\n", sc->sc_dev.dv_xname); +static bool +pckbd_resume(device_t dv) +{ + struct pckbd_softc *sc = device_private(dv); + u_char cmd[1], resp[1]; + int res; - /* XXX jmcneill reset the keyboard */ - cmd[0] = KBC_RESET; - res = pckbport_poll_cmd(sc->id->t_kbctag, sc->id->t_kbcslot, - cmd, 1, 1, resp, 1); + /* XXX jmcneill reset the keyboard */ + pckbport_flush(sc->id->t_kbctag, sc->id->t_kbcslot); + + cmd[0] = KBC_RESET; + res = pckbport_poll_cmd(sc->id->t_kbctag, + sc->id->t_kbcslot, cmd, 1, 1, resp, 1); #ifdef DEBUG - if (res) - printf("pckbdprobe: reset error %d\n", res); + if (res) + printf("pckbdprobe: reset error %d\n", res); #endif - if (resp[0] != KBR_RSTDONE) - printf("pckbdprobe: reset response 0x%x\n", resp[0]); - - pckbport_flush(sc->id->t_kbctag, sc->id->t_kbcslot); + if (resp[0] != KBR_RSTDONE) + printf("pckbdprobe: reset response 0x%x\n", + resp[0]); - pckbd_set_xtscancode(sc->id->t_kbctag, sc->id->t_kbcslot); + pckbport_flush(sc->id->t_kbctag, sc->id->t_kbcslot); - pckbd_enable(sc, 1); - break; - } + pckbd_enable(sc, 1); - return; + return true; } /* @@ -404,11 +401,8 @@ pckbdattach(struct device *parent, struct device *self, void *aux) a.accessops = &pckbd_accessops; a.accesscookie = sc; - sc->sc_powerhook = powerhook_establish(sc->sc_dev.dv_xname, - pckbd_powerhook, sc); - if (sc->sc_powerhook == NULL) - aprint_error("%s: unable to install powerhook\n", - sc->sc_dev.dv_xname); + if (!pmf_device_register(self, pckbd_suspend, pckbd_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); /* * Attach the wskbd, saving a handle to it. diff --git a/sys/dev/pckbport/pms.c b/sys/dev/pckbport/pms.c index 12b25da6e58..8dfaeb952b8 100644 --- a/sys/dev/pckbport/pms.c +++ b/sys/dev/pckbport/pms.c @@ -1,4 +1,4 @@ -/* $NetBSD: pms.c,v 1.21 2007/12/01 14:36:15 jmcneill Exp $ */ +/* $NetBSD: pms.c,v 1.22 2007/12/09 20:28:13 jmcneill Exp $ */ /*- * Copyright (c) 2004 Kentaro Kurahone. @@ -26,7 +26,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pms.c,v 1.21 2007/12/01 14:36:15 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pms.c,v 1.22 2007/12/09 20:28:13 jmcneill Exp $"); #include "opt_pms.h" @@ -85,9 +85,9 @@ static void pms_reset_thread(void*); int pms_enable(void *); int pms_ioctl(void *, u_long, void *, int, struct lwp *); void pms_disable(void *); -#ifndef PMS_DISABLE_POWERHOOK -void pms_power(int, void *); -#endif /* !PMS_DISABLE_POWERHOOK */ + +static bool pms_suspend(device_t); +static bool pms_resume(device_t); const struct wsmouse_accessops pms_accessops = { pms_enable, @@ -230,9 +230,10 @@ pmsattach(struct device *parent, struct device *self, void *aux) &sc->sc_event_thread, sc->sc_dev.dv_xname); #ifndef PMS_DISABLE_POWERHOOK - sc->sc_powerhook = powerhook_establish(self->dv_xname, pms_power, sc); sc->sc_suspended = 0; -#endif /* !PMS_DISABLE_POWERHOOK */ +#endif + if (!pmf_device_register(self, pms_suspend, pms_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); } static void @@ -334,43 +335,36 @@ pms_disable(void *v) splx(s); } -#ifndef PMS_DISABLE_POWERHOOK -void -pms_power(int why, void *v) +static bool +pms_suspend(device_t dv) { - struct pms_softc *sc = v; + struct pms_softc *sc = device_private(dv); + + if (sc->sc_enabled) + do_disable(sc); + + return true; +} + +static bool +pms_resume(device_t dv) +{ + struct pms_softc *sc = device_private(dv); - switch (why) { - case PWR_STANDBY: - break; - case PWR_SUSPEND: - if (sc->sc_enabled) { - do_disable(sc); - sc->sc_suspended = 1; - } - break; - case PWR_RESUME: #ifdef PMS_SYNAPTICS_TOUCHPAD - if (sc->protocol == PMS_SYNAPTICS) { - pms_synaptics_resume(sc); - sc->sc_suspended = 0; - do_enable(sc); - } + if (sc->protocol == PMS_SYNAPTICS) { + pms_synaptics_resume(sc); + do_enable(sc); + } else #endif - if (sc->sc_enabled && sc->sc_suspended) { - /* recheck protocol & init mouse */ - sc->protocol = PMS_UNKNOWN; - sc->sc_suspended = 0; - do_enable(sc); /* only if we were suspended */ - } - break; - case PWR_SOFTSUSPEND: - case PWR_SOFTSTANDBY: - case PWR_SOFTRESUME: - break; + if (sc->sc_enabled) { + /* recheck protocol & init mouse */ + sc->protocol = PMS_UNKNOWN; + do_enable(sc); /* only if we were suspended */ } + + return true; } -#endif /* !PMS_DISABLE_POWERHOOK */ int pms_ioctl(void *v, u_long cmd, void *data, int flag, diff --git a/sys/dev/pckbport/wskbdmap_mfii.c b/sys/dev/pckbport/wskbdmap_mfii.c index 8a7bcdbfeac..527d797c461 100644 --- a/sys/dev/pckbport/wskbdmap_mfii.c +++ b/sys/dev/pckbport/wskbdmap_mfii.c @@ -1,4 +1,4 @@ -/* $NetBSD: wskbdmap_mfii.c,v 1.11 2006/04/01 23:02:32 christos Exp $ */ +/* $NetBSD: wskbdmap_mfii.c,v 1.12 2007/12/09 20:28:13 jmcneill Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: wskbdmap_mfii.c,v 1.11 2006/04/01 23:02:32 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: wskbdmap_mfii.c,v 1.12 2007/12/09 20:28:13 jmcneill Exp $"); #include <sys/types.h> #include <dev/wscons/wsksymdef.h> @@ -136,7 +136,10 @@ static const keysym_t pckbd_keydesc_us[] = { KC(127), KS_Pause, /* Break */ KC(156), KS_KP_Enter, KC(157), KS_Control_R, + KC(160), KS_Cmd_VolumeToggle, KC(170), KS_Print_Screen, + KC(174), KS_Cmd_VolumeDown, + KC(176), KS_Cmd_VolumeUp, KC(181), KS_KP_Divide, KC(183), KS_Print_Screen, KC(184), KS_Alt_R, KS_Multi_key, diff --git a/sys/dev/pcmcia/if_an_pcmcia.c b/sys/dev/pcmcia/if_an_pcmcia.c index 2762f9c247c..6ebb53be71e 100644 --- a/sys/dev/pcmcia/if_an_pcmcia.c +++ b/sys/dev/pcmcia/if_an_pcmcia.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_an_pcmcia.c,v 1.32 2007/10/19 12:01:04 ad Exp $ */ +/* $NetBSD: if_an_pcmcia.c,v 1.33 2007/12/09 20:28:14 jmcneill Exp $ */ /*- * Copyright (c) 2000, 2004 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_an_pcmcia.c,v 1.32 2007/10/19 12:01:04 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_an_pcmcia.c,v 1.33 2007/12/09 20:28:14 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -84,7 +84,6 @@ struct an_pcmcia_softc { int sc_io_window; /* our i/o window */ struct pcmcia_function *sc_pf; /* our PCMCIA function */ void *sc_ih; /* interrupt handle */ - void *sc_powerhook; /* power hook descriptor */ int sc_state; #define AN_PCMCIA_ATTACHED 3 @@ -164,7 +163,10 @@ an_pcmcia_attach(struct device *parent, struct device *self, goto fail2; } - psc->sc_powerhook = powerhook_establish(self->dv_xname, an_power, sc); + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); + else + pmf_class_network_register(self, &sc->sc_if); an_pcmcia_disable(sc); sc->sc_enabled = 0; @@ -188,8 +190,7 @@ an_pcmcia_detach(struct device *self, int flags) if (psc->sc_state != AN_PCMCIA_ATTACHED) return (0); - if (psc->sc_powerhook) - powerhook_disestablish(psc->sc_powerhook); + pmf_device_deregister(self); error = an_detach(&psc->sc_an); if (error) diff --git a/sys/dev/pcmcia/if_ray.c b/sys/dev/pcmcia/if_ray.c index db6213f6387..4a04394654f 100644 --- a/sys/dev/pcmcia/if_ray.c +++ b/sys/dev/pcmcia/if_ray.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_ray.c,v 1.67 2007/10/19 12:01:05 ad Exp $ */ +/* $NetBSD: if_ray.c,v 1.68 2007/12/09 20:28:14 jmcneill Exp $ */ /* * Copyright (c) 2000 Christian E. Hopps @@ -57,7 +57,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_ray.c,v 1.67 2007/10/19 12:01:05 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_ray.c,v 1.68 2007/12/09 20:28:14 jmcneill Exp $"); #include "opt_inet.h" #include "bpfilter.h" @@ -158,12 +158,8 @@ struct ray_softc { struct pcmcia_function *sc_pf; void *sc_ih; - void *sc_sdhook; - void *sc_pwrhook; int sc_attached; - int sc_flags; /*. misc flags */ -#define RAY_FLAGS_RESUMEINIT 0x0001 int sc_resetloop; struct callout sc_check_ccs_ch; @@ -302,6 +298,7 @@ static u_int ray_find_free_tx_ccs(struct ray_softc *, u_int); static u_int8_t ray_free_ccs(struct ray_softc *, bus_size_t); static void ray_free_ccs_chain(struct ray_softc *, u_int); static void ray_if_start(struct ifnet *); +static void ray_if_stop(struct ifnet *, int); static int ray_init(struct ray_softc *); static int ray_intr(void *); static void ray_intr_start(struct ray_softc *); @@ -310,7 +307,6 @@ static int ray_issue_cmd(struct ray_softc *, bus_size_t, u_int); static int ray_match(struct device *, struct cfdata *, void *); static int ray_media_change(struct ifnet *); static void ray_media_status(struct ifnet *, struct ifmediareq *); -void ray_power(int, void *); static ray_cmd_func_t ray_rccs_intr(struct ray_softc *, bus_size_t); static void ray_read_region(struct ray_softc *, bus_size_t,void *,size_t); static void ray_recv(struct ray_softc *, bus_size_t); @@ -320,7 +316,6 @@ static void ray_reset(struct ray_softc *); static void ray_reset_resetloop(void *); static int ray_send_auth(struct ray_softc *, u_int8_t *, u_int8_t); static void ray_set_pending(struct ray_softc *, u_int); -static void ray_shutdown(void *); static int ray_simple_cmd(struct ray_softc *, u_int, u_int); static void ray_start_assoc(struct ray_softc *); static void ray_start_join_net(struct ray_softc *); @@ -571,7 +566,6 @@ ray_attach(struct device *parent, struct device *self, void *aux) sc->sc_omode = sc->sc_mode = RAY_MODE_DEFAULT; sc->sc_countrycode = sc->sc_dcountrycode = RAY_PID_COUNTRY_CODE_DEFAULT; - sc->sc_flags &= ~RAY_FLAGS_RESUMEINIT; /* * attach the interface @@ -590,6 +584,7 @@ ray_attach(struct device *parent, struct device *self, void *aux) memcpy(ifp->if_xname, self->dv_xname, IFNAMSIZ); ifp->if_softc = sc; ifp->if_start = ray_if_start; + ifp->if_stop = ray_if_stop; ifp->if_ioctl = ray_ioctl; ifp->if_mtu = ETHERMTU; ifp->if_flags = IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST; @@ -609,8 +604,10 @@ ray_attach(struct device *parent, struct device *self, void *aux) else ifmedia_set(&sc->sc_media, IFM_INFRA); - sc->sc_sdhook = shutdownhook_establish(ray_shutdown, sc); - sc->sc_pwrhook = powerhook_establish(self->dv_xname, ray_power, sc); + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); + else + pmf_class_network_register(self, ifp); /* The attach is successful. */ sc->sc_attached = 1; @@ -655,17 +652,14 @@ ray_detach(struct device *self, int flags) struct ray_softc *sc; struct ifnet *ifp; - sc = (struct ray_softc *)self; + sc = device_private(self); ifp = &sc->sc_if; RAY_DPRINTF(("%s: detach\n", sc->sc_xname)); if (!sc->sc_attached) return (0); - if (sc->sc_pwrhook) - powerhook_disestablish(sc->sc_pwrhook); - if (sc->sc_sdhook) - shutdownhook_disestablish(sc->sc_sdhook); + pmf_device_deregister(self); if (sc->sc_if.if_flags & IFF_UP) ray_disable(sc); @@ -760,7 +754,6 @@ ray_init(sc) sc->sc_running = 0; sc->sc_txfree = RAY_CCS_NTX; sc->sc_checkcounters = 0; - sc->sc_flags &= ~RAY_FLAGS_RESUMEINIT; sc->sc_authstate = RAY_AUTH_UNAUTH; /* get startup results */ @@ -878,42 +871,6 @@ ray_reset_resetloop(arg) sc->sc_resetloop = 0; } -void -ray_power(int why, void *arg) -{ -#if 0 - struct ray_softc *sc; - - /* can't do this until power hooks are called from thread */ - sc = arg; - switch (why) { - case PWR_RESUME: - if ((sc->sc_flags & RAY_FLAGS_RESUMEINIT)) - ray_init(sc); - break; - case PWR_SUSPEND: - if ((sc->sc_if.if_flags & IFF_RUNNING)) { - ray_stop(sc); - sc->sc_flags |= RAY_FLAGS_RESUMEINIT; - } - break; - case PWR_STANDBY: - default: - break; - } -#endif -} - -static void -ray_shutdown(arg) - void *arg; -{ - struct ray_softc *sc; - - sc = arg; - ray_disable(sc); -} - static int ray_ioctl(ifp, cmd, data) struct ifnet *ifp; @@ -1070,6 +1027,14 @@ ray_if_start(ifp) ray_intr_start(sc); } +static void +ray_if_stop(struct ifnet *ifp, int disable) +{ + struct ray_softc *sc = ifp->if_softc; + + ray_stop(sc); +} + static int ray_media_change(ifp) struct ifnet *ifp; diff --git a/sys/dev/pcmcia/if_wi_pcmcia.c b/sys/dev/pcmcia/if_wi_pcmcia.c index 769621aa38f..609c02df62d 100644 --- a/sys/dev/pcmcia/if_wi_pcmcia.c +++ b/sys/dev/pcmcia/if_wi_pcmcia.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_wi_pcmcia.c,v 1.76 2007/10/19 12:01:05 ad Exp $ */ +/* $NetBSD: if_wi_pcmcia.c,v 1.77 2007/12/09 20:28:14 jmcneill Exp $ */ /*- * Copyright (c) 2001, 2004 The NetBSD Foundation, Inc. @@ -41,7 +41,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_wi_pcmcia.c,v 1.76 2007/10/19 12:01:05 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_wi_pcmcia.c,v 1.77 2007/12/09 20:28:14 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -87,8 +87,6 @@ static void wi_pcmcia_attach(struct device *, struct device *, void *); static int wi_pcmcia_detach(struct device *, int); static int wi_pcmcia_enable(struct wi_softc *); static void wi_pcmcia_disable(struct wi_softc *); -static void wi_pcmcia_powerhook(int, void *); -static void wi_pcmcia_shutdown(void *); #if WI_PCMCIA_SPECTRUM24T_FW /* support to download firmware for symbol CF card */ @@ -100,8 +98,6 @@ static int wi_pcmcia_set_hcr(struct wi_softc *, int); struct wi_pcmcia_softc { struct wi_softc sc_wi; - void *sc_powerhook; /* power hook descriptor */ - void *sc_sdhook; /* shutdown hook */ int sc_symbol_cf; /* Spectrum24t CF card */ struct pcmcia_function *sc_pf; /* PCMCIA function */ @@ -392,9 +388,10 @@ wi_pcmcia_attach(struct device *parent, struct device *self, goto fail2; } - psc->sc_sdhook = shutdownhook_establish(wi_pcmcia_shutdown, psc); - psc->sc_powerhook = powerhook_establish(self->dv_xname, - wi_pcmcia_powerhook, psc); + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); + else + pmf_class_network_register(self, &sc->sc_if); wi_pcmcia_disable(sc); psc->sc_state = WI_PCMCIA_ATTACHED; @@ -415,11 +412,6 @@ wi_pcmcia_detach(struct device *self, int flags) if (psc->sc_state != WI_PCMCIA_ATTACHED) return (0); - if (psc->sc_powerhook) - powerhook_disestablish(psc->sc_powerhook); - if (psc->sc_sdhook) - shutdownhook_disestablish(psc->sc_sdhook); - error = wi_detach(&psc->sc_wi); if (error != 0) return (error); @@ -429,27 +421,6 @@ wi_pcmcia_detach(struct device *self, int flags) return (0); } -static void -wi_pcmcia_powerhook(why, arg) - int why; - void *arg; -{ - struct wi_pcmcia_softc *psc = arg; - struct wi_softc *sc = &psc->sc_wi; - - wi_power(sc, why); -} - -static void -wi_pcmcia_shutdown(arg) - void *arg; -{ - struct wi_pcmcia_softc *psc = arg; - struct wi_softc *sc = &psc->sc_wi; - - wi_shutdown(sc); -} - /* * Special routines to download firmware for Symbol CF card. * XXX: This should be modified generic into any PRISM-2 based card. diff --git a/sys/dev/pcmcia/pcmcia.c b/sys/dev/pcmcia/pcmcia.c index 67d579624d5..059fe6f69d2 100644 --- a/sys/dev/pcmcia/pcmcia.c +++ b/sys/dev/pcmcia/pcmcia.c @@ -1,4 +1,4 @@ -/* $NetBSD: pcmcia.c,v 1.83 2007/12/01 14:36:57 jmcneill Exp $ */ +/* $NetBSD: pcmcia.c,v 1.84 2007/12/09 20:28:14 jmcneill Exp $ */ /* * Copyright (c) 2004 Charles M. Hannum. All rights reserved. @@ -48,7 +48,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pcmcia.c,v 1.83 2007/12/01 14:36:57 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pcmcia.c,v 1.84 2007/12/09 20:28:14 jmcneill Exp $"); #include "opt_pcmciaverbose.h" @@ -56,6 +56,8 @@ __KERNEL_RCSID(0, "$NetBSD: pcmcia.c,v 1.83 2007/12/01 14:36:57 jmcneill Exp $") #include <sys/systm.h> #include <sys/device.h> +#include <net/if.h> + #include <dev/pcmcia/pcmciareg.h> #include <dev/pcmcia/pcmciachip.h> #include <dev/pcmcia/pcmciavar.h> @@ -138,6 +140,9 @@ pcmcia_attach(struct device *parent, struct device *self, void *aux) sc->iosize = paa->iosize; sc->ih = NULL; + + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); } int diff --git a/sys/dev/rasops/rasops.c b/sys/dev/rasops/rasops.c index 5008b4beb37..1cd1961927b 100644 --- a/sys/dev/rasops/rasops.c +++ b/sys/dev/rasops/rasops.c @@ -1,4 +1,4 @@ -/* $NetBSD: rasops.c,v 1.56 2007/07/28 20:28:57 mjf Exp $ */ +/* $NetBSD: rasops.c,v 1.57 2007/12/09 20:28:14 jmcneill Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rasops.c,v 1.56 2007/07/28 20:28:57 mjf Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rasops.c,v 1.57 2007/12/09 20:28:14 jmcneill Exp $"); #include "opt_rasops.h" #include "rasops_glue.h" @@ -945,8 +945,10 @@ rasops_do_cursor(ri) *(int32_t *)dp ^= ~0; dp += 4; if (ri->ri_hwbits) { - *(int32_t *)hp ^= ~0; + dp -= 4; + *(int32_t *)hp = *(int32_t *)dp; hp += 4; + dp += 4; } } } @@ -962,16 +964,19 @@ rasops_do_cursor(ri) if (slop1 & 1) { *dp++ ^= ~0; - if (ri->ri_hwbits) - *hp++ ^= ~0; + if (ri->ri_hwbits) { + *hp++ = *(dp - 1); + } } if (slop1 & 2) { *(int16_t *)dp ^= ~0; dp += 2; if (ri->ri_hwbits) { - *(int16_t *)hp ^= ~0; + dp -= 2; + *(int16_t *)hp = *(int16_t *)dp; hp += 2; + dp += 2; } } @@ -979,21 +984,23 @@ rasops_do_cursor(ri) *(int32_t *)dp ^= ~0; dp += 4; if (ri->ri_hwbits) { - *(int32_t *)hp ^= ~0; + dp -= 4; + *(int32_t *)hp = *(int32_t *)dp; hp += 4; + dp += 4; } } if (slop2 & 1) { *dp++ ^= ~0; if (ri->ri_hwbits) - *hp++ ^= ~0; + *hp++ = *(dp - 1); } if (slop2 & 2) { *(int16_t *)dp ^= ~0; if (ri->ri_hwbits) - *(int16_t *)hp ^= ~0; + *(int16_t *)hp = *(int16_t *)(dp - 2); } } } diff --git a/sys/dev/rasops/rasops8.c b/sys/dev/rasops/rasops8.c index 1fe5f08d4ec..f5d01a1e375 100644 --- a/sys/dev/rasops/rasops8.c +++ b/sys/dev/rasops/rasops8.c @@ -1,4 +1,4 @@ -/* $NetBSD: rasops8.c,v 1.22 2007/03/04 06:02:39 christos Exp $ */ +/* $NetBSD: rasops8.c,v 1.23 2007/12/09 20:28:14 jmcneill Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rasops8.c,v 1.22 2007/03/04 06:02:39 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rasops8.c,v 1.23 2007/12/09 20:28:14 jmcneill Exp $"); #include "opt_rasops.h" @@ -289,7 +289,8 @@ rasops8_putchar8(cookie, row, col, uc, attr) rp[0] = rp[1] = stamp[0]; DELTA(rp, ri->ri_stride, int32_t *); if (ri->ri_hwbits) { - hp[0] = hp[1] = stamp[0]; + hp[0] = stamp[0]; + hp[1] = stamp[0]; DELTA(hp, ri->ri_stride, int32_t *); } } @@ -321,7 +322,8 @@ rasops8_putchar8(cookie, row, col, uc, attr) rp[0] = rp[1] = stamp[15]; if (ri->ri_hwbits) { DELTA(hp, -(ri->ri_stride << 1), int32_t *); - hp[0] = hp[1] = stamp[15]; + hp[0] = stamp[15]; + hp[1] = stamp[15]; } } @@ -385,7 +387,9 @@ rasops8_putchar12(cookie, row, col, uc, attr) rp[0] = rp[1] = rp[2] = c; DELTA(rp, ri->ri_stride, int32_t *); if (ri->ri_hwbits) { - hrp[0] = hrp[1] = hrp[2] = c; + hrp[0] = c; + hrp[1] = c; + hrp[2] = c; DELTA(hrp, ri->ri_stride, int32_t *); } } @@ -417,7 +421,9 @@ rasops8_putchar12(cookie, row, col, uc, attr) rp[0] = rp[1] = rp[2] = stamp[15]; if (ri->ri_hwbits) { DELTA(hrp, -(ri->ri_stride << 1), int32_t *); - hrp[0] = hrp[1] = hrp[2] = stamp[15]; + hrp[0] = stamp[15]; + hrp[1] = stamp[15]; + hrp[2] = stamp[15]; } } @@ -478,8 +484,12 @@ rasops8_putchar16(cookie, row, col, uc, attr) if (uc == ' ') { while (height--) { rp[0] = rp[1] = rp[2] = rp[3] = stamp[0]; - if (ri->ri_hwbits) - hrp[0] = hrp[1] = hrp[2] = hrp[3] = stamp[0]; + if (ri->ri_hwbits) { + hrp[0] = stamp[0]; + hrp[1] = stamp[0]; + hrp[2] = stamp[0]; + hrp[3] = stamp[0]; + } } } else { uc -= ri->ri_font->firstchar; @@ -511,7 +521,10 @@ rasops8_putchar16(cookie, row, col, uc, attr) rp[0] = rp[1] = rp[2] = rp[3] = stamp[15]; if (ri->ri_hwbits) { DELTA(hrp, -(ri->ri_stride << 1), int32_t *); - hrp[0] = hrp[1] = hrp[2] = hrp[3] = stamp[15]; + hrp[0] = stamp[15]; + hrp[1] = stamp[15]; + hrp[2] = stamp[15]; + hrp[3] = stamp[15]; } } diff --git a/sys/dev/scsipi/atapiconf.c b/sys/dev/scsipi/atapiconf.c index 8e85012215f..21bbd59d3bf 100644 --- a/sys/dev/scsipi/atapiconf.c +++ b/sys/dev/scsipi/atapiconf.c @@ -1,4 +1,4 @@ -/* $NetBSD: atapiconf.c,v 1.73 2007/12/01 14:46:04 jmcneill Exp $ */ +/* $NetBSD: atapiconf.c,v 1.74 2007/12/09 20:28:22 jmcneill Exp $ */ /* * Copyright (c) 1996, 2001 Manuel Bouyer. All rights reserved. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: atapiconf.c,v 1.73 2007/12/01 14:46:04 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: atapiconf.c,v 1.74 2007/12/09 20:28:22 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -162,6 +162,9 @@ atapibusattach(struct device *parent, struct device *self, void *aux) chan->chan_init_cb_arg = NULL; scsipi_channel_init(chan); + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); + /* Probe the bus for devices. */ atapi_probe_bus(sc, -1); } diff --git a/sys/dev/scsipi/cd.c b/sys/dev/scsipi/cd.c index dc5dfa379f7..7f0f12731df 100644 --- a/sys/dev/scsipi/cd.c +++ b/sys/dev/scsipi/cd.c @@ -1,4 +1,4 @@ -/* $NetBSD: cd.c,v 1.270 2007/11/27 18:06:37 reinoud Exp $ */ +/* $NetBSD: cd.c,v 1.271 2007/12/09 20:28:22 jmcneill Exp $ */ /*- * Copyright (c) 1998, 2001, 2003, 2004, 2005 The NetBSD Foundation, Inc. @@ -57,7 +57,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: cd.c,v 1.270 2007/11/27 18:06:37 reinoud Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cd.c,v 1.271 2007/12/09 20:28:22 jmcneill Exp $"); #include "rnd.h" @@ -289,6 +289,9 @@ cdattach(struct device *parent, struct device *self, void *aux) rnd_attach_source(&cd->rnd_source, cd->sc_dev.dv_xname, RND_TYPE_DISK, 0); #endif + + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); } static int @@ -3485,4 +3488,3 @@ mmc_gettrackinfo(struct scsipi_periph *periph, return 0; } - diff --git a/sys/dev/scsipi/scsiconf.c b/sys/dev/scsipi/scsiconf.c index 21057d8d322..4b36b440f6a 100644 --- a/sys/dev/scsipi/scsiconf.c +++ b/sys/dev/scsipi/scsiconf.c @@ -1,4 +1,4 @@ -/* $NetBSD: scsiconf.c,v 1.243 2007/03/04 06:02:42 christos Exp $ */ +/* $NetBSD: scsiconf.c,v 1.244 2007/12/09 20:28:22 jmcneill Exp $ */ /*- * Copyright (c) 1998, 1999, 2004 The NetBSD Foundation, Inc. @@ -55,7 +55,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: scsiconf.c,v 1.243 2007/03/04 06:02:42 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: scsiconf.c,v 1.244 2007/12/09 20:28:22 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -166,6 +166,9 @@ scsibusattach(struct device *parent, struct device *self, void *aux) struct scsipi_channel *chan = aux; struct scsi_initq *scsi_initq; + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); + sc->sc_channel = chan; chan->chan_name = sc->sc_dev.dv_xname; @@ -285,6 +288,7 @@ scsibusdetach(struct device *self, int flags) struct scsipi_xfer *xs; int error; + pmf_device_deregister(self); /* * Process outstanding commands (which will never complete as the diff --git a/sys/dev/scsipi/sd.c b/sys/dev/scsipi/sd.c index 252f1c42c45..31ca48e508d 100644 --- a/sys/dev/scsipi/sd.c +++ b/sys/dev/scsipi/sd.c @@ -1,4 +1,4 @@ -/* $NetBSD: sd.c,v 1.267 2007/10/08 16:41:14 ad Exp $ */ +/* $NetBSD: sd.c,v 1.268 2007/12/09 20:28:23 jmcneill Exp $ */ /*- * Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc. @@ -54,7 +54,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sd.c,v 1.267 2007/10/08 16:41:14 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sd.c,v 1.268 2007/12/09 20:28:23 jmcneill Exp $"); #include "opt_scsi.h" #include "rnd.h" @@ -107,7 +107,7 @@ static int sdgetdisklabel(struct sd_softc *); static void sdstart(struct scsipi_periph *); static void sdrestart(void *); static void sddone(struct scsipi_xfer *, int); -static void sd_shutdown(void *); +static bool sd_suspend(device_t); static int sd_interpret_sense(struct scsipi_xfer *); static int sd_mode_sense(struct sd_softc *, u_int8_t, void *, size_t, int, @@ -306,18 +306,8 @@ sdattach(struct device *parent, struct device *self, void *aux) } aprint_normal("\n"); - /* - * Establish a shutdown hook so that we can ensure that - * our data has actually made it onto the platter at - * shutdown time. Note that this relies on the fact - * that the shutdown hook code puts us at the head of - * the list (thus guaranteeing that our hook runs before - * our ancestors'). - */ - if ((sd->sc_sdhook = - shutdownhook_establish(sd_shutdown, sd)) == NULL) - aprint_error("%s: WARNING: unable to establish shutdown hook\n", - sd->sc_dev.dv_xname); + if (!pmf_device_register(self, sd_suspend, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); #if NRND > 0 /* @@ -391,8 +381,7 @@ sddetach(struct device *self, int flags) disk_detach(&sd->sc_dk); disk_destroy(&sd->sc_dk); - /* Get rid of the shutdown hook. */ - shutdownhook_disestablish(sd->sc_sdhook); + pmf_device_deregister(self); #if NRND > 0 /* Unhook the entropy source. */ @@ -1324,10 +1313,10 @@ sdgetdisklabel(struct sd_softc *sd) return 0; } -static void -sd_shutdown(void *arg) +static bool +sd_suspend(device_t dv) { - struct sd_softc *sd = arg; + struct sd_softc *sd = device_private(dv); /* * If the disk cache needs to be flushed, and the disk supports @@ -1342,6 +1331,8 @@ sd_shutdown(void *arg) } else sd->flags &= ~(SDF_FLUSHING|SDF_DIRTY); } + + return true; } /* diff --git a/sys/dev/sysmon/sysmon_power.c b/sys/dev/sysmon/sysmon_power.c index e975082a0a7..d75539bc6dc 100644 --- a/sys/dev/sysmon/sysmon_power.c +++ b/sys/dev/sysmon/sysmon_power.c @@ -1,4 +1,4 @@ -/* $NetBSD: sysmon_power.c,v 1.32 2007/12/05 17:19:54 pooka Exp $ */ +/* $NetBSD: sysmon_power.c,v 1.33 2007/12/09 20:28:23 jmcneill Exp $ */ /*- * Copyright (c) 2007 Juan Romero Pardines. @@ -69,7 +69,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sysmon_power.c,v 1.32 2007/12/05 17:19:54 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sysmon_power.c,v 1.33 2007/12/09 20:28:23 jmcneill Exp $"); #include "opt_compat_netbsd.h" #include <sys/param.h> @@ -896,6 +896,23 @@ sysmon_pswitch_event(struct sysmon_pswitch *smpsw, int event) KASSERT(smpsw != NULL); + /* + * For pnp specific events, we don't care if the power daemon + * is running or not + */ + if (smpsw->smpsw_type == PSWITCH_TYPE_LID) { + switch (event) { + case PSWITCH_EVENT_PRESSED: + pmf_event_inject(NULL, PMFE_CHASSIS_LID_CLOSE); + break; + case PSWITCH_EVENT_RELEASED: + pmf_event_inject(NULL, PMFE_CHASSIS_LID_OPEN); + break; + default: + break; + } + } + if (sysmon_power_daemon != NULL) { /* * Create a new dictionary for the event. diff --git a/sys/dev/usb/ehci.c b/sys/dev/usb/ehci.c index 48b248bc268..5fd95361483 100644 --- a/sys/dev/usb/ehci.c +++ b/sys/dev/usb/ehci.c @@ -1,4 +1,4 @@ -/* $NetBSD: ehci.c,v 1.126 2007/12/05 07:15:53 ad Exp $ */ +/* $NetBSD: ehci.c,v 1.127 2007/12/09 20:28:23 jmcneill Exp $ */ /* * Copyright (c) 2004,2005 The NetBSD Foundation, Inc. @@ -61,7 +61,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.126 2007/12/05 07:15:53 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.127 2007/12/09 20:28:23 jmcneill Exp $"); #include "ohci.h" #include "uhci.h" @@ -129,7 +129,6 @@ struct ehci_pipe { }; Static void ehci_shutdown(void *); -Static void ehci_power(int, void *); Static usbd_status ehci_open(usbd_pipe_handle); Static void ehci_poll(struct usbd_bus *); @@ -416,8 +415,6 @@ ehci_init(ehci_softc_t *sc) sc->sc_bus.methods = &ehci_bus_methods; sc->sc_bus.pipe_size = sizeof(struct ehci_pipe); - sc->sc_powerhook = powerhook_establish(USBDEVNAME(sc->sc_bus.bdev), - ehci_power, sc); sc->sc_shutdownhook = shutdownhook_establish(ehci_shutdown, sc); sc->sc_eintrs = EHCI_NORMAL_INTRS; @@ -539,7 +536,7 @@ ehci_intr(void *v) { ehci_softc_t *sc = v; - if (sc == NULL || sc->sc_dying) + if (sc == NULL || sc->sc_dying || !device_has_power(&sc->sc_bus.bdev)) return (0); /* If we get an interrupt while polling, then just ignore it. */ @@ -925,8 +922,6 @@ ehci_detach(struct ehci_softc *sc, int flags) usb_uncallout(sc->sc_tmo_intrlist, ehci_intrlist_timeout, sc); - if (sc->sc_powerhook != NULL) - powerhook_disestablish(sc->sc_powerhook); if (sc->sc_shutdownhook != NULL) shutdownhook_disestablish(sc->sc_shutdownhook); @@ -964,102 +959,122 @@ ehci_activate(device_ptr_t self, enum devact act) * We need to switch to polling mode here, because this routine is * called from an interrupt context. This is all right since we * are almost suspended anyway. + * + * Note that this power handler isn't to be registered directly; the + * bus glue needs to call out to it. */ -void -ehci_power(int why, void *v) +bool +ehci_suspend(device_t dv) { - ehci_softc_t *sc = v; - u_int32_t cmd, hcr; - int s, i; - -#ifdef EHCI_DEBUG - DPRINTF(("ehci_power: sc=%p, why=%d\n", sc, why)); - if (ehcidebug > 0) - ehci_dump_regs(sc); -#endif + ehci_softc_t *sc = (ehci_softc_t *)dv; + int i, s; + uint32_t cmd, hcr; s = splhardusb(); - switch (why) { - case PWR_SUSPEND: - case PWR_STANDBY: - sc->sc_bus.use_polling++; - sc->sc_cmd = EOREAD4(sc, EHCI_USBCMD); + sc->sc_bus.use_polling++; - cmd = sc->sc_cmd & ~(EHCI_CMD_ASE | EHCI_CMD_PSE); - EOWRITE4(sc, EHCI_USBCMD, cmd); + for (i = 1; i <= sc->sc_noport; i++) { + cmd = EOREAD4(sc, EHCI_PORTSC(i)); + if ((cmd & EHCI_PS_PO) == 0 && (cmd & EHCI_PS_PE) == EHCI_PS_PE) + EOWRITE4(sc, EHCI_PORTSC(i), cmd | EHCI_PS_SUSP); + } - for (i = 0; i < 100; i++) { - hcr = EOREAD4(sc, EHCI_USBSTS) & - (EHCI_STS_ASS | EHCI_STS_PSS); - if (hcr == 0) - break; + sc->sc_cmd = EOREAD4(sc, EHCI_USBCMD); - usb_delay_ms(&sc->sc_bus, 1); - } - if (hcr != 0) { - printf("%s: reset timeout\n", - USBDEVNAME(sc->sc_bus.bdev)); - } + cmd = sc->sc_cmd & ~(EHCI_CMD_ASE | EHCI_CMD_PSE); + EOWRITE4(sc, EHCI_USBCMD, cmd); - cmd &= ~EHCI_CMD_RS; - EOWRITE4(sc, EHCI_USBCMD, cmd); + for (i = 0; i < 100; i++) { + hcr = EOREAD4(sc, EHCI_USBSTS) & (EHCI_STS_ASS | EHCI_STS_PSS); + if (hcr == 0) + break; - for (i = 0; i < 100; i++) { - hcr = EOREAD4(sc, EHCI_USBSTS) & EHCI_STS_HCH; - if (hcr == EHCI_STS_HCH) - break; + usb_delay_ms(&sc->sc_bus, 1); + } + if (hcr != 0) + printf("%s: reset timeout\n", USBDEVNAME(sc->sc_bus.bdev)); - usb_delay_ms(&sc->sc_bus, 1); - } - if (hcr != EHCI_STS_HCH) { - printf("%s: config timeout\n", - USBDEVNAME(sc->sc_bus.bdev)); - } + cmd &= ~EHCI_CMD_RS; + EOWRITE4(sc, EHCI_USBCMD, cmd); - sc->sc_bus.use_polling--; - break; + for (i = 0; i < 100; i++) { + hcr = EOREAD4(sc, EHCI_USBSTS) & EHCI_STS_HCH; + if (hcr == EHCI_STS_HCH) + break; - case PWR_RESUME: - sc->sc_bus.use_polling++; + usb_delay_ms(&sc->sc_bus, 1); + } + if (hcr != EHCI_STS_HCH) + printf("%s: config timeout\n", USBDEVNAME(sc->sc_bus.bdev)); - /* restore things in case the bios sucks */ - EOWRITE4(sc, EHCI_CTRLDSSEGMENT, 0); - EOWRITE4(sc, EHCI_PERIODICLISTBASE, DMAADDR(&sc->sc_fldma, 0)); - EOWRITE4(sc, EHCI_ASYNCLISTADDR, - sc->sc_async_head->physaddr | EHCI_LINK_QH); - EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs); + sc->sc_bus.use_polling--; + splx(s); - EOWRITE4(sc, EHCI_USBCMD, sc->sc_cmd); + return true; +} - for (i = 0; i < 100; i++) { - hcr = EOREAD4(sc, EHCI_USBSTS) & EHCI_STS_HCH; - if (hcr != EHCI_STS_HCH) - break; +bool +ehci_resume(device_t dv) +{ + ehci_softc_t *sc = (ehci_softc_t *)dv; + int i, s; + uint32_t cmd, hcr; - usb_delay_ms(&sc->sc_bus, 1); - } - if (hcr == EHCI_STS_HCH) { - printf("%s: config timeout\n", - USBDEVNAME(sc->sc_bus.bdev)); + s = splhardusb(); + + sc->sc_bus.use_polling++; + + /* restore things in case the bios sucks */ + EOWRITE4(sc, EHCI_CTRLDSSEGMENT, 0); + EOWRITE4(sc, EHCI_PERIODICLISTBASE, DMAADDR(&sc->sc_fldma, 0)); + EOWRITE4(sc, EHCI_ASYNCLISTADDR, + sc->sc_async_head->physaddr | EHCI_LINK_QH); + EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs); + + EOWRITE4(sc, EHCI_USBCMD, sc->sc_cmd); + + hcr = 0; + for (i = 1; i <= sc->sc_noport; i++) { + cmd = EOREAD4(sc, EHCI_PORTSC(i)); + if ((cmd & EHCI_PS_PO) == 0 && + (cmd & EHCI_PS_SUSP) == EHCI_PS_SUSP) { + EOWRITE4(sc, EHCI_PORTSC(i), cmd | EHCI_PS_FPR); + hcr = 1; } + } + if (hcr) { usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT); - sc->sc_bus.use_polling--; - break; - case PWR_SOFTSUSPEND: - case PWR_SOFTSTANDBY: - case PWR_SOFTRESUME: - break; + for (i = 1; i <= sc->sc_noport; i++) { + cmd = EOREAD4(sc, EHCI_PORTSC(i)); + if ((cmd & EHCI_PS_PO) == 0 && + (cmd & EHCI_PS_SUSP) == EHCI_PS_SUSP) + EOWRITE4(sc, EHCI_PORTSC(i), + cmd & ~EHCI_PS_FPR); + } } + + EOWRITE4(sc, EHCI_USBCMD, sc->sc_cmd); + + for (i = 0; i < 100; i++) { + hcr = EOREAD4(sc, EHCI_USBSTS) & EHCI_STS_HCH; + if (hcr != EHCI_STS_HCH) + break; + + usb_delay_ms(&sc->sc_bus, 1); + } + if (hcr == EHCI_STS_HCH) + printf("%s: config timeout\n", USBDEVNAME(sc->sc_bus.bdev)); + + usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT); + + sc->sc_bus.use_polling--; + splx(s); -#ifdef EHCI_DEBUG - DPRINTF(("ehci_power: sc=%p\n", sc)); - if (ehcidebug > 0) - ehci_dump_regs(sc); -#endif + return true; } /* diff --git a/sys/dev/usb/ehcivar.h b/sys/dev/usb/ehcivar.h index fc80e45bb4e..a88beafbebb 100644 --- a/sys/dev/usb/ehcivar.h +++ b/sys/dev/usb/ehcivar.h @@ -1,4 +1,4 @@ -/* $NetBSD: ehcivar.h,v 1.25 2007/12/05 07:15:54 ad Exp $ */ +/* $NetBSD: ehcivar.h,v 1.26 2007/12/09 20:28:23 jmcneill Exp $ */ /* * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -97,7 +97,6 @@ typedef struct ehci_softc { int sc_id_vendor; /* vendor ID for root hub */ u_int32_t sc_cmd; /* shadow of cmd reg during suspend */ - void *sc_powerhook; /* cookie from power hook */ void *sc_shutdownhook; /* cookie from shutdown hook */ u_int sc_ncomp; @@ -161,3 +160,5 @@ usbd_status ehci_init(ehci_softc_t *); int ehci_intr(void *); int ehci_detach(ehci_softc_t *, int); int ehci_activate(device_ptr_t, enum devact); +bool ehci_suspend(device_t dv); +bool ehci_resume(device_t dv); diff --git a/sys/dev/usb/if_rum.c b/sys/dev/usb/if_rum.c index 5cff532ab84..8e46a81f096 100644 --- a/sys/dev/usb/if_rum.c +++ b/sys/dev/usb/if_rum.c @@ -1,5 +1,5 @@ -/* $OpenBSD: if_rum.c,v 1.65 2007/09/07 19:05:05 damien Exp $ */ -/* $NetBSD: if_rum.c,v 1.18 2007/11/25 09:30:10 kiyohara Exp $ */ +/* $OpenBSD: if_rum.c,v 1.40 2006/09/18 16:20:20 damien Exp $ */ +/* $NetBSD: if_rum.c,v 1.19 2007/12/09 20:28:23 jmcneill Exp $ */ /*- * Copyright (c) 2005-2007 Damien Bergamini <damien.bergamini@free.fr> @@ -24,7 +24,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_rum.c,v 1.18 2007/11/25 09:30:10 kiyohara Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_rum.c,v 1.19 2007/12/09 20:28:23 jmcneill Exp $"); #include "bpfilter.h" diff --git a/sys/dev/usb/ohci.c b/sys/dev/usb/ohci.c index ffed3e114a0..dcc9fc1bad8 100644 --- a/sys/dev/usb/ohci.c +++ b/sys/dev/usb/ohci.c @@ -1,4 +1,4 @@ -/* $NetBSD: ohci.c,v 1.184 2007/10/19 12:01:21 ad Exp $ */ +/* $NetBSD: ohci.c,v 1.185 2007/12/09 20:28:23 jmcneill Exp $ */ /* $FreeBSD: src/sys/dev/usb/ohci.c,v 1.22 1999/11/17 22:33:40 n_hibma Exp $ */ /* @@ -48,7 +48,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ohci.c,v 1.184 2007/10/19 12:01:21 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ohci.c,v 1.185 2007/12/09 20:28:23 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -137,7 +137,6 @@ Static usbd_status ohci_alloc_std_chain(struct ohci_pipe *, ohci_soft_td_t *, ohci_soft_td_t **); Static void ohci_shutdown(void *v); -Static void ohci_power(int, void *); Static usbd_status ohci_open(usbd_pipe_handle); Static void ohci_poll(struct usbd_bus *); Static void ohci_softintr(void *); @@ -396,7 +395,6 @@ ohci_detach(struct ohci_softc *sc, int flags) usb_uncallout(sc->sc_tmo_rhsc, ohci_rhsc_enable, sc); #if defined(__NetBSD__) || defined(__OpenBSD__) - powerhook_disestablish(sc->sc_powerhook); shutdownhook_disestablish(sc->sc_shutdownhook); #endif @@ -904,8 +902,6 @@ ohci_init(ohci_softc_t *sc) #if defined(__NetBSD__) || defined(__OpenBSD__) sc->sc_control = sc->sc_intre = 0; - sc->sc_powerhook = powerhook_establish(USBDEVNAME(sc->sc_bus.bdev), - ohci_power, sc); sc->sc_shutdownhook = shutdownhook_establish(ohci_shutdown, sc); #endif @@ -1017,72 +1013,66 @@ ohci_shutdown(void *v) OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET); } -/* - * Handle suspend/resume. - * - * We need to switch to polling mode here, because this routine is - * called from an interupt context. This is all right since we - * are almost suspended anyway. - */ -void -ohci_power(int why, void *v) +bool +ohci_resume(device_t dv) { - ohci_softc_t *sc = v; - u_int32_t ctl; + ohci_softc_t *sc = device_private(dv); + uint32_t ctl; int s; -#ifdef OHCI_DEBUG - DPRINTF(("ohci_power: sc=%p, why=%d\n", sc, why)); - ohci_dumpregs(sc); -#endif + s = splhardusb(); + 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--; + + return true; +} + +bool +ohci_suspend(device_t dv) +{ + ohci_softc_t *sc = device_private(dv); + uint32_t ctl; + int s; s = splhardusb(); - switch (why) { - case PWR_SUSPEND: - case PWR_STANDBY: - 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; - case PWR_SOFTSUSPEND: - case PWR_SOFTSTANDBY: - case PWR_SOFTRESUME: - break; + sc->sc_bus.use_polling++; + ctl = OREAD4(sc, OHCI_CONTROL) & ~OHCI_HCFS_MASK; + if (sc->sc_control == 0) { + /* + * Preserve register values, in case that 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--; splx(s); + + return true; } #ifdef OHCI_DEBUG @@ -1133,7 +1123,7 @@ ohci_intr(void *p) { ohci_softc_t *sc = p; - if (sc == NULL || sc->sc_dying) + if (sc == NULL || sc->sc_dying || !device_has_power(&sc->sc_bus.bdev)) return (0); /* If we get an interrupt while polling, then just ignore it. */ diff --git a/sys/dev/usb/ohcivar.h b/sys/dev/usb/ohcivar.h index 7130e24f186..269482fd16b 100644 --- a/sys/dev/usb/ohcivar.h +++ b/sys/dev/usb/ohcivar.h @@ -1,4 +1,4 @@ -/* $NetBSD: ohcivar.h,v 1.39 2005/12/27 04:06:45 chs Exp $ */ +/* $NetBSD: ohcivar.h,v 1.40 2007/12/09 20:28:24 jmcneill Exp $ */ /* $FreeBSD: src/sys/dev/usb/ohcivar.h,v 1.13 1999/11/17 22:33:41 n_hibma Exp $ */ /* @@ -155,3 +155,5 @@ int ohci_intr(void *); int ohci_detach(ohci_softc_t *, int); int ohci_activate(device_ptr_t, enum devact); #endif +bool ohci_resume(device_t); +bool ohci_suspend(device_t); diff --git a/sys/dev/usb/ugen.c b/sys/dev/usb/ugen.c index 7e9ccb07dc6..6994dae5eae 100644 --- a/sys/dev/usb/ugen.c +++ b/sys/dev/usb/ugen.c @@ -1,4 +1,4 @@ -/* $NetBSD: ugen.c,v 1.94 2007/12/05 17:19:55 pooka Exp $ */ +/* $NetBSD: ugen.c,v 1.95 2007/12/09 20:28:24 jmcneill Exp $ */ /* * Copyright (c) 1998, 2004 The NetBSD Foundation, Inc. @@ -44,7 +44,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ugen.c,v 1.94 2007/12/05 17:19:55 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ugen.c,v 1.95 2007/12/09 20:28:24 jmcneill Exp $"); #include "opt_ugen_bulk_ra_wb.h" #include "opt_compat_netbsd.h" @@ -271,6 +271,9 @@ USB_ATTACH(ugen) usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, USBDEV(sc->sc_dev)); + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); + USB_ATTACH_SUCCESS_RETURN; } diff --git a/sys/dev/usb/uhci.c b/sys/dev/usb/uhci.c index 5827659be8c..7c039bcd10a 100644 --- a/sys/dev/usb/uhci.c +++ b/sys/dev/usb/uhci.c @@ -1,4 +1,4 @@ -/* $NetBSD: uhci.c,v 1.211 2007/10/19 12:01:22 ad Exp $ */ +/* $NetBSD: uhci.c,v 1.212 2007/12/09 20:28:24 jmcneill Exp $ */ /* $FreeBSD: src/sys/dev/usb/uhci.c,v 1.33 1999/11/17 22:33:41 n_hibma Exp $ */ /* @@ -49,7 +49,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uhci.c,v 1.211 2007/10/19 12:01:22 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uhci.c,v 1.212 2007/12/09 20:28:24 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -165,8 +165,6 @@ struct uhci_pipe { Static void uhci_globalreset(uhci_softc_t *); Static usbd_status uhci_portreset(uhci_softc_t*, int); Static void uhci_reset(uhci_softc_t *); -Static void uhci_shutdown(void *v); -Static void uhci_power(int, void *); Static usbd_status uhci_run(uhci_softc_t *, int run); Static uhci_soft_td_t *uhci_alloc_std(uhci_softc_t *); Static void uhci_free_std(uhci_softc_t *, uhci_soft_td_t *); @@ -545,13 +543,6 @@ uhci_init(uhci_softc_t *sc) sc->sc_bus.methods = &uhci_bus_methods; sc->sc_bus.pipe_size = sizeof(struct uhci_pipe); -#if defined(__NetBSD__) || defined(__OpenBSD__) - sc->sc_suspend = PWR_RESUME; - sc->sc_powerhook = powerhook_establish(USBDEVNAME(sc->sc_bus.bdev), - uhci_power, sc); - sc->sc_shutdownhook = shutdownhook_establish(uhci_shutdown, sc); -#endif - UHCICMD(sc, UHCI_CMD_MAXP); /* Assume 64 byte packets at frame end */ DPRINTFN(1,("uhci_init: enabling\n")); @@ -593,11 +584,6 @@ uhci_detach(struct uhci_softc *sc, int flags) if (rv != 0) return (rv); -#if defined(__NetBSD__) || defined(__OpenBSD__) - powerhook_disestablish(sc->sc_powerhook); - shutdownhook_disestablish(sc->sc_shutdownhook); -#endif - /* Free all xfers associated with this HC. */ for (;;) { xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers); @@ -712,111 +698,88 @@ uhci_freex(struct usbd_bus *bus, usbd_xfer_handle xfer) } /* - * Shut down the controller when the system is going down. + * Handle suspend/resume. + * + * We need to switch to polling mode here, because this routine is + * called from an interrupt context. This is all right since we + * are almost suspended anyway. */ -void -uhci_shutdown(void *v) +bool +uhci_resume(device_t dv) { - uhci_softc_t *sc = v; + uhci_softc_t *sc = device_private(dv); + int cmd; int s; - DPRINTF(("uhci_shutdown: stopping the HC\n")); - - /* - * Use polling mode to prevent the interrupts shutting - * us down before we shut them down. - */ s = splhardusb(); + + cmd = UREAD2(sc, UHCI_CMD); sc->sc_bus.use_polling++; - uhci_run(sc, 0); /* stop the controller */ + if (cmd & UHCI_CMD_RS) + uhci_run(sc, 0); + + /* restore saved state */ + UWRITE4(sc, UHCI_FLBASEADDR, DMAADDR(&sc->sc_dma, 0)); + UWRITE2(sc, UHCI_FRNUM, sc->sc_saved_frnum); + UWRITE1(sc, UHCI_SOF, sc->sc_saved_sof); + + UHCICMD(sc, cmd | UHCI_CMD_FGR); /* force resume */ + usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY); + UHCICMD(sc, cmd & ~UHCI_CMD_EGSM); /* back to normal */ + UHCICMD(sc, UHCI_CMD_MAXP); + UWRITE2(sc, UHCI_INTR, UHCI_INTR_TOCRCIE | + UHCI_INTR_RIE | UHCI_INTR_IOCE | UHCI_INTR_SPIE); + uhci_run(sc, 1); /* and start traffic again */ + usb_delay_ms(&sc->sc_bus, USB_RESUME_RECOVERY); sc->sc_bus.use_polling--; + if (sc->sc_intr_xfer != NULL) + usb_callout(sc->sc_poll_handle, sc->sc_ival, uhci_poll_hub, + sc->sc_intr_xfer); +#ifdef UHCI_DEBUG + if (uhcidebug > 2) + uhci_dumpregs(sc); +#endif + splx(s); + + return true; } -/* - * Handle suspend/resume. - * - * We need to switch to polling mode here, because this routine is - * called from an interrupt context. This is all right since we - * are almost suspended anyway. - */ -void -uhci_power(int why, void *v) +bool +uhci_suspend(device_t dv) { - uhci_softc_t *sc = v; + uhci_softc_t *sc = device_private(dv); int cmd; int s; s = splhardusb(); - cmd = UREAD2(sc, UHCI_CMD); - DPRINTF(("uhci_power: sc=%p, why=%d (was %d), cmd=0x%x\n", - sc, why, sc->sc_suspend, cmd)); + cmd = UREAD2(sc, UHCI_CMD); - switch (why) { - case PWR_SUSPEND: - case PWR_STANDBY: #ifdef UHCI_DEBUG - if (uhcidebug > 2) - uhci_dumpregs(sc); -#endif - if (sc->sc_intr_xfer != NULL) - usb_uncallout(sc->sc_poll_handle, uhci_poll_hub, - sc->sc_intr_xfer); - sc->sc_bus.use_polling++; - uhci_run(sc, 0); /* stop the controller */ - cmd &= ~UHCI_CMD_RS; + if (uhcidebug > 2) + uhci_dumpregs(sc); +#endif + if (sc->sc_intr_xfer != NULL) + usb_uncallout(sc->sc_poll_handle, uhci_poll_hub, + sc->sc_intr_xfer); + sc->sc_bus.use_polling++; + uhci_run(sc, 0); /* stop the controller */ + cmd &= ~UHCI_CMD_RS; - /* save some state if BIOS doesn't */ - sc->sc_saved_frnum = UREAD2(sc, UHCI_FRNUM); - sc->sc_saved_sof = UREAD1(sc, UHCI_SOF); + /* save some state if BIOS doesn't */ + sc->sc_saved_frnum = UREAD2(sc, UHCI_FRNUM); + sc->sc_saved_sof = UREAD1(sc, UHCI_SOF); - UWRITE2(sc, UHCI_INTR, 0); /* disable intrs */ + UWRITE2(sc, UHCI_INTR, 0); /* disable intrs */ + + UHCICMD(sc, cmd | UHCI_CMD_EGSM); /* enter suspend */ + usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT); + sc->sc_bus.use_polling--; - UHCICMD(sc, cmd | UHCI_CMD_EGSM); /* enter global suspend */ - usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT); - sc->sc_suspend = why; - sc->sc_bus.use_polling--; - DPRINTF(("uhci_power: cmd=0x%x\n", UREAD2(sc, UHCI_CMD))); - break; - case PWR_RESUME: -#ifdef DIAGNOSTIC - if (sc->sc_suspend == PWR_RESUME) - printf("uhci_power: weird, resume without suspend.\n"); -#endif - sc->sc_bus.use_polling++; - sc->sc_suspend = why; - if (cmd & UHCI_CMD_RS) - uhci_run(sc, 0); /* in case BIOS has started it */ - - /* restore saved state */ - UWRITE4(sc, UHCI_FLBASEADDR, DMAADDR(&sc->sc_dma, 0)); - UWRITE2(sc, UHCI_FRNUM, sc->sc_saved_frnum); - UWRITE1(sc, UHCI_SOF, sc->sc_saved_sof); - - UHCICMD(sc, cmd | UHCI_CMD_FGR); /* force global resume */ - usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY); - UHCICMD(sc, cmd & ~UHCI_CMD_EGSM); /* back to normal */ - UHCICMD(sc, UHCI_CMD_MAXP); - UWRITE2(sc, UHCI_INTR, UHCI_INTR_TOCRCIE | UHCI_INTR_RIE | - UHCI_INTR_IOCE | UHCI_INTR_SPIE); /* re-enable intrs */ - uhci_run(sc, 1); /* and start traffic again */ - usb_delay_ms(&sc->sc_bus, USB_RESUME_RECOVERY); - sc->sc_bus.use_polling--; - if (sc->sc_intr_xfer != NULL) - usb_callout(sc->sc_poll_handle, sc->sc_ival, - uhci_poll_hub, sc->sc_intr_xfer); -#ifdef UHCI_DEBUG - if (uhcidebug > 2) - uhci_dumpregs(sc); -#endif - break; - case PWR_SOFTSUSPEND: - case PWR_SOFTSTANDBY: - case PWR_SOFTRESUME: - break; - } splx(s); + + return true; } #ifdef UHCI_DEBUG @@ -1226,7 +1189,7 @@ uhci_intr(void *arg) { uhci_softc_t *sc = arg; - if (sc->sc_dying) + if (sc->sc_dying || !device_has_power(&sc->sc_bus.bdev)) return (0); if (sc->sc_bus.use_polling) { diff --git a/sys/dev/usb/uhcivar.h b/sys/dev/usb/uhcivar.h index b0ddd3c45fa..436ff437d02 100644 --- a/sys/dev/usb/uhcivar.h +++ b/sys/dev/usb/uhcivar.h @@ -1,4 +1,4 @@ -/* $NetBSD: uhcivar.h,v 1.40 2005/12/27 04:06:45 chs Exp $ */ +/* $NetBSD: uhcivar.h,v 1.41 2007/12/09 20:28:24 jmcneill Exp $ */ /* $FreeBSD: src/sys/dev/usb/uhcivar.h,v 1.14 1999/11/17 22:33:42 n_hibma Exp $ */ /* @@ -177,9 +177,6 @@ typedef struct uhci_softc { char sc_vendor[32]; /* vendor string for root hub */ int sc_id_vendor; /* vendor ID for root hub */ - void *sc_powerhook; /* cookie from power hook */ - void *sc_shutdownhook; /* cookie from shutdown hook */ - #if defined(__NetBSD__) || defined(__OpenBSD__) device_ptr_t sc_child; /* /dev/usb# device */ #endif @@ -193,5 +190,7 @@ int uhci_intr(void *); #if defined(__NetBSD__) || defined(__OpenBSD__) int uhci_detach(uhci_softc_t *, int); int uhci_activate(device_ptr_t, enum devact); +bool uhci_resume(device_t); +bool uhci_suspend(device_t); #endif diff --git a/sys/dev/usb/uhub.c b/sys/dev/usb/uhub.c index ee93d521354..d4a2f04b955 100644 --- a/sys/dev/usb/uhub.c +++ b/sys/dev/usb/uhub.c @@ -1,4 +1,4 @@ -/* $NetBSD: uhub.c,v 1.91 2007/12/01 04:50:50 jmcneill Exp $ */ +/* $NetBSD: uhub.c,v 1.92 2007/12/09 20:28:24 jmcneill Exp $ */ /* $FreeBSD: src/sys/dev/usb/uhub.c,v 1.18 1999/11/17 22:33:43 n_hibma Exp $ */ /* @@ -43,7 +43,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uhub.c,v 1.91 2007/12/01 04:50:50 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uhub.c,v 1.92 2007/12/09 20:28:24 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -358,6 +358,9 @@ USB_ATTACH(uhub) sc->sc_running = 1; + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); + USB_ATTACH_SUCCESS_RETURN; bad: diff --git a/sys/dev/usb/umass.c b/sys/dev/usb/umass.c index 507c3f75445..e2fc01bc9cf 100644 --- a/sys/dev/usb/umass.c +++ b/sys/dev/usb/umass.c @@ -1,4 +1,4 @@ -/* $NetBSD: umass.c,v 1.124 2007/03/13 13:51:56 drochner Exp $ */ +/* $NetBSD: umass.c,v 1.125 2007/12/09 20:28:24 jmcneill Exp $ */ /* * Copyright (c) 2003 The NetBSD Foundation, Inc. @@ -131,7 +131,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: umass.c,v 1.124 2007/03/13 13:51:56 drochner Exp $"); +__KERNEL_RCSID(0, "$NetBSD: umass.c,v 1.125 2007/12/09 20:28:24 jmcneill Exp $"); #include "atapibus.h" #include "scsibus.h" @@ -636,6 +636,9 @@ USB_ATTACH(umass) usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, USBDEV(sc->sc_dev)); + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); + DPRINTF(UDMASS_GEN, ("%s: Attach finished\n", USBDEVNAME(sc->sc_dev))); USB_ATTACH_SUCCESS_RETURN; @@ -649,6 +652,8 @@ USB_DETACH(umass) DPRINTF(UDMASS_USB, ("%s: detached\n", USBDEVNAME(sc->sc_dev))); + pmf_device_deregister(self); + /* Abort the pipes to wake up any waiting processes. */ for (i = 0 ; i < UMASS_NEP ; i++) { if (sc->sc_pipe[i] != NULL) diff --git a/sys/dev/usb/usb.c b/sys/dev/usb/usb.c index 7e714fd663a..f665ea7345a 100644 --- a/sys/dev/usb/usb.c +++ b/sys/dev/usb/usb.c @@ -1,4 +1,4 @@ -/* $NetBSD: usb.c,v 1.103 2007/12/05 17:19:56 pooka Exp $ */ +/* $NetBSD: usb.c,v 1.104 2007/12/09 20:28:25 jmcneill Exp $ */ /* * Copyright (c) 1998, 2002 The NetBSD Foundation, Inc. @@ -44,7 +44,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: usb.c,v 1.103 2007/12/05 17:19:56 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: usb.c,v 1.104 2007/12/09 20:28:25 jmcneill Exp $"); #include "opt_compat_netbsd.h" @@ -248,6 +248,9 @@ USB_ATTACH(usb) config_pending_incr(); usb_kthread_create(usb_create_event_thread, sc); + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); + USB_ATTACH_SUCCESS_RETURN; } diff --git a/sys/dev/wscons/wsdisplay.c b/sys/dev/wscons/wsdisplay.c index 3e46ba7af52..a1715d68a13 100644 --- a/sys/dev/wscons/wsdisplay.c +++ b/sys/dev/wscons/wsdisplay.c @@ -1,4 +1,4 @@ -/* $NetBSD: wsdisplay.c,v 1.112 2007/11/19 18:51:51 ad Exp $ */ +/* $NetBSD: wsdisplay.c,v 1.113 2007/12/09 20:28:25 jmcneill Exp $ */ /* * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: wsdisplay.c,v 1.112 2007/11/19 18:51:51 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: wsdisplay.c,v 1.113 2007/12/09 20:28:25 jmcneill Exp $"); #include "opt_wsdisplay_compat.h" #include "opt_wsmsgattrs.h" @@ -108,6 +108,7 @@ static void wsdisplay_shutdownhook(void *); static void wsdisplay_addscreen_print(struct wsdisplay_softc *, int, int); static void wsdisplay_closescreen(struct wsdisplay_softc *, struct wsscreen *); int wsdisplay_delscreen(struct wsdisplay_softc *, int, int); +static void wsdisplay_switchto(int); #define WSDISPLAY_MAXSCREEN 8 @@ -158,10 +159,12 @@ static int wsdisplay_emul_match(device_t , struct cfdata *, void *); static void wsdisplay_emul_attach(device_t, device_t, void *); static int wsdisplay_noemul_match(device_t, struct cfdata *, void *); static void wsdisplay_noemul_attach(device_t, device_t, void *); +static bool wsdisplay_resume(device_t dv); +static bool wsdisplay_suspend(device_t dv); CFATTACH_DECL_NEW(wsdisplay_emul, sizeof (struct wsdisplay_softc), wsdisplay_emul_match, wsdisplay_emul_attach, NULL, NULL); - + CFATTACH_DECL_NEW(wsdisplay_noemul, sizeof (struct wsdisplay_softc), wsdisplay_noemul_match, wsdisplay_noemul_attach, NULL, NULL); @@ -598,6 +601,21 @@ wsdisplay_noemul_attach(device_t parent, device_t self, void *aux) ap->accessops, ap->accesscookie); } +static bool +wsdisplay_suspend(device_t dv) +{ + wsdisplay_switchtoconsole(); + + return true; +} + +static bool +wsdisplay_resume(device_t dv) +{ + + return true; +} + /* Print function (for parent devices). */ int wsdisplaydevprint(void *aux, const char *pnp) @@ -696,6 +714,9 @@ wsdisplay_common_attach(struct wsdisplay_softc *sc, int console, int kbdmux, if (i > start) wsdisplay_addscreen_print(sc, start, i-start); + if (!pmf_device_register(sc->sc_dev, wsdisplay_suspend, wsdisplay_resume)) + aprint_error_dev(sc->sc_dev, "couldn't establish power handler\n"); + if (hookset == 0) shutdownhook_establish(wsdisplay_shutdownhook, NULL); hookset = 1; @@ -2057,18 +2078,15 @@ wsdisplay_unset_cons_kbd(void) wsdisplay_cons_kbd_pollc = 0; } -/* - * Switch the console display to it's first screen. - */ -void -wsdisplay_switchtoconsole(void) +static void +wsdisplay_switchto(int no) { struct wsdisplay_softc *sc; struct wsscreen *scr; if (wsdisplay_console_device != NULL) { sc = wsdisplay_console_device; - if ((scr = sc->sc_scr[0]) == NULL) + if ((scr = sc->sc_scr[no]) == NULL) return; (*sc->sc_accessops->show_screen)(sc->sc_accesscookie, scr->scr_dconf->emulcookie, @@ -2077,6 +2095,15 @@ wsdisplay_switchtoconsole(void) } /* + * Switch the console display to it's first screen. + */ +void +wsdisplay_switchtoconsole(void) +{ + wsdisplay_switchto(0); +} + +/* * Switch the console at shutdown. */ static void diff --git a/sys/dev/wscons/wskbd.c b/sys/dev/wscons/wskbd.c index cc154617c6d..42abfce3b8a 100644 --- a/sys/dev/wscons/wskbd.c +++ b/sys/dev/wscons/wskbd.c @@ -1,4 +1,4 @@ -/* $NetBSD: wskbd.c,v 1.108 2007/12/01 05:22:02 jmcneill Exp $ */ +/* $NetBSD: wskbd.c,v 1.109 2007/12/09 20:28:25 jmcneill Exp $ */ /* * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. @@ -79,7 +79,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: wskbd.c,v 1.108 2007/12/01 05:22:02 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: wskbd.c,v 1.109 2007/12/09 20:28:25 jmcneill Exp $"); #include "opt_ddb.h" #include "opt_kgdb.h" @@ -464,6 +464,11 @@ wskbd_attach(struct device *parent, struct device *self, void *aux) sc->sc_base.me_dv.dv_xname, error); } #endif + + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); + else if (!pmf_class_input_register(self)) + aprint_error_dev(self, "couldn't register as input device\n"); } void @@ -620,6 +625,8 @@ wskbd_input(struct device *dev, u_int type, int value) callout_stop(&sc->sc_repeat_ch); } + device_active(dev, DVA_HARDWARE); + #if NWSDISPLAY > 0 /* * If /dev/wskbdN is not connected in event mode translate and @@ -689,7 +696,7 @@ wskbd_deliver_event(struct wskbd_softc *sc, u_int type, int value) return; } #endif - + event.type = type; event.value = value; if (wsevent_inject(evar, &event, 1) != 0) @@ -1453,6 +1460,18 @@ internal_command(struct wskbd_softc *sc, u_int *type, keysym_t ksym, u_int state = 0; #endif switch (ksym) { + case KS_Cmd_VolumeToggle: + if (*type == WSCONS_EVENT_KEY_DOWN) + pmf_event_inject(NULL, PMFE_AUDIO_VOLUME_TOGGLE); + break; + case KS_Cmd_VolumeUp: + if (*type == WSCONS_EVENT_KEY_DOWN) + pmf_event_inject(NULL, PMFE_AUDIO_VOLUME_UP); + break; + case KS_Cmd_VolumeDown: + if (*type == WSCONS_EVENT_KEY_DOWN) + pmf_event_inject(NULL, PMFE_AUDIO_VOLUME_DOWN); + break; #ifdef WSDISPLAY_SCROLLSUPPORT case KS_Cmd_ScrollFastUp: case KS_Cmd_ScrollFastDown: diff --git a/sys/dev/wscons/wsksymdef.h b/sys/dev/wscons/wsksymdef.h index 8bc48f04924..1d082521a87 100644 --- a/sys/dev/wscons/wsksymdef.h +++ b/sys/dev/wscons/wsksymdef.h @@ -1,4 +1,4 @@ -/* $NetBSD: wsksymdef.h,v 1.58 2007/04/04 14:50:21 mishka Exp $ */ +/* $NetBSD: wsksymdef.h,v 1.59 2007/12/09 20:28:25 jmcneill Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -524,6 +524,9 @@ #define KS_Cmd_ScrollFastDown 0xf42d #define KS_Cmd_ScrollSlowUp 0xf42e #define KS_Cmd_ScrollSlowDown 0xf42f +#define KS_Cmd_VolumeUp 0xf430 +#define KS_Cmd_VolumeDown 0xf431 +#define KS_Cmd_VolumeToggle 0xf432 /* * Group 5 (internal) diff --git a/sys/dev/wscons/wsmouse.c b/sys/dev/wscons/wsmouse.c index 05bab1a2ebe..4b8cd0616fa 100644 --- a/sys/dev/wscons/wsmouse.c +++ b/sys/dev/wscons/wsmouse.c @@ -1,4 +1,4 @@ -/* $NetBSD: wsmouse.c,v 1.54 2007/12/01 05:40:44 jmcneill Exp $ */ +/* $NetBSD: wsmouse.c,v 1.55 2007/12/09 20:28:25 jmcneill Exp $ */ /*- * Copyright (c) 2006 The NetBSD Foundation, Inc. @@ -111,7 +111,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: wsmouse.c,v 1.54 2007/12/01 05:40:44 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: wsmouse.c,v 1.55 2007/12/09 20:28:25 jmcneill Exp $"); #include "wsmouse.h" #include "wsdisplay.h" @@ -275,6 +275,9 @@ wsmouse_attach(struct device *parent, struct device *self, void *aux) aprint_naive("\n"); aprint_normal("\n"); + + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); } int |
