Commit 6b5501ef authored by Jeff Garzik's avatar Jeff Garzik

Merge redhat.com:/spare/repo/netdev-2.6/pcnet32

into redhat.com:/spare/repo/net-drivers-2.6
parents bcb15a27 7b29c58b
......@@ -132,6 +132,8 @@ static const char pcnet32_gstrings_test[][ETH_GSTRING_LEN] = {
};
#define PCNET32_TEST_LEN (sizeof(pcnet32_gstrings_test) / ETH_GSTRING_LEN)
#define PCNET32_NUM_REGS 146
#define MAX_UNITS 8 /* More are supported, limit only on options */
static int options[MAX_UNITS];
static int full_duplex[MAX_UNITS];
......@@ -234,7 +236,9 @@ static int full_duplex[MAX_UNITS];
* Jim Lewis <jklewis@us.ibm.com> added ethernet loopback test.
* Thomas Munck Steenholdt <tmus@tmus.dk> non-mii ioctl corrections.
* v1.29 6 Apr 2004 Jim Lewis <jklewis@us.ibm.com> added physical
* identification code (blink led's).
* identification code (blink led's) and register dump.
* Don Fry added timer for 971/972 so skbufs don't remain on tx ring
* forever.
*/
......@@ -372,6 +376,9 @@ static void pcnet32_ethtool_test(struct net_device *dev,
static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1);
static int pcnet32_phys_id(struct net_device *dev, u32 data);
static void pcnet32_led_blink_callback(struct net_device *dev);
static int pcnet32_get_regs_len(struct net_device *dev);
static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
void *ptr);
enum pci_flags_bit {
PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
......@@ -492,9 +499,9 @@ static struct pcnet32_access pcnet32_dwio = {
#ifdef CONFIG_NET_POLL_CONTROLLER
static void pcnet32_poll_controller(struct net_device *dev)
{
disable_irq(dev->irq);
pcnet32_interrupt(0, dev, NULL);
enable_irq(dev->irq);
disable_irq(dev->irq);
pcnet32_interrupt(0, dev, NULL);
enable_irq(dev->irq);
}
#endif
......@@ -681,7 +688,7 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1)
for (i=0; i<6; i++)
*packet++ = dev->dev_addr[i];
for (i=0; i<6; i++)
*packet++ = dev->dev_addr[i];
*packet++ = dev->dev_addr[i];
/* type */
*packet++ = 0x08;
*packet++ = 0x06;
......@@ -837,6 +844,72 @@ static int pcnet32_phys_id(struct net_device *dev, u32 data)
return 0;
}
int pcnet32_get_regs_len(struct net_device *dev)
{
return(PCNET32_NUM_REGS * sizeof(u16));
}
void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
void *ptr)
{
int i, csr0;
u16 *buff = ptr;
struct pcnet32_private *lp = dev->priv;
struct pcnet32_access *a = &lp->a;
ulong ioaddr = dev->base_addr;
int ticks;
unsigned long flags;
spin_lock_irqsave(&lp->lock, flags);
csr0 = a->read_csr(ioaddr, 0);
if (!(csr0 & 0x0004)) { /* If not stopped */
/* set SUSPEND (SPND) - CSR5 bit 0 */
a->write_csr(ioaddr, 5, 0x0001);
/* poll waiting for bit to be set */
ticks = 0;
while (!(a->read_csr(ioaddr, 5) & 0x0001)) {
spin_unlock_irqrestore(&lp->lock, flags);
mdelay(1);
spin_lock_irqsave(&lp->lock, flags);
ticks++;
if (ticks > 200) {
if (netif_msg_hw(lp))
printk(KERN_DEBUG "%s: Error getting into suspend!\n",
dev->name);
break;
}
}
}
/* read address PROM */
for (i=0; i<16; i += 2)
*buff++ = inw(ioaddr + i);
for (i = 0; i <= 89; i++) {
*buff++ = a->read_csr(ioaddr, i);
}
*buff++ = a->read_csr(ioaddr, 112);
*buff++ = a->read_csr(ioaddr, 114);
for (i = 0; i <= 35; i++) {
*buff++ = a->read_bcr(ioaddr, i);
}
if (!(csr0 & 0x0004)) { /* If not stopped */
/* clear SUSPEND (SPND) - CSR5 bit 0 */
a->write_csr(ioaddr, 5, 0x0000);
}
i = buff - (u16 *)ptr;
for (; i < PCNET32_NUM_REGS; i++)
*buff++ = 0;
spin_unlock_irqrestore(&lp->lock, flags);
}
static struct ethtool_ops pcnet32_ethtool_ops = {
.get_settings = pcnet32_get_settings,
.set_settings = pcnet32_set_settings,
......@@ -853,6 +926,8 @@ static struct ethtool_ops pcnet32_ethtool_ops = {
.self_test_count = pcnet32_self_test_count,
.self_test = pcnet32_ethtool_test,
.phys_id = pcnet32_phys_id,
.get_regs_len = pcnet32_get_regs_len,
.get_regs = pcnet32_get_regs,
};
/* only probes for non-PCI devices, the rest are handled by
......@@ -1032,6 +1107,13 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
ltint = 1;
}
if (ltint) {
/* Enable timer to prevent skbuffs from remaining on the tx ring
* forever if no other tx being done. Set timer period to about
* 122 ms */
a->write_bcr(ioaddr, 31, 0x253b);
}
dev = alloc_etherdev(0);
if (!dev) {
if (pcnet32_debug & NETIF_MSG_PROBE)
......@@ -1371,13 +1453,18 @@ pcnet32_open(struct net_device *dev)
/* Re-initialize the PCNET32, and start it when done. */
lp->a.write_csr (ioaddr, 1, (lp->dma_addr +
offsetof(struct pcnet32_private, init_block)) & 0xffff);
offsetof(struct pcnet32_private, init_block)) & 0xffff);
lp->a.write_csr (ioaddr, 2, (lp->dma_addr +
offsetof(struct pcnet32_private, init_block)) >> 16);
lp->a.write_csr (ioaddr, 4, 0x0915);
lp->a.write_csr (ioaddr, 0, 0x0001);
if (lp->ltint) {
/* start the software timer */
lp->a.write_csr(ioaddr, 7, 0x0400); /* set STINTE */
}
netif_start_queue(dev);
/* If we have mii, print the link status and start the watchdog */
......@@ -1579,13 +1666,13 @@ pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev)
int entry;
unsigned long flags;
spin_lock_irqsave(&lp->lock, flags);
if (netif_msg_tx_queued(lp)) {
printk(KERN_DEBUG "%s: pcnet32_start_xmit() called, csr0 %4.4x.\n",
dev->name, lp->a.read_csr(ioaddr, 0));
}
spin_lock_irqsave(&lp->lock, flags);
/* Default status -- will not enable Successful-TxDone
* interrupt when that option is available to us.
*/
......@@ -1646,7 +1733,7 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
struct net_device *dev = dev_id;
struct pcnet32_private *lp;
unsigned long ioaddr;
u16 csr0,rap;
u16 csr0, csr7, rap;
int boguscnt = max_interrupt_work;
int must_restart;
......@@ -1663,13 +1750,19 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
spin_lock(&lp->lock);
rap = lp->a.read_rap(ioaddr);
while ((csr0 = lp->a.read_csr (ioaddr, 0)) & 0x8600 && --boguscnt >= 0) {
csr0 = lp->a.read_csr (ioaddr, 0);
csr7 = lp->ltint ? lp->a.read_csr(ioaddr, 7) : 0;
while ((csr0 & 0x8600 || csr7 & 0x0800) && --boguscnt >= 0) {
if (csr0 == 0xffff) {
break; /* PCMCIA remove happened */
}
/* Acknowledge all of the current interrupt sources ASAP. */
lp->a.write_csr (ioaddr, 0, csr0 & ~0x004f);
if (csr7 & 0x0800)
lp->a.write_csr(ioaddr, 7, csr7);
must_restart = 0;
if (netif_msg_intr(lp))
......@@ -1679,7 +1772,7 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
if (csr0 & 0x0400) /* Rx interrupt */
pcnet32_rx(dev);
if (csr0 & 0x0200) { /* Tx-done interrupt */
if (csr0 & 0x0200 || csr7 & 0x0800) { /* Tx-done or Timer interrupt */
unsigned int dirty_tx = lp->dirty_tx;
int delta;
......@@ -1786,6 +1879,9 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
lp->a.write_csr (ioaddr, 0, 0x0004);
pcnet32_restart(dev, 0x0002);
}
csr0 = lp->a.read_csr (ioaddr, 0);
csr7 = lp->ltint ? lp->a.read_csr(ioaddr, 7) : 0;
}
/* Clear any other interrupt, and set interrupt enable. */
......@@ -1872,6 +1968,7 @@ pcnet32_rx(struct net_device *dev)
if (i > RX_RING_SIZE -2) {
lp->stats.rx_dropped++;
lp->rx_ring[entry].status |= le16_to_cpu(0x8000);
wmb(); /* Make sure adapter sees owner change */
lp->cur_rx++;
}
break;
......@@ -1935,6 +2032,10 @@ pcnet32_close(struct net_device *dev)
/* We stop the PCNET32 here -- it occasionally polls memory if we don't. */
lp->a.write_csr (ioaddr, 0, 0x0004);
if (lp->ltint) { /* Disable timer interrupts */
lp->a.write_csr(ioaddr, 7, 0x0000);
}
/*
* Switch back to 16bit mode to avoid problems with dumb
* DOS packet driver after a warm reboot
......@@ -1945,9 +2046,12 @@ pcnet32_close(struct net_device *dev)
free_irq(dev->irq, dev);
spin_lock_irqsave(&lp->lock, flags);
/* free all allocated skbuffs */
for (i = 0; i < RX_RING_SIZE; i++) {
lp->rx_ring[i].status = 0;
wmb(); /* Make sure adapter sees owner change */
if (lp->rx_skbuff[i]) {
pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], PKT_BUF_SZ-2,
PCI_DMA_FROMDEVICE);
......@@ -1958,6 +2062,8 @@ pcnet32_close(struct net_device *dev)
}
for (i = 0; i < TX_RING_SIZE; i++) {
lp->tx_ring[i].status = 0; /* CPU owns buffer */
wmb(); /* Make sure adapter sees owner change */
if (lp->tx_skbuff[i]) {
pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[i],
lp->tx_skbuff[i]->len, PCI_DMA_TODEVICE);
......@@ -1967,6 +2073,8 @@ pcnet32_close(struct net_device *dev)
lp->tx_dma_addr[i] = 0;
}
spin_unlock_irqrestore(&lp->lock, flags);
return 0;
}
......
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