Initial WOL support. NS DP8315 was tested but SiS900/SiS7016 was
not tested. While I'm here, clean up SIOCSIFCAP handler.
This commit is contained in:
parent
7968da57dc
commit
0af3989be9
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=212167
@ -147,12 +147,15 @@ static void sis_initl(struct sis_softc *);
|
|||||||
static void sis_intr(void *);
|
static void sis_intr(void *);
|
||||||
static int sis_ioctl(struct ifnet *, u_long, caddr_t);
|
static int sis_ioctl(struct ifnet *, u_long, caddr_t);
|
||||||
static int sis_newbuf(struct sis_softc *, struct sis_rxdesc *);
|
static int sis_newbuf(struct sis_softc *, struct sis_rxdesc *);
|
||||||
|
static int sis_resume(device_t);
|
||||||
static int sis_rxeof(struct sis_softc *);
|
static int sis_rxeof(struct sis_softc *);
|
||||||
static void sis_start(struct ifnet *);
|
static void sis_start(struct ifnet *);
|
||||||
static void sis_startl(struct ifnet *);
|
static void sis_startl(struct ifnet *);
|
||||||
static void sis_stop(struct sis_softc *);
|
static void sis_stop(struct sis_softc *);
|
||||||
|
static int sis_suspend(device_t);
|
||||||
static void sis_add_sysctls(struct sis_softc *);
|
static void sis_add_sysctls(struct sis_softc *);
|
||||||
static void sis_watchdog(struct sis_softc *);
|
static void sis_watchdog(struct sis_softc *);
|
||||||
|
static void sis_wol(struct sis_softc *);
|
||||||
|
|
||||||
|
|
||||||
static struct resource_spec sis_res_spec[] = {
|
static struct resource_spec sis_res_spec[] = {
|
||||||
@ -935,6 +938,9 @@ sis_reset(struct sis_softc *sc)
|
|||||||
if (sc->sis_type == SIS_TYPE_83815) {
|
if (sc->sis_type == SIS_TYPE_83815) {
|
||||||
CSR_WRITE_4(sc, NS_CLKRUN, NS_CLKRUN_PMESTS);
|
CSR_WRITE_4(sc, NS_CLKRUN, NS_CLKRUN_PMESTS);
|
||||||
CSR_WRITE_4(sc, NS_CLKRUN, 0);
|
CSR_WRITE_4(sc, NS_CLKRUN, 0);
|
||||||
|
} else {
|
||||||
|
/* Disable WOL functions. */
|
||||||
|
CSR_WRITE_4(sc, SIS_PWRMAN_CTL, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -971,7 +977,7 @@ sis_attach(device_t dev)
|
|||||||
u_char eaddr[ETHER_ADDR_LEN];
|
u_char eaddr[ETHER_ADDR_LEN];
|
||||||
struct sis_softc *sc;
|
struct sis_softc *sc;
|
||||||
struct ifnet *ifp;
|
struct ifnet *ifp;
|
||||||
int error = 0, waittime = 0;
|
int error = 0, pmc, waittime = 0;
|
||||||
|
|
||||||
waittime = 0;
|
waittime = 0;
|
||||||
sc = device_get_softc(dev);
|
sc = device_get_softc(dev);
|
||||||
@ -1147,6 +1153,14 @@ sis_attach(device_t dev)
|
|||||||
ifp->if_snd.ifq_drv_maxlen = SIS_TX_LIST_CNT - 1;
|
ifp->if_snd.ifq_drv_maxlen = SIS_TX_LIST_CNT - 1;
|
||||||
IFQ_SET_READY(&ifp->if_snd);
|
IFQ_SET_READY(&ifp->if_snd);
|
||||||
|
|
||||||
|
if (pci_find_extcap(sc->sis_dev, PCIY_PMG, &pmc) == 0) {
|
||||||
|
if (sc->sis_type == SIS_TYPE_83815)
|
||||||
|
ifp->if_capabilities |= IFCAP_WOL;
|
||||||
|
else
|
||||||
|
ifp->if_capabilities |= IFCAP_WOL_MAGIC;
|
||||||
|
ifp->if_capenable = ifp->if_capabilities;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do MII setup.
|
* Do MII setup.
|
||||||
*/
|
*/
|
||||||
@ -2227,7 +2241,7 @@ sis_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
|
|||||||
struct sis_softc *sc = ifp->if_softc;
|
struct sis_softc *sc = ifp->if_softc;
|
||||||
struct ifreq *ifr = (struct ifreq *) data;
|
struct ifreq *ifr = (struct ifreq *) data;
|
||||||
struct mii_data *mii;
|
struct mii_data *mii;
|
||||||
int error = 0;
|
int error = 0, mask;
|
||||||
|
|
||||||
switch (command) {
|
switch (command) {
|
||||||
case SIOCSIFFLAGS:
|
case SIOCSIFFLAGS:
|
||||||
@ -2264,32 +2278,37 @@ sis_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
|
|||||||
error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
|
error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
|
||||||
break;
|
break;
|
||||||
case SIOCSIFCAP:
|
case SIOCSIFCAP:
|
||||||
/* ok, disable interrupts */
|
SIS_LOCK(sc);
|
||||||
|
mask = ifr->ifr_reqcap ^ ifp->if_capenable;
|
||||||
#ifdef DEVICE_POLLING
|
#ifdef DEVICE_POLLING
|
||||||
if (ifr->ifr_reqcap & IFCAP_POLLING &&
|
if ((mask & IFCAP_POLLING) != 0 &&
|
||||||
!(ifp->if_capenable & IFCAP_POLLING)) {
|
(IFCAP_POLLING & ifp->if_capabilities) != 0) {
|
||||||
error = ether_poll_register(sis_poll, ifp);
|
ifp->if_capenable ^= IFCAP_POLLING;
|
||||||
if (error)
|
if ((IFCAP_POLLING & ifp->if_capenable) != 0) {
|
||||||
return (error);
|
error = ether_poll_register(sis_poll, ifp);
|
||||||
SIS_LOCK(sc);
|
if (error != 0) {
|
||||||
/* Disable interrupts */
|
SIS_UNLOCK(sc);
|
||||||
CSR_WRITE_4(sc, SIS_IER, 0);
|
break;
|
||||||
ifp->if_capenable |= IFCAP_POLLING;
|
}
|
||||||
SIS_UNLOCK(sc);
|
/* Disable interrupts. */
|
||||||
return (error);
|
CSR_WRITE_4(sc, SIS_IER, 0);
|
||||||
|
} else {
|
||||||
}
|
error = ether_poll_deregister(ifp);
|
||||||
if (!(ifr->ifr_reqcap & IFCAP_POLLING) &&
|
/* Enable interrupts. */
|
||||||
ifp->if_capenable & IFCAP_POLLING) {
|
CSR_WRITE_4(sc, SIS_IER, 1);
|
||||||
error = ether_poll_deregister(ifp);
|
}
|
||||||
/* Enable interrupts. */
|
|
||||||
SIS_LOCK(sc);
|
|
||||||
CSR_WRITE_4(sc, SIS_IER, 1);
|
|
||||||
ifp->if_capenable &= ~IFCAP_POLLING;
|
|
||||||
SIS_UNLOCK(sc);
|
|
||||||
return (error);
|
|
||||||
}
|
}
|
||||||
#endif /* DEVICE_POLLING */
|
#endif /* DEVICE_POLLING */
|
||||||
|
if ((mask & IFCAP_WOL) != 0 &&
|
||||||
|
(ifp->if_capabilities & IFCAP_WOL) != 0) {
|
||||||
|
if ((mask & IFCAP_WOL_UCAST) != 0)
|
||||||
|
ifp->if_capenable ^= IFCAP_WOL_UCAST;
|
||||||
|
if ((mask & IFCAP_WOL_MCAST) != 0)
|
||||||
|
ifp->if_capenable ^= IFCAP_WOL_MCAST;
|
||||||
|
if ((mask & IFCAP_WOL_MAGIC) != 0)
|
||||||
|
ifp->if_capenable ^= IFCAP_WOL_MAGIC;
|
||||||
|
}
|
||||||
|
SIS_UNLOCK(sc);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error = ether_ioctl(ifp, command, data);
|
error = ether_ioctl(ifp, command, data);
|
||||||
@ -2384,13 +2403,8 @@ sis_stop(struct sis_softc *sc)
|
|||||||
static int
|
static int
|
||||||
sis_shutdown(device_t dev)
|
sis_shutdown(device_t dev)
|
||||||
{
|
{
|
||||||
struct sis_softc *sc;
|
|
||||||
|
|
||||||
sc = device_get_softc(dev);
|
return (sis_suspend(dev));
|
||||||
SIS_LOCK(sc);
|
|
||||||
sis_stop(sc);
|
|
||||||
SIS_UNLOCK(sc);
|
|
||||||
return (0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -2401,6 +2415,7 @@ sis_suspend(device_t dev)
|
|||||||
sc = device_get_softc(dev);
|
sc = device_get_softc(dev);
|
||||||
SIS_LOCK(sc);
|
SIS_LOCK(sc);
|
||||||
sis_stop(sc);
|
sis_stop(sc);
|
||||||
|
sis_wol(sc);
|
||||||
SIS_UNLOCK(sc);
|
SIS_UNLOCK(sc);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@ -2422,6 +2437,56 @@ sis_resume(device_t dev)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sis_wol(struct sis_softc *sc)
|
||||||
|
{
|
||||||
|
struct ifnet *ifp;
|
||||||
|
uint32_t val;
|
||||||
|
uint16_t pmstat;
|
||||||
|
int pmc;
|
||||||
|
|
||||||
|
ifp = sc->sis_ifp;
|
||||||
|
if ((ifp->if_capenable & IFCAP_WOL) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (sc->sis_type == SIS_TYPE_83815) {
|
||||||
|
/* Reset RXDP. */
|
||||||
|
CSR_WRITE_4(sc, SIS_RX_LISTPTR, 0);
|
||||||
|
|
||||||
|
/* Configure WOL events. */
|
||||||
|
CSR_READ_4(sc, NS_WCSR);
|
||||||
|
val = 0;
|
||||||
|
if ((ifp->if_capenable & IFCAP_WOL_UCAST) != 0)
|
||||||
|
val |= NS_WCSR_WAKE_UCAST;
|
||||||
|
if ((ifp->if_capenable & IFCAP_WOL_MCAST) != 0)
|
||||||
|
val |= NS_WCSR_WAKE_MCAST;
|
||||||
|
if ((ifp->if_capenable & IFCAP_WOL_MAGIC) != 0)
|
||||||
|
val |= NS_WCSR_WAKE_MAGIC;
|
||||||
|
CSR_WRITE_4(sc, NS_WCSR, val);
|
||||||
|
/* Enable PME and clear PMESTS. */
|
||||||
|
val = CSR_READ_4(sc, NS_CLKRUN);
|
||||||
|
val |= NS_CLKRUN_PMEENB | NS_CLKRUN_PMESTS;
|
||||||
|
CSR_WRITE_4(sc, NS_CLKRUN, val);
|
||||||
|
/* Enable silent RX mode. */
|
||||||
|
SIS_SETBIT(sc, SIS_CSR, SIS_CSR_RX_ENABLE);
|
||||||
|
} else {
|
||||||
|
if (pci_find_extcap(sc->sis_dev, PCIY_PMG, &pmc) != 0)
|
||||||
|
return;
|
||||||
|
val = 0;
|
||||||
|
if ((ifp->if_capenable & IFCAP_WOL_MAGIC) != 0)
|
||||||
|
val |= SIS_PWRMAN_WOL_MAGIC;
|
||||||
|
CSR_WRITE_4(sc, SIS_PWRMAN_CTL, val);
|
||||||
|
/* Request PME. */
|
||||||
|
pmstat = pci_read_config(sc->sis_dev,
|
||||||
|
pmc + PCIR_POWER_STATUS, 2);
|
||||||
|
pmstat &= ~(PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE);
|
||||||
|
if ((ifp->if_capenable & IFCAP_WOL_MAGIC) != 0)
|
||||||
|
pmstat |= PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE;
|
||||||
|
pci_write_config(sc->sis_dev,
|
||||||
|
pmc + PCIR_POWER_STATUS, pmstat, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sis_add_sysctls(struct sis_softc *sc)
|
sis_add_sysctls(struct sis_softc *sc)
|
||||||
{
|
{
|
||||||
|
@ -77,6 +77,7 @@
|
|||||||
/* NS DP83815/6 registers */
|
/* NS DP83815/6 registers */
|
||||||
#define NS_IHR 0x1C
|
#define NS_IHR 0x1C
|
||||||
#define NS_CLKRUN 0x3C
|
#define NS_CLKRUN 0x3C
|
||||||
|
#define NS_WCSR 0x40
|
||||||
#define NS_SRR 0x58
|
#define NS_SRR 0x58
|
||||||
#define NS_BMCR 0x80
|
#define NS_BMCR 0x80
|
||||||
#define NS_BMSR 0x84
|
#define NS_BMSR 0x84
|
||||||
@ -99,6 +100,29 @@
|
|||||||
#define NS_CLKRUN_PMEENB 0x00000100
|
#define NS_CLKRUN_PMEENB 0x00000100
|
||||||
#define NS_CLNRUN_CLKRUN_ENB 0x00000001
|
#define NS_CLNRUN_CLKRUN_ENB 0x00000001
|
||||||
|
|
||||||
|
#define NS_WCSR_WAKE_PHYINTR 0x00000001
|
||||||
|
#define NS_WCSR_WAKE_UCAST 0x00000002
|
||||||
|
#define NS_WCSR_WAKE_MCAST 0x00000004
|
||||||
|
#define NS_WCSR_WAKE_BCAST 0x00000008
|
||||||
|
#define NS_WCSR_WAKE_ARP 0x00000010
|
||||||
|
#define NS_WCSR_WAKE_PATTERN0 0x00000020
|
||||||
|
#define NS_WCSR_WAKE_PATTERN1 0x00000040
|
||||||
|
#define NS_WCSR_WAKE_PATTERN2 0x00000080
|
||||||
|
#define NS_WCSR_WAKE_PATTERN3 0x00000100
|
||||||
|
#define NS_WCSR_WAKE_MAGIC 0x00000200
|
||||||
|
#define NS_WCSR_WAKE_MAGIC_SEC 0x00000400
|
||||||
|
#define NS_WCSR_DET_MAGIC_SECH 0x00100000
|
||||||
|
#define NS_WCSR_DET_PHYINTR 0x00400000
|
||||||
|
#define NS_WCSR_DET_UCAST 0x00800000
|
||||||
|
#define NS_WCSR_DET_MCAST 0x01000000
|
||||||
|
#define NS_WCSR_DET_BCAST 0x02000000
|
||||||
|
#define NS_WCSR_DET_ARP 0x04000000
|
||||||
|
#define NS_WCSR_DET_PATTERN0 0x08000000
|
||||||
|
#define NS_WCSR_DET_PATTERN1 0x10000000
|
||||||
|
#define NS_WCSR_DET_PATTERN2 0x20000000
|
||||||
|
#define NS_WCSR_DET_PATTERN3 0x40000000
|
||||||
|
#define NS_WCSR_DET_MAGIC 0x80000000
|
||||||
|
|
||||||
/* NS silicon revisions */
|
/* NS silicon revisions */
|
||||||
#define NS_SRR_15C 0x302
|
#define NS_SRR_15C 0x302
|
||||||
#define NS_SRR_15D 0x403
|
#define NS_SRR_15D 0x403
|
||||||
@ -303,6 +327,10 @@
|
|||||||
#define NS_FILTADDR_FMEM_LO 0x00000200
|
#define NS_FILTADDR_FMEM_LO 0x00000200
|
||||||
#define NS_FILTADDR_FMEM_HI 0x000003FE
|
#define NS_FILTADDR_FMEM_HI 0x000003FE
|
||||||
|
|
||||||
|
#define SIS_PWRMAN_WOL_LINK_OFF 0x00000001
|
||||||
|
#define SIS_PWRMAN_WOL_LINK_ON 0x00000002
|
||||||
|
#define SIS_PWRMAN_WOL_MAGIC 0x00000400
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TX/RX DMA descriptor structures.
|
* TX/RX DMA descriptor structures.
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user