Ok. I didn't make 2.4.0 in 2000. Tough. I tried, but we had some
[davej-history.git] / drivers / net / ariadne.c
blobaf06e74f642b5b702dac96d750e59d43e9e06906
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 volatilestruct TDRE *tx_ring[TX_RING_SIZE];
100 volatilestruct RDRE *rx_ring[RX_RING_SIZE];
101 volatile u_short *tx_buff[TX_RING_SIZE];
102 volatile u_short *rx_buff[RX_RING_SIZE];
103 int cur_tx, cur_rx;/* The next free ring entry */
104 int dirty_tx;/* The ring entries to be free()ed. */
105 struct net_device_stats stats;
106 char tx_full;
107 struct net_device *dev;/* Backpointer */
108 struct ariadne_private *next_module;
113 * Structure Created in the Ariadne's RAM Buffer
116 struct lancedata {
117 struct TDRE tx_ring[TX_RING_SIZE];
118 struct RDRE rx_ring[RX_RING_SIZE];
119 u_short tx_buff[TX_RING_SIZE][PKT_BUF_SIZE/sizeof(u_short)];
120 u_short rx_buff[RX_RING_SIZE][PKT_BUF_SIZE/sizeof(u_short)];
123 #ifdef MODULE
124 static struct ariadne_private *root_ariadne_dev = NULL;
125 #endif
127 static intariadne_open(struct net_device *dev);
128 static voidariadne_init_ring(struct net_device *dev);
129 static intariadne_start_xmit(struct sk_buff *skb,struct net_device *dev);
130 static voidariadne_tx_timeout(struct net_device *dev);
131 static intariadne_rx(struct net_device *dev);
132 static voidariadne_reset(struct net_device *dev);
133 static voidariadne_interrupt(int irq,void*data,struct pt_regs *fp);
134 static intariadne_close(struct net_device *dev);
135 static struct net_device_stats *ariadne_get_stats(struct net_device *dev);
136 #ifdef HAVE_MULTICAST
137 static voidset_multicast_list(struct net_device *dev);
138 #endif
141 static voidmemcpyw(volatile u_short *dest, u_short *src,int len)
143 while(len >=2) {
144 *(dest++) = *(src++);
145 len -=2;
147 if(len ==1)
148 *dest = (*(u_char *)src)<<8;
152 static int __init ariadne_probe(void)
154 struct zorro_dev *z = NULL;
155 struct net_device *dev;
156 struct ariadne_private *priv;
157 int res = -ENODEV;
159 while((z =zorro_find_device(ZORRO_PROD_VILLAGE_TRONIC_ARIADNE, z))) {
160 unsigned long board = z->resource.start;
161 unsigned long base_addr = board+ARIADNE_LANCE;
162 unsigned long mem_start = board+ARIADNE_RAM;
164 if(!request_mem_region(base_addr,sizeof(struct Am79C960),
165 "Am79C960"))
166 continue;
167 if(!request_mem_region(mem_start, ARIADNE_RAM_SIZE,"RAM")) {
168 release_mem_region(base_addr,sizeof(struct Am79C960));
169 continue;
172 dev =init_etherdev(NULL,sizeof(struct ariadne_private));
174 if(dev == NULL) {
175 release_mem_region(base_addr,sizeof(struct Am79C960));
176 release_mem_region(mem_start, ARIADNE_RAM_SIZE);
177 return-ENOMEM;
179 priv = (struct ariadne_private *)dev->priv;
180 memset(priv,0,sizeof(struct ariadne_private));
182 priv->dev = dev;
183 dev->dev_addr[0] =0x00;
184 dev->dev_addr[1] =0x60;
185 dev->dev_addr[2] =0x30;
186 dev->dev_addr[3] = (z->rom.er_SerialNumber>>16) &0xff;
187 dev->dev_addr[4] = (z->rom.er_SerialNumber>>8) &0xff;
188 dev->dev_addr[5] = z->rom.er_SerialNumber &0xff;
189 printk("%s: Ariadne at 0x%08lx, Ethernet Address "
190 "%02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, board,
191 dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
192 dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
194 dev->base_addr =ZTWO_VADDR(base_addr);
195 dev->mem_start =ZTWO_VADDR(mem_start);
196 dev->mem_end = dev->mem_start+ARIADNE_RAM_SIZE;
198 dev->open = &ariadne_open;
199 dev->stop = &ariadne_close;
200 dev->hard_start_xmit = &ariadne_start_xmit;
201 dev->tx_timeout = &ariadne_tx_timeout;
202 dev->watchdog_timeo =5*HZ;
203 dev->get_stats = &ariadne_get_stats;
204 dev->set_multicast_list = &set_multicast_list;
206 #ifdef MODULE
207 priv->next_module = root_ariadne_dev;
208 root_ariadne_dev = priv;
209 #endif
210 res =0;
212 return res;
216 static intariadne_open(struct net_device *dev)
218 volatilestruct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
219 u_short in;
220 u_long version;
222 /* Reset the LANCE */
223 in = lance->Reset;
225 /* Stop the LANCE */
226 lance->RAP = CSR0;/* PCnet-ISA Controller Status */
227 lance->RDP = STOP;
229 /* Check the LANCE version */
230 lance->RAP = CSR88;/* Chip ID */
231 version =swapw(lance->RDP);
232 lance->RAP = CSR89;/* Chip ID */
233 version |=swapw(lance->RDP)<<16;
234 if((version &0x00000fff) !=0x00000003) {
235 printk("ariadne_open: Couldn't find AMD Ethernet Chip\n");
236 return-EAGAIN;
238 if((version &0x0ffff000) !=0x00003000) {
239 printk("ariadne_open: Couldn't find Am79C960 (Wrong part number = %ld)\n",
240 (version &0x0ffff000)>>12);
241 return-EAGAIN;
243 #if 0
244 printk("ariadne_open: Am79C960 (PCnet-ISA) Revision %ld\n",
245 (version &0xf0000000)>>28);
246 #endif
248 ariadne_init_ring(dev);
250 /* Miscellaneous Stuff */
251 lance->RAP = CSR3;/* Interrupt Masks and Deferral Control */
252 lance->RDP =0x0000;
253 lance->RAP = CSR4;/* Test and Features Control */
254 lance->RDP = DPOLL|APAD_XMT|MFCOM|RCVCCOM|TXSTRTM|JABM;
256 /* Set the Multicast Table */
257 lance->RAP = CSR8;/* Logical Address Filter, LADRF[15:0] */
258 lance->RDP =0x0000;
259 lance->RAP = CSR9;/* Logical Address Filter, LADRF[31:16] */
260 lance->RDP =0x0000;
261 lance->RAP = CSR10;/* Logical Address Filter, LADRF[47:32] */
262 lance->RDP =0x0000;
263 lance->RAP = CSR11;/* Logical Address Filter, LADRF[63:48] */
264 lance->RDP =0x0000;
266 /* Set the Ethernet Hardware Address */
267 lance->RAP = CSR12;/* Physical Address Register, PADR[15:0] */
268 lance->RDP = ((u_short *)&dev->dev_addr[0])[0];
269 lance->RAP = CSR13;/* Physical Address Register, PADR[31:16] */
270 lance->RDP = ((u_short *)&dev->dev_addr[0])[1];
271 lance->RAP = CSR14;/* Physical Address Register, PADR[47:32] */
272 lance->RDP = ((u_short *)&dev->dev_addr[0])[2];
274 /* Set the Init Block Mode */
275 lance->RAP = CSR15;/* Mode Register */
276 lance->RDP =0x0000;
278 /* Set the Transmit Descriptor Ring Pointer */
279 lance->RAP = CSR30;/* Base Address of Transmit Ring */
280 lance->RDP =swloww(ARIADNE_RAM+offsetof(struct lancedata, tx_ring));
281 lance->RAP = CSR31;/* Base Address of transmit Ring */
282 lance->RDP =swhighw(ARIADNE_RAM+offsetof(struct lancedata, tx_ring));
284 /* Set the Receive Descriptor Ring Pointer */
285 lance->RAP = CSR24;/* Base Address of Receive Ring */
286 lance->RDP =swloww(ARIADNE_RAM+offsetof(struct lancedata, rx_ring));
287 lance->RAP = CSR25;/* Base Address of Receive Ring */
288 lance->RDP =swhighw(ARIADNE_RAM+offsetof(struct lancedata, rx_ring));
290 /* Set the Number of RX and TX Ring Entries */
291 lance->RAP = CSR76;/* Receive Ring Length */
292 lance->RDP =swapw(((u_short)-RX_RING_SIZE));
293 lance->RAP = CSR78;/* Transmit Ring Length */
294 lance->RDP =swapw(((u_short)-TX_RING_SIZE));
296 /* Enable Media Interface Port Auto Select (10BASE-2/10BASE-T) */
297 lance->RAP = ISACSR2;/* Miscellaneous Configuration */
298 lance->IDP = ASEL;
300 /* LED Control */
301 lance->RAP = ISACSR5;/* LED1 Status */
302 lance->IDP = PSE|XMTE;
303 lance->RAP = ISACSR6;/* LED2 Status */
304 lance->IDP = PSE|COLE;
305 lance->RAP = ISACSR7;/* LED3 Status */
306 lance->IDP = PSE|RCVE;
308 netif_start_queue(dev);
310 if(request_irq(IRQ_AMIGA_PORTS, ariadne_interrupt, SA_SHIRQ,
311 "Ariadne Ethernet", dev))
312 return-EAGAIN;
314 lance->RAP = CSR0;/* PCnet-ISA Controller Status */
315 lance->RDP = INEA|STRT;
317 MOD_INC_USE_COUNT;
319 return0;
323 static voidariadne_init_ring(struct net_device *dev)
325 struct ariadne_private *priv = (struct ariadne_private *)dev->priv;
326 volatilestruct lancedata *lancedata = (struct lancedata *)dev->mem_start;
327 int i;
329 netif_stop_queue(dev);
331 priv->tx_full =0;
332 priv->cur_rx = priv->cur_tx =0;
333 priv->dirty_tx =0;
335 /* Set up TX Ring */
336 for(i =0; i < TX_RING_SIZE; i++) {
337 volatilestruct TDRE *t = &lancedata->tx_ring[i];
338 t->TMD0 =swloww(ARIADNE_RAM+offsetof(struct lancedata, tx_buff[i]));
339 t->TMD1 =swhighw(ARIADNE_RAM+offsetof(struct lancedata, tx_buff[i])) |
340 TF_STP | TF_ENP;
341 t->TMD2 =swapw((u_short)-PKT_BUF_SIZE);
342 t->TMD3 =0;
343 priv->tx_ring[i] = &lancedata->tx_ring[i];
344 priv->tx_buff[i] = lancedata->tx_buff[i];
345 #if 0
346 printk("TX Entry %2d at %p, Buf at %p\n", i, &lancedata->tx_ring[i],
347 lancedata->tx_buff[i]);
348 #endif
351 /* Set up RX Ring */
352 for(i =0; i < RX_RING_SIZE; i++) {
353 volatilestruct RDRE *r = &lancedata->rx_ring[i];
354 r->RMD0 =swloww(ARIADNE_RAM+offsetof(struct lancedata, rx_buff[i]));
355 r->RMD1 =swhighw(ARIADNE_RAM+offsetof(struct lancedata, rx_buff[i])) |
356 RF_OWN;
357 r->RMD2 =swapw((u_short)-PKT_BUF_SIZE);
358 r->RMD3 =0x0000;
359 priv->rx_ring[i] = &lancedata->rx_ring[i];
360 priv->rx_buff[i] = lancedata->rx_buff[i];
361 #if 0
362 printk("RX Entry %2d at %p, Buf at %p\n", i, &lancedata->rx_ring[i],
363 lancedata->rx_buff[i]);
364 #endif
369 static intariadne_close(struct net_device *dev)
371 struct ariadne_private *priv = (struct ariadne_private *)dev->priv;
372 volatilestruct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
374 netif_stop_queue(dev);
376 lance->RAP = CSR112;/* Missed Frame Count */
377 priv->stats.rx_missed_errors =swapw(lance->RDP);
378 lance->RAP = CSR0;/* PCnet-ISA Controller Status */
380 if(ariadne_debug >1) {
381 printk("%s: Shutting down ethercard, status was %2.2x.\n", dev->name,
382 lance->RDP);
383 printk("%s: %lu packets missed\n", dev->name,
384 priv->stats.rx_missed_errors);
387 /* We stop the LANCE here -- it occasionally polls memory if we don't. */
388 lance->RDP = STOP;
390 free_irq(IRQ_AMIGA_PORTS, dev);
392 MOD_DEC_USE_COUNT;
394 return0;
398 staticinlinevoidariadne_reset(struct net_device *dev)
400 volatilestruct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
402 lance->RAP = CSR0;/* PCnet-ISA Controller Status */
403 lance->RDP = STOP;
404 ariadne_init_ring(dev);
405 lance->RDP = INEA|STRT;
406 netif_start_queue(dev);
410 static voidariadne_interrupt(int irq,void*data,struct pt_regs *fp)
412 struct net_device *dev = (struct net_device *)data;
413 volatilestruct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
414 struct ariadne_private *priv;
415 int csr0, boguscnt;
417 if(dev == NULL) {
418 printk("ariadne_interrupt(): irq for unknown device.\n");
419 return;
422 lance->RAP = CSR0;/* PCnet-ISA Controller Status */
424 if(!(lance->RDP & INTR))/* Check if any interrupt has been */
425 return;/* generated by the board. */
427 priv = (struct ariadne_private *)dev->priv;
429 boguscnt =10;
430 while((csr0 = lance->RDP) & (ERR|RINT|TINT) && --boguscnt >=0) {
431 /* Acknowledge all of the current interrupt sources ASAP. */
432 lance->RDP = csr0 & ~(INEA|TDMD|STOP|STRT|INIT);
434 #if 0
435 if(ariadne_debug >5) {
436 printk("%s: interrupt csr0=%#2.2x new csr=%#2.2x.", dev->name,
437 csr0, lance->RDP);
438 printk("[");
439 if(csr0 & INTR)
440 printk(" INTR");
441 if(csr0 & INEA)
442 printk(" INEA");
443 if(csr0 & RXON)
444 printk(" RXON");
445 if(csr0 & TXON)
446 printk(" TXON");
447 if(csr0 & TDMD)
448 printk(" TDMD");
449 if(csr0 & STOP)
450 printk(" STOP");
451 if(csr0 & STRT)
452 printk(" STRT");
453 if(csr0 & INIT)
454 printk(" INIT");
455 if(csr0 & ERR)
456 printk(" ERR");
457 if(csr0 & BABL)
458 printk(" BABL");
459 if(csr0 & CERR)
460 printk(" CERR");
461 if(csr0 & MISS)
462 printk(" MISS");
463 if(csr0 & MERR)
464 printk(" MERR");
465 if(csr0 & RINT)
466 printk(" RINT");
467 if(csr0 & TINT)
468 printk(" TINT");
469 if(csr0 & IDON)
470 printk(" IDON");
471 printk(" ]\n");
473 #endif
475 if(csr0 & RINT)/* Rx interrupt */
476 ariadne_rx(dev);
478 if(csr0 & TINT) {/* Tx-done interrupt */
479 int dirty_tx = priv->dirty_tx;
481 while(dirty_tx < priv->cur_tx) {
482 int entry = dirty_tx % TX_RING_SIZE;
483 int status =lowb(priv->tx_ring[entry]->TMD1);
485 if(status & TF_OWN)
486 break;/* It still hasn't been Txed */
488 priv->tx_ring[entry]->TMD1 &=0xff00;
490 if(status & TF_ERR) {
491 /* There was an major error, log it. */
492 int err_status = priv->tx_ring[entry]->TMD3;
493 priv->stats.tx_errors++;
494 if(err_status & EF_RTRY)
495 priv->stats.tx_aborted_errors++;
496 if(err_status & EF_LCAR)
497 priv->stats.tx_carrier_errors++;
498 if(err_status & EF_LCOL)
499 priv->stats.tx_window_errors++;
500 if(err_status & EF_UFLO) {
501 /* Ackk! On FIFO errors the Tx unit is turned off! */
502 priv->stats.tx_fifo_errors++;
503 /* Remove this verbosity later! */
504 printk("%s: Tx FIFO error! Status %4.4x.\n", dev->name,
505 csr0);
506 /* Restart the chip. */
507 lance->RDP = STRT;
509 }else{
510 if(status & (TF_MORE|TF_ONE))
511 priv->stats.collisions++;
512 priv->stats.tx_packets++;
514 dirty_tx++;
517 #ifndef final_version
518 if(priv->cur_tx - dirty_tx >= TX_RING_SIZE) {
519 printk("out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
520 dirty_tx, priv->cur_tx, priv->tx_full);
521 dirty_tx += TX_RING_SIZE;
523 #endif
525 if(priv->tx_full &&netif_queue_stopped(dev) &&
526 dirty_tx > priv->cur_tx - TX_RING_SIZE +2) {
527 /* The ring is no longer full. */
528 priv->tx_full =0;
529 netif_wake_queue(dev);
532 priv->dirty_tx = dirty_tx;
535 /* Log misc errors. */
536 if(csr0 & BABL)
537 priv->stats.tx_errors++;/* Tx babble. */
538 if(csr0 & MISS)
539 priv->stats.rx_errors++;/* Missed a Rx frame. */
540 if(csr0 & MERR) {
541 printk("%s: Bus master arbitration failure, status %4.4x.\n",
542 dev->name, csr0);
543 /* Restart the chip. */
544 lance->RDP = STRT;
548 /* Clear any other interrupt, and set interrupt enable. */
549 lance->RAP = CSR0;/* PCnet-ISA Controller Status */
550 lance->RDP = INEA|BABL|CERR|MISS|MERR|IDON;
552 #if 0
553 if(ariadne_debug >4)
554 printk("%s: exiting interrupt, csr%d=%#4.4x.\n", dev->name, lance->RAP,
555 lance->RDP);
556 #endif
557 return;
561 static voidariadne_tx_timeout(struct net_device *dev)
563 volatilestruct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
565 printk(KERN_ERR "%s: transmit timed out, status %4.4x, resetting.\n",
566 dev->name, lance->RDP);
567 ariadne_reset(dev);
568 netif_wake_queue(dev);
572 static intariadne_start_xmit(struct sk_buff *skb,struct net_device *dev)
574 struct ariadne_private *priv = (struct ariadne_private *)dev->priv;
575 volatilestruct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
576 int entry;
577 unsigned long flags;
579 #if 0
580 if(ariadne_debug >3) {
581 lance->RAP = CSR0;/* PCnet-ISA Controller Status */
582 printk("%s: ariadne_start_xmit() called, csr0 %4.4x.\n", dev->name,
583 lance->RDP);
584 lance->RDP =0x0000;
586 #endif
588 /* Fill in a Tx ring entry */
590 #if 0
591 printk("TX pkt type 0x%04x from ", ((u_short *)skb->data)[6]);
593 int i;
594 u_char *ptr = &((u_char *)skb->data)[6];
595 for(i =0; i <6; i++)
596 printk("%02x", ptr[i]);
598 printk(" to ");
600 int i;
601 u_char *ptr = (u_char *)skb->data;
602 for(i =0; i <6; i++)
603 printk("%02x", ptr[i]);
605 printk(" data 0x%08x len %d\n", (int)skb->data, (int)skb->len);
606 #endif
608 save_flags(flags);
609 cli();
611 entry = priv->cur_tx % TX_RING_SIZE;
613 /* Caution: the write order is important here, set the base address with
614 the "ownership" bits last. */
616 priv->tx_ring[entry]->TMD2 =swapw((u_short)-skb->len);
617 priv->tx_ring[entry]->TMD3 =0x0000;
618 memcpyw(priv->tx_buff[entry], (u_short *)skb->data,
619 skb->len <= ETH_ZLEN ? ETH_ZLEN : skb->len);
621 #if 0
623 int i, len;
625 len = skb->len >64?64: skb->len;
626 len >>=1;
627 for(i =0; i < len; i +=8) {
628 int j;
629 printk("%04x:", i);
630 for(j =0; (j <8) && ((i+j) < len); j++) {
631 if(!(j &1))
632 printk(" ");
633 printk("%04x", priv->tx_buff[entry][i+j]);
635 printk("\n");
638 #endif
640 priv->tx_ring[entry]->TMD1 = (priv->tx_ring[entry]->TMD1&0xff00)|TF_OWN|TF_STP|TF_ENP;
642 dev_kfree_skb(skb);
644 priv->cur_tx++;
645 if((priv->cur_tx >= TX_RING_SIZE) && (priv->dirty_tx >= TX_RING_SIZE)) {
647 #if 0
648 printk("*** Subtracting TX_RING_SIZE from cur_tx (%d) and dirty_tx (%d)\n",
649 priv->cur_tx, priv->dirty_tx);
650 #endif
652 priv->cur_tx -= TX_RING_SIZE;
653 priv->dirty_tx -= TX_RING_SIZE;
656 /* Trigger an immediate send poll. */
657 lance->RAP = CSR0;/* PCnet-ISA Controller Status */
658 lance->RDP = INEA|TDMD;
660 dev->trans_start = jiffies;
662 if(lowb(priv->tx_ring[(entry+1) % TX_RING_SIZE]->TMD1) !=0) {
663 netif_stop_queue(dev);
664 priv->tx_full =1;
666 restore_flags(flags);
668 return0;
672 static intariadne_rx(struct net_device *dev)
674 struct ariadne_private *priv = (struct ariadne_private *)dev->priv;
675 int entry = priv->cur_rx % RX_RING_SIZE;
676 int i;
678 /* If we own the next entry, it's a new packet. Send it up. */
679 while(!(lowb(priv->rx_ring[entry]->RMD1) & RF_OWN)) {
680 int status =lowb(priv->rx_ring[entry]->RMD1);
682 if(status != (RF_STP|RF_ENP)) {/* There was an error. */
683 /* There is a tricky error noted by John Murphy,
684 <murf@perftech.com> to Russ Nelson: Even with full-sized
685 buffers it's possible for a jabber packet to use two
686 buffers, with only the last correctly noting the error. */
687 if(status & RF_ENP)
688 /* Only count a general error at the end of a packet.*/
689 priv->stats.rx_errors++;
690 if(status & RF_FRAM)
691 priv->stats.rx_frame_errors++;
692 if(status & RF_OFLO)
693 priv->stats.rx_over_errors++;
694 if(status & RF_CRC)
695 priv->stats.rx_crc_errors++;
696 if(status & RF_BUFF)
697 priv->stats.rx_fifo_errors++;
698 priv->rx_ring[entry]->RMD1 &=0xff00|RF_STP|RF_ENP;
699 }else{
700 /* Malloc up new buffer, compatible with net-3. */
701 short pkt_len =swapw(priv->rx_ring[entry]->RMD3);
702 struct sk_buff *skb;
704 skb =dev_alloc_skb(pkt_len+2);
705 if(skb == NULL) {
706 printk("%s: Memory squeeze, deferring packet.\n", dev->name);
707 for(i =0; i < RX_RING_SIZE; i++)
708 if(lowb(priv->rx_ring[(entry+i) % RX_RING_SIZE]->RMD1) & RF_OWN)
709 break;
711 if(i > RX_RING_SIZE-2) {
712 priv->stats.rx_dropped++;
713 priv->rx_ring[entry]->RMD1 |= RF_OWN;
714 priv->cur_rx++;
716 break;
720 skb->dev = dev;
721 skb_reserve(skb,2);/* 16 byte align */
722 skb_put(skb,pkt_len);/* Make room */
723 eth_copy_and_sum(skb, (char*)priv->rx_buff[entry], pkt_len,0);
724 skb->protocol=eth_type_trans(skb,dev);
725 #if 0
726 printk("RX pkt type 0x%04x from ", ((u_short *)skb->data)[6]);
728 int i;
729 u_char *ptr = &((u_char *)skb->data)[6];
730 for(i =0; i <6; i++)
731 printk("%02x", ptr[i]);
733 printk(" to ");
735 int i;
736 u_char *ptr = (u_char *)skb->data;
737 for(i =0; i <6; i++)
738 printk("%02x", ptr[i]);
740 printk(" data 0x%08x len %d\n", (int)skb->data, (int)skb->len);
741 #endif
743 netif_rx(skb);
744 priv->stats.rx_packets++;
747 priv->rx_ring[entry]->RMD1 |= RF_OWN;
748 entry = (++priv->cur_rx) % RX_RING_SIZE;
751 priv->cur_rx = priv->cur_rx % RX_RING_SIZE;
753 /* We should check that at least two ring entries are free. If not,
754 we should free one and mark stats->rx_dropped++. */
756 return0;
760 static struct net_device_stats *ariadne_get_stats(struct net_device *dev)
762 struct ariadne_private *priv = (struct ariadne_private *)dev->priv;
763 volatilestruct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
764 short saved_addr;
765 unsigned long flags;
767 save_flags(flags);
768 cli();
769 saved_addr = lance->RAP;
770 lance->RAP = CSR112;/* Missed Frame Count */
771 priv->stats.rx_missed_errors =swapw(lance->RDP);
772 lance->RAP = saved_addr;
773 restore_flags(flags);
775 return&priv->stats;
779 /* Set or clear the multicast filter for this adaptor.
780 num_addrs == -1 Promiscuous mode, receive all packets
781 num_addrs == 0 Normal mode, clear multicast list
782 num_addrs > 0 Multicast mode, receive normal and MC packets, and do
783 best-effort filtering.
785 static voidset_multicast_list(struct net_device *dev)
787 volatilestruct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
789 if(!netif_running(dev))
790 return;
792 netif_stop_queue(dev);
794 /* We take the simple way out and always enable promiscuous mode. */
795 lance->RAP = CSR0;/* PCnet-ISA Controller Status */
796 lance->RDP = STOP;/* Temporarily stop the lance. */
797 ariadne_init_ring(dev);
799 if(dev->flags & IFF_PROMISC) {
800 /* Log any net taps. */
801 printk("%s: Promiscuous mode enabled.\n", dev->name);
802 lance->RAP = CSR15;/* Mode Register */
803 lance->RDP = PROM;/* Set promiscuous mode */
804 }else{
805 short multicast_table[4];
806 int num_addrs = dev->mc_count;
807 int i;
808 /* We don't use the multicast table, but rely on upper-layer filtering. */
809 memset(multicast_table, (num_addrs ==0) ?0: -1,
810 sizeof(multicast_table));
811 for(i =0; i <4; i++) {
812 lance->RAP = CSR8+(i<<8);/* Logical Address Filter */
813 lance->RDP =swapw(multicast_table[i]);
815 lance->RAP = CSR15;/* Mode Register */
816 lance->RDP =0x0000;/* Unset promiscuous mode */
819 lance->RAP = CSR0;/* PCnet-ISA Controller Status */
820 lance->RDP = INEA|STRT|IDON;/* Resume normal operation. */
822 netif_wake_queue(dev);
826 static void __exit ariadne_cleanup(void)
828 #ifdef MODULE
829 struct ariadne_private *next;
830 struct net_device *dev;
832 while(root_ariadne_dev) {
833 next = root_ariadne_dev->next_module;
834 dev = root_ariadne_dev->dev;
835 unregister_netdev(dev);
836 release_mem_region(ZTWO_PADDR(dev->base_addr),sizeof(struct Am79C960));
837 release_mem_region(ZTWO_PADDR(dev->mem_start), ARIADNE_RAM_SIZE);
838 kfree(dev);
839 root_ariadne_dev = next;
841 #endif
844 module_init(ariadne_probe);
845 module_exit(ariadne_cleanup);
close