patch-2.4.4 linux/drivers/net/tulip/tulip_core.c
Next file: linux/drivers/net/tun.c
Previous file: linux/drivers/net/tulip/tulip.h
Back to the patch index
Back to the overall index
- Lines: 678
- Date:
Fri Apr 20 11:54:22 2001
- Orig file:
v2.4.3/linux/drivers/net/tulip/tulip_core.c
- Orig date:
Fri Mar 2 11:02:14 2001
diff -u --recursive --new-file v2.4.3/linux/drivers/net/tulip/tulip_core.c linux/drivers/net/tulip/tulip_core.c
@@ -2,20 +2,15 @@
/*
Maintained by Jeff Garzik <jgarzik@mandrakesoft.com>
- Copyright 2000 The Linux Kernel Team
- Written/copyright 1994-1999 by Donald Becker.
+ Copyright 2000,2001 The Linux Kernel Team
+ Written/copyright 1994-2001 by Donald Becker.
This software may be used and distributed according to the terms
of the GNU General Public License, incorporated herein by reference.
- Please read Documentation/networking/tulip.txt for more
- information.
-
- For this specific driver variant please use linux-kernel for
- bug reports.
-
- Additional information available at
- http://cesdis.gsfc.nasa.gov/linux/drivers/tulip.html
+ Please refer to Documentation/DocBook/tulip.{pdf,ps,html}
+ for more information on this driver, or visit the project
+ Web page at http://sourceforge.net/projects/tulip/
*/
@@ -28,7 +23,7 @@
#include <asm/unaligned.h>
static char version[] __devinitdata =
- "Linux Tulip driver version 0.9.14 (February 20, 2001)\n";
+ "Linux Tulip driver version 0.9.14e (April 20, 2001)\n";
/* A few user-configurable values. */
@@ -43,16 +38,19 @@
static int mtu[MAX_UNITS]; /* Jumbo MTU for interfaces. */
/* The possible media types that can be set in options[] are: */
-const char * const medianame[] = {
+const char * const medianame[32] = {
"10baseT", "10base2", "AUI", "100baseTx",
- "10baseT-FD", "100baseTx-FD", "100baseT4", "100baseFx",
- "100baseFx-FD", "MII 10baseT", "MII 10baseT-FD", "MII",
- "10baseT(forced)", "MII 100baseTx", "MII 100baseTx-FD", "MII 100baseT4",
+ "10baseT-FDX", "100baseTx-FDX", "100baseT4", "100baseFx",
+ "100baseFx-FDX", "MII 10baseT", "MII 10baseT-FDX", "MII",
+ "10baseT(forced)", "MII 100baseTx", "MII 100baseTx-FDX", "MII 100baseT4",
+ "MII 100baseFx-HDX", "MII 100baseFx-FDX", "Home-PNA 1Mbps", "Invalid-19",
+ "","","","", "","","","", "","","","Transceiver reset",
};
/* Set the copy breakpoint for the copy-only-tiny-buffer Rx structure. */
#if defined(__alpha__) || defined(__arm__) || defined(__hppa__) \
- || defined(__sparc_) || defined(__ia64__)
+ || defined(__sparc_) || defined(__ia64__) \
+ || defined(__sh__) || defined(__mips__)
static int rx_copybreak = 1518;
#else
static int rx_copybreak = 100;
@@ -81,7 +79,7 @@
* any more than that.
*/
static int csr0 = 0x01A00000 | 0x9000;
-#elif defined(__arm__)
+#elif defined(__arm__) || defined(__sh__)
static int csr0 = 0x01A00000 | 0x4800;
#else
#warning Processor architecture undefined!
@@ -162,7 +160,7 @@
/* COMET */
{ "ADMtek Comet", 256, 0x0001abef,
- MC_HASH_ONLY, comet_timer },
+ MC_HASH_ONLY | COMET_MAC_ADDR, comet_timer },
/* COMPEX9881 */
{ "Compex 9881 PMAC", 128, 0x0001ebef,
@@ -177,6 +175,11 @@
{ "Davicom DM9102/DM9102A", 128, 0x0001ebef,
HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | HAS_ACPI,
tulip_timer },
+
+ /* CONEXANT */
+ { "Conexant LANfinity", 0x100, 0x0001ebef,
+ HAS_MII | HAS_ACPI,
+ tulip_timer },
};
@@ -204,14 +207,16 @@
{ 0x1282, 0x9102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DM910X },
{ 0x1113, 0x1216, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
{ 0x1113, 0x1217, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MX98715 },
- {0, }
+ { 0x1113, 0x9511, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
+ { 0x14f1, 0x1803, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CONEXANT },
+ { } /* terminate list */
};
MODULE_DEVICE_TABLE(pci, tulip_pci_tbl);
/* A full-duplex map for media types. */
-const char tulip_media_cap[] =
-{0,0,0,16, 3,19,16,24, 27,4,7,5, 0,20,23,20 };
+const char tulip_media_cap[32] =
+{0,0,0,16, 3,19,16,24, 27,4,7,5, 0,20,23,20, 28,31,0,0, };
u8 t21040_csr13[] = {2,0x0C,8,4, 4,0,0,0, 0,0,0,0, 4,0,0,0};
/* 21041 transceiver register settings: 10-T, 10-2, AUI, 10-T, 10T-FD*/
@@ -286,6 +291,14 @@
if (tulip_debug > 1)
printk(KERN_DEBUG "%s: tulip_up(), irq==%d.\n", dev->name, dev->irq);
+ if (tp->chip_id == PNIC2) {
+ u32 addr_high = (dev->dev_addr[1]<<8) + (dev->dev_addr[0]<<0);
+ /* This address setting does not appear to impact chip operation?? */
+ outl((dev->dev_addr[5]<<8) + dev->dev_addr[4] +
+ (dev->dev_addr[3]<<24) + (dev->dev_addr[2]<<16),
+ ioaddr + 0xB0);
+ outl(addr_high + (addr_high<<16), ioaddr + 0xB8);
+ }
if (tp->flags & MC_HASH_ONLY) {
u32 addr_low = cpu_to_le32(get_unaligned((u32 *)dev->dev_addr));
u32 addr_high = cpu_to_le32(get_unaligned((u16 *)(dev->dev_addr+4)));
@@ -294,7 +307,7 @@
outl(addr_low, ioaddr + CSR14);
outl(1, ioaddr + CSR13);
outl(addr_high, ioaddr + CSR14);
- } else if (tp->chip_id == COMET) {
+ } else if (tp->flags & COMET_MAC_ADDR) {
outl(addr_low, ioaddr + 0xA4);
outl(addr_high, ioaddr + 0xA8);
outl(0, ioaddr + 0xAC);
@@ -316,13 +329,13 @@
mapping = pci_map_single(tp->pdev, tp->setup_frame,
sizeof(tp->setup_frame),
PCI_DMA_TODEVICE);
- tp->tx_buffers[0].skb = NULL;
- tp->tx_buffers[0].mapping = mapping;
+ tp->tx_buffers[tp->cur_tx].skb = NULL;
+ tp->tx_buffers[tp->cur_tx].mapping = mapping;
/* Put the setup frame on the Tx list. */
- tp->tx_ring[0].length = cpu_to_le32(0x08000000 | 192);
- tp->tx_ring[0].buffer1 = cpu_to_le32(mapping);
- tp->tx_ring[0].status = cpu_to_le32(DescOwned);
+ tp->tx_ring[tp->cur_tx].length = cpu_to_le32(0x08000000 | 192);
+ tp->tx_ring[tp->cur_tx].buffer1 = cpu_to_le32(mapping);
+ tp->tx_ring[tp->cur_tx].status = cpu_to_le32(DescOwned);
tp->cur_tx++;
}
@@ -349,7 +362,7 @@
}
}
if ((tp->mtable->defaultmedia & 0x0800) == 0) {
- int looking_for = tp->mtable->defaultmedia & 15;
+ int looking_for = tp->mtable->defaultmedia & MEDIA_MASK;
for (i = 0; i < tp->mtable->leafcount; i++)
if (tp->mtable->mleaf[i].media == looking_for) {
printk(KERN_INFO "%s: Using EEPROM-set media %s.\n",
@@ -418,7 +431,9 @@
outl(0x0000, ioaddr + CSR14);
outl(0x0008, ioaddr + CSR15);
} else if (tp->chip_id == COMET) {
- dev->if_port = 0;
+ /* Enable automatic Tx underrun recovery. */
+ outl(inl(ioaddr + 0x88) | 1, ioaddr + 0x88);
+ dev->if_port = tp->mii_cnt ? 11 : 0;
tp->csr6 = 0x00040000;
} else if (tp->chip_id == AX88140) {
tp->csr6 = tp->mii_cnt ? 0x00040100 : 0x00000100;
@@ -789,16 +804,16 @@
/* Provide ioctl() calls to examine the MII xcvr state. */
-static int private_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+static int private_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
{
- struct tulip_private *tp = (struct tulip_private *)dev->priv;
+ struct tulip_private *tp = dev->priv;
long ioaddr = dev->base_addr;
- u16 *data = (u16 *)&rq->ifr_data;
+ u16 *data = (u16 *) & rq->ifr_data;
int phy = tp->phys[0] & 0x1f;
- long flags;
+ unsigned int regnum = data[1];
- switch(cmd) {
- case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */
+ switch (cmd) {
+ case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */
if (tp->mii_cnt)
data[0] = phy;
else if (tp->flags & HAS_NWAY)
@@ -807,42 +822,64 @@
data[0] = 1;
else
return -ENODEV;
- case SIOCDEVPRIVATE+1: /* Read the specified MII register. */
- if (data[0] == 32 && (tp->flags & HAS_NWAY)) {
- int csr12 = inl(ioaddr + CSR12);
- int csr14 = inl(ioaddr + CSR14);
- switch (data[1]) {
- case 0: {
- data[3] = (csr14<<5) & 0x1000;
- break; }
+ case SIOCDEVPRIVATE + 1: /* Read the specified MII register. */
+ if (data[0] == 32 && (tp->flags & HAS_NWAY)) {
+ int csr12 = inl (ioaddr + CSR12);
+ int csr14 = inl (ioaddr + CSR14);
+ switch (regnum) {
+ case 0:
+ data[3] = (csr14 << 5) & 0x1000;
+ break;
case 1:
- data[3] = 0x7848 + ((csr12&0x7000) == 0x5000 ? 0x20 : 0)
- + (csr12&0x06 ? 0x04 : 0);
+ data[3] =
+ 0x7848 +
+ ((csr12 & 0x7000) == 0x5000 ? 0x20 : 0) +
+ (csr12 & 0x06 ? 0x04 : 0);
break;
- case 4: {
- data[3] = ((csr14>>9)&0x07C0) +
- ((inl(ioaddr + CSR6)>>3)&0x0040) + ((csr14>>1)&0x20) + 1;
+ case 4:
+ data[3] =
+ ((csr14 >> 9) & 0x07C0) +
+ ((inl (ioaddr + CSR6) >> 3) & 0x0040) +
+ ((csr14 >> 1) & 0x20) + 1;
+ break;
+ case 5:
+ data[3] = csr12 >> 16;
+ break;
+ default:
+ data[3] = 0;
break;
- }
- case 5: data[3] = csr12 >> 16; break;
- default: data[3] = 0; break;
}
} else {
- spin_lock_irqsave (&tp->lock, flags);
- data[3] = tulip_mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f);
- spin_unlock_irqrestore (&tp->lock, flags);
+ data[3] = tulip_mdio_read (dev, data[0] & 0x1f, regnum);
}
return 0;
- case SIOCDEVPRIVATE+2: /* Write the specified MII register */
- if (!capable(CAP_NET_ADMIN))
+ case SIOCDEVPRIVATE + 2: /* Write the specified MII register */
+ if (!capable (CAP_NET_ADMIN))
return -EPERM;
- if (data[0] == 32 && (tp->flags & HAS_NWAY)) {
- if (data[1] == 5)
+ if (regnum & ~0x1f)
+ return -EINVAL;
+ if (data[0] == phy) {
+ u16 value = data[2];
+ switch (regnum) {
+ case 0: /* Check for autonegotiation on or reset. */
+ tp->full_duplex_lock = (value & 0x9000) ? 0 : 1;
+ if (tp->full_duplex_lock)
+ tp->full_duplex = (value & 0x0100) ? 1 : 0;
+ break;
+ case 4:
tp->to_advertise = data[2];
+ break;
+ }
+ }
+ if (data[0] == 32 && (tp->flags & HAS_NWAY)) {
+ u16 value = data[2];
+ if (regnum == 0) {
+ if ((value & 0x1200) == 0x1200)
+ t21142_start_nway (dev);
+ } else if (regnum == 4)
+ tp->to_advertise = value;
} else {
- spin_lock_irqsave (&tp->lock, flags);
- tulip_mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]);
- spin_unlock_irqrestore(&tp->lock, flags);
+ tulip_mdio_write (dev, data[0] & 0x1f, regnum, data[2]);
}
return 0;
default:
@@ -967,38 +1004,56 @@
tp->csr6 &= ~0x00D5;
if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */
- tp->csr6 |= 0x00C0;
- csr6 |= 0x00C0;
+ tp->csr6 |= AcceptAllMulticast | AcceptAllPhys;
+ csr6 |= AcceptAllMulticast | AcceptAllPhys;
/* Unconditionally log net taps. */
printk(KERN_INFO "%s: Promiscuous mode enabled.\n", dev->name);
} else if ((dev->mc_count > 1000) || (dev->flags & IFF_ALLMULTI)) {
/* Too many to filter well -- accept all multicasts. */
- tp->csr6 |= 0x0080;
- csr6 |= 0x0080;
+ tp->csr6 |= AcceptAllMulticast;
+ csr6 |= AcceptAllMulticast;
} else if (tp->flags & MC_HASH_ONLY) {
/* Some work-alikes have only a 64-entry hash filter table. */
/* Should verify correctness on big-endian/__powerpc__ */
struct dev_mc_list *mclist;
int i;
- u32 mc_filter[2]; /* Multicast hash filter */
if (dev->mc_count > 64) { /* Arbitrary non-effective limit. */
- tp->csr6 |= 0x0080;
- csr6 |= 0x0080;
+ tp->csr6 |= AcceptAllMulticast;
+ csr6 |= AcceptAllMulticast;
} else {
- mc_filter[1] = mc_filter[0] = 0;
+ u32 mc_filter[2] = {0, 0}; /* Multicast hash filter */
+ int filterbit;
for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
- i++, mclist = mclist->next)
- set_bit(ether_crc(ETH_ALEN, mclist->dmi_addr)>>26, mc_filter);
-
- if (tp->chip_id == AX88140) {
+ i++, mclist = mclist->next) {
+ if (tp->flags & COMET_MAC_ADDR)
+ filterbit = ether_crc_le(ETH_ALEN, mclist->dmi_addr);
+ else
+ filterbit = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26;
+ filterbit &= 0x3f;
+ set_bit(filterbit, mc_filter);
+ if (tulip_debug > 2) {
+ printk(KERN_INFO "%s: Added filter for %2.2x:%2.2x:%2.2x:"
+ "%2.2x:%2.2x:%2.2x %8.8x bit %d.\n", dev->name,
+ mclist->dmi_addr[0], mclist->dmi_addr[1],
+ mclist->dmi_addr[2], mclist->dmi_addr[3],
+ mclist->dmi_addr[4], mclist->dmi_addr[5],
+ ether_crc(ETH_ALEN, mclist->dmi_addr), filterbit);
+ }
+ }
+ if (mc_filter[0] == tp->mc_filter[0] &&
+ mc_filter[1] == tp->mc_filter[1])
+ ; /* No change. */
+ else if (tp->flags & IS_ASIX) {
outl(2, ioaddr + CSR13);
outl(mc_filter[0], ioaddr + CSR14);
outl(3, ioaddr + CSR13);
outl(mc_filter[1], ioaddr + CSR14);
- } else if (tp->chip_id == COMET) { /* Has a simple hash filter. */
+ } else if (tp->flags & COMET_MAC_ADDR) {
outl(mc_filter[0], ioaddr + 0xAC);
outl(mc_filter[1], ioaddr + 0xB0);
}
+ tp->mc_filter[0] = mc_filter[0];
+ tp->mc_filter[1] = mc_filter[1];
}
} else {
unsigned long flags;
@@ -1068,12 +1123,11 @@
static int __devinit tulip_init_one (struct pci_dev *pdev,
const struct pci_device_id *ent)
{
- static int did_version; /* Already printed version info. */
struct tulip_private *tp;
/* See note below on the multiport cards. */
static unsigned char last_phys_addr[6] = {0x00, 'L', 'i', 'n', 'u', 'x'};
static int last_irq;
- static int multiport_cnt; /* For four-port boards w/one EEPROM */
+ static int multiport_cnt; /* For four-port boards w/one EEPROM */
u8 chip_rev;
int i, irq;
unsigned short sum;
@@ -1082,11 +1136,16 @@
long ioaddr;
static int board_idx = -1;
int chip_idx = ent->driver_data;
+ int t2104x_mode = 0;
+ int eeprom_missing = 0;
- board_idx++;
-
+#ifndef MODULE
+ static int did_version; /* Already printed version info. */
if (tulip_debug > 0 && did_version++ == 0)
printk (KERN_INFO "%s", version);
+#endif
+
+ board_idx++;
/*
* Lan media wire a tulip chip to a wan interface. Needs a very
@@ -1146,7 +1205,7 @@
irq = pdev->irq;
/* init_etherdev ensures aligned and zeroed private structures */
- dev = init_etherdev (NULL, sizeof (*tp));
+ dev = alloc_etherdev (sizeof (*tp));
if (!dev) {
printk (KERN_ERR PFX "ether device alloc failed, aborting\n");
return -ENOMEM;
@@ -1154,36 +1213,23 @@
if (pci_resource_len (pdev, 0) < tulip_tbl[chip_idx].io_size) {
printk (KERN_ERR PFX "%s: I/O region (0x%lx@0x%lx) too small, "
- "aborting\n", dev->name, pci_resource_len (pdev, 0),
+ "aborting\n", pdev->slot_name,
+ pci_resource_len (pdev, 0),
pci_resource_start (pdev, 0));
goto err_out_free_netdev;
}
/* grab all resources from both PIO and MMIO regions, as we
* don't want anyone else messing around with our hardware */
- if (!request_region (pci_resource_start (pdev, 0),
- pci_resource_len (pdev, 0),
- dev->name)) {
- printk (KERN_ERR PFX "%s: I/O region (0x%lx@0x%lx) unavailable, "
- "aborting\n", dev->name, pci_resource_len (pdev, 0),
- pci_resource_start (pdev, 0));
+ if (pci_request_regions (pdev, "tulip"))
goto err_out_free_netdev;
- }
- if (!request_mem_region (pci_resource_start (pdev, 1),
- pci_resource_len (pdev, 1),
- dev->name)) {
- printk (KERN_ERR PFX "%s: MMIO region (0x%lx@0x%lx) unavailable, "
- "aborting\n", dev->name, pci_resource_len (pdev, 1),
- pci_resource_start (pdev, 1));
- goto err_out_free_pio_res;
- }
pci_set_master(pdev);
pci_read_config_byte (pdev, PCI_REVISION_ID, &chip_rev);
/*
- * initialize priviate data structure 'tp'
+ * initialize private data structure 'tp'
* it is zeroed and aligned in init_etherdev
*/
tp = dev->priv;
@@ -1193,7 +1239,7 @@
sizeof(struct tulip_tx_desc) * TX_RING_SIZE,
&tp->rx_ring_dma);
if (!tp->rx_ring)
- goto err_out_free_mmio_res;
+ goto err_out_free_res;
tp->tx_ring = (struct tulip_tx_desc *)(tp->rx_ring + RX_RING_SIZE);
tp->tx_ring_dma = tp->rx_ring_dma + sizeof(struct tulip_rx_desc) * RX_RING_SIZE;
@@ -1204,24 +1250,10 @@
tp->revision = chip_rev;
tp->csr0 = csr0;
spin_lock_init(&tp->lock);
+ spin_lock_init(&tp->mii_lock);
dev->base_addr = ioaddr;
dev->irq = irq;
- pci_set_drvdata(pdev, dev);
-
-#ifdef TULIP_FULL_DUPLEX
- tp->full_duplex = 1;
- tp->full_duplex_lock = 1;
-#endif
-#ifdef TULIP_DEFAULT_MEDIA
- tp->default_port = TULIP_DEFAULT_MEDIA;
-#endif
-#ifdef TULIP_NO_MEDIA_SWITCH
- tp->medialock = 1;
-#endif
-
- printk(KERN_INFO "%s: %s rev %d at %#3lx,",
- dev->name, tulip_tbl[chip_idx].chip_name, chip_rev, ioaddr);
/* bugfix: the ASIX must have a burst limit or horrible things happen. */
if (chip_idx == AX88140) {
@@ -1239,10 +1271,10 @@
if (chip_idx == DC21041) {
if (inl(ioaddr + CSR9) & 0x8000) {
- printk(" 21040 compatible mode,");
chip_idx = DC21040;
+ t2104x_mode = 1;
} else {
- printk(" 21041 mode,");
+ t2104x_mode = 2;
}
}
@@ -1315,7 +1347,7 @@
Many PCI BIOSes also incorrectly report the IRQ line, so we correct
that here as well. */
if (sum == 0 || sum == 6*0xff) {
- printk(" EEPROM not present,");
+ eeprom_missing = 1;
for (i = 0; i < 5; i++)
dev->dev_addr[i] = last_phys_addr[i];
dev->dev_addr[i] = last_phys_addr[i] + 1;
@@ -1326,21 +1358,23 @@
}
for (i = 0; i < 6; i++)
- printk("%c%2.2X", i ? ':' : ' ', last_phys_addr[i] = dev->dev_addr[i]);
- printk(", IRQ %d.\n", irq);
+ last_phys_addr[i] = dev->dev_addr[i];
last_irq = irq;
/* The lower four bits are the media type. */
if (board_idx >= 0 && board_idx < MAX_UNITS) {
- tp->default_port = options[board_idx] & 15;
- if ((options[board_idx] & 0x90) || full_duplex[board_idx] > 0)
+ if (options[board_idx] & MEDIA_MASK)
+ tp->default_port = options[board_idx] & MEDIA_MASK;
+ if ((options[board_idx] & FullDuplex) || full_duplex[board_idx] > 0)
tp->full_duplex = 1;
if (mtu[board_idx] > 0)
dev->mtu = mtu[board_idx];
}
- if (dev->mem_start)
- tp->default_port = dev->mem_start;
+ if (dev->mem_start & MEDIA_MASK)
+ tp->default_port = dev->mem_start & MEDIA_MASK;
if (tp->default_port) {
+ printk(KERN_INFO "%s: Transceiver selection forced to %s.\n",
+ pdev->slot_name, medianame[tp->default_port & MEDIA_MASK]);
tp->medialock = 1;
if (tulip_media_cap[tp->default_port] & MediaAlwaysFD)
tp->full_duplex = 1;
@@ -1356,16 +1390,18 @@
else
tp->to_advertise = 0x01e1;
- /* This is logically part of _init_one(), but too complex to write inline. */
if (tp->flags & HAS_MEDIA_TABLE) {
memcpy(tp->eeprom, ee_data, sizeof(tp->eeprom));
+
+ sprintf(dev->name, "tulip%d", board_idx); /* hack */
tulip_parse_eeprom(dev);
+ strcpy(dev->name, "eth%d"); /* un-hack */
}
if ((tp->flags & ALWAYS_CHECK_MII) ||
(tp->mtable && tp->mtable->has_mii) ||
( ! tp->mtable && (tp->flags & HAS_MII))) {
- int phy, phy_idx;
+ int phyn, phy_idx = 0;
if (tp->mtable && tp->mtable->has_mii) {
for (i = 0; i < tp->mtable->leafcount; i++)
if (tp->mtable->mleaf[i].media == 11) {
@@ -1379,8 +1415,8 @@
/* Find the connected MII xcvrs.
Doing this in open() would allow detecting external xcvrs later,
but takes much time. */
- for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(tp->phys);
- phy++) {
+ for (phyn = 1; phyn <= 32 && phy_idx < sizeof(tp->phys); phyn++) {
+ int phy = phyn & 0x1f;
int mii_status = tulip_mdio_read(dev, phy, 1);
if ((mii_status & 0x8301) == 0x8001 ||
((mii_status & 0x8000) == 0 && (mii_status & 0x7800) != 0)) {
@@ -1391,15 +1427,15 @@
tp->advertising[phy_idx++] = reg4;
printk(KERN_INFO "%s: MII transceiver #%d "
"config %4.4x status %4.4x advertising %4.4x.\n",
- dev->name, phy, mii_reg0, mii_status, mii_advert);
+ pdev->slot_name, phy, mii_reg0, mii_status, mii_advert);
/* Fixup for DLink with miswired PHY. */
if (mii_advert != reg4) {
printk(KERN_DEBUG "%s: Advertising %4.4x on PHY %d,"
" previously advertising %4.4x.\n",
- dev->name, reg4, phy, mii_advert);
+ pdev->slot_name, reg4, phy, mii_advert);
printk(KERN_DEBUG "%s: Advertising %4.4x (to advertise"
" is %4.4x).\n",
- dev->name, reg4, tp->to_advertise);
+ pdev->slot_name, reg4, tp->to_advertise);
tulip_mdio_write(dev, phy, 4, reg4);
}
/* Enable autonegotiation: some boards default to off. */
@@ -1411,7 +1447,7 @@
tp->mii_cnt = phy_idx;
if (tp->mtable && tp->mtable->has_mii && phy_idx == 0) {
printk(KERN_INFO "%s: ***WARNING***: No MII transceiver found!\n",
- dev->name);
+ pdev->slot_name);
tp->phys[0] = 1;
}
}
@@ -1426,6 +1462,23 @@
dev->do_ioctl = private_ioctl;
dev->set_multicast_list = set_rx_mode;
+ if (register_netdev(dev))
+ goto err_out_mtable;
+
+ printk(KERN_INFO "%s: %s rev %d at %#3lx,",
+ dev->name, tulip_tbl[chip_idx].chip_name, chip_rev, ioaddr);
+ pci_set_drvdata(pdev, dev);
+
+ if (t2104x_mode == 1)
+ printk(" 21040 compatible mode,");
+ else if (t2104x_mode == 2)
+ printk(" 21041 mode,");
+ if (eeprom_missing)
+ printk(" EEPROM not present,");
+ for (i = 0; i < 6; i++)
+ printk("%c%2.2X", i ? ':' : ' ', dev->dev_addr[i]);
+ printk(", IRQ %d.\n", irq);
+
if ((tp->flags & HAS_NWAY) || tp->chip_id == DC21041)
tp->link_change = t21142_lnk_change;
else if (tp->flags & HAS_PNICNWAY)
@@ -1493,12 +1546,11 @@
return 0;
-err_out_free_mmio_res:
- release_mem_region (pci_resource_start (pdev, 1),
- pci_resource_len (pdev, 1));
-err_out_free_pio_res:
- release_region (pci_resource_start (pdev, 0),
- pci_resource_len (pdev, 0));
+err_out_mtable:
+ if (tp->mtable)
+ kfree (tp->mtable);
+err_out_free_res:
+ pci_release_regions (pdev);
err_out_free_netdev:
unregister_netdev (dev);
kfree (dev);
@@ -1510,7 +1562,7 @@
{
struct net_device *dev = pci_get_drvdata(pdev);
- if (dev && netif_device_present (dev)) {
+ if (dev && netif_running (dev) && netif_device_present (dev)) {
netif_device_detach (dev);
tulip_down (dev);
/* pci_power_off(pdev, -1); */
@@ -1522,10 +1574,10 @@
{
struct net_device *dev = pci_get_drvdata(pdev);
+ if (dev && netif_running (dev) && !netif_device_present (dev)) {
#if 1
- pci_enable_device (pdev);
+ pci_enable_device (pdev);
#endif
- if (dev && !netif_device_present (dev)) {
/* pci_power_on(pdev); */
tulip_up (dev);
netif_device_attach (dev);
@@ -1547,14 +1599,10 @@
sizeof (struct tulip_tx_desc) * TX_RING_SIZE,
tp->rx_ring, tp->rx_ring_dma);
unregister_netdev (dev);
- release_mem_region (pci_resource_start (pdev, 1),
- pci_resource_len (pdev, 1));
- release_region (pci_resource_start (pdev, 0),
- pci_resource_len (pdev, 0));
if (tp->mtable)
kfree (tp->mtable);
kfree (dev);
-
+ pci_release_regions (pdev);
pci_set_drvdata (pdev, NULL);
/* pci_power_off (pdev, -1); */
@@ -1573,6 +1621,10 @@
static int __init tulip_init (void)
{
+#ifdef MODULE
+ printk (KERN_INFO "%s", version);
+#endif
+
/* copy module parms into globals */
tulip_rx_copybreak = rx_copybreak;
tulip_max_interrupt_work = max_interrupt_work;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)