It seems to work, I'm not really sure if any laptops used rhine, but this makes ACPI suspend/resume work on one of my early ACPI-capable systems.
Tested on: vr0 at pci0 dev 12 function 0 "VIA VT6105 RhineIII" rev 0x86: apic 2 int 19, address 00:19:5b:82:a1:e0 -Bryan. Index: if_vr.c =================================================================== RCS file: /cvs/src/sys/dev/pci/if_vr.c,v retrieving revision 1.112 diff -u -p -u -r1.112 if_vr.c --- dev/pci/if_vr.c 8 Dec 2011 20:19:23 -0000 1.112 +++ dev/pci/if_vr.c 20 Dec 2011 01:02:56 -0000 @@ -103,9 +103,11 @@ int vr_probe(struct device *, void *, void *); int vr_quirks(struct pci_attach_args *); void vr_attach(struct device *, struct device *, void *); +int vr_activate(struct device *, int); struct cfattach vr_ca = { - sizeof(struct vr_softc), vr_probe, vr_attach + sizeof(struct vr_softc), vr_probe, vr_attach, NULL, + vr_activate }; struct cfdriver vr_cd = { NULL, "vr", DV_IFNET @@ -120,6 +122,7 @@ void vr_rxtick(void *); int vr_intr(void *); void vr_start(struct ifnet *); int vr_ioctl(struct ifnet *, u_long, caddr_t); +void vr_chipinit(struct vr_softc *); void vr_init(void *); void vr_stop(struct vr_softc *); void vr_watchdog(struct ifnet *); @@ -567,27 +570,10 @@ vr_attach(struct device *parent, struct printf(": %s", intrstr); sc->vr_revid = PCI_REVISION(pa->pa_class); + sc->sc_pc = pa->pa_pc; + sc->sc_tag = pa->pa_tag; - /* - * Windows may put the chip in suspend mode when it - * shuts down. Be sure to kick it in the head to wake it - * up again. - */ - if (pci_get_capability(pa->pa_pc, pa->pa_tag, - PCI_CAP_PWRMGMT, NULL, NULL)) - VR_CLRBIT(sc, VR_STICKHW, (VR_STICKHW_DS0|VR_STICKHW_DS1)); - - /* Reset the adapter. */ - vr_reset(sc); - - /* - * Turn on bit2 (MIION) in PCI configuration register 0x53 during - * initialization and disable AUTOPOLL. - */ - pci_conf_write(pa->pa_pc, pa->pa_tag, VR_PCI_MODE, - pci_conf_read(pa->pa_pc, pa->pa_tag, VR_PCI_MODE) | - (VR_MODE3_MIION << 24)); - VR_CLRBIT(sc, VR_MIICMD, VR_MIICMD_AUTOPOLL); + vr_chipinit(sc); /* * Get station address. The way the Rhine chips work, @@ -697,6 +683,31 @@ fail_1: bus_space_unmap(sc->vr_btag, sc->vr_bhandle, size); } +int +vr_activate(struct device *self, int act) +{ + struct vr_softc *sc = (struct vr_softc *)self; + struct ifnet *ifp = &sc->arpcom.ac_if; + int rv = 0; + + switch (act) { + case DVACT_QUIESCE: + rv = config_activate_children(self, act); + break; + case DVACT_SUSPEND: + if (ifp->if_flags & IFF_RUNNING) + vr_stop(sc); + rv = config_activate_children(self, act); + break; + case DVACT_RESUME: + rv = config_activate_children(self, act); + if (ifp->if_flags & IFF_UP) + vr_init(sc); + break; + } + return (rv); +} + /* * Initialize the transmit descriptors. */ @@ -1296,6 +1307,29 @@ vr_start(struct ifnet *ifp) } void +vr_chipinit(struct vr_softc *sc) +{ + /* + * Make sure it isn't suspended. + */ + if (pci_get_capability(sc->sc_pc, sc->sc_tag, + PCI_CAP_PWRMGMT, NULL, NULL)) + VR_CLRBIT(sc, VR_STICKHW, (VR_STICKHW_DS0|VR_STICKHW_DS1)); + + /* Reset the adapter. */ + vr_reset(sc); + + /* + * Turn on bit2 (MIION) in PCI configuration register 0x53 during + * initialization and disable AUTOPOLL. + */ + pci_conf_write(sc->sc_pc, sc->sc_tag, VR_PCI_MODE, + pci_conf_read(sc->sc_pc, sc->sc_tag, VR_PCI_MODE) | + (VR_MODE3_MIION << 24)); + VR_CLRBIT(sc, VR_MIICMD, VR_MIICMD_AUTOPOLL); +} + +void vr_init(void *xsc) { struct vr_softc *sc = xsc; @@ -1309,7 +1343,7 @@ vr_init(void *xsc) * Cancel pending I/O and free all RX/TX buffers. */ vr_stop(sc); - vr_reset(sc); + vr_chipinit(sc); /* * Set our station address. Index: if_vrreg.h =================================================================== RCS file: /cvs/src/sys/dev/pci/if_vrreg.h,v retrieving revision 1.29 diff -u -p -u -r1.29 if_vrreg.h --- dev/pci/if_vrreg.h 8 Dec 2011 20:19:24 -0000 1.29 +++ dev/pci/if_vrreg.h 20 Dec 2011 01:02:57 -0000 @@ -481,6 +481,8 @@ struct vr_mii_frame { struct vr_softc { struct device sc_dev; /* generic device structure */ + pci_chipset_tag_t sc_pc; /* PCI registers info */ + pcitag_t sc_tag; void * sc_ih; /* interrupt handler cookie */ struct arpcom arpcom; /* interface info */ bus_space_handle_t vr_bhandle; /* bus space handle */