On Thu, Mar 31, 2011 at 06:54:44PM +0200, Stefan Sperling wrote: > This is an attempt to add wol support to xl(4). > > Unfortunately, while I have an xl(4) card to test with none of the > motherboards I have will do WOL with it since they all lack an > on-board WOL connector :( > > So test reports are needed. > Please also check whether WOL is disabled by default.
I haven't received any test reports yet. If someone could donate a motherboard with a wol connector, preferrably with suitable cpu and ram, that would help with getting wol support for this and some other drivers for similarly old hardware. It doesn't need to be a fast machine. I just need a board that has a connector. > > Index: ic/xl.c > =================================================================== > RCS file: /cvs/src/sys/dev/ic/xl.c,v > retrieving revision 1.99 > diff -u -p -r1.99 xl.c > --- ic/xl.c 22 Sep 2010 08:49:14 -0000 1.99 > +++ ic/xl.c 31 Mar 2011 15:48:36 -0000 > @@ -191,6 +191,9 @@ void xl_testpacket(struct xl_softc *); > int xl_miibus_readreg(struct device *, int, int); > void xl_miibus_writereg(struct device *, int, int, int); > void xl_miibus_statchg(struct device *); > +#ifndef SMALL_KERNEL > +int xl_wol(struct ifnet *, int); > +#endif > > int > xl_activate(struct device *self, int act) > @@ -2368,6 +2371,12 @@ xl_stop(struct xl_softc *sc) > ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); > > xl_freetxrx(sc); > + > +#ifndef SMALL_KERNEL > + /* Call upper layer WOL power routine if WOL is enabled. */ > + if ((sc->xl_flags & XL_FLAG_WOL) && sc->wol_power) > + sc->wol_power(sc->wol_power_arg); > +#endif > } > > void > @@ -2637,6 +2646,15 @@ xl_attach(struct xl_softc *sc) > CSR_WRITE_2(sc, XL_W0_MFG_ID, XL_NO_XCVR_PWR_MAGICBITS); > } > > +#ifndef SMALL_KERNEL > + /* Check availability of WOL. */ > + if ((sc->xl_caps & XL_CAPS_PWRMGMT) != 0) { > + ifp->if_capabilities |= IFCAP_WOL; > + ifp->if_wol = xl_wol; > + xl_wol(ifp, 0); > + } > +#endif > + > /* > * Call MI attach routines. > */ > @@ -2668,6 +2686,24 @@ xl_detach(struct xl_softc *sc) > > return (0); > } > + > +#ifndef SMALL_KERNEL > +int > +xl_wol(struct ifnet *ifp, int enable) > +{ > + struct xl_softc *sc = ifp->if_softc; > + > + XL_SEL_WIN(7); > + if (enable) { > + CSR_WRITE_2(sc, XL_W7_BM_PME, XL_BM_PME_MAGIC); > + sc->xl_flags |= XL_FLAG_WOL; > + } else { > + CSR_WRITE_2(sc, XL_W7_BM_PME, 0); > + sc->xl_flags &= ~XL_FLAG_WOL; > + } > + return (0); > +} > +#endif > > struct cfdriver xl_cd = { > 0, "xl", DV_IFNET > Index: ic/xlreg.h > =================================================================== > RCS file: /cvs/src/sys/dev/ic/xlreg.h,v > retrieving revision 1.26 > diff -u -p -r1.26 xlreg.h > --- ic/xlreg.h 21 Sep 2010 01:05:12 -0000 1.26 > +++ ic/xlreg.h 31 Mar 2011 15:42:36 -0000 > @@ -411,6 +411,12 @@ > #define XL_W7_BM_LEN 0x06 > #define XL_W7_BM_STATUS 0x0B > #define XL_W7_BM_TIMEr 0x0A > +#define XL_W7_BM_PME 0x0C > + > +#define XL_BM_PME_WAKE 0x0001 > +#define XL_BM_PME_MAGIC 0x0002 > +#define XL_BM_PME_LINKCHG 0x0004 > +#define XL_BM_PME_WAKETIMER 0x0008 > > /* > * bus master control registers > @@ -571,6 +577,7 @@ struct xl_mii_frame { > #define XL_FLAG_NO_XCVR_PWR 0x0080 > #define XL_FLAG_USE_MMIO 0x0100 > #define XL_FLAG_NO_MMIO 0x0200 > +#define XL_FLAG_WOL 0x0400 > > #define XL_NO_XCVR_PWR_MAGICBITS 0x0900 > > @@ -604,6 +611,8 @@ struct xl_softc { > caddr_t sc_listkva; > bus_dmamap_t sc_rx_sparemap; > bus_dmamap_t sc_tx_sparemap; > + void (*wol_power)(void *); > + void *wol_power_arg; > }; > > #define xl_rx_goodframes(x) \ > @@ -740,6 +749,13 @@ struct xl_stats { > #define XL_PSTATE_D3 0x0003 > #define XL_PME_EN 0x0010 > #define XL_PME_STATUS 0x8000 > + > +/* Bits in the XL_PCI_PWRMGMTCAP register */ > +#define XL_PME_CAP_D0 0x0800 > +#define XL_PME_CAP_D1 0x1000 > +#define XL_PME_CAP_D2 0x2000 > +#define XL_PME_CAP_D3_HOT 0x4000 > +#define XL_PME_CAP_D3_COLD 0x8000 > > extern int xl_intr(void *); > extern void xl_attach(struct xl_softc *); > Index: pci/if_xl_pci.c > =================================================================== > RCS file: /cvs/src/sys/dev/pci/if_xl_pci.c,v > retrieving revision 1.34 > diff -u -p -r1.34 if_xl_pci.c > --- pci/if_xl_pci.c 19 Sep 2010 09:22:58 -0000 1.34 > +++ pci/if_xl_pci.c 31 Mar 2011 15:43:05 -0000 > @@ -92,10 +92,14 @@ int xl_pci_match(struct device *, void * > void xl_pci_attach(struct device *, struct device *, void *); > int xl_pci_detach(struct device *, int); > void xl_pci_intr_ack(struct xl_softc *); > +#ifndef SMALL_KERNEL > +void xl_pci_wol_power(void *); > +#endif > > struct xl_pci_softc { > struct xl_softc psc_softc; > pci_chipset_tag_t psc_pc; > + pcitag_t psc_tag; > bus_size_t psc_iosize; > bus_size_t psc_funsize; > }; > @@ -156,9 +160,11 @@ xl_pci_attach(struct device *parent, str > u_int32_t command; > > psc->psc_pc = pc; > + psc->psc_tag = pa->pa_tag; > sc->sc_dmat = pa->pa_dmat; > > sc->xl_flags = 0; > + sc->wol_power = sc->wol_power_arg = NULL; > > /* set required flags */ > switch (PCI_PRODUCT(pa->pa_id)) { > @@ -260,6 +266,18 @@ xl_pci_attach(struct device *parent, str > pci_conf_write(pc, pa->pa_tag, XL_PCI_LOMEM, mem); > pci_conf_write(pc, pa->pa_tag, XL_PCI_INTLINE, irq); > } > + > +#ifndef SMALL_KERNEL > + /* The card is WOL-capable if it supports PME# assertion > + * from D3hot power state. Install a callback to configure > + * PCI power state for WOL. It will be invoked when the > + * interface stops and WOL was enabled. */ > + command = pci_conf_read(pc, pa->pa_tag, XL_PCI_PWRMGMTCAP); > + if (command & XL_PME_CAP_D3_HOT) { > + sc->wol_power = xl_pci_wol_power; > + sc->wol_power_arg = psc; > + } > +#endif > } > > /* > @@ -342,3 +360,18 @@ xl_pci_intr_ack(struct xl_softc *sc) > bus_space_write_4(sc->xl_funct, sc->xl_funch, XL_PCI_INTR, > XL_PCI_INTRACK); > } > + > +#ifndef SMALL_KERNEL > +void > +xl_pci_wol_power(void *ppsc) > +{ > + u_int32_t command; > + struct xl_pci_softc *psc = (struct xl_pci_softc*)ppsc; > + > + /* Make sure power management is enabled, and set the card into > + * D3hot power state so it stays active after system shutdown. */ > + command = pci_conf_read(psc->psc_pc, psc->psc_tag, XL_PCI_PWRMGMTCTRL); > + command |= XL_PME_EN | XL_PSTATE_D3; > + pci_conf_write(psc->psc_pc, psc->psc_tag, XL_PCI_PWRMGMTCTRL, command); > +} > +#endif