This should work on sparc64?

if so I can test in my sunfire v210... - this box isn't set up to
build a kernel so it will be some work to make it build -

On Wed, Apr 23, 2014 at 11:15 AM, Stefan Sperling <s...@openbsd.org> wrote:
> The reason we don't enable WOL with bge cards is that they contain
> ASF firmware support which should not be exposed to untrusted traffic,
> so it's safer to power down bge devices altogether on power down.
> Since all bges except the rare 5700 version support ASF, this currently
> means no WOL support for bge cards at all.
>
> (If you want to know what's so bad about ASF, search the net for
> security problems with intel AMT -- ASF is a precursor to this.)
>
> Apparently there is an eeprom configuration bit that tells us
> if ASF is enabled or not. Can we trust this bit?
> If we decide that the bit is trustworthy enough, we could allow
> users to enable wol for bge cards as long as ASF is disabled
> (yet I'd still want a warning in the man page).
>
> The diff below tries to do this. I don't have any hardware to test
> with so I'd be delighted if some bge owners could give this a spin.
> If this doesn't make wol work and the problem can't be fixed, then
> we can skip the entire ASF discussion anyway.
>
> To test this:
>
>  - recompile your kernel with the below diff
>  - reboot
>  - run 'ifconfig bge0 wol'
>  - run 'shutdown -hp now'
>  - try to send a magic packet from another machine with 'arp -W MAC_ADDR'
>    and hope for the bge box to power back up
>
> If it doesn't work, please check your BIOS for WOL and ASF-related
> configuration settings and check if tweaking them helps.
>
> Thanks.
>
> Index: mii/brgphyreg.h
> ===================================================================
> RCS file: /cvs/src/sys/dev/mii/brgphyreg.h,v
> retrieving revision 1.16
> diff -u -p -r1.16 brgphyreg.h
> --- mii/brgphyreg.h     13 Jan 2013 05:40:05 -0000      1.16
> +++ mii/brgphyreg.h     23 Apr 2014 14:11:06 -0000
> @@ -206,6 +206,7 @@
>  #define BRGPHY_AUXCTL_TX_TST   0x0400  /* TX test, always 1 */
>  #define BRGPHY_AUXCTL_DIS_PRF  0x0080  /* dis part resp filter */
>  #define BRGPHY_AUXCTL_DIAG_MODE        0x0004  /* Diagnostic mode */
> +#define BRGPHY_AUXCTL_WOL_ENBL 0x000A  /* Enable WOL */
>
>  #define BRGPHY_MII_AUXSTS      0x19    /* AUX status */
>  #define BRGPHY_AUXSTS_ACOMP    0x8000  /* autoneg complete */
> Index: pci/if_bge.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/if_bge.c,v
> retrieving revision 1.353
> diff -u -p -r1.353 if_bge.c
> --- pci/if_bge.c        24 Feb 2014 20:00:48 -0000      1.353
> +++ pci/if_bge.c        23 Apr 2014 15:33:54 -0000
> @@ -202,6 +202,10 @@ void bge_sig_pre_reset(struct bge_softc
>  void bge_stop_fw(struct bge_softc *, int);
>  void bge_reset(struct bge_softc *);
>  void bge_link_upd(struct bge_softc *);
> +#ifndef SMALL_KERNEL
> +int bge_wol(struct ifnet *, int);
> +void bge_wol_power(struct bge_softc *);
> +#endif
>
>  void bge_ape_lock_init(struct bge_softc *);
>  void bge_ape_read_fw_ver(struct bge_softc *);
> @@ -3064,6 +3068,35 @@ bge_attach(struct device *parent, struct
>         if (BGE_IS_5755_PLUS(sc) && sc->bge_flags & BGE_MSI)
>                 CSR_WRITE_4(sc, BGE_MSI_MODE, CSR_READ_4(sc, BGE_MSI_MODE) &
>                     ~BGE_MSIMODE_ONE_SHOT_DISABLE);
> +
> +#ifndef SMALL_KERNEL
> +       if (hwcfg & BGE_HWCFG_NO_GPIO2)
> +               sc->bge_flags |= BGE_NO_GPIO2;
> +
> +       if (BGE_ASICREV(sc->bge_chipid) != BGE_ASICREV_BCM5700) {
> +               /* Check if ASF is enabled. */
> +               if (!(sc->bge_flags & BGE_NO_EEPROM)) {
> +                   if (bge_read_eeprom(sc, (caddr_t)&hwcfg,
> +                       BGE_EE_FEATURE_CFG_OFFSET, sizeof(hwcfg)) == 0) {
> +                               hwcfg = ntohl(hwcfg);
> +                               if (hwcfg & BGE_HWCFG_ASF)
> +                                       sc->bge_flags |= BGE_ASF_MODE;
> +                   }
> +               } else if (hwcfg & BGE_HWCFG_ASF) {
> +                       sc->bge_flags |= BGE_ASF_MODE;
> +               }
> +       }
> +
> +       /* Allow WoL if ASF is unsupported or disabled. */
> +       if (!(sc->bge_flags & BGE_ASF_MODE)) {
> +               ifp->if_capabilities |= IFCAP_WOL;
> +               ifp->if_wol = bge_wol;
> +
> +               /* This heuristic matches the Linux driver. */
> +               if (!(hwcfg & BGE_HWCFG_EEPROM_WRITE_PROTECT))
> +                       sc->bge_flags |= BGE_WOL_NEEDS_VAUX;
> +       }
> +#endif
>
>         /* Hookup IRQ last. */
>         DPRINTFN(5, ("pci_intr_establish\n"));
> @@ -3160,6 +3193,9 @@ bge_activate(struct device *self, int ac
>                 rv = config_activate_children(self, act);
>                 if (ifp->if_flags & IFF_RUNNING)
>                         bge_stop(sc);
> +#ifndef SMALL_KERNEL
> +               bge_wol_power(sc);
> +#endif
>                 break;
>         case DVACT_RESUME:
>                 if (ifp->if_flags & IFF_UP)
> @@ -4728,3 +4764,177 @@ bge_link_upd(struct bge_softc *sc)
>             BGE_MACSTAT_CFG_CHANGED|BGE_MACSTAT_MI_COMPLETE|
>             BGE_MACSTAT_LINK_CHANGED);
>  }
> +
> +#ifndef SMALL_KERNEL
> +int
> +bge_wol(struct ifnet *ifp, int enable)
> +{
> +       struct bge_softc *sc = ifp->if_softc;
> +
> +       if (enable)
> +               sc->bge_flags |= BGE_WOL;
> +       else
> +               sc->bge_flags &= ~BGE_WOL;
> +
> +       return (0);
> +}
> +
> +void
> +bge_wol_power(struct bge_softc *sc)
> +{
> +       struct ifnet *ifp = &sc->arpcom.ac_if;
> +       struct pci_attach_args *pa = &sc->bge_pa;
> +       pcireg_t pcireg;
> +       int s, offset, if_flags;
> +       u_int32_t reg;
> +
> +       if (!(sc->bge_flags & BGE_WOL))
> +               return;
> +
> +       s = splnet();
> +
> +       /*
> +        * In case the interface was never up we need to init the
> +        * chip for WOL to work.
> +        * XXX Need a smaller hammer than bge_init()/bge_stop().
> +        */
> +       bge_init(sc);
> +
> +       /* Tell the firmware we're taking control of WOL. */
> +       bge_writemem_ind(sc, BGE_SOFTWARE_GENCOMM_WOL, BGE_MAGIC_WOL_NUMBER);
> +       DELAY(100);
> +
> +       bge_stop(sc);
> +
> +       /* Disable host interrupts. */
> +       BGE_SETBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_MASK_PCI_INTR);
> +
> +       /* Clear the PME status bit. */
> +       if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_PWRMGMT,
> +           &offset, &pcireg))
> +               pci_conf_write(pa->pa_pc, pa->pa_tag, offset + PCI_PMCSR,
> +                   pcireg|PCI_PMCSR_PME_STATUS);
> +
> +       /* Configure 10Mbps, the chip draws too much power in D3cold. */
> +       if (!(sc->bge_flags & BGE_FIBER_TBI) &&
> +           !(sc->bge_flags & BGE_FIBER_MII)) {
> +               sc->bge_ifmedia.ifm_media = IFM_ETHER|IFM_10_T;
> +               if_flags = ifp->if_flags;
> +               ifp->if_flags |= IFF_UP;
> +               bge_ifmedia_upd(ifp);
> +               ifp->if_flags = if_flags;
> +       }
> +
> +       /* Disable DMA. */
> +       BGE_CLRBIT(sc, BGE_MAC_MODE, BGE_MACMODE_FRMHDR_DMA_ENB|
> +           BGE_MACMODE_TXDMA_ENB|BGE_MACMODE_RXDMA_ENB);
> +
> +       /* Halt CPUs. */
> +       BGE_SETBIT(sc, BGE_TXCPU_MODE, BGE_TXCPUMODE_HALTCPU);
> +       BGE_SETBIT(sc, BGE_RXCPU_MODE, BGE_RXCPUMODE_HALTCPU);
> +
> +       /* Configure the PHY for WOL mode. */
> +       bge_miibus_writereg(&sc->bge_dev, 1, BRGPHY_MII_AUXCTL,
> +           BRGPHY_AUXCTL_WOL_ENBL);
> +       BGE_CLRBIT(sc, BGE_MAC_MODE, BGE_MACMODE_PORTMODE);
> +       CSR_WRITE_4(sc, BGE_MAC_MODE, BGE_PORTMODE_MII|
> +           BGE_MACMODE_LINK_POLARITY|BGE_MACMODE_MAGIC_PKT_ENB);
> +       DELAY(100);
> +
> +       /* Disable RX and TX CPUs, enable alternate clock. */
> +       BGE_SETBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_CLOCKCTL_RW);
> +       BGE_SETBIT(sc, BGE_PCI_CLKCTL,
> +           BGE_PCICLOCKCTL_RXCPU_CLK_DIS|BGE_PCICLOCKCTL_TXCPU_CLK_DIS|
> +           BGE_PCICLOCKCTL_ALTCLK|BGE_PCICLOCKCTL_LOW_SPEED_PLL);
> +       DELAY(500);
> +       BGE_CLRBIT(sc, BGE_PCI_CLKCTL, BGE_PCICLOCKCTL_ALTCLK);
> +       BGE_CLRBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_CLOCKCTL_RW);
> +
> +       if (sc->bge_flags & BGE_WOL_NEEDS_VAUX) {
> +               /* Switch from main power to aux power. */
> +               if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5700 ||
> +                   BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5701) {
> +                       BGE_SETBIT(sc, BGE_MISC_LOCAL_CTL,
> +                           BGE_MLC_INTR_ONATTN|BGE_MLC_AUTO_EEPROM|
> +                           BGE_MLC_MISCIO_OUTEN0|BGE_MLC_MISCIO_OUTEN1|
> +                           BGE_MLC_MISCIO_OUTEN2|
> +                           BGE_MLC_MISCIO_OUT0|BGE_MLC_MISCIO_OUT1);
> +                       DELAY(100);
> +               } else if (PCI_PRODUCT(pa->pa_id) ==
> +                   PCI_PRODUCT_BROADCOM_BCM5761 ||
> +                   PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROADCOM_BCM5761S) {
> +                       /* These have GPIO 0 and GPIO 2 swapped. */
> +                       reg = (BGE_MLC_INTR_ONATTN|BGE_MLC_AUTO_EEPROM|
> +                           BGE_MLC_MISCIO_OUTEN0|BGE_MLC_MISCIO_OUTEN1|
> +                           BGE_MLC_MISCIO_OUTEN2|
> +                           BGE_MLC_MISCIO_OUT0|BGE_MLC_MISCIO_OUT1);
> +                       BGE_SETBIT(sc, BGE_MISC_LOCAL_CTL, reg);
> +                       DELAY(100);
> +                       reg |= BGE_MLC_MISCIO_OUT2;
> +                       BGE_SETBIT(sc, BGE_MISC_LOCAL_CTL, reg);
> +                       DELAY(100);
> +                       reg &= ~BGE_MLC_MISCIO_OUT0;
> +                       BGE_SETBIT(sc, BGE_MISC_LOCAL_CTL, reg);
> +                       DELAY(100);
> +               } else {
> +                       reg = 0;
> +
> +                       /* Workaround for drawing too much power. */
> +                       if (BGE_ASICREV(sc->bge_chipid) ==
> +                           BGE_ASICREV_BCM5714) {
> +                               reg |= BGE_MLC_MISCIO_OUTEN3;
> +                               BGE_SETBIT(sc, BGE_MISC_LOCAL_CTL, reg);
> +                               DELAY(100);
> +                       }
> +
> +                       if (sc->bge_flags & BGE_NO_GPIO2) {
> +                               reg |= (BGE_MLC_MISCIO_OUTEN0|
> +                                   BGE_MLC_MISCIO_OUTEN1|
> +                                   BGE_MLC_MISCIO_OUT1);
> +                       } else {
> +                               reg |= (BGE_MLC_MISCIO_OUTEN0|
> +                                   BGE_MLC_MISCIO_OUTEN1|
> +                                   BGE_MLC_MISCIO_OUTEN2|
> +                                   BGE_MLC_MISCIO_OUT1|
> +                                   BGE_MLC_MISCIO_OUT2);
> +                       }
> +
> +                       BGE_SETBIT(sc, BGE_MISC_LOCAL_CTL, reg);
> +                       DELAY(100);
> +
> +                       reg |= BGE_MLC_MISCIO_OUT0;
> +                       BGE_SETBIT(sc, BGE_MISC_LOCAL_CTL, reg);
> +                       DELAY(100);
> +
> +                       if (!(sc->bge_flags & BGE_NO_GPIO2)) {
> +                               reg &= ~BGE_MLC_MISCIO_OUT2;
> +                               BGE_SETBIT(sc, BGE_MISC_LOCAL_CTL, reg);
> +                               DELAY(100);
> +                       }
> +               }
> +       } else if (BGE_ASICREV(sc->bge_chipid) != BGE_ASICREV_BCM5700 &&
> +                  BGE_ASICREV(sc->bge_chipid) != BGE_ASICREV_BCM5701) {
> +               /* Die with vmain power. */
> +               BGE_SETBIT(sc, BGE_MISC_LOCAL_CTL,
> +                   BGE_MLC_MISCIO_OUT1|BGE_MLC_MISCIO_OUTEN1);
> +               DELAY(100);
> +               BGE_CLRBIT(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_MISCIO_OUT1);
> +               DELAY(100);
> +               BGE_SETBIT(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_MISCIO_OUT1);
> +               DELAY(100);
> +       }
> +
> +       /* Re-enable RX in promiscuous mode. */
> +       BGE_SETBIT(sc, BGE_RX_MODE, BGE_RXMODE_ENABLE|BGE_RXMODE_RX_PROMISC);
> +
> +       /* Enable PME assertion and put the device to sleep. */
> +       if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_PWRMGMT,
> +           &offset, &reg)) {
> +               pci_conf_write(pa->pa_pc, pa->pa_tag, offset + PCI_PMCSR,
> +                   reg|PCI_PMCSR_PME_EN);
> +               pci_set_powerstate(pa->pa_pc, pa->pa_tag, PCI_PMCSR_STATE_D3);
> +       }
> +
> +       splx(s);
> +}
> +#endif
> Index: pci/if_bgereg.h
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/if_bgereg.h,v
> retrieving revision 1.123
> diff -u -p -r1.123 if_bgereg.h
> --- pci/if_bgereg.h     5 Feb 2014 05:59:42 -0000       1.123
> +++ pci/if_bgereg.h     23 Apr 2014 15:14:07 -0000
> @@ -80,6 +80,7 @@
>  #define           BGE_VER_SHIFT                        16
>  #define        BGE_SOFTWARE_GENCOMM_FW         0x00000B78
>  #define           BGE_FW_PAUSE                         0x00000002
> +#define BGE_SOFTWARE_GENCOMM_WOL       0x00000D30
>  #define        BGE_SOFTWARE_GENCOMM_NICCFG2    0x00000D38
>  #define        BGE_SOFTWARE_GENCOMM_NICCFG3    0x00000D3C
>  #define        BGE_SOFTWARE_GENCOMM_NICCFG4    0x00000D60
> @@ -438,6 +439,7 @@
>  #define        BGE_PCICLOCKCTL_PCIPLL_DISABLE  0x00004000
>  #define        BGE_PCICLOCKCTL_SYSPLL_DISABLE  0x00008000
>  #define        BGE_PCICLOCKCTL_BIST_ENABLE     0x00010000
> +#define BGE_PCICLOCKCTL_LOW_SPEED_PLL  0x00020000
>
>  /*
>   * High priority mailbox registers
> @@ -2102,6 +2104,8 @@
>  #define        BGE_MLC_INTR_CLR                0x00000002
>  #define        BGE_MLC_INTR_SET                0x00000004
>  #define        BGE_MLC_INTR_ONATTN             0x00000008
> +#define        BGE_MLC_MISCIO_OUTEN3           0x00000040
> +#define        BGE_MLC_MISCIO_OUT3             0x00000080
>  #define        BGE_MLC_MISCIO_IN0              0x00000100
>  #define        BGE_MLC_MISCIO_IN1              0x00000200
>  #define        BGE_MLC_MISCIO_IN2              0x00000400
> @@ -2292,6 +2296,12 @@
>   */
>  #define        BGE_MAGIC_NUMBER                0x4B657654
>
> +/*
> + * This magic number needs to be written to the firmware mailbox at
> + * 0xd30 before WOL is configured.
> + */
> +#define BGE_MAGIC_WOL_NUMBER           0x474C0000
> +
>  typedef struct {
>         u_int32_t               bge_addr_hi;
>         u_int32_t               bge_addr_lo;
> @@ -2470,12 +2480,15 @@ struct bge_status_block {
>   */
>  #define        BGE_EE_MAC_OFFSET               0x7C
>  #define        BGE_EE_MAC_OFFSET_5906          0x10
> +#define        BGE_EE_FEATURE_CFG_OFFSET       0xC4
>  #define        BGE_EE_HWCFG_OFFSET             0xC8
>
>  #define        BGE_HWCFG_VOLTAGE               0x00000003
>  #define        BGE_HWCFG_PHYLED_MODE           0x0000000C
>  #define        BGE_HWCFG_MEDIA                 0x00000030
>  #define        BGE_HWCFG_ASF                   0x00000080
> +#define BGE_HWCFG_EEPROM_WRITE_PROTECT 0x00000100
> +#define BGE_HWCFG_NO_GPIO2             0x00100000
>
>  #define        BGE_VOLTAGE_1POINT3             0x00000000
>  #define        BGE_VOLTAGE_1POINT8             0x00000001
> @@ -2869,6 +2882,9 @@ struct bge_softc {
>  #define        BGE_TAGGED_STATUS       0x00200000
>  #define        BGE_MSI                 0x00400000
>  #define        BGE_RDMA_BUG            0x00800000
> +#define BGE_WOL                        0x04000000
> +#define BGE_WOL_NEEDS_VAUX     0x08000000
> +#define BGE_NO_GPIO2           0x10000000
>
>         u_int32_t               bge_phy_flags;
>  #define        BGE_PHY_NO_3LED         0x00000001
> Index: pci/pcireg.h
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/pcireg.h,v
> retrieving revision 1.46
> diff -u -p -r1.46 pcireg.h
> --- pci/pcireg.h        9 Apr 2014 06:36:33 -0000       1.46
> +++ pci/pcireg.h        23 Apr 2014 14:11:06 -0000
> @@ -518,11 +518,13 @@ typedef u_int8_t pci_revision_t;
>   * Power Management Control Status Register; access via capability pointer.
>   */
>  #define PCI_PMCSR              0x04
> -#define PCI_PMCSR_STATE_MASK   0x03
> -#define PCI_PMCSR_STATE_D0     0x00
> -#define PCI_PMCSR_STATE_D1     0x01
> -#define PCI_PMCSR_STATE_D2     0x02
> -#define PCI_PMCSR_STATE_D3     0x03
> +#define PCI_PMCSR_STATE_MASK   0x0003
> +#define PCI_PMCSR_STATE_D0     0x0000
> +#define PCI_PMCSR_STATE_D1     0x0001
> +#define PCI_PMCSR_STATE_D2     0x0002
> +#define PCI_PMCSR_STATE_D3     0x0003
> +#define PCI_PMCSR_PME_STATUS   0x8000
> +#define PCI_PMCSR_PME_EN       0x0100
>
>  /*
>   * HyperTransport; access via capability pointer.
>
>
>
>

Reply via email to