patch-2.1.16 linux/drivers/net/sunlance.c
Next file: linux/drivers/net/sunqe.c
Previous file: linux/drivers/net/sunhme.h
Back to the patch index
Back to the overall index
- Lines: 719
- Date:
Fri Dec 13 11:37:32 1996
- Orig file:
v2.1.15/linux/drivers/net/sunlance.c
- Orig date:
Sun Apr 21 12:41:57 1996
diff -u --recursive --new-file v2.1.15/linux/drivers/net/sunlance.c linux/drivers/net/sunlance.c
@@ -1,25 +1,51 @@
/* lance.c: Linux/Sparc/Lance driver */
/*
- Written 1995, 1996 by Miguel de Icaza
+ Written 1995, 1996 by Miguel de Icaza
Sources:
- The Linux depca driver
- The Linux lance driver.
- The Linux skeleton driver.
- The NetBSD Sparc/Lance driver.
- Theo de Raadt (deraadt@openbsd.org)
- NCR92C990 Lan Controller manual
+ The Linux depca driver
+ The Linux lance driver.
+ The Linux skeleton driver.
+ The NetBSD Sparc/Lance driver.
+ Theo de Raadt (deraadt@openbsd.org)
+ NCR92C990 Lan Controller manual
1.4:
- Added support to run with a ledma on the Sun4m
+ Added support to run with a ledma on the Sun4m
1.5:
- Added multiple card detection.
+ Added multiple card detection.
+
+ 4/17/96: Burst sizes and tpe selection on sun4m by Eddie C. Dost
+ (ecd@skynet.be)
+
+ 5/15/96: auto carrier detection on sun4m by Eddie C. Dost
+ (ecd@skynet.be)
+
+ 5/17/96: lebuffer on scsi/ether cards now work David S. Miller
+ (davem@caip.rutgers.edu)
+
+ 5/29/96: override option 'tpe-link-test?', if it is 'false', as
+ this disables auto carrier detection on sun4m. Eddie C. Dost
+ (ecd@skynet.be)
+1.7:
+ 6/26/96: Bug fix for multiple ledmas, miguel.
+1.8:
+ Stole multicast code from depca.c, fixed lance_tx.
+1.9:
+ Fixed the multicast code (Pedro Roque)
+
+ 8/28/96: Send fake packet in lance_open() if auto_select is true,
+ so we can detect the carrier loss condition in time.
+ Eddie C. Dost (ecd@skynet.be)
+
+ 9/15/96: Align rx_buf so that eth_copy_and_sum() won't cause an
+ MNA trap during chksum_partial_copy(). (ecd@skynet.be)
+
+ 11/17/96: Handle LE_C0_MERR in lance_interrupt(). (ecd@skynet.be)
- 4/17/97: Burst sizes and tpe selection on sun4m by Christian Dost
- (ecd@pool.informatik.rwth-aachen.de)
*/
#undef DEBUG_DRIVER
static char *version =
- "sunlance.c:v1.6 19/Apr/96 Miguel de Icaza (miguel@nuclecu.unam.mx)\n";
+ "sunlance.c:v1.9 21/Aug/96 Miguel de Icaza (miguel@nuclecu.unam.mx)\n";
static char *lancestr = "LANCE";
static char *lancedma = "LANCE DMA";
@@ -49,6 +75,7 @@
#include <asm/sbus.h>
#include <asm/openprom.h>
#include <asm/oplib.h>
+#include <asm/auxio.h> /* For tpe-link-test? setting */
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
@@ -60,6 +87,9 @@
#define LANCE_LOG_RX_BUFFERS 4
#endif
+#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */
+#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */
+
#define LE_CSR0 0
#define LE_CSR1 1
#define LE_CSR2 2
@@ -162,8 +192,9 @@
struct lance_rx_desc brx_ring[RX_RING_SIZE];
struct lance_tx_desc btx_ring[TX_RING_SIZE];
- char rx_buf [RX_RING_SIZE][RX_BUFF_SIZE];
char tx_buf [TX_RING_SIZE][TX_BUFF_SIZE];
+ char pad[2]; /* align rx_buf for copy_and_sum(). */
+ char rx_buf [RX_RING_SIZE][RX_BUFF_SIZE];
};
struct lance_private {
@@ -178,7 +209,9 @@
struct Linux_SBus_DMA *ledma; /* if set this points to ledma and arch=4m */
int tpe; /* cable-selection is TPE */
+ int auto_select; /* cable-selection by carrier */
int burst_sizes; /* ledma SBus burst sizes */
+ unsigned short busmaster_regval, pio_buffer;
};
#define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\
@@ -196,6 +229,11 @@
/* The Lance uses 24 bit addresses */
/* On the Sun4c the DVMA will provide the remaining bytes for us */
/* On the Sun4m we have to instruct the ledma to provide them */
+/* Even worse, on scsi/ether SBUS cards, the init block and the
+ * transmit/receive buffers are addresses as offsets from absolute
+ * zero on the lebuffer PIO area. -davem
+ */
+
#define LANCE_ADDR(x) ((int)(x) & ~0xff000000)
/* Load the CSR registers */
@@ -205,13 +243,16 @@
volatile struct lance_init_block *ib = lp->init_block;
int leptr;
- leptr = LANCE_ADDR (ib);
+ if(lp->pio_buffer)
+ leptr = 0;
+ else
+ leptr = LANCE_ADDR (ib);
ll->rap = LE_CSR1;
ll->rdp = (leptr & 0xFFFF);
ll->rap = LE_CSR2;
ll->rdp = leptr >> 16;
ll->rap = LE_CSR3;
- ll->rdp = LE_C3_BSWP | LE_C3_ACON | LE_C3_BCON;
+ ll->rdp = lp->busmaster_regval;
/* Point back to csr0 */
ll->rap = LE_CSR0;
@@ -225,9 +266,15 @@
{
struct lance_private *lp = (struct lance_private *) dev->priv;
volatile struct lance_init_block *ib = lp->init_block;
+ volatile struct lance_init_block *aib; /* for LANCE_ADDR computations */
int leptr;
int i;
+ if(lp->pio_buffer)
+ aib = 0;
+ else
+ aib = ib;
+
/* Lock out other processes while setting up hardware */
dev->tbusy = 1;
lp->rx_new = lp->tx_new = 0;
@@ -250,7 +297,7 @@
/* Setup the Tx ring entries */
for (i = 0; i <= TX_RING_SIZE; i++) {
- leptr = LANCE_ADDR(&ib->tx_buf[i][0]);
+ leptr = LANCE_ADDR(&aib->tx_buf[i][0]);
ib->btx_ring [i].tmd0 = leptr;
ib->btx_ring [i].tmd1_hadr = leptr >> 16;
ib->btx_ring [i].tmd1_bits = 0;
@@ -264,7 +311,7 @@
if (ZERO)
printk ("RX rings:\n");
for (i = 0; i < RX_RING_SIZE; i++) {
- leptr = LANCE_ADDR(&ib->rx_buf[i][0]);
+ leptr = LANCE_ADDR(&aib->rx_buf[i][0]);
ib->brx_ring [i].rmd0 = leptr;
ib->brx_ring [i].rmd1_hadr = leptr >> 16;
@@ -278,14 +325,14 @@
/* Setup the initialization block */
/* Setup rx descriptor pointer */
- leptr = LANCE_ADDR(&ib->brx_ring);
+ leptr = LANCE_ADDR(&aib->brx_ring);
ib->rx_len = (LANCE_LOG_RX_BUFFERS << 13) | (leptr >> 16);
ib->rx_ptr = leptr;
if (ZERO)
printk ("RX ptr: %8.8x\n", leptr);
/* Setup tx descriptor pointer */
- leptr = LANCE_ADDR(&ib->btx_ring);
+ leptr = LANCE_ADDR(&aib->btx_ring);
ib->tx_len = (LANCE_LOG_TX_BUFFERS << 13) | (leptr >> 16);
ib->tx_ptr = leptr;
if (ZERO)
@@ -305,8 +352,11 @@
struct sparc_dma_registers *dregs = lp->ledma->regs;
unsigned long creg;
- while (dregs->cond_reg & DMA_FIFO_ISDRAIN) /* E-Cache draining */
- barrier();
+ if (!(dregs->cond_reg & DMA_HNDL_ERROR)) {
+ /* E-Cache draining */
+ while (dregs->cond_reg & DMA_FIFO_ISDRAIN)
+ barrier();
+ }
creg = dregs->cond_reg;
if (lp->burst_sizes & DMA_BURST32)
@@ -353,9 +403,10 @@
{
struct lance_private *lp = (struct lance_private *) dev->priv;
volatile struct lance_init_block *ib = lp->init_block;
- volatile struct lance_regs *ll = lp->ll;
volatile struct lance_rx_desc *rd;
unsigned char bits;
+ int len;
+ struct sk_buff *skb;
#ifdef TEST_HITS
printk ("[");
@@ -370,12 +421,9 @@
printk ("]");
#endif
- ll->rdp = LE_C0_RINT|LE_C0_INEA;
for (rd = &ib->brx_ring [lp->rx_new];
!((bits = rd->rmd1_bits) & LE_R1_OWN);
rd = &ib->brx_ring [lp->rx_new]) {
- int pkt_len;
- struct sk_buff *skb;
/* We got an incomplete frame? */
if ((bits & LE_R1_POK) != LE_R1_POK) {
@@ -383,16 +431,19 @@
lp->stats.rx_errors++;
continue;
} else if (bits & LE_R1_ERR) {
- /* Count only the end frame as a tx error, not the beginning */
+ /* Count only the end frame as a rx error,
+ * not the beginning
+ */
if (bits & LE_R1_BUF) lp->stats.rx_fifo_errors++;
if (bits & LE_R1_CRC) lp->stats.rx_crc_errors++;
if (bits & LE_R1_OFL) lp->stats.rx_over_errors++;
if (bits & LE_R1_FRA) lp->stats.rx_frame_errors++;
if (bits & LE_R1_EOP) lp->stats.rx_errors++;
} else {
- pkt_len = rd->mblength;
- skb = dev_alloc_skb (pkt_len+2);
- if (skb == NULL) {
+ len = (rd->mblength & 0xfff) - 4;
+ skb = dev_alloc_skb (len+2);
+
+ if (skb == 0) {
printk ("%s: Memory squeeze, deferring packet.\n",
dev->name);
lp->stats.rx_dropped++;
@@ -403,12 +454,12 @@
}
skb->dev = dev;
- skb_reserve (skb, 2); /* 16 byte align */
- skb_put (skb, pkt_len); /* make room */
+ skb_reserve (skb, 2); /* 16 byte align */
+ skb_put (skb, len); /* make room */
eth_copy_and_sum(skb,
(unsigned char *)&(ib->rx_buf [lp->rx_new][0]),
- pkt_len, 0);
- skb->protocol = eth_type_trans (skb,dev);
+ len, 0);
+ skb->protocol = eth_type_trans (skb, dev);
netif_rx (skb);
lp->stats.rx_packets++;
}
@@ -430,23 +481,40 @@
int i, j;
int status;
- /* csr0 is 2f3 */
- ll->rdp = LE_C0_TINT | LE_C0_INEA;
- /* csr0 is 73 */
j = lp->tx_old;
- for (i = 0; i < TX_RING_SIZE; i++) {
- td = &ib->btx_ring [j];
+ for (i = j; i != lp->tx_new; i = j) {
+ td = &ib->btx_ring [i];
+ /* If we hit a packet not owned by us, stop */
+ if (td->tmd1_bits & LE_T1_OWN)
+ break;
+
if (td->tmd1_bits & LE_T1_ERR) {
status = td->misc;
lp->stats.tx_errors++;
if (status & LE_T3_RTY) lp->stats.tx_aborted_errors++;
- if (status & LE_T3_CLOS) lp->stats.tx_carrier_errors++;
if (status & LE_T3_LCOL) lp->stats.tx_window_errors++;
- /* buffer errors and underflows turn off the transmitter */
- /* Restart the adapter */
+ if (status & LE_T3_CLOS) {
+ lp->stats.tx_carrier_errors++;
+ if (lp->auto_select) {
+ lp->tpe = 1 - lp->tpe;
+ printk("%s: Carrier Lost, trying %s\n",
+ dev->name, lp->tpe?"TPE":"AUI");
+ /* Stop the lance */
+ ll->rap = LE_CSR0;
+ ll->rdp = LE_C0_STOP;
+ lance_init_ring (dev);
+ load_csrs (lp);
+ init_restart_lance (lp);
+ return 0;
+ }
+ }
+
+ /* Buffer errors and underflows turn off the
+ * transmitter, restart the adapter.
+ */
if (status & (LE_T3_BUF|LE_T3_UFL)) {
lp->stats.tx_fifo_errors++;
@@ -474,58 +542,37 @@
if (td->tmd1_bits & LE_T1_EMORE)
lp->stats.collisions += 2;
- /* What to set here? */
- if (td->tmd1_bits & LE_T1_EDEF)
- /* EMPTY */ ;
-
lp->stats.tx_packets++;
}
j = (j + 1) & TX_RING_MOD_MASK;
}
- lp->tx_old = (lp->tx_old+1) & TX_RING_MOD_MASK;
-
- ll->rdp = LE_C0_TINT | LE_C0_INEA;
+ lp->tx_old = j;
return 0;
}
static void lance_interrupt (int irq, void *dev_id, struct pt_regs *regs)
{
- struct device *dev;
- struct lance_private *lp;
- volatile struct lance_regs *ll;
+ struct device *dev = (struct device *)dev_id;
+ struct lance_private *lp = (struct lance_private *)dev->priv;
+ volatile struct lance_regs *ll = lp->ll;
int csr0;
-#ifdef OLD_STYLE_IRQ
- dev = (struct device *) (irq2dev_map [irq]);
-#else
- dev = (struct device *) dev_id;
-#endif
-
- lp = (struct lance_private *) dev->priv;
- ll = lp->ll;
-
- if (lp->ledma) {
- if (lp->ledma->regs->cond_reg & DMA_HNDL_ERROR) {
- printk ("%s: should reset my ledma (dmacsr=%8.8x, csr=%4.4x\n",
- dev->name, (unsigned int) lp->ledma->regs->cond_reg,
- ll->rdp);
- printk ("send mail to miguel@nuclecu.unam.mx\n");
- }
- }
if (dev->interrupt)
printk ("%s: again", dev->name);
dev->interrupt = 1;
+ ll->rap = LE_CSR0;
csr0 = ll->rdp;
/* Acknowledge all the interrupt sources ASAP */
- ll->rdp = csr0 & 0x004f;
+ ll->rdp = csr0 & (LE_C0_INTR | LE_C0_TINT | LE_C0_RINT);
if ((csr0 & LE_C0_ERR)) {
/* Clear the error condition */
- ll->rdp = LE_C0_BABL|LE_C0_ERR|LE_C0_MISS|LE_C0_INEA;
+ ll->rdp = LE_C0_BABL | LE_C0_ERR | LE_C0_MISS |
+ LE_C0_CERR | LE_C0_MERR;
}
if (csr0 & LE_C0_RINT)
@@ -538,9 +585,32 @@
dev->tbusy = 0;
mark_bh (NET_BH);
}
- ll->rap = LE_CSR0;
- ll->rdp = 0x7940;
+ if (csr0 & LE_C0_BABL)
+ lp->stats.tx_errors++;
+
+ if (csr0 & LE_C0_MISS)
+ lp->stats.rx_errors++;
+
+ if (csr0 & LE_C0_MERR) {
+ struct sparc_dma_registers *dregs = lp->ledma->regs;
+ unsigned long tst = (unsigned long)dregs->st_addr;
+
+ printk ("%s: Memory error, status %04x, addr %06lx\n",
+ dev->name, csr0, tst & 0xffffff);
+
+ ll->rdp = LE_C0_STOP;
+
+ if (lp->ledma)
+ lp->ledma->regs->cond_reg |= DMA_FIFO_INV;
+
+ lance_init_ring (dev);
+ load_csrs (lp);
+ init_restart_lance (lp);
+ dev->tbusy = 0;
+ }
+
+ ll->rdp = LE_C0_INEA;
dev->interrupt = 0;
}
@@ -554,7 +624,7 @@
last_dev = dev;
- if (request_irq (dev->irq, &lance_interrupt, 0, lancestr, (void *) dev)) {
+ if (request_irq (dev->irq, &lance_interrupt, SA_SHIRQ, lancestr, (void *) dev)) {
printk ("Lance: Can't get irq %d\n", dev->irq);
return -EAGAIN;
}
@@ -563,10 +633,6 @@
ll->rap = LE_CSR0;
ll->rdp = LE_C0_STOP;
-#ifdef OLD_STYLE_IRQ
- irq2dev_map [dev->irq] = dev;
-#endif
-
/* On the 4m, setup the ledma to provide the upper bits for buffers */
if (lp->ledma)
lp->ledma->regs->dma_test = ((unsigned int) lp->init_block) & 0xff000000;
@@ -586,6 +652,34 @@
ip_get_mask (dev->pa_addr),
0, dev, dev->mtu, 0, 0);
#endif
+ if (!status && lp->auto_select) {
+ /*
+ * Build a fake network packet and send it to ourselfs.
+ */
+ volatile struct lance_init_block *ib = lp->init_block;
+ volatile unsigned long flush;
+ unsigned char packet[ETH_ZLEN];
+ struct ethhdr *eth = (struct ethhdr *)packet;
+ int i, entry;
+
+ memset(packet, 0, ETH_ZLEN);
+ for (i = 0; i < 6; i++) {
+ eth->h_dest[i] = dev->dev_addr[i];
+ eth->h_source[i] = dev->dev_addr[i];
+ }
+
+ entry = lp->tx_new & TX_RING_MOD_MASK;
+ ib->btx_ring[entry].length = (-ETH_ZLEN) | 0xf000;
+ ib->btx_ring[entry].misc = 0;
+
+ memcpy((char *)&ib->tx_buf[entry][0], packet, ETH_ZLEN);
+ ib->btx_ring[entry].tmd1_bits = (LE_T1_POK|LE_T1_OWN);
+ lp->tx_new = (lp->tx_new + 1) & TX_RING_MOD_MASK;
+
+ ll->rdp = LE_C0_INEA | LE_C0_TDMD;
+ flush = ll->rdp;
+ }
+
return status;
}
@@ -601,10 +695,7 @@
ll->rap = LE_CSR0;
ll->rdp = LE_C0_STOP;
- free_irq (dev->irq, NULL);
-#ifdef OLD_STYLE_IRQ
- irq2dev_map [dev->irq] = NULL;
-#endif
+ free_irq (dev->irq, (void *) dev);
return 0;
}
@@ -671,7 +762,7 @@
}
if (skb->len <= 0) {
- printk ("skb len is %ld\n", skb->len);
+ printk ("skb len is %d\n", skb->len);
return 0;
}
/* Block a timer-based transmit from overlapping. */
@@ -739,22 +830,83 @@
return &lp->stats;
}
+/* taken from the depca driver */
+static void lance_load_multicast (struct device *dev)
+{
+ struct lance_private *lp = (struct lance_private *) dev->priv;
+ volatile struct lance_init_block *ib = lp->init_block;
+ volatile u16 *mcast_table = (u16 *)&ib->filter;
+ struct dev_mc_list *dmi=dev->mc_list;
+ char *addrs;
+ int i, j, bit, byte;
+ u32 crc, poly = CRC_POLYNOMIAL_LE;
+
+ /* set all multicast bits */
+ if (dev->flags & IFF_ALLMULTI){
+ ib->filter [0] = 0xffffffff;
+ ib->filter [1] = 0xffffffff;
+ return;
+ }
+ /* clear the multicast filter */
+ ib->filter [0] = 0;
+ ib->filter [1] = 0;
+
+ /* Add addresses */
+ for (i = 0; i < dev->mc_count; i++){
+ addrs = dmi->dmi_addr;
+ dmi = dmi->next;
+
+ /* multicast address? */
+ if (!(*addrs & 1))
+ continue;
+
+ crc = 0xffffffff;
+ for (byte = 0; byte < 6; byte++)
+ for (bit = *addrs++, j = 0; j < 8; j++, bit>>=1)
+ {
+ int test;
+
+ test = ((bit ^ crc) & 0x01);
+ crc >>= 1;
+
+ if (test)
+ {
+ crc = crc ^ poly;
+ }
+ }
+
+ crc = crc >> 26;
+ mcast_table [crc >> 4] |= 1 << (crc & 0xf);
+ }
+ return;
+}
+
static void lance_set_multicast (struct device *dev)
{
-#ifdef NOT_YET
struct lance_private *lp = (struct lance_private *) dev->priv;
volatile struct lance_init_block *ib = lp->init_block;
volatile struct lance_regs *ll = lp->ll;
+ while (dev->tbusy)
+ schedule();
+ set_bit (0, (void *) &dev->tbusy);
+
+ while (lp->tx_old != lp->tx_new)
+ schedule();
+
ll->rap = LE_CSR0;
ll->rdp = LE_C0_STOP;
lance_init_ring (dev);
- ib->mode |= LE_MO_PROM;
- lance_init_ring (dev);
+
+ if (dev->flags & IFF_PROMISC) {
+ ib->mode |= LE_MO_PROM;
+ } else {
+ ib->mode &= ~LE_MO_PROM;
+ lance_load_multicast (dev);
+ }
load_csrs (lp);
init_restart_lance (lp);
dev->tbusy = 0;
-#endif
}
int sparc_lance_init (struct device *dev, struct linux_sbus_device *sdev,
@@ -786,11 +938,11 @@
*/
for (i = 0; i < 6; i++)
printk ("%2.2x%c",
- dev->dev_addr [i] = idprom->id_eaddr [i], i == 5 ? ' ': ':');
+ dev->dev_addr[i] = idprom->id_ethaddr[i], i == 5 ? ' ': ':');
printk("\n");
/* Get the IO region */
- prom_apply_sbus_ranges (&sdev->reg_addrs [0], sdev->num_registers);
+ prom_apply_sbus_ranges (sdev->my_bus, &sdev->reg_addrs [0], sdev->num_registers);
ll = sparc_alloc_io (sdev->reg_addrs [0].phys_addr, 0,
sizeof (struct lance_regs), lancestr,
sdev->reg_addrs[0].which_io, 0x0);
@@ -801,16 +953,21 @@
memset ((char *)dev->priv, 0, sizeof (struct lance_private));
if (lebuffer){
- prom_apply_sbus_ranges (&sdev->reg_addrs [0], sdev->num_registers);
+ prom_apply_sbus_ranges (lebuffer->my_bus, &lebuffer->reg_addrs [0],
+ lebuffer->num_registers);
lp->init_block = (void *)
sparc_alloc_io (lebuffer->reg_addrs [0].phys_addr, 0,
sizeof (struct lance_init_block), "lebuffer",
lebuffer->reg_addrs [0].which_io, 0);
+ lp->pio_buffer = 1;
} else {
lp->init_block = (void *)
sparc_dvma_malloc (sizeof (struct lance_init_block),
lancedma);
+ lp->pio_buffer = 0;
}
+ lp->busmaster_regval = prom_getintdefault(sdev->prom_node, "busmaster-regval",
+ (LE_C3_BSWP|LE_C3_ACON|LE_C3_BCON));
lp->ll = ll;
lp->name = lancestr;
@@ -818,7 +975,7 @@
lp->burst_sizes = 0;
if (lp->ledma) {
- char cable_prop[4];
+ char prop[6];
unsigned int sbmask;
/* Find burst-size property for ledma */
@@ -831,12 +988,48 @@
lp->burst_sizes &= sbmask;
/* Get the cable-selection property */
+ memset(prop, 0, sizeof(prop));
prom_getstring(ledma->SBus_dev->prom_node, "cable-selection",
- cable_prop, sizeof(cable_prop));
- if (!strcmp(cable_prop, "aui"))
+ prop, sizeof(prop));
+ if (prop[0] == 0) {
+ int topnd, nd;
+
+ printk("%s: using auto-carrier-detection.\n",
+ dev->name);
+
+ /* Is this found at /options .attributes in all
+ * Prom versions? XXX
+ */
+ topnd = prom_getchild(prom_root_node);
+
+ nd = prom_searchsiblings(topnd, "options");
+ if (!nd)
+ goto no_link_test;
+
+ if (!prom_node_has_property(nd, "tpe-link-test?"))
+ goto no_link_test;
+
+ memset(prop, 0, sizeof(prop));
+ prom_getstring(nd, "tpe-link-test?", prop,
+ sizeof(prop));
+
+ if (strcmp(prop, "true")) {
+ printk("%s: warning: overriding option 'tpe-link-test?'\n",
+ dev->name);
+ printk("%s: warning: mail any problems to ecd@skynet.be\n",
+ dev->name);
+ set_auxio(AUXIO_LINK_TEST, 0);
+ }
+no_link_test:
+ lp->auto_select = 1;
lp->tpe = 0;
- else
+ } else if (!strcmp(prop, "aui")) {
+ lp->auto_select = 0;
+ lp->tpe = 0;
+ } else {
+ lp->auto_select = 0;
lp->tpe = 1;
+ }
/* Reset ledma */
lp->ledma->regs->cond_reg |= DMA_RST_ENET;
@@ -881,30 +1074,33 @@
struct linux_sbus *bus;
struct linux_sbus_device *sdev = 0;
struct Linux_SBus_DMA *ledma = 0;
+ static int called = 0;
int cards = 0, v;
+ if(called)
+ return ENODEV;
+ called++;
for_each_sbus (bus) {
for_each_sbusdev (sdev, bus) {
if (cards) dev = NULL;
if (strcmp (sdev->prom_name, "le") == 0) {
cards++;
- if ((v = sparc_lance_init(dev, sdev, ledma,0)))
+ if ((v = sparc_lance_init(dev, sdev, 0, 0)))
return v;
+ continue;
}
if (strcmp (sdev->prom_name, "ledma") == 0) {
cards++;
ledma = find_ledma (sdev);
- sdev = sdev->child;
- if ((v = sparc_lance_init(dev, sdev, ledma,0)))
+ if ((v = sparc_lance_init(dev, sdev->child, ledma, 0)))
return v;
- break;
+ continue;
}
if (strcmp (sdev->prom_name, "lebuffer") == 0){
- struct linux_sbus_device *le = sdev->child;
cards++;
- if ((v = sparc_lance_init(dev, le, ledma,sdev)))
+ if ((v = sparc_lance_init(dev, sdev->child, 0, sdev)))
return v;
- break;
+ continue;
}
} /* for each sbusdev */
} /* for each sbus */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov