Commit 6896827e authored by Jeff Garzik's avatar Jeff Garzik

Merge mandrakesoft.com:/home/jgarzik/repo/linus-2.5

into mandrakesoft.com:/home/jgarzik/repo/net-drivers-2.5
parents 461a50a3 7d42b087
......@@ -1525,6 +1525,13 @@ CONFIG_SUNDANCE
More specific information and updates are available from
<http://www.scyld.com/network/sundance.html>.
CONFIG_SUNDANCE_MMIO
Enable memory-mapped I/O for interaction with Sundance NIC registers.
Do NOT enable this by default, PIO (enabled when MMIO is disabled)
is known to solve bugs on certain chips.
If unsure, say N.
CONFIG_ZNET
The Zenith Z-Note notebook computer has a built-in network
(Ethernet) card, and this is the Linux driver for it. Note that the
......
......@@ -177,6 +177,7 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
dep_tristate ' SiS 900/7016 PCI Fast Ethernet Adapter support' CONFIG_SIS900 $CONFIG_PCI
dep_tristate ' SMC EtherPower II' CONFIG_EPIC100 $CONFIG_PCI
dep_tristate ' Sundance Alta support' CONFIG_SUNDANCE $CONFIG_PCI
dep_mbool ' Use MMIO instead of PIO' CONFIG_SUNDANCE_MMIO $CONFIG_SUNDANCE
if [ "$CONFIG_PCI" = "y" -o "$CONFIG_EISA" = "y" ]; then
tristate ' TI ThunderLAN support' CONFIG_TLAN
fi
......
......@@ -70,7 +70,7 @@ obj-$(CONFIG_AIRONET4500_PROC) += aironet4500_proc.o
obj-$(CONFIG_AIRONET4500_CS) += aironet4500_proc.o
obj-$(CONFIG_WINBOND_840) += mii.o
obj-$(CONFIG_SUNDANCE) += sundance.o
obj-$(CONFIG_SUNDANCE) += sundance.o mii.o
obj-$(CONFIG_HAMACHI) += hamachi.o
obj-$(CONFIG_NET) += Space.o setup.o net_init.o loopback.o
obj-$(CONFIG_SEEQ8005) += seeq8005.o
......
......@@ -850,7 +850,30 @@ static int __devinit speedo_found1(struct pci_dev *pdev,
return 0;
}
static void do_slow_command(struct net_device *dev, int cmd)
{
long cmd_ioaddr = dev->base_addr + SCBCmd;
int wait = 0;
do
if (inb(cmd_ioaddr) == 0) break;
while(++wait <= 200);
if (wait > 100)
printk(KERN_ERR "Command %4.4x never accepted (%d polls)!\n",
inb(cmd_ioaddr), wait);
outb(cmd, cmd_ioaddr);
for (wait = 0; wait <= 100; wait++)
if (inb(cmd_ioaddr) == 0) return;
for (; wait <= 20000; wait++)
if (inb(cmd_ioaddr) == 0) return;
else udelay(1);
printk(KERN_ERR "Command %4.4x was not accepted after %d polls!"
" Current status %8.8x.\n",
cmd, wait, inl(dev->base_addr + SCBStatus));
}
/* Serial EEPROM section.
A "bit" grungy, but we work our way through bit-by-bit :->. */
/* EEPROM_Ctrl bits. */
......@@ -1015,7 +1038,7 @@ speedo_open(struct net_device *dev)
/* Start the chip hardware after a full reset. */
static void speedo_resume(struct net_device *dev)
{
struct speedo_private *sp = (struct speedo_private *)dev->priv;
struct speedo_private *sp = dev->priv;
long ioaddr = dev->base_addr;
/* Start with a Tx threshold of 256 (0x..20.... 8 byte units). */
......@@ -1023,34 +1046,40 @@ static void speedo_resume(struct net_device *dev)
/* Set the segment registers to '0'. */
wait_for_cmd_done(ioaddr + SCBCmd);
outl(0, ioaddr + SCBPointer);
/* impose a delay to avoid a bug */
inl(ioaddr + SCBPointer);
udelay(10);
outb(RxAddrLoad, ioaddr + SCBCmd);
wait_for_cmd_done(ioaddr + SCBCmd);
outb(CUCmdBase, ioaddr + SCBCmd);
if (inb(ioaddr + SCBCmd)) {
outl(PortPartialReset, ioaddr + SCBPort);
udelay(10);
}
outl(0, ioaddr + SCBPointer);
inl(ioaddr + SCBPointer); /* Flush to PCI. */
udelay(10); /* Bogus, but it avoids the bug. */
/* Note: these next two operations can take a while. */
do_slow_command(dev, RxAddrLoad);
do_slow_command(dev, CUCmdBase);
/* Load the statistics block and rx ring addresses. */
wait_for_cmd_done(ioaddr + SCBCmd);
outl(sp->lstats_dma, ioaddr + SCBPointer);
inl(ioaddr + SCBPointer); /* Flush to PCI */
outb(CUStatsAddr, ioaddr + SCBCmd);
sp->lstats->done_marker = 0;
wait_for_cmd_done(ioaddr + SCBCmd);
if (sp->rx_ringp[sp->cur_rx % RX_RING_SIZE] == NULL) {
if (speedo_debug > 2)
printk(KERN_DEBUG "%s: NULL cur_rx in speedo_resume().\n",
dev->name);
} else {
wait_for_cmd_done(ioaddr + SCBCmd);
outl(sp->rx_ring_dma[sp->cur_rx % RX_RING_SIZE],
ioaddr + SCBPointer);
outb(RxStart, ioaddr + SCBCmd);
inl(ioaddr + SCBPointer); /* Flush to PCI */
}
wait_for_cmd_done(ioaddr + SCBCmd);
outb(CUDumpStats, ioaddr + SCBCmd);
udelay(30);
/* Note: RxStart should complete instantly. */
do_slow_command(dev, RxStart);
do_slow_command(dev, CUDumpStats);
/* Fill the first command with our physical address. */
{
......@@ -1063,11 +1092,12 @@ static void speedo_resume(struct net_device *dev)
ias_cmd->link =
cpu_to_le32(TX_RING_ELEM_DMA(sp, sp->cur_tx % TX_RING_SIZE));
memcpy(ias_cmd->params, dev->dev_addr, 6);
if (sp->last_cmd)
clear_suspend(sp->last_cmd);
sp->last_cmd = ias_cmd;
}
/* Start the chip's Tx process and unmask interrupts. */
wait_for_cmd_done(ioaddr + SCBCmd);
outl(TX_RING_ELEM_DMA(sp, sp->dirty_tx % TX_RING_SIZE),
ioaddr + SCBPointer);
/* We are not ACK-ing FCP and ER in the interrupt handler yet so they should
......
......@@ -18,26 +18,54 @@
http://www.scyld.com/network/sundance.html
Version 1.01a (jgarzik):
Version LK1.01a (jgarzik):
- Replace some MII-related magic numbers with constants
Version 1.02 (D-Link):
Version LK1.02 (D-Link):
- Add new board to PCI ID list
- Fix multicast bug
Version 1.03 (D-Link):
Version LK1.03 (D-Link):
- New Rx scheme, reduce Rx congestion
- Option to disable flow control
Version 1.04 (D-Link):
Version LK1.04 (D-Link):
- Tx timeout recovery
- More support for ethtool.
Version LK1.04a:
- Remove unused/constant members from struct pci_id_info
(which then allows removal of 'drv_flags' from private struct)
(jgarzik)
- If no phy is found, fail to load that board (jgarzik)
- Always start phy id scan at id 1 to avoid problems (Donald Becker)
- Autodetect where mii_preable_required is needed,
default to not needed. (Donald Becker)
Version LK1.04b:
- Remove mii_preamble_required module parameter (Donald Becker)
- Add per-interface mii_preamble_required (setting is autodetected)
(Donald Becker)
- Remove unnecessary cast from void pointer (jgarzik)
- Re-align comments in private struct (jgarzik)
Version LK1.04c (jgarzik):
- Support bitmapped message levels (NETIF_MSG_xxx), and the
two ethtool ioctls that get/set them
- Don't hand-code MII ethtool support, use standard API/lib
Version LK1.04d:
- Merge from Donald Becker's sundance.c: (Jason Lunz)
* proper support for variably-sized MTUs
* default to PIO, to fix chip bugs
- Add missing unregister_netdev (Jason Lunz)
- Add CONFIG_SUNDANCE_MMIO config option (jgarzik)
*/
#define DRV_NAME "sundance"
#define DRV_VERSION "1.04"
#define DRV_RELDATE "19-Aug-2002"
#define DRV_VERSION "1.01+LK1.04d"
#define DRV_RELDATE "19-Sep-2002"
/* The user-configurable values.
......@@ -45,7 +73,6 @@
static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */
/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
static int max_interrupt_work = 0;
static int mtu;
/* Maximum number of multicast addresses to filter (vs. rx-all-multicast).
Typical is a 64 element hash table based on the Ethernet CRC. */
static int multicast_filter_limit = 32;
......@@ -70,8 +97,10 @@ static int flowctrl=1;
3 100Mbps half duplex.
4 100Mbps full duplex.
*/
#define MAX_UNITS 8
#define MAX_UNITS 8
static char *media[MAX_UNITS];
/* Operational parameters that are set at compile time. */
/* Keep the ring sizes a power of two for compile efficiency.
......@@ -140,16 +169,15 @@ MODULE_DESCRIPTION("Sundance Alta Ethernet driver");
MODULE_LICENSE("GPL");
MODULE_PARM(max_interrupt_work, "i");
MODULE_PARM(mtu, "i");
MODULE_PARM(debug, "i");
MODULE_PARM(rx_copybreak, "i");
MODULE_PARM(media, "1-" __MODULE_STRING(MAX_UNITS) "s");
MODULE_PARM(flowctrl, "i");
MODULE_PARM_DESC(max_interrupt_work, "Sundance Alta maximum events handled per interrupt");
MODULE_PARM_DESC(mtu, "Sundance Alta MTU (all boards)");
MODULE_PARM_DESC(debug, "Sundance Alta debug level (0-5)");
MODULE_PARM_DESC(rx_copybreak, "Sundance Alta copy breakpoint for copy-only-tiny-frames");
MODULE_PARM_DESC(flowctrl, "Sundance Alta flow control [0|1]");
/*
Theory of Operation
......@@ -224,19 +252,9 @@ IVc. Errata
*/
enum pci_id_flags_bits {
/* Set PCI command register bits before calling probe1(). */
PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
/* Read and map the single following PCI BAR. */
PCI_ADDR0=0<<4, PCI_ADDR1=1<<4, PCI_ADDR2=2<<4, PCI_ADDR3=3<<4,
PCI_ADDR_64BITS=0x100, PCI_NO_ACPI_WAKE=0x200, PCI_NO_MIN_LATENCY=0x400,
};
enum chip_capability_flags {CanHaveMII=1, };
#ifdef USE_IO_OPS
#define PCI_IOTYPE (PCI_USES_MASTER | PCI_USES_IO | PCI_ADDR0)
#else
#define PCI_IOTYPE (PCI_USES_MASTER | PCI_USES_MEM | PCI_ADDR1)
/* Work-around for Kendin chip bugs. */
#ifndef CONFIG_SUNDANCE_MMIO
#define USE_IO_OPS 1
#endif
static struct pci_device_id sundance_pci_tbl[] __devinitdata = {
......@@ -250,31 +268,20 @@ static struct pci_device_id sundance_pci_tbl[] __devinitdata = {
};
MODULE_DEVICE_TABLE(pci, sundance_pci_tbl);
enum {
netdev_io_size = 128
};
struct pci_id_info {
const char *name;
struct match_info {
int pci, pci_mask, subsystem, subsystem_mask;
int revision, revision_mask; /* Only 8 bits. */
} id;
enum pci_id_flags_bits pci_flags;
int io_size; /* Needed for I/O region check or ioremap(). */
int drv_flags; /* Driver use, intended as capability flags. */
};
static struct pci_id_info pci_id_tbl[] = {
{"D-Link DFE-550TX FAST Ethernet Adapter", {0x10021186, 0xffffffff,},
PCI_IOTYPE, 128, CanHaveMII},
{"D-Link DFE-550FX 100Mbps Fiber-optics Adapter",
{0x10031186, 0xffffffff,},
PCI_IOTYPE, 128, CanHaveMII},
{"D-Link DFE-580TX 4 port Server Adapter", {0x10121186, 0xffffffff,},
PCI_IOTYPE, 128, CanHaveMII},
{"D-Link DFE-530TXS FAST Ethernet Adapter", {0x10021186, 0xffffffff,},
PCI_IOTYPE, 128, CanHaveMII},
{"D-Link DL10050-based FAST Ethernet Adapter",
{0x10021186, 0xffffffff,},
PCI_IOTYPE, 128, CanHaveMII},
{"Sundance Technology Alta", {0x020113F0, 0xffffffff,},
PCI_IOTYPE, 128, CanHaveMII},
{"D-Link DFE-550TX FAST Ethernet Adapter"},
{"D-Link DFE-550FX 100Mbps Fiber-optics Adapter"},
{"D-Link DFE-580TX 4 port Server Adapter"},
{"D-Link DFE-530TXS FAST Ethernet Adapter"},
{"D-Link DL10050-based FAST Ethernet Adapter"},
{"Sundance Technology Alta"},
{0,}, /* 0 terminated list. */
};
......@@ -331,7 +338,7 @@ enum alta_offsets {
MACCtrl0 = 0x50,
MACCtrl1 = 0x52,
StationAddr = 0x54,
MaxTxSize = 0x5A,
MaxFrameSize = 0x5A,
RxMode = 0x5c,
MIICtrl = 0x5e,
MulticastFilter0 = 0x60,
......@@ -360,7 +367,7 @@ enum alta_offsets {
enum ASICCtrl_HiWord_bit {
GlobalReset = 0x0001,
RxReset = 0x0002,
TxReset = 0x0004,
TxReset = 0x0004,
DMAReset = 0x0008,
FIFOReset = 0x0010,
NetworkReset = 0x0020,
......@@ -426,17 +433,17 @@ struct netdev_private {
dma_addr_t tx_ring_dma;
dma_addr_t rx_ring_dma;
struct net_device_stats stats;
struct timer_list timer; /* Media monitoring timer. */
struct timer_list timer; /* Media monitoring timer. */
/* Frequently used values: keep some adjacent for cache effect. */
spinlock_t lock;
spinlock_t rx_lock; /* Group with Tx control cache line. */
int chip_id, drv_flags;
spinlock_t rx_lock; /* Group with Tx control cache line. */
int msg_enable;
int chip_id;
unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indices */
unsigned int rx_buf_sz; /* Based on MTU+slack. */
unsigned int rx_buf_sz; /* Based on MTU+slack. */
struct netdev_desc *last_tx; /* Last Tx descriptor used. */
unsigned int cur_tx, dirty_tx;
/* These values are keep track of the transceiver/media in use. */
unsigned int full_duplex:1; /* Full-duplex operation requested. */
unsigned int flowctrl:1;
unsigned int default_port:4; /* Last dev->if_port value. */
unsigned int an_enable:1;
......@@ -444,11 +451,11 @@ struct netdev_private {
struct tasklet_struct rx_tasklet;
int budget;
/* Multicast and receive mode. */
spinlock_t mcastlock; /* SMP lock multicast updates. */
spinlock_t mcastlock; /* SMP lock multicast updates. */
u16 mcast_filter[4];
/* MII transceiver section. */
int mii_cnt; /* MII device addresses. */
u16 advertising; /* NWay media advertisement */
struct mii_if_info mii_if;
int mii_preamble_required;
unsigned char phys[MII_CNT]; /* MII device addresses, only first one used. */
struct pci_dev *pci_dev;
};
......@@ -459,6 +466,7 @@ struct netdev_private {
IntrDrvRqst | IntrTxDone | StatsMax | \
LinkChange)
static int change_mtu(struct net_device *dev, int new_mtu);
static int eeprom_read(long ioaddr, int location);
static int mdio_read(struct net_device *dev, int phy_id, int location);
static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
......@@ -479,7 +487,7 @@ 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_close(struct net_device *dev);
static int __devinit sundance_probe1 (struct pci_dev *pdev,
const struct pci_device_id *ent)
......@@ -521,7 +529,7 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
ioaddr = pci_resource_start(pdev, 0);
#else
ioaddr = pci_resource_start(pdev, 1);
ioaddr = (long) ioremap (ioaddr, pci_id_tbl[chip_idx].io_size);
ioaddr = (long) ioremap (ioaddr, netdev_io_size);
if (!ioaddr)
goto err_out_res;
#endif
......@@ -534,9 +542,9 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
dev->irq = irq;
np = dev->priv;
np->chip_id = chip_idx;
np->drv_flags = pci_id_tbl[chip_idx].drv_flags;
np->pci_dev = pdev;
np->chip_id = chip_idx;
np->msg_enable = (1 << debug) - 1;
spin_lock_init(&np->lock);
tasklet_init(&np->rx_tasklet, rx_poll, (unsigned long)dev);
......@@ -552,6 +560,10 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
np->rx_ring = (struct netdev_desc *)ring_space;
np->rx_ring_dma = ring_dma;
np->mii_if.dev = dev;
np->mii_if.mdio_read = mdio_read;
np->mii_if.mdio_write = mdio_write;
/* The chip-specific entries in the device structure. */
dev->open = &netdev_open;
dev->hard_start_xmit = &start_tx;
......@@ -561,11 +573,9 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
dev->do_ioctl = &netdev_ioctl;
dev->tx_timeout = &tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
dev->change_mtu = &change_mtu;
pci_set_drvdata(pdev, dev);
if (mtu)
dev->mtu = mtu;
i = register_netdev(dev);
if (i)
goto err_out_unmap_rx;
......@@ -579,21 +589,30 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
if (1) {
int phy, phy_idx = 0;
np->phys[0] = 1; /* Default setting */
for (phy = 0; phy < 32 && phy_idx < MII_CNT; phy++) {
int mii_status = mdio_read(dev, phy, 1);
np->mii_preamble_required++;
for (phy = 1; phy < 32 && phy_idx < MII_CNT; phy++) {
int mii_status = mdio_read(dev, phy, MII_BMSR);
if (mii_status != 0xffff && mii_status != 0x0000) {
np->phys[phy_idx++] = phy;
np->advertising = mdio_read(dev, phy, 4);
np->mii_if.advertising = mdio_read(dev, phy, MII_ADVERTISE);
if ((mii_status & 0x0040) == 0)
np->mii_preamble_required++;
printk(KERN_INFO "%s: MII PHY found at address %d, status "
"0x%4.4x advertising %4.4x.\n",
dev->name, phy, mii_status, np->advertising);
dev->name, phy, mii_status, np->mii_if.advertising);
}
}
np->mii_cnt = phy_idx;
if (phy_idx == 0)
printk(KERN_INFO "%s: No MII transceiver found!, ASIC status %x\n",
np->mii_preamble_required--;
if (phy_idx == 0) {
printk(KERN_INFO "%s: No MII transceiver found, aborting. ASIC status %x\n",
dev->name, readl(ioaddr + ASICCtrl));
goto err_out_unregister;
}
np->mii_if.phy_id = np->phys[0];
}
/* Parse override configuration */
np->an_enable = 1;
if (card_idx < MAX_UNITS) {
......@@ -602,24 +621,24 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
if (strcmp (media[card_idx], "100mbps_fd") == 0 ||
strcmp (media[card_idx], "4") == 0) {
np->speed = 100;
np->full_duplex = 1;
np->mii_if.full_duplex = 1;
} else if (strcmp (media[card_idx], "100mbps_hd") == 0
|| strcmp (media[card_idx], "3") == 0) {
np->speed = 100;
np->full_duplex = 0;
np->mii_if.full_duplex = 0;
} else if (strcmp (media[card_idx], "10mbps_fd") == 0 ||
strcmp (media[card_idx], "2") == 0) {
np->speed = 10;
np->full_duplex = 1;
np->mii_if.full_duplex = 1;
} else if (strcmp (media[card_idx], "10mbps_hd") == 0 ||
strcmp (media[card_idx], "1") == 0) {
np->speed = 10;
np->full_duplex = 0;
np->mii_if.full_duplex = 0;
} else {
np->an_enable = 1;
}
}
if (tx_coalesce < 1)
if (tx_coalesce < 1)
tx_coalesce = 1;
else if (tx_coalesce > TX_QUEUE_LEN - 1)
tx_coalesce = TX_QUEUE_LEN - 1;
......@@ -632,7 +651,7 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
/* Default 100Mbps Full */
if (np->an_enable) {
np->speed = 100;
np->full_duplex = 1;
np->mii_if.full_duplex = 1;
np->an_enable = 0;
}
}
......@@ -644,24 +663,26 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
if (!np->an_enable) {
mii_ctl = 0;
mii_ctl |= (np->speed == 100) ? BMCR_SPEED100 : 0;
mii_ctl |= (np->full_duplex) ? BMCR_FULLDPLX : 0;
mii_ctl |= (np->mii_if.full_duplex) ? BMCR_FULLDPLX : 0;
mdio_write (dev, np->phys[0], MII_BMCR, mii_ctl);
printk (KERN_INFO "Override speed=%d, %s duplex\n",
np->speed, np->full_duplex ? "Full" : "Half");
np->speed, np->mii_if.full_duplex ? "Full" : "Half");
}
/* Perhaps move the reset here? */
/* Reset the chip to erase previous misconfiguration. */
if (debug > 1)
if (netif_msg_hw(np))
printk("ASIC Control is %x.\n", readl(ioaddr + ASICCtrl));
writew(0x007f, ioaddr + ASICCtrl + 2);
if (debug > 1)
if (netif_msg_hw(np))
printk("ASIC Control is now %x.\n", readl(ioaddr + ASICCtrl));
card_idx++;
return 0;
err_out_unregister:
unregister_netdev(dev);
err_out_unmap_rx:
pci_free_consistent(pdev, RX_TOTAL_SIZE, np->rx_ring, np->rx_ring_dma);
err_out_unmap_tx:
......@@ -678,7 +699,16 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
return -ENODEV;
}
static int change_mtu(struct net_device *dev, int new_mtu)
{
if ((new_mtu < 68) || (new_mtu > 8191)) /* Set by RxDMAFrameLen */
return -EINVAL;
if (netif_running(dev))
return -EBUSY;
dev->mtu = new_mtu;
return 0;
}
/* Read the EEPROM and MII Management Data I/O (MDIO) interfaces. */
static int __devinit eeprom_read(long ioaddr, int location)
{
......@@ -701,11 +731,6 @@ static int __devinit eeprom_read(long ioaddr, int location)
met by back-to-back 33Mhz PCI cycles. */
#define mdio_delay() readb(mdio_addr)
/* Set iff a MII transceiver on any interface requires mdio preamble.
This only set with older tranceivers, so the extra
code size of a per-interface flag is not worthwhile. */
static const char mii_preamble_required = 1;
enum mii_reg_bits {
MDIO_ShiftClk=0x0001, MDIO_Data=0x0002, MDIO_EnbOutput=0x0004,
};
......@@ -730,11 +755,12 @@ static void mdio_sync(long mdio_addr)
static int mdio_read(struct net_device *dev, int phy_id, int location)
{
struct netdev_private *np = dev->priv;
long mdio_addr = dev->base_addr + MIICtrl;
int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
int i, retval = 0;
if (mii_preamble_required)
if (np->mii_preamble_required)
mdio_sync(mdio_addr);
/* Shift the read command bits out. */
......@@ -759,11 +785,12 @@ static int mdio_read(struct net_device *dev, int phy_id, int location)
static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
{
struct netdev_private *np = dev->priv;
long mdio_addr = dev->base_addr + MIICtrl;
int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value;
int i;
if (mii_preamble_required)
if (np->mii_preamble_required)
mdio_sync(mdio_addr);
/* Shift the command bits out. */
......@@ -797,7 +824,7 @@ static int netdev_open(struct net_device *dev)
if (i)
return i;
if (debug > 1)
if (netif_msg_ifup(np))
printk(KERN_DEBUG "%s: netdev_open() irq %d.\n",
dev->name, dev->irq);
......@@ -810,6 +837,10 @@ static int netdev_open(struct net_device *dev)
writeb(dev->dev_addr[i], ioaddr + StationAddr + i);
/* Initialize other registers. */
writew(dev->mtu + 14, ioaddr + MaxFrameSize);
if (dev->mtu > 2047)
writel(readl(ioaddr + ASICCtrl) | 0x0C, ioaddr + ASICCtrl);
/* Configure the PCI bus bursts and FIFO thresholds. */
if (dev->if_port == 0)
......@@ -827,7 +858,7 @@ static int netdev_open(struct net_device *dev)
writew(StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl1);
if (debug > 2)
if (netif_msg_ifup(np))
printk(KERN_DEBUG "%s: Done netdev_open(), status: Rx %x Tx %x "
"MAC Control %x, %4.4x %4.4x.\n",
dev->name, readl(ioaddr + RxStatus), readb(ioaddr + TxStatus),
......@@ -840,7 +871,7 @@ static int netdev_open(struct net_device *dev)
np->timer.data = (unsigned long)dev;
np->timer.function = &netdev_timer; /* timer handler */
add_timer(&np->timer);
/* Enable interrupts by setting the interrupt mask. */
writew(DEFAULT_INTR, ioaddr + IntrEnable);
......@@ -852,21 +883,22 @@ static void check_duplex(struct net_device *dev)
struct netdev_private *np = dev->priv;
long ioaddr = dev->base_addr;
int mii_lpa = mdio_read(dev, np->phys[0], MII_LPA);
int negotiated = mii_lpa & np->advertising;
int negotiated = mii_lpa & np->mii_if.advertising;
int duplex;
/* Force media */
if (!np->an_enable || mii_lpa == 0xffff) {
if (np->full_duplex)
if (np->mii_if.full_duplex)
writew (readw (ioaddr + MACCtrl0) | EnbFullDuplex,
ioaddr + MACCtrl0);
return;
}
/* Autonegotiation */
duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040;
if (np->full_duplex != duplex) {
np->full_duplex = duplex;
if (debug)
if (np->mii_if.full_duplex != duplex) {
np->mii_if.full_duplex = duplex;
if (netif_msg_link(np))
printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d "
"negotiated capability %4.4x.\n", dev->name,
duplex ? "full" : "half", np->phys[0], negotiated);
......@@ -881,7 +913,7 @@ static void netdev_timer(unsigned long data)
long ioaddr = dev->base_addr;
int next_tick = 10*HZ;
if (debug > 3) {
if (netif_msg_timer(np)) {
printk(KERN_DEBUG "%s: Media selection timer tick, intr status %4.4x, "
"Tx %x Rx %x.\n",
dev->name, readw(ioaddr + IntrEnable),
......@@ -941,11 +973,11 @@ static void init_ring(struct net_device *dev)
np->cur_rx = np->cur_tx = 0;
np->dirty_rx = np->dirty_tx = 0;
np->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32);
np->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 36);
/* Initialize all Rx descriptors. */
for (i = 0; i < RX_RING_SIZE; i++) {
np->rx_ring[i].next_desc = cpu_to_le32(np->rx_ring_dma +
np->rx_ring[i].next_desc = cpu_to_le32(np->rx_ring_dma +
((i+1)%RX_RING_SIZE)*sizeof(*np->rx_ring));
np->rx_ring[i].status = 0;
np->rx_ring[i].frag[0].length = 0;
......@@ -961,7 +993,7 @@ static void init_ring(struct net_device *dev)
skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* 16 byte align the IP header. */
np->rx_ring[i].frag[0].addr = cpu_to_le32(
pci_map_single(np->pci_dev, skb->tail, np->rx_buf_sz,
pci_map_single(np->pci_dev, skb->tail, np->rx_buf_sz,
PCI_DMA_FROMDEVICE));
np->rx_ring[i].frag[0].length = cpu_to_le32(np->rx_buf_sz | LastFrag);
}
......@@ -977,7 +1009,7 @@ static void init_ring(struct net_device *dev)
static int
start_tx (struct sk_buff *skb, struct net_device *dev)
{
struct netdev_private *np = (struct netdev_private *) dev->priv;
struct netdev_private *np = dev->priv;
struct netdev_desc *txdesc;
unsigned entry;
long ioaddr = dev->base_addr;
......@@ -992,9 +1024,9 @@ start_tx (struct sk_buff *skb, struct net_device *dev)
txdesc->next_desc = 0;
/* Note: disable the interrupt generation here before releasing. */
if (entry % tx_coalesce == 0) {
txdesc->status = cpu_to_le32 ((entry << 2) |
txdesc->status = cpu_to_le32 ((entry << 2) |
DescIntrOnTx | DisableAlign);
} else {
txdesc->status = cpu_to_le32 ((entry << 2) | DisableAlign);
}
......@@ -1009,7 +1041,7 @@ start_tx (struct sk_buff *skb, struct net_device *dev)
np->cur_tx++;
/* On some architectures: explicitly flush cache lines here. */
if (np->cur_tx - np->dirty_tx < TX_QUEUE_LEN - 1
if (np->cur_tx - np->dirty_tx < TX_QUEUE_LEN - 1
&& !netif_queue_stopped(dev)) {
/* do nothing */
} else {
......@@ -1022,7 +1054,7 @@ start_tx (struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
if (debug > 4) {
if (netif_msg_tx_queued(np)) {
printk (KERN_DEBUG
"%s: Transmit frame #%d queued in slot %d.\n",
dev->name, np->cur_tx, entry);
......@@ -1038,7 +1070,7 @@ reset_tx (struct net_device *dev, int irq)
long ioaddr = dev->base_addr;
int i;
int frame_id;
frame_id = readb(ioaddr + TxFrameId);
writew (TxReset | DMAReset | FIFOReset | NetworkReset,
ioaddr + ASICCtrl + 2);
......@@ -1054,8 +1086,8 @@ reset_tx (struct net_device *dev, int irq)
break;
skb = np->tx_skbuff[entry];
/* Free the original skb. */
pci_unmap_single(np->pci_dev,
np->tx_ring[entry].frag[0].addr,
pci_unmap_single(np->pci_dev,
np->tx_ring[entry].frag[0].addr,
skb->len, PCI_DMA_TODEVICE);
if (irq)
dev_kfree_skb_irq (np->tx_skbuff[entry]);
......@@ -1085,7 +1117,7 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
int intr_status = readw(ioaddr + IntrStatus);
writew(intr_status, ioaddr + IntrStatus);
if (debug > 4)
if (netif_msg_intr(np))
printk(KERN_DEBUG "%s: Interrupt, status %4.4x.\n",
dev->name, intr_status);
......@@ -1093,7 +1125,7 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
break;
if (intr_status & (IntrRxDMADone)) {
writew(DEFAULT_INTR & ~(IntrRxDone|IntrRxDMADone),
writew(DEFAULT_INTR & ~(IntrRxDone|IntrRxDMADone),
ioaddr + IntrEnable);
if (np->budget < 0)
np->budget = RX_BUDGET;
......@@ -1104,7 +1136,7 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
int boguscnt = 32;
int tx_status = readw (ioaddr + TxStatus);
while (tx_status & 0x80) {
if (debug > 4)
if (netif_msg_tx_done(np))
printk
("%s: Transmit status is %2.2x.\n",
dev->name, tx_status);
......@@ -1142,14 +1174,14 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
break;
skb = np->tx_skbuff[entry];
/* Free the original skb. */
pci_unmap_single(np->pci_dev,
np->tx_ring[entry].frag[0].addr,
pci_unmap_single(np->pci_dev,
np->tx_ring[entry].frag[0].addr,
skb->len, PCI_DMA_TODEVICE);
dev_kfree_skb_irq (np->tx_skbuff[entry]);
np->tx_skbuff[entry] = 0;
}
spin_unlock(&np->lock);
if (netif_queue_stopped(dev) &&
if (netif_queue_stopped(dev) &&
np->cur_tx - np->dirty_tx < TX_QUEUE_LEN - 4) {
/* The ring is no longer full, clear tbusy. */
netif_wake_queue (dev);
......@@ -1160,14 +1192,14 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
netdev_error(dev, intr_status);
if (--boguscnt < 0) {
get_stats(dev);
if (debug > 1)
if (netif_msg_hw(np))
printk(KERN_WARNING "%s: Too much work at interrupt, "
"status=0x%4.4x / 0x%4.4x.\n",
dev->name, intr_status, readw(ioaddr + IntrClear));
break;
}
} while (1);
if (debug > 3)
if (netif_msg_intr(np))
printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",
dev->name, readw(ioaddr + IntrStatus));
if (np->cur_tx - np->dirty_tx > 0 && tx_coalesce > 1)
......@@ -1196,15 +1228,15 @@ static void rx_poll(unsigned long data)
if (!(desc->status & DescOwn))
break;
pkt_len = frame_status & 0x1fff; /* Chip omits the CRC. */
if (debug > 4)
if (netif_msg_rx_status(np))
printk(KERN_DEBUG " netdev_rx() status was %8.8x.\n",
frame_status);
pci_dma_sync_single(np->pci_dev, desc->frag[0].addr,
np->rx_buf_sz, PCI_DMA_FROMDEVICE);
if (frame_status & 0x001f4000) {
/* There was a error. */
if (debug > 2)
if (netif_msg_rx_err(np))
printk(KERN_DEBUG " netdev_rx() Rx error was %8.8x.\n",
frame_status);
np->stats.rx_errors++;
......@@ -1220,7 +1252,7 @@ static void rx_poll(unsigned long data)
} else {
struct sk_buff *skb;
#ifndef final_version
if (debug > 4)
if (netif_msg_rx_status(np))
printk(KERN_DEBUG " netdev_rx() normal Rx pkt length %d"
", bogus_cnt %d.\n",
pkt_len, boguscnt);
......@@ -1234,9 +1266,9 @@ static void rx_poll(unsigned long data)
eth_copy_and_sum(skb, np->rx_skbuff[entry]->tail, pkt_len, 0);
skb_put(skb, pkt_len);
} else {
pci_unmap_single(np->pci_dev,
pci_unmap_single(np->pci_dev,
desc->frag[0].addr,
np->rx_buf_sz,
np->rx_buf_sz,
PCI_DMA_FROMDEVICE);
skb_put(skb = np->rx_skbuff[entry], pkt_len);
np->rx_skbuff[entry] = NULL;
......@@ -1255,7 +1287,7 @@ static void rx_poll(unsigned long data)
writew(DEFAULT_INTR, ioaddr + IntrEnable);
return;
not_done:
not_done:
np->cur_rx = entry;
refill_rx (dev);
if (!received)
......@@ -1286,7 +1318,7 @@ static void refill_rx (struct net_device *dev)
skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
np->rx_ring[entry].frag[0].addr = cpu_to_le32(
pci_map_single(np->pci_dev, skb->tail,
pci_map_single(np->pci_dev, skb->tail,
np->rx_buf_sz, PCI_DMA_FROMDEVICE));
}
/* Perhaps we need not reset this field. */
......@@ -1303,7 +1335,7 @@ static void netdev_error(struct net_device *dev, int intr_status)
struct netdev_private *np = dev->priv;
u16 mii_ctl, mii_advertise, mii_lpa;
int speed;
if (intr_status & LinkChange) {
if (np->an_enable) {
mii_advertise = mdio_read (dev, np->phys[0], MII_ADVERTISE);
......@@ -1421,12 +1453,12 @@ static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
{
struct netdev_private *np = dev->priv;
u32 ethcmd;
long ioaddr = dev->base_addr;
if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
return -EFAULT;
switch (ethcmd) {
/* get constant driver settings/info */
case ETHTOOL_GDRVINFO: {
struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
strcpy(info.driver, DRV_NAME);
......@@ -1437,116 +1469,60 @@ static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
return -EFAULT;
return 0;
}
/* get media settings */
case ETHTOOL_GSET: {
struct ethtool_cmd cmd = { ETHTOOL_GSET };
if (readl (ioaddr + ASICCtrl) & 0x80) {
/* fiber device */
cmd.supported = SUPPORTED_Autoneg |
SUPPORTED_FIBRE;
cmd.advertising= ADVERTISED_Autoneg |
ADVERTISED_FIBRE;
cmd.port = PORT_FIBRE;
cmd.transceiver = XCVR_INTERNAL;
} else {
/* copper device */
cmd.supported = SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Half |
SUPPORTED_100baseT_Full |
SUPPORTED_Autoneg |
SUPPORTED_MII;
cmd.advertising = ADVERTISED_10baseT_Half |
ADVERTISED_10baseT_Full |
ADVERTISED_100baseT_Half |
ADVERTISED_100baseT_Full |
ADVERTISED_Autoneg |
ADVERTISED_MII;
cmd.port = PORT_MII;
cmd.transceiver = XCVR_INTERNAL;
}
if (readb(ioaddr + MIICtrl) & 0x80) {
cmd.speed = np->speed;
cmd.duplex = np->full_duplex ?
DUPLEX_FULL : DUPLEX_HALF;
} else {
cmd.speed = -1;
cmd.duplex = -1;
}
if ( np->an_enable)
cmd.autoneg = AUTONEG_ENABLE;
else
cmd.autoneg = AUTONEG_DISABLE;
cmd.phy_address = np->phys[0];
if (copy_to_user(useraddr, &cmd,
sizeof(cmd)))
struct ethtool_cmd ecmd = { ETHTOOL_GSET };
spin_lock_irq(&np->lock);
mii_ethtool_gset(&np->mii_if, &ecmd);
spin_unlock_irq(&np->lock);
if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
return -EFAULT;
return 0;
return 0;
}
/* set media settings */
case ETHTOOL_SSET: {
struct ethtool_cmd cmd;
if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
int r;
struct ethtool_cmd ecmd;
if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
return -EFAULT;
netif_carrier_off(dev);
if (cmd.autoneg == AUTONEG_ENABLE) {
if (np->an_enable)
return 0;
else {
np->an_enable = 1;
/* Reset PHY */
mdio_write (dev, np->phys[0], MII_BMCR,
BMCR_RESET);
mdelay (300);
/* Start auto negotiation */
mdio_write (dev, np->phys[0], MII_BMCR,
BMCR_ANENABLE|BMCR_ANRESTART);
return 0;
}
} else {
/* Reset PHY */
mdio_write (dev, np->phys[0], MII_BMCR,
BMCR_RESET);
mdelay (300);
np->an_enable = 0;
switch(cmd.speed + cmd.duplex){
case SPEED_10 + DUPLEX_HALF:
np->speed = 10;
np->full_duplex = 0;
break;
case SPEED_10 + DUPLEX_FULL:
np->speed = 10;
np->full_duplex = 1;
break;
case SPEED_100 + DUPLEX_HALF:
np->speed = 100;
np->full_duplex = 0;
break;
case SPEED_100 + DUPLEX_FULL:
np->speed = 100;
np->full_duplex = 1;
break;
default:
return -EINVAL;
}
mdio_write (dev, np->phys[0], MII_BMCR,
((np->speed == 100) ? BMCR_SPEED100 : 0) |
((np->full_duplex) ? BMCR_FULLDPLX : 0) );
spin_lock_irq(&np->lock);
r = mii_ethtool_sset(&np->mii_if, &ecmd);
spin_unlock_irq(&np->lock);
return r;
}
}
return 0;
/* restart autonegotiation */
case ETHTOOL_NWAY_RST: {
return mii_nway_restart(&np->mii_if);
}
#ifdef ETHTOOL_GLINK
case ETHTOOL_GLINK:{
struct ethtool_value link = { ETHTOOL_GLINK };
link.data = readb(ioaddr + MIICtrl) & 0x80;
if (copy_to_user(useraddr, &link, sizeof(link)))
return -EFAULT;
return 0;
}
#endif
/* get link status */
case ETHTOOL_GLINK: {
struct ethtool_value edata = {ETHTOOL_GLINK};
edata.data = mii_link_ok(&np->mii_if);
if (copy_to_user(useraddr, &edata, sizeof(edata)))
return -EFAULT;
return 0;
}
/* get message-level */
case ETHTOOL_GMSGLVL: {
struct ethtool_value edata = {ETHTOOL_GMSGLVL};
edata.data = np->msg_enable;
if (copy_to_user(useraddr, &edata, sizeof(edata)))
return -EFAULT;
return 0;
}
/* set message-level */
case ETHTOOL_SMSGLVL: {
struct ethtool_value edata;
if (copy_from_user(&edata, useraddr, sizeof(edata)))
return -EFAULT;
np->msg_enable = edata.data;
return 0;
}
default:
return -EOPNOTSUPP;
......@@ -1587,7 +1563,7 @@ static int netdev_close(struct net_device *dev)
netif_stop_queue(dev);
if (debug > 1) {
if (netif_msg_ifdown(np)) {
printk(KERN_DEBUG "%s: Shutting down ethercard, status was Tx %2.2x "
"Rx %4.4x Int %2.2x.\n",
dev->name, readb(ioaddr + TxStatus),
......@@ -1603,7 +1579,7 @@ static int netdev_close(struct net_device *dev)
writew(TxDisable | RxDisable | StatsDisable, ioaddr + MACCtrl1);
#ifdef __i386__
if (debug > 2) {
if (netif_msg_hw(np)) {
printk("\n"KERN_DEBUG" Tx ring at %8.8x:\n",
(int)(np->tx_ring_dma));
for (i = 0; i < TX_RING_SIZE; i++)
......@@ -1630,8 +1606,8 @@ static int netdev_close(struct net_device *dev)
np->rx_ring[i].frag[0].addr = 0xBADF00D0; /* An invalid address. */
skb = np->rx_skbuff[i];
if (skb) {
pci_unmap_single(np->pci_dev,
np->rx_ring[i].frag[0].addr, np->rx_buf_sz,
pci_unmap_single(np->pci_dev,
np->rx_ring[i].frag[0].addr, np->rx_buf_sz,
PCI_DMA_FROMDEVICE);
dev_kfree_skb(skb);
np->rx_skbuff[i] = 0;
......@@ -1640,7 +1616,7 @@ static int netdev_close(struct net_device *dev)
for (i = 0; i < TX_RING_SIZE; i++) {
skb = np->tx_skbuff[i];
if (skb) {
pci_unmap_single(np->pci_dev,
pci_unmap_single(np->pci_dev,
np->tx_ring[i].frag[0].addr, skb->len,
PCI_DMA_TODEVICE);
dev_kfree_skb(skb);
......@@ -1654,15 +1630,15 @@ static int netdev_close(struct net_device *dev)
static void __devexit sundance_remove1 (struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
if (dev) {
struct netdev_private *np = dev->priv;
unregister_netdev(dev);
pci_free_consistent(pdev, RX_TOTAL_SIZE, np->rx_ring,
pci_free_consistent(pdev, RX_TOTAL_SIZE, np->rx_ring,
np->rx_ring_dma);
pci_free_consistent(pdev, TX_TOTAL_SIZE, np->tx_ring,
pci_free_consistent(pdev, TX_TOTAL_SIZE, np->tx_ring,
np->tx_ring_dma);
pci_release_regions(pdev);
#ifndef USE_IO_OPS
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment