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

Reply via email to