diff -ruN dist+patches-2.4.8/drivers/net/natsemi.c cobalt-2.4.8/drivers/net/natsemi.c --- dist+patches-2.4.8/drivers/net/natsemi.c Tue Jul 17 18:53:55 2001 +++ cobalt-2.4.8/drivers/net/natsemi.c Mon Aug 13 16:42:04 2001 @@ -60,16 +60,20 @@ from Myrio Corporation, Greg Smith] * suspend/resume + version 1.0.8 (Tim Hockin ) + * ETHTOOL_* support + * Wake on lan support (Erik Gilling) + * MXDMA fixes for serverworks + * EEPROM reload TODO: * big endian support with CFG:BEM instead of cpu_to_le32 * support for an external PHY * flow control - * Wake-On-LAN */ #define DRV_NAME "natsemi" -#define DRV_VERSION "1.07+LK1.0.7" -#define DRV_RELDATE "May 18, 2001" +#define DRV_VERSION "1.07+LK1.0.8" +#define DRV_RELDATE "Aug 07, 2001" /* Updated to recommendations in pci-skeleton v2.03. */ @@ -125,7 +129,7 @@ /* Time in jiffies before concluding the transmitter is hung. */ #define TX_TIMEOUT (2*HZ) -#define NATSEMI_HW_TIMEOUT 200 +#define NATSEMI_HW_TIMEOUT 400 #define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/ @@ -302,18 +306,30 @@ WOLCmd=0x40, PauseCmd=0x44, RxFilterAddr=0x48, RxFilterData=0x4C, BootRomAddr=0x50, BootRomData=0x54, SiliconRev=0x58, StatsCtrl=0x5C, StatsData=0x60, RxPktErrs=0x60, RxMissed=0x68, RxCRCErrs=0x64, - PCIPM=0x44, PhyStatus=0xC0, MIntrCtrl=0xC4, MIntrStatus=0xC8, + BasicControl=0x80, BasicStatus=0x84, + AnegAdv=0x90, AnegPeer = 0x94, PhyStatus=0xC0, MIntrCtrl=0xC4, + MIntrStatus=0xC8, PhyCtrl=0xE4, - /* These are from the spec, around page 78... on a separate table. */ + /* These are from the spec, around page 78... on a separate table. + * The meaning of these registers depend on the value of PGSEL. */ PGSEL=0xCC, PMDCSR=0xE4, TSTDAT=0xFC, DSPCFG=0xF4, SDCFG=0x8C }; +/* misc PCI space registers */ +enum PCISpaceRegs { + PCIPM=0x44, +}; + /* Bit in ChipCmd. */ enum ChipCmdBits { ChipReset=0x100, RxReset=0x20, TxReset=0x10, RxOff=0x08, RxOn=0x04, TxOff=0x02, TxOn=0x01, }; +enum PCIBusCfgBits { + EepromReload=0x4, +}; + /* Bits in the interrupt status/mask registers. */ enum intr_status_bits { IntrRxDone=0x0001, IntrRxIntr=0x0002, IntrRxErr=0x0004, IntrRxEarly=0x0008, @@ -324,7 +340,7 @@ WOLPkt=0x2000, RxResetDone=0x1000000, TxResetDone=0x2000000, IntrPCIErr=0x00f00000, - IntrNormalSummary=0x0251, IntrAbnormalSummary=0xED20, + IntrNormalSummary=0x025f, IntrAbnormalSummary=0xCD20, }; /* Bits in the RxMode register. */ @@ -335,6 +351,34 @@ AcceptAllPhys=0x10000000, AcceptMyPhys=0x08000000, }; +/* Bits in WOLCmd register. */ +enum wol_bits { + WakePhy=0x1, WakeUnicast=0x2, WakeMulticast=0x4, WakeBroadcast=0x8, + WakeArp=0x10, WakePMatch0=0x20, WakePMatch1=0x40, WakePMatch2=0x80, + WakePMatch3=0x100, WakeMagic=0x200, WakeMagicSecure=0x400, + SecureHack=0x100000, WokePhy=0x400000, WokeUnicast=0x800000, + WokeMulticast=0x1000000, WokeBroadcast=0x2000000, WokeArp=0x4000000, + WokePMatch0=0x8000000, WokePMatch1=0x10000000, WokePMatch2=0x20000000, + WokePMatch3=0x40000000, WokeMagic=0x80000000, WakeOptsSummary=0x7ff +}; + +enum aneg_bits { + Aneg10BaseT=0x20, Aneg10BaseTFull=0x40, + Aneg100BaseT=0x80, Aneg100BaseTFull=0x100, +}; + +enum config_bits { + CfgPhyDis=0x200, CfgPhyRst=0x400, CfgAnegEnable=0x2000, + CfgAneg100=0x4000, CfgAnegFull=0x8000, CfgAnegDone=0x8000000, + CfgFullDuplex=0x20000000, + CfgSpeed100=0x40000000, CfgLink=0x80000000, +}; + +enum bmcr_bits { + BMCRDuplex=0x100, BMCRAnegRestart=0x200, BMCRAnegEnable=0x1000, + BMCRSpeed=0x2000, BMCRPhyReset=0x8000, +}; + /* The Rx and Tx buffer descriptors. */ /* Note that using only 32 bit fields simplifies conversion to big-endian architectures. */ @@ -408,6 +452,12 @@ static void __get_stats(struct net_device *dev); static struct net_device_stats *get_stats(struct net_device *dev); static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); +static int netdev_set_wol(struct net_device *dev, u32 newval); +static int netdev_get_wol(struct net_device *dev, u32 *supported, u32 *cur); +static int netdev_set_sopass(struct net_device *dev, u8 *newval); +static int netdev_get_sopass(struct net_device *dev, u8 *data); +static int netdev_get_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd); +static int netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd); static int netdev_close(struct net_device *dev); @@ -530,6 +580,7 @@ pci_set_drvdata(pdev, NULL); return i; } + netif_carrier_off(dev); printk(KERN_INFO "%s: %s at 0x%lx, ", dev->name, natsemi_pci_info[chip_idx].name, ioaddr); @@ -548,7 +599,8 @@ chip_config & 0x8000 ? "full" : "half"); } printk(KERN_INFO "%s: Transceiver status 0x%4.4x advertising %4.4x.\n", - dev->name, (int)readl(ioaddr + 0x84), np->advertising); + dev->name, (int)readl(ioaddr + BasicStatus), + np->advertising); return 0; } @@ -617,7 +669,7 @@ static int mdio_read(struct net_device *dev, int phy_id, int location) { if (phy_id == 1 && location < 32) - return readl(dev->base_addr + 0x80 + (location<<2)) & 0xffff; + return readl(dev->base_addr+BasicControl+(location<<2))&0xffff; else return 0xffff; } @@ -639,6 +691,20 @@ printk(KERN_DEBUG "%s: reset completed in %d usec.\n", dev->name, i*5); } + + writel(EepromReload, dev->base_addr + PCIBusCfg); + for (i=0;ibase_addr + PCIBusCfg) & EepromReload)) + break; + udelay(5); + } + if (i==NATSEMI_HW_TIMEOUT && debug) { + printk(KERN_INFO "%s: EEPROM did not reload in %d usec.\n", + dev->name, i*5); + } else if (debug > 2) { + printk(KERN_DEBUG "%s: EEPROM reloaded in %d usec.\n", + dev->name, i*5); + } } @@ -733,23 +799,20 @@ if (debug > 4) printk(KERN_DEBUG "%s: found silicon revision %xh.\n", dev->name, readl(ioaddr + SiliconRev)); + /* On page 78 of the spec, they recommend some settings for "optimum performance" to be done in sequence. These settings optimize some - of the 100Mbit autodetection circuitry. Also, we only want to do - this for rev C of the chip. - - There seems to be a typo on page 78, but there isn't. The fixup - should be performed for "DP83815CVNG (SRR = 203h)", which is a - pretty old rev. This is not to be confused with 302h, which is - current. Confirmed with engineers at NSC. + of the 100Mbit autodetection circuitry. They say we only want to + do this for rev C of the chip, but engineers at NSC (Bradley + Kennedy) recommends always setting them. If you don't, you get + errors on some autonegotiations that make the device unusable. */ - if (readl(ioaddr + SiliconRev) == 0x203) { - writew(0x0001, ioaddr + PGSEL); - writew(0x189C, ioaddr + PMDCSR); - writew(0x0000, ioaddr + TSTDAT); - writew(0x5040, ioaddr + DSPCFG); - writew(0x008C, ioaddr + SDCFG); - } + writew(0x0001, ioaddr + PGSEL); + writew(0x189C, ioaddr + PMDCSR); + writew(0x0000, ioaddr + TSTDAT); + writew(0x5040, ioaddr + DSPCFG); + writew(0x008C, ioaddr + SDCFG); + writew(0x0000, ioaddr + PGSEL); /* Enable PHY Specific event based interrupts. Link state change and Auto-Negotiation Completion are among the affected. @@ -774,16 +837,16 @@ /* DRTH: 2: start tx if 64 bytes are in the fifo * FLTH: 0x10: refill with next packet if 512 bytes are free - * MXDMA: 0: up to 512 byte bursts. + * MXDMA: 0: up to 256 byte bursts. * MXDMA must be <= FLTH * ECRETRY=1 * ATP=1 */ - np->tx_config = 0x10801002; + np->tx_config = 0x10f01002; /* DRTH 0x10: start copying to memory if 128 bytes are in the fifo - * MXDMA 0: up to 512 byte bursts + * MXDMA 0: up to 256 byte bursts */ - np->rx_config = 0x0020; + np->rx_config = 0x700020; writel(np->tx_config, ioaddr + TxConfig); writel(np->rx_config, ioaddr + RxConfig); @@ -800,11 +863,11 @@ __set_rx_mode(dev); /* Enable interrupts by setting the interrupt mask. */ - writel(IntrNormalSummary | IntrAbnormalSummary | 0x1f, ioaddr + IntrMask); + writel(IntrNormalSummary | IntrAbnormalSummary, ioaddr + IntrMask); writel(1, ioaddr + IntrEnable); writel(RxOn | TxOn, ioaddr + ChipCmd); - writel(4, ioaddr + StatsCtrl); /* Clear Stats */ + writel(4, ioaddr + StatsCtrl); /* Clear Stats */ } static void netdev_timer(unsigned long data) @@ -1190,7 +1253,8 @@ if (intr_status & LinkChange) { printk(KERN_NOTICE "%s: Link changed: Autonegotiation advertising" " %4.4x partner %4.4x.\n", dev->name, - (int)readl(ioaddr + 0x90), (int)readl(ioaddr + 0x94)); + (int)readl(ioaddr + AnegAdv), + (int)readl(ioaddr + AnegPeer)); /* read MII int status to clear the flag */ readw(ioaddr + MIntrStatus); check_link(dev); @@ -1208,7 +1272,7 @@ } if (intr_status & WOLPkt) { int wol_status = readl(ioaddr + WOLCmd); - printk(KERN_NOTICE "%s: Link wake-up event %8.8x", + printk(KERN_NOTICE "%s: Link wake-up event %8.8x\n", dev->name, wol_status); } if ((intr_status & ~(LinkChange|StatsMax|RxResetDone|TxResetDone|0xA7ff)) @@ -1230,7 +1294,7 @@ /* The chip only need report frame silently dropped. */ np->stats.rx_crc_errors += readl(ioaddr + RxCRCErrs); - np->stats.rx_missed_errors += readl(ioaddr + RxMissed); + np->stats.rx_missed_errors += readl(ioaddr + RxMissed); } static struct net_device_stats *get_stats(struct net_device *dev) @@ -1349,12 +1413,12 @@ static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr) { struct netdev_private *np = dev->priv; - u32 ethcmd; + struct ethtool_cmd ecmd; - if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) + if (copy_from_user(&ecmd, useraddr, sizeof(ecmd))) return -EFAULT; - switch (ethcmd) { + switch (ecmd.cmd) { case ETHTOOL_GDRVINFO: { struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; strcpy(info.driver, DRV_NAME); @@ -1364,12 +1428,257 @@ return -EFAULT; return 0; } + case ETHTOOL_GSET: { + spin_lock_irq(&np->lock); + netdev_get_ecmd(dev, &ecmd); + spin_unlock_irq(&np->lock); + if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) + return -EFAULT; + return 0; + } + case ETHTOOL_SSET: { + int r; + if (copy_from_user(&ecmd, useraddr, sizeof(ecmd))) + return -EFAULT; + spin_lock_irq(&np->lock); + r = netdev_set_ecmd(dev, &ecmd); + spin_unlock_irq(&np->lock); + return r; + } + case ETHTOOL_GWOL: { + struct ethtool_wolinfo wol = {ETHTOOL_GWOL}; + spin_lock_irq(&np->lock); + netdev_get_wol(dev, &wol.supported, &wol.wolopts); + netdev_get_sopass(dev, wol.sopass); + spin_unlock_irq(&np->lock); + if (copy_to_user(useraddr, &wol, sizeof(wol))) + return -EFAULT; + return 0; + } + case ETHTOOL_SWOL: { + struct ethtool_wolinfo wol; + int r; + if (copy_from_user(&wol, useraddr, sizeof(wol))) + return -EFAULT; + spin_lock_irq(&np->lock); + netdev_set_wol(dev, wol.wolopts); + r = netdev_set_sopass(dev, wol.sopass); + spin_unlock_irq(&np->lock); + return r; + } } return -EOPNOTSUPP; } +static int netdev_set_wol(struct net_device *dev, u32 newval) +{ + u32 data = readl(dev->base_addr + WOLCmd) & ~WakeOptsSummary; + + /* translate to bitmasks this chip understands */ + if (newval & WAKE_PHY) + data |= WakePhy; + if (newval & WAKE_UCAST) + data |= WakeUnicast; + if (newval & WAKE_MCAST) + data |= WakeMulticast; + if (newval & WAKE_BCAST) + data |= WakeBroadcast; + if (newval & WAKE_ARP) + data |= WakeArp; + if (newval & WAKE_MAGIC) + data |= WakeMagic; + if (newval & WAKE_MAGICSECURE) + data |= WakeMagicSecure; + + writel(data, dev->base_addr + WOLCmd); + + /* should we burn these into the EEPROM? */ + + return 0; +} + +static int netdev_get_wol(struct net_device *dev, u32 *supported, u32 *cur) +{ + u32 regval = readl(dev->base_addr + WOLCmd); + + *supported = (WAKE_PHY | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST + | WAKE_ARP | WAKE_MAGIC | WAKE_MAGICSECURE); + *cur = 0; + /* translate from chip bitmasks */ + if (regval & 0x1) + *cur |= WAKE_PHY; + if (regval & 0x2) + *cur |= WAKE_UCAST; + if (regval & 0x4) + *cur |= WAKE_MCAST; + if (regval & 0x8) + *cur |= WAKE_BCAST; + if (regval & 0x10) + *cur |= WAKE_ARP; + if (regval & 0x200) + *cur |= WAKE_MAGIC; + if (regval & 0x400) + *cur |= WAKE_MAGICSECURE; + + return 0; +} + +static int netdev_set_sopass(struct net_device *dev, u8 *newval) +{ + u16 *sval = (u16 *)newval; + u32 addr = readl(dev->base_addr + RxFilterAddr) & ~0x3ff; + + /* enable writing to these registers by disabling the RX filter */ + addr &= ~0x80000000; + writel(addr, dev->base_addr + RxFilterAddr); + + /* write the three words to (undocumented) RFCR vals 0xa, 0xc, 0xe */ + writel(addr | 0xa, dev->base_addr + RxFilterAddr); + writew(sval[0], dev->base_addr + RxFilterData); + + writel(addr | 0xc, dev->base_addr + RxFilterAddr); + writew(sval[1], dev->base_addr + RxFilterData); + + writel(addr | 0xe, dev->base_addr + RxFilterAddr); + writew(sval[2], dev->base_addr + RxFilterData); + + /* re-enable the RX filter */ + writel(addr | 0x80000000, dev->base_addr + RxFilterAddr); + + /* should we burn this into the EEPROM? */ + + return 0; +} + +static int netdev_get_sopass(struct net_device *dev, u8 *data) +{ + u16 *sval = (u16 *)data; + u32 addr = readl(dev->base_addr + RxFilterAddr) & ~0x3ff; + + /* read the three words from (undocumented) RFCR vals 0xa, 0xc, 0xe */ + writel(addr | 0xa, dev->base_addr + RxFilterAddr); + sval[0] = readw(dev->base_addr + RxFilterData); + + writel(addr | 0xc, dev->base_addr + RxFilterAddr); + sval[1] = readw(dev->base_addr + RxFilterData); + + writel(addr | 0xe, dev->base_addr + RxFilterAddr); + sval[2] = readw(dev->base_addr + RxFilterData); + + return 0; +} + +static int netdev_get_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + u32 tmp; + + ecmd->supported = + (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | + SUPPORTED_Autoneg | SUPPORTED_TP); + + /* only supports twisted-pair */ + ecmd->port = PORT_TP; + + /* only supports internal transceiver */ + ecmd->transceiver = XCVR_INTERNAL; + + /* this isn't fully supported at higher layers */ + ecmd->phy_address = readw(dev->base_addr + PhyCtrl) & 0xf; + + tmp = readl(dev->base_addr + AnegAdv); + ecmd->advertising = ADVERTISED_TP; + if (tmp & Aneg10BaseT) + ecmd->advertising |= ADVERTISED_10baseT_Half; + if (tmp & Aneg10BaseTFull) + ecmd->advertising |= ADVERTISED_10baseT_Full; + if (tmp & Aneg100BaseT) + ecmd->advertising |= ADVERTISED_100baseT_Half; + if (tmp & Aneg100BaseTFull) + ecmd->advertising |= ADVERTISED_100baseT_Full; + + tmp = readl(dev->base_addr + ChipConfig); + if (tmp & CfgAnegEnable) { + ecmd->advertising |= ADVERTISED_Autoneg; + ecmd->autoneg = AUTONEG_ENABLE; + } else { + ecmd->autoneg = AUTONEG_DISABLE; + } + + if (tmp & CfgSpeed100) { + ecmd->speed = SPEED_100; + } else { + ecmd->speed = SPEED_10; + } + + if (tmp & CfgFullDuplex) { + ecmd->duplex = DUPLEX_FULL; + } else { + ecmd->duplex = DUPLEX_HALF; + } + + /* ignore maxtxpkt, maxrxpkt for now */ + + return 0; +} + +static int netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct netdev_private *np = dev->priv; + u32 tmp; + + if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100) + return -EINVAL; + if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL) + return -EINVAL; + if (ecmd->port != PORT_TP) + return -EINVAL; + if (ecmd->transceiver != XCVR_INTERNAL) + return -EINVAL; + if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE) + return -EINVAL; + /* ignore phy_address, maxtxpkt, maxrxpkt for now */ + + /* WHEW! now lets bang some bits */ + + if (ecmd->autoneg == AUTONEG_ENABLE) { + /* advertise only what has been requested */ + tmp = readl(dev->base_addr + ChipConfig); + tmp &= ~(CfgAneg100 | CfgAnegFull); + tmp |= CfgAnegEnable; + if (ecmd->advertising & ADVERTISED_100baseT_Half + || ecmd->advertising & ADVERTISED_100baseT_Full) { + tmp |= CfgAneg100; + } + if (ecmd->advertising & ADVERTISED_10baseT_Full + || ecmd->advertising & ADVERTISED_100baseT_Full) { + tmp |= CfgAnegFull; + } + writel(tmp, dev->base_addr + ChipConfig); + /* turn on autonegotiation, and force a renegotiate */ + tmp = readl(dev->base_addr + BasicControl); + tmp |= BMCRAnegEnable | BMCRAnegRestart; + writel(tmp, dev->base_addr + BasicControl); + np->advertising = mdio_read(dev, 1, 4); + } else { + /* turn off auto negotiation, set speed and duplexity */ + tmp = readl(dev->base_addr + BasicControl); + tmp &= ~(BMCRAnegEnable | BMCRSpeed | BMCRDuplex); + if (ecmd->speed == SPEED_100) { + tmp |= BMCRSpeed; + } + if (ecmd->duplex == DUPLEX_FULL) { + tmp |= BMCRDuplex; + } else { + np->full_duplex = 0; + } + writel(tmp, dev->base_addr + BasicControl); + } + return 0; +} + static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { struct netdev_private *np = dev->priv; @@ -1395,7 +1704,8 @@ if (data->phy_id == 1) { u16 miireg = data->reg_num & 0x1f; u16 value = data->val_in; - writew(value, dev->base_addr + 0x80 + (miireg << 2)); + writew(value, dev->base_addr + BasicControl + + (miireg << 2)); switch (miireg) { case 4: np->advertising = value; break; } @@ -1410,8 +1720,11 @@ { long ioaddr = dev->base_addr; struct netdev_private *np = dev->priv; + u32 wol = readl(ioaddr + WOLCmd) & WakeOptsSummary; + u32 clkrun; netif_stop_queue(dev); + netif_carrier_off(dev); if (debug > 1) { printk(KERN_DEBUG "%s: Shutting down ethercard, status was %4.4x.", @@ -1420,14 +1733,23 @@ dev->name, np->cur_tx, np->dirty_tx, np->cur_rx, np->dirty_rx); } - /* Disable interrupts using the mask. */ - writel(0, ioaddr + IntrMask); - writel(0, ioaddr + IntrEnable); - writel(2, ioaddr + StatsCtrl); /* Freeze Stats */ - - /* Stop the chip's Tx and Rx processes. */ - writel(RxOff | TxOff, ioaddr + ChipCmd); - + /* Only shut down chip if wake on lan is not set */ + if (!wol) { + /* Disable interrupts using the mask. */ + writel(0, ioaddr + IntrMask); + writel(0, ioaddr + IntrEnable); + writel(2, ioaddr + StatsCtrl); /* Freeze Stats */ + + /* Stop the chip's Tx and Rx processes. */ + writel(RxOff | TxOff, ioaddr + ChipCmd); + } else if (debug > 1) { + printk(KERN_INFO "%s: remaining active for wake-on-lan\n", + dev->name); + /* spec says write 0 here */ + writel(0, ioaddr + RxRingPtr); + /* allow wake-event interrupts now */ + writel(readl(ioaddr + IntrMask) | WOLPkt, ioaddr + IntrMask); + } del_timer_sync(&np->timer); #ifdef __i386__ @@ -1451,8 +1773,15 @@ drain_ring(dev); free_ring(dev); + clkrun = np->SavedClkRun; + if (wol) { + /* make sure to enable PME */ + clkrun |= 0x100; + } + /* Restore PME enable bit */ writel(np->SavedClkRun, ioaddr + ClkRun); + #if 0 writel(0x0200, ioaddr + ChipConfig); /* Power down Xcvr. */ #endif diff -ruN dist+patches-2.4.8/include/linux/ethtool.h cobalt-2.4.8/include/linux/ethtool.h --- dist+patches-2.4.8/include/linux/ethtool.h Thu Jul 19 17:47:14 2001 +++ cobalt-2.4.8/include/linux/ethtool.h Mon Aug 13 16:42:49 2001 @@ -38,11 +38,22 @@ u32 regdump_len; /* Amount of data from ETHTOOL_GREGS */ }; +#define SOPASS_MAX 6 +/* wake-on-lan settings */ +struct ethtool_wolinfo { + u32 cmd; + u32 supported; + u32 wolopts; + u8 sopass[SOPASS_MAX]; /* SecureOn(tm) password */ +}; + /* CMDs currently supported */ #define ETHTOOL_GSET 0x00000001 /* Get settings. */ #define ETHTOOL_SSET 0x00000002 /* Set settings, privileged. */ #define ETHTOOL_GDRVINFO 0x00000003 /* Get driver info. */ #define ETHTOOL_GREGS 0x00000004 /* Get NIC registers, privileged. */ +#define ETHTOOL_GWOL 0x00000005 /* Get wake-on-lan options. */ +#define ETHTOOL_SWOL 0x00000006 /* Set wake-on-lan options. */ /* compatibility with older code */ #define SPARC_ETH_GSET ETHTOOL_GSET @@ -108,5 +119,14 @@ */ #define AUTONEG_DISABLE 0x00 #define AUTONEG_ENABLE 0x01 + +/* Wake-On-Lan options. */ +#define WAKE_PHY (1 << 0) +#define WAKE_UCAST (1 << 1) +#define WAKE_MCAST (1 << 2) +#define WAKE_BCAST (1 << 3) +#define WAKE_ARP (1 << 4) +#define WAKE_MAGIC (1 << 5) +#define WAKE_MAGICSECURE (1 << 6) /* only meaningful if WAKE_MAGIC */ #endif /* _LINUX_ETHTOOL_H */