* add p cc
[mascara-docs.git] / i386 / linux / linux-2.3.21 / drivers / net / ariadne.c
blob75bff9f36dbdcdc24a911255f32695a6e459e9f8
1 /*
2 * Amiga Linux/m68k Ariadne Ethernet Driver
4 * © Copyright 1995 by Geert Uytterhoeven (geert@linux-m68k.org)
5 * Peter De Schrijver
6 * (Peter.DeSchrijver@linux.cc.kuleuven.ac.be)
8 * ---------------------------------------------------------------------------
10 * This program is based on
12 * lance.c: An AMD LANCE ethernet driver for linux.
13 * Written 1993-94 by Donald Becker.
15 * Am79C960: PCnet(tm)-ISA Single-Chip Ethernet Controller
16 * Advanced Micro Devices
17 * Publication #16907, Rev. B, Amendment/0, May 1994
19 * MC68230: Parallel Interface/Timer (PI/T)
20 * Motorola Semiconductors, December, 1983
22 * ---------------------------------------------------------------------------
24 * This file is subject to the terms and conditions of the GNU General Public
25 * License. See the file COPYING in the main directory of the Linux
26 * distribution for more details.
28 * ---------------------------------------------------------------------------
30 * The Ariadne is a Zorro-II board made by Village Tronic. It contains:
32 * - an Am79C960 PCnet-ISA Single-Chip Ethernet Controller with both
33 * 10BASE-2 (thin coax) and 10BASE-T (UTP) connectors
35 * - an MC68230 Parallel Interface/Timer configured as 2 parallel ports
38 #include <linux/module.h>
39 #include <linux/stddef.h>
40 #include <linux/kernel.h>
41 #include <linux/sched.h>
42 #include <linux/string.h>
43 #include <linux/ptrace.h>
44 #include <linux/errno.h>
45 #include <linux/ioport.h>
46 #include <linux/malloc.h>
47 #include <linux/netdevice.h>
48 #include <linux/etherdevice.h>
49 #include <linux/interrupt.h>
50 #include <linux/skbuff.h>
51 #include <linux/init.h>
53 #include <asm/bitops.h>
54 #include <asm/amigaints.h>
55 #include <asm/amigahw.h>
56 #include <linux/zorro.h>
57 #include <asm/io.h>
58 #include <asm/irq.h>
60 #include "ariadne.h"
63 #ifdef ARIADNE_DEBUG
64 int ariadne_debug = ARIADNE_DEBUG;
65 #else
66 int ariadne_debug = 1;
67 #endif
71 * Macros to Fix Endianness problems
74 /* Swap the Bytes in a WORD */
75 #define swapw(x) (((x>>8)&0x00ff)|((x<<8)&0xff00))
76 /* Get the Low BYTE in a WORD */
77 #define lowb(x) (x&0xff)
78 /* Get the Swapped High WORD in a LONG */
79 #define swhighw(x) ((((x)>>8)&0xff00)|(((x)>>24)&0x00ff))
80 /* Get the Swapped Low WORD in a LONG */
81 #define swloww(x) ((((x)<<8)&0xff00)|(((x)>>8)&0x00ff))
85 * Transmit/Receive Ring Definitions
88 #define TX_RING_SIZE 5
89 #define RX_RING_SIZE 16
91 #define PKT_BUF_SIZE 1520
95 * Private Device Data
98 struct ariadne_private {
99 struct AriadneBoard *board;
100 struct TDRE *tx_ring[TX_RING_SIZE];
101 struct RDRE *rx_ring[RX_RING_SIZE];
102 u_short *tx_buff[TX_RING_SIZE];
103 u_short *rx_buff[RX_RING_SIZE];
104 int cur_tx, cur_rx; /* The next free ring entry */
105 int dirty_tx; /* The ring entries to be free()ed. */
106 struct net_device_stats stats;
107 char tx_full;
108 unsigned long lock;
109 unsigned int key;
114 * Structure Created in the Ariadne's RAM Buffer
117 struct lancedata {
118 struct TDRE tx_ring[TX_RING_SIZE];
119 struct RDRE rx_ring[RX_RING_SIZE];
120 u_short tx_buff[TX_RING_SIZE][PKT_BUF_SIZE/sizeof(u_short)];
121 u_short rx_buff[RX_RING_SIZE][PKT_BUF_SIZE/sizeof(u_short)];
125 static int ariadne_open(struct net_device *dev);
126 static void ariadne_init_ring(struct net_device *dev);
127 static int ariadne_start_xmit(struct sk_buff *skb, struct net_device *dev);
128 static int ariadne_rx(struct net_device *dev);
129 static void ariadne_interrupt(int irq, void *data, struct pt_regs *fp);
130 static int ariadne_close(struct net_device *dev);
131 static struct net_device_stats *ariadne_get_stats(struct net_device *dev);
132 #ifdef HAVE_MULTICAST
133 static void set_multicast_list(struct net_device *dev);
134 #endif
137 static void memcpyw(u_short *dest, u_short *src, int len)
139 while (len >= 2) {
140 *(dest++) = *(src++);
141 len -= 2;
143 if (len == 1)
144 *dest = (*(u_char *)src)<<8;
148 int __init ariadne_probe(struct net_device *dev)
150 unsigned int key;
151 const struct ConfigDev *cd;
152 u_long board;
153 struct ariadne_private *priv;
155 /* Ethernet is part 0, Parallel is part 1 */
156 if ((key = zorro_find(ZORRO_PROD_VILLAGE_TRONIC_ARIADNE, 0, 0))) {
157 cd = zorro_get_board(key);
158 if ((board = (u_long)cd->cd_BoardAddr)) {
159 dev->dev_addr[0] = 0x00;
160 dev->dev_addr[1] = 0x60;
161 dev->dev_addr[2] = 0x30;
162 dev->dev_addr[3] = (cd->cd_Rom.er_SerialNumber>>16)&0xff;
163 dev->dev_addr[4] = (cd->cd_Rom.er_SerialNumber>>8)&0xff;
164 dev->dev_addr[5] = cd->cd_Rom.er_SerialNumber&0xff;
165 printk("%s: Ariadne at 0x%08lx, Ethernet Address "
166 "%02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, board,
167 dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
168 dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
170 init_etherdev(dev, 0);
172 dev->priv = kmalloc(sizeof(struct ariadne_private), GFP_KERNEL);
173 if (dev->priv == NULL)
174 return -ENOMEM;
175 priv = (struct ariadne_private *)dev->priv;
176 memset(priv, 0, sizeof(struct ariadne_private));
178 priv->board = (struct AriadneBoard *)ZTWO_VADDR(board);
179 priv->key = key;
181 dev->open = &ariadne_open;
182 dev->stop = &ariadne_close;
183 dev->hard_start_xmit = &ariadne_start_xmit;
184 dev->get_stats = &ariadne_get_stats;
185 dev->set_multicast_list = &set_multicast_list;
187 zorro_config_board(key, 0);
188 return(0);
191 return(ENODEV);
195 static int ariadne_open(struct net_device *dev)
197 struct ariadne_private *priv = (struct ariadne_private *)dev->priv;
198 struct AriadneBoard *board = priv->board;
199 struct lancedata *lancedata;
200 u_short in;
201 u_long version;
203 /* Reset the LANCE */
204 in = board->Lance.Reset;
206 /* Stop the LANCE */
207 board->Lance.RAP = CSR0; /* PCnet-ISA Controller Status */
208 board->Lance.RDP = STOP;
210 /* Check the LANCE version */
211 board->Lance.RAP = CSR88; /* Chip ID */
212 version = swapw(board->Lance.RDP);
213 board->Lance.RAP = CSR89; /* Chip ID */
214 version |= swapw(board->Lance.RDP)<<16;
215 if ((version & 0x00000fff) != 0x00000003) {
216 printk("ariadne_open: Couldn't find AMD Ethernet Chip\n");
217 return(-EAGAIN);
219 if ((version & 0x0ffff000) != 0x00003000) {
220 printk("ariadne_open: Couldn't find Am79C960 (Wrong part number = %ld)\n",
221 (version & 0x0ffff000)>>12);
222 return(-EAGAIN);
224 #if 0
225 printk("ariadne_open: Am79C960 (PCnet-ISA) Revision %ld\n",
226 (version & 0xf0000000)>>28);
227 #endif
229 ariadne_init_ring(dev);
231 /* Miscellaneous Stuff */
232 board->Lance.RAP = CSR3; /* Interrupt Masks and Deferral Control */
233 board->Lance.RDP = 0x0000;
234 board->Lance.RAP = CSR4; /* Test and Features Control */
235 board->Lance.RDP = DPOLL|APAD_XMT|MFCOM|RCVCCOM|TXSTRTM|JABM;
237 /* Set the Multicast Table */
238 board->Lance.RAP = CSR8; /* Logical Address Filter, LADRF[15:0] */
239 board->Lance.RDP = 0x0000;
240 board->Lance.RAP = CSR9; /* Logical Address Filter, LADRF[31:16] */
241 board->Lance.RDP = 0x0000;
242 board->Lance.RAP = CSR10; /* Logical Address Filter, LADRF[47:32] */
243 board->Lance.RDP = 0x0000;
244 board->Lance.RAP = CSR11; /* Logical Address Filter, LADRF[63:48] */
245 board->Lance.RDP = 0x0000;
247 /* Set the Ethernet Hardware Address */
248 board->Lance.RAP = CSR12; /* Physical Address Register, PADR[15:0] */
249 board->Lance.RDP = ((u_short *)&dev->dev_addr[0])[0];
250 board->Lance.RAP = CSR13; /* Physical Address Register, PADR[31:16] */
251 board->Lance.RDP = ((u_short *)&dev->dev_addr[0])[1];
252 board->Lance.RAP = CSR14; /* Physical Address Register, PADR[47:32] */
253 board->Lance.RDP = ((u_short *)&dev->dev_addr[0])[2];
255 /* Set the Init Block Mode */
256 board->Lance.RAP = CSR15; /* Mode Register */
257 board->Lance.RDP = 0x0000;
259 lancedata = (struct lancedata *)offsetof(struct AriadneBoard, RAM);
261 /* Set the Transmit Descriptor Ring Pointer */
262 board->Lance.RAP = CSR30; /* Base Address of Transmit Ring */
263 board->Lance.RDP = swloww((u_long)&lancedata->tx_ring);
264 board->Lance.RAP = CSR31; /* Base Address of transmit Ring */
265 board->Lance.RDP = swhighw((u_long)&lancedata->tx_ring);
267 /* Set the Receive Descriptor Ring Pointer */
268 board->Lance.RAP = CSR24; /* Base Address of Receive Ring */
269 board->Lance.RDP = swloww((u_long)&lancedata->rx_ring);
270 board->Lance.RAP = CSR25; /* Base Address of Receive Ring */
271 board->Lance.RDP = swhighw((u_long)&lancedata->rx_ring);
273 /* Set the Number of RX and TX Ring Entries */
274 board->Lance.RAP = CSR76; /* Receive Ring Length */
275 board->Lance.RDP = swapw(((u_short)-RX_RING_SIZE));
276 board->Lance.RAP = CSR78; /* Transmit Ring Length */
277 board->Lance.RDP = swapw(((u_short)-TX_RING_SIZE));
279 /* Enable Media Interface Port Auto Select (10BASE-2/10BASE-T) */
280 board->Lance.RAP = ISACSR2; /* Miscellaneous Configuration */
281 board->Lance.IDP = ASEL;
283 /* LED Control */
284 board->Lance.RAP = ISACSR5; /* LED1 Status */
285 board->Lance.IDP = PSE|XMTE;
286 board->Lance.RAP = ISACSR6; /* LED2 Status */
287 board->Lance.IDP = PSE|COLE;
288 board->Lance.RAP = ISACSR7; /* LED3 Status */
289 board->Lance.IDP = PSE|RCVE;
291 dev->tbusy = 0;
292 dev->interrupt = 0;
293 dev->start = 1;
295 if (request_irq(IRQ_AMIGA_PORTS, ariadne_interrupt, SA_SHIRQ,
296 "Ariadne Ethernet", dev))
297 return(-EAGAIN);
299 board->Lance.RAP = CSR0; /* PCnet-ISA Controller Status */
300 board->Lance.RDP = INEA|STRT;
302 MOD_INC_USE_COUNT;
304 return(0);
308 static void ariadne_init_ring(struct net_device *dev)
310 struct ariadne_private *priv = (struct ariadne_private *)dev->priv;
311 struct AriadneBoard *board = priv->board;
312 struct lancedata *lancedata; /* LANCE point of view */
313 struct lancedata *alancedata; /* Amiga point of view */
314 int i;
316 priv->lock = 0, priv->tx_full = 0;
317 priv->cur_rx = priv->cur_tx = 0;
318 priv->dirty_tx = 0;
320 lancedata = (struct lancedata *)offsetof(struct AriadneBoard, RAM);
321 alancedata = (struct lancedata *)board->RAM;
323 /* Set up TX Ring */
324 for (i = 0; i < TX_RING_SIZE; i++) {
325 alancedata->tx_ring[i].TMD0 = swloww((u_long)lancedata->tx_buff[i]);
326 alancedata->tx_ring[i].TMD1 = swhighw((u_long)lancedata->tx_buff[i])|TF_STP|TF_ENP;
327 alancedata->tx_ring[i].TMD2 = swapw((u_short)-PKT_BUF_SIZE);
328 alancedata->tx_ring[i].TMD3 = 0;
329 priv->tx_ring[i] = &alancedata->tx_ring[i];
330 priv->tx_buff[i] = alancedata->tx_buff[i];
331 #if 0
332 printk("TX Entry %2d @ 0x%08x (LANCE 0x%08x), Buf @ 0x%08x (LANCE 0x%08x)\n",
333 i, (int)&alancedata->tx_ring[i], (int)&lancedata->tx_ring[i],
334 (int)alancedata->tx_buff[i], (int)lancedata->tx_buff[i]);
335 #endif
338 /* Set up RX Ring */
339 for (i = 0; i < RX_RING_SIZE; i++) {
340 alancedata->rx_ring[i].RMD0 = swloww((u_long)lancedata->rx_buff[i]);
341 alancedata->rx_ring[i].RMD1 = swhighw((u_long)lancedata->rx_buff[i])|RF_OWN;
342 alancedata->rx_ring[i].RMD2 = swapw((u_short)-PKT_BUF_SIZE);
343 alancedata->rx_ring[i].RMD3 = 0x0000;
344 priv->rx_ring[i] = &alancedata->rx_ring[i];
345 priv->rx_buff[i] = alancedata->rx_buff[i];
346 #if 0
347 printk("RX Entry %2d @ 0x%08x (LANCE 0x%08x), Buf @ 0x%08x (LANCE 0x%08x)\n",
348 i, (int)&alancedata->rx_ring[i], (int)&lancedata->rx_ring[i],
349 (int)alancedata->rx_buff[i], (int)lancedata->rx_buff[i]);
350 #endif
355 static int ariadne_close(struct net_device *dev)
357 struct ariadne_private *priv = (struct ariadne_private *)dev->priv;
358 struct AriadneBoard *board = priv->board;
360 dev->start = 0;
361 dev->tbusy = 1;
363 board->Lance.RAP = CSR112; /* Missed Frame Count */
364 priv->stats.rx_missed_errors = swapw(board->Lance.RDP);
365 board->Lance.RAP = CSR0; /* PCnet-ISA Controller Status */
367 if (ariadne_debug > 1) {
368 printk("%s: Shutting down ethercard, status was %2.2x.\n", dev->name,
369 board->Lance.RDP);
370 printk("%s: %lu packets missed\n", dev->name,
371 priv->stats.rx_missed_errors);
374 /* We stop the LANCE here -- it occasionally polls memory if we don't. */
375 board->Lance.RDP = STOP;
377 free_irq(IRQ_AMIGA_PORTS, dev);
379 MOD_DEC_USE_COUNT;
381 return(0);
385 static void ariadne_interrupt(int irq, void *data, struct pt_regs *fp)
387 struct net_device *dev = (struct net_device *)data;
388 struct ariadne_private *priv;
389 struct AriadneBoard *board;
390 int csr0, boguscnt = 10;
392 if (dev == NULL) {
393 printk("ariadne_interrupt(): irq for unknown device.\n");
394 return;
397 priv = (struct ariadne_private *)dev->priv;
398 board = priv->board;
400 board->Lance.RAP = CSR0; /* PCnet-ISA Controller Status */
402 if (!(board->Lance.RDP & INTR)) /* Check if any interrupt has been */
403 return; /* generated by the board. */
405 if (dev->interrupt)
406 printk("%s: Re-entering the interrupt handler.\n", dev->name);
408 dev->interrupt = 1;
410 while ((csr0 = board->Lance.RDP) & (ERR|RINT|TINT) && --boguscnt >= 0) {
411 /* Acknowledge all of the current interrupt sources ASAP. */
412 board->Lance.RDP = csr0 & ~(INEA|TDMD|STOP|STRT|INIT);
414 #if 0
415 if (ariadne_debug > 5) {
416 printk("%s: interrupt csr0=%#2.2x new csr=%#2.2x.", dev->name,
417 csr0, board->Lance.RDP);
418 printk("[");
419 if (csr0 & INTR)
420 printk(" INTR");
421 if (csr0 & INEA)
422 printk(" INEA");
423 if (csr0 & RXON)
424 printk(" RXON");
425 if (csr0 & TXON)
426 printk(" TXON");
427 if (csr0 & TDMD)
428 printk(" TDMD");
429 if (csr0 & STOP)
430 printk(" STOP");
431 if (csr0 & STRT)
432 printk(" STRT");
433 if (csr0 & INIT)
434 printk(" INIT");
435 if (csr0 & ERR)
436 printk(" ERR");
437 if (csr0 & BABL)
438 printk(" BABL");
439 if (csr0 & CERR)
440 printk(" CERR");
441 if (csr0 & MISS)
442 printk(" MISS");
443 if (csr0 & MERR)
444 printk(" MERR");
445 if (csr0 & RINT)
446 printk(" RINT");
447 if (csr0 & TINT)
448 printk(" TINT");
449 if (csr0 & IDON)
450 printk(" IDON");
451 printk(" ]\n");
453 #endif
455 if (csr0 & RINT) /* Rx interrupt */
456 ariadne_rx(dev);
458 if (csr0 & TINT) { /* Tx-done interrupt */
459 int dirty_tx = priv->dirty_tx;
461 while (dirty_tx < priv->cur_tx) {
462 int entry = dirty_tx % TX_RING_SIZE;
463 int status = lowb(priv->tx_ring[entry]->TMD1);
465 if (status & TF_OWN)
466 break; /* It still hasn't been Txed */
468 priv->tx_ring[entry]->TMD1 &= 0xff00;
470 if (status & TF_ERR) {
471 /* There was an major error, log it. */
472 int err_status = priv->tx_ring[entry]->TMD3;
473 priv->stats.tx_errors++;
474 if (err_status & EF_RTRY)
475 priv->stats.tx_aborted_errors++;
476 if (err_status & EF_LCAR)
477 priv->stats.tx_carrier_errors++;
478 if (err_status & EF_LCOL)
479 priv->stats.tx_window_errors++;
480 if (err_status & EF_UFLO) {
481 /* Ackk! On FIFO errors the Tx unit is turned off! */
482 priv->stats.tx_fifo_errors++;
483 /* Remove this verbosity later! */
484 printk("%s: Tx FIFO error! Status %4.4x.\n", dev->name,
485 csr0);
486 /* Restart the chip. */
487 board->Lance.RDP = STRT;
489 } else {
490 if (status & (TF_MORE|TF_ONE))
491 priv->stats.collisions++;
492 priv->stats.tx_packets++;
494 dirty_tx++;
497 #ifndef final_version
498 if (priv->cur_tx - dirty_tx >= TX_RING_SIZE) {
499 printk("out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
500 dirty_tx, priv->cur_tx, priv->tx_full);
501 dirty_tx += TX_RING_SIZE;
503 #endif
505 if (priv->tx_full && dev->tbusy &&
506 dirty_tx > priv->cur_tx - TX_RING_SIZE + 2) {
507 /* The ring is no longer full, clear tbusy. */
508 priv->tx_full = 0;
509 dev->tbusy = 0;
510 mark_bh(NET_BH);
513 priv->dirty_tx = dirty_tx;
516 /* Log misc errors. */
517 if (csr0 & BABL)
518 priv->stats.tx_errors++; /* Tx babble. */
519 if (csr0 & MISS)
520 priv->stats.rx_errors++; /* Missed a Rx frame. */
521 if (csr0 & MERR) {
522 printk("%s: Bus master arbitration failure, status %4.4x.\n",
523 dev->name, csr0);
524 /* Restart the chip. */
525 board->Lance.RDP = STRT;
529 /* Clear any other interrupt, and set interrupt enable. */
530 board->Lance.RAP = CSR0; /* PCnet-ISA Controller Status */
531 board->Lance.RDP = INEA|BABL|CERR|MISS|MERR|IDON;
533 #if 0
534 if (ariadne_debug > 4)
535 printk("%s: exiting interrupt, csr%d=%#4.4x.\n", dev->name,
536 board->Lance.RAP, board->Lance.RDP);
537 #endif
539 dev->interrupt = 0;
540 return;
544 static int ariadne_start_xmit(struct sk_buff *skb, struct net_device *dev)
546 struct ariadne_private *priv = (struct ariadne_private *)dev->priv;
547 struct AriadneBoard *board = priv->board;
548 int entry;
549 unsigned long flags;
551 /* Transmitter timeout, serious problems. */
552 if (dev->tbusy) {
553 int tickssofar = jiffies - dev->trans_start;
554 if (tickssofar < 20)
555 return(1);
556 board->Lance.RAP = CSR0; /* PCnet-ISA Controller Status */
557 printk("%s: transmit timed out, status %4.4x, resetting.\n", dev->name,
558 board->Lance.RDP);
559 board->Lance.RDP = STOP;
560 priv->stats.tx_errors++;
561 #ifndef final_version
563 int i;
564 printk(" Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d.",
565 priv->dirty_tx, priv->cur_tx, priv->tx_full ? " (full)" : "",
566 priv->cur_rx);
567 for (i = 0 ; i < RX_RING_SIZE; i++)
568 printk("%s %08x %04x %04x", i & 0x3 ? "" : "\n ",
569 (swapw((priv->rx_ring[i]->RMD1))<<16)|swapw(priv->rx_ring[i]->RMD0),
570 swapw(-priv->rx_ring[i]->RMD2), swapw(priv->rx_ring[i]->RMD3));
571 for (i = 0 ; i < TX_RING_SIZE; i++)
572 printk("%s %08x %04x %04x", i & 0x3 ? "" : "\n ",
573 (swapw((priv->tx_ring[i]->TMD1))<<16)|swapw(priv->tx_ring[i]->TMD0),
574 swapw(-priv->tx_ring[i]->TMD2), priv->tx_ring[i]->TMD3);
575 printk("\n");
577 #endif
578 ariadne_init_ring(dev);
579 board->Lance.RDP = INEA|STRT;
581 dev->tbusy = 0;
582 dev->trans_start = jiffies;
584 return(0);
587 #if 0
588 if (ariadne_debug > 3) {
589 board->Lance.RAP = CSR0; /* PCnet-ISA Controller Status */
590 printk("%s: ariadne_start_xmit() called, csr0 %4.4x.\n", dev->name,
591 board->Lance.RDP);
592 board->Lance.RDP = 0x0000;
594 #endif
596 /* Block a timer-based transmit from overlapping. This could better be
597 done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
598 if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
599 printk("%s: Transmitter access conflict.\n", dev->name);
600 return(1);
603 if (test_and_set_bit(0, (void*)&priv->lock) != 0) {
604 if (ariadne_debug > 0)
605 printk("%s: tx queue lock!.\n", dev->name);
606 /* don't clear dev->tbusy flag. */
607 return(1);
610 /* Fill in a Tx ring entry */
612 #if 0
613 printk("TX pkt type 0x%04x from ", ((u_short *)skb->data)[6]);
615 int i;
616 u_char *ptr = &((u_char *)skb->data)[6];
617 for (i = 0; i < 6; i++)
618 printk("%02x", ptr[i]);
620 printk(" to ");
622 int i;
623 u_char *ptr = (u_char *)skb->data;
624 for (i = 0; i < 6; i++)
625 printk("%02x", ptr[i]);
627 printk(" data 0x%08x len %d\n", (int)skb->data, (int)skb->len);
628 #endif
630 save_flags(flags);
631 cli();
633 entry = priv->cur_tx % TX_RING_SIZE;
635 /* Caution: the write order is important here, set the base address with
636 the "ownership" bits last. */
638 priv->tx_ring[entry]->TMD2 = swapw((u_short)-skb->len);
639 priv->tx_ring[entry]->TMD3 = 0x0000;
640 memcpyw(priv->tx_buff[entry], (u_short *)skb->data, skb->len);
642 #if 0
644 int i, len;
646 len = skb->len > 64 ? 64 : skb->len;
647 len >>= 1;
648 for (i = 0; i < len; i += 8) {
649 int j;
650 printk("%04x:", i);
651 for (j = 0; (j < 8) && ((i+j) < len); j++) {
652 if (!(j & 1))
653 printk(" ");
654 printk("%04x", priv->tx_buff[entry][i+j]);
656 printk("\n");
659 #endif
661 priv->tx_ring[entry]->TMD1 = (priv->tx_ring[entry]->TMD1&0xff00)|TF_OWN|TF_STP|TF_ENP;
663 dev_kfree_skb(skb);
665 priv->cur_tx++;
666 if ((priv->cur_tx >= TX_RING_SIZE) && (priv->dirty_tx >= TX_RING_SIZE)) {
668 #if 0
669 printk("*** Subtracting TX_RING_SIZE from cur_tx (%d) and dirty_tx (%d)\n",
670 priv->cur_tx, priv->dirty_tx);
671 #endif
673 priv->cur_tx -= TX_RING_SIZE;
674 priv->dirty_tx -= TX_RING_SIZE;
677 /* Trigger an immediate send poll. */
678 board->Lance.RAP = CSR0; /* PCnet-ISA Controller Status */
679 board->Lance.RDP = INEA|TDMD;
681 dev->trans_start = jiffies;
683 priv->lock = 0;
684 if (lowb(priv->tx_ring[(entry+1) % TX_RING_SIZE]->TMD1) == 0)
685 dev->tbusy = 0;
686 else
687 priv->tx_full = 1;
688 restore_flags(flags);
690 return(0);
694 static int ariadne_rx(struct net_device *dev)
696 struct ariadne_private *priv = (struct ariadne_private *)dev->priv;
697 int entry = priv->cur_rx % RX_RING_SIZE;
698 int i;
700 /* If we own the next entry, it's a new packet. Send it up. */
701 while (!(lowb(priv->rx_ring[entry]->RMD1) & RF_OWN)) {
702 int status = lowb(priv->rx_ring[entry]->RMD1);
704 if (status != (RF_STP|RF_ENP)) { /* There was an error. */
705 /* There is a tricky error noted by John Murphy,
706 <murf@perftech.com> to Russ Nelson: Even with full-sized
707 buffers it's possible for a jabber packet to use two
708 buffers, with only the last correctly noting the error. */
709 if (status & RF_ENP)
710 /* Only count a general error at the end of a packet.*/
711 priv->stats.rx_errors++;
712 if (status & RF_FRAM)
713 priv->stats.rx_frame_errors++;
714 if (status & RF_OFLO)
715 priv->stats.rx_over_errors++;
716 if (status & RF_CRC)
717 priv->stats.rx_crc_errors++;
718 if (status & RF_BUFF)
719 priv->stats.rx_fifo_errors++;
720 priv->rx_ring[entry]->RMD1 &= 0xff00|RF_STP|RF_ENP;
721 } else {
722 /* Malloc up new buffer, compatible with net-3. */
723 short pkt_len = swapw(priv->rx_ring[entry]->RMD3);
724 struct sk_buff *skb;
726 skb = dev_alloc_skb(pkt_len+2);
727 if (skb == NULL) {
728 printk("%s: Memory squeeze, deferring packet.\n", dev->name);
729 for (i = 0; i < RX_RING_SIZE; i++)
730 if (lowb(priv->rx_ring[(entry+i) % RX_RING_SIZE]->RMD1) & RF_OWN)
731 break;
733 if (i > RX_RING_SIZE-2) {
734 priv->stats.rx_dropped++;
735 priv->rx_ring[entry]->RMD1 |= RF_OWN;
736 priv->cur_rx++;
738 break;
742 skb->dev = dev;
743 skb_reserve(skb,2); /* 16 byte align */
744 skb_put(skb,pkt_len); /* Make room */
745 eth_copy_and_sum(skb, (char *)priv->rx_buff[entry], pkt_len,0);
746 skb->protocol=eth_type_trans(skb,dev);
747 #if 0
748 printk("RX pkt type 0x%04x from ", ((u_short *)skb->data)[6]);
750 int i;
751 u_char *ptr = &((u_char *)skb->data)[6];
752 for (i = 0; i < 6; i++)
753 printk("%02x", ptr[i]);
755 printk(" to ");
757 int i;
758 u_char *ptr = (u_char *)skb->data;
759 for (i = 0; i < 6; i++)
760 printk("%02x", ptr[i]);
762 printk(" data 0x%08x len %d\n", (int)skb->data, (int)skb->len);
763 #endif
765 netif_rx(skb);
766 priv->stats.rx_packets++;
769 priv->rx_ring[entry]->RMD1 |= RF_OWN;
770 entry = (++priv->cur_rx) % RX_RING_SIZE;
773 priv->cur_rx = priv->cur_rx % RX_RING_SIZE;
775 /* We should check that at least two ring entries are free. If not,
776 we should free one and mark stats->rx_dropped++. */
778 return(0);
782 static struct net_device_stats *ariadne_get_stats(struct net_device *dev)
784 struct ariadne_private *priv = (struct ariadne_private *)dev->priv;
785 struct AriadneBoard *board = priv->board;
786 short saved_addr;
787 unsigned long flags;
789 save_flags(flags);
790 cli();
791 saved_addr = board->Lance.RAP;
792 board->Lance.RAP = CSR112; /* Missed Frame Count */
793 priv->stats.rx_missed_errors = swapw(board->Lance.RDP);
794 board->Lance.RAP = saved_addr;
795 restore_flags(flags);
797 return(&priv->stats);
801 /* Set or clear the multicast filter for this adaptor.
802 num_addrs == -1 Promiscuous mode, receive all packets
803 num_addrs == 0 Normal mode, clear multicast list
804 num_addrs > 0 Multicast mode, receive normal and MC packets, and do
805 best-effort filtering.
807 static void set_multicast_list(struct net_device *dev)
809 struct ariadne_private *priv = (struct ariadne_private *)dev->priv;
810 struct AriadneBoard *board = priv->board;
812 /* We take the simple way out and always enable promiscuous mode. */
813 board->Lance.RAP = CSR0; /* PCnet-ISA Controller Status */
814 board->Lance.RDP = STOP; /* Temporarily stop the lance. */
816 if (dev->flags & IFF_PROMISC) {
817 /* Log any net taps. */
818 printk("%s: Promiscuous mode enabled.\n", dev->name);
819 board->Lance.RAP = CSR15; /* Mode Register */
820 board->Lance.RDP = PROM; /* Set promiscuous mode */
821 } else {
822 short multicast_table[4];
823 int num_addrs = dev->mc_count;
824 int i;
825 /* We don't use the multicast table, but rely on upper-layer filtering. */
826 memset(multicast_table, (num_addrs == 0) ? 0 : -1,
827 sizeof(multicast_table));
828 for (i = 0; i < 4; i++) {
829 board->Lance.RAP = CSR8+(i<<8); /* Logical Address Filter */
830 board->Lance.RDP = swapw(multicast_table[i]);
832 board->Lance.RAP = CSR15; /* Mode Register */
833 board->Lance.RDP = 0x0000; /* Unset promiscuous mode */
836 board->Lance.RAP = CSR0; /* PCnet-ISA Controller Status */
837 board->Lance.RDP = INEA|STRT|IDON; /* Resume normal operation. */
841 #ifdef MODULE
842 static char devicename[9] = { 0, };
844 static struct net_device ariadne_dev =
846 devicename, /* filled in by register_netdev() */
847 0, 0, 0, 0, /* memory */
848 0, 0, /* base, irq */
849 0, 0, 0, NULL, ariadne_probe,
852 int init_module(void)
854 int err;
856 if ((err = register_netdev(&ariadne_dev))) {
857 if (err == -EIO)
858 printk("No Ariadne board found. Module not loaded.\n");
859 return(err);
861 return(0);
864 void cleanup_module(void)
866 struct ariadne_private *priv = (struct ariadne_private *)ariadne_dev.priv;
868 unregister_netdev(&ariadne_dev);
869 zorro_unconfig_board(priv->key, 0);
870 kfree(priv);
873 #endif /* MODULE */