Merge with 2.3.99-pre9.
[linux-2.6/linux-mips.git] / drivers / net / am79c961a.c
blob83012de44910e67cea8da76c934240462b75c9ed
1 /*
2 * linux/drivers/net/am79c961.c
4 * Derived from various things including skeleton.c
6 * Russell King 1995-2000.
8 * This is a special driver for the am79c961A Lance chip used in the
9 * Intel (formally Digital Equipment Corp) EBSA110 platform.
11 #include <linux/module.h>
12 #include <linux/kernel.h>
13 #include <linux/sched.h>
14 #include <linux/types.h>
15 #include <linux/fcntl.h>
16 #include <linux/interrupt.h>
17 #include <linux/ptrace.h>
18 #include <linux/ioport.h>
19 #include <linux/in.h>
20 #include <linux/malloc.h>
21 #include <linux/string.h>
22 #include <linux/errno.h>
23 #include <linux/netdevice.h>
24 #include <linux/etherdevice.h>
25 #include <linux/skbuff.h>
26 #include <linux/delay.h>
27 #include <linux/init.h>
29 #include <asm/system.h>
30 #include <asm/bitops.h>
31 #include <asm/irq.h>
32 #include <asm/io.h>
33 #include <asm/dma.h>
34 #include <asm/ecard.h>
36 #define TX_BUFFERS 15
37 #define RX_BUFFERS 25
39 #include "am79c961a.h"
41 static void am79c961_interrupt (int irq, void *dev_id, struct pt_regs *regs);
42 static void am79c961_rx (struct net_device *dev, struct dev_priv *priv);
43 static void am79c961_tx (struct net_device *dev, struct dev_priv *priv);
45 static unsigned int net_debug = NET_DEBUG;
47 static char *version = "am79c961 ethernet driver (c) 1995 R.M.King v0.02\n";
49 /* --------------------------------------------------------------------------- */
51 #ifdef __arm__
52 static void
53 write_rreg (unsigned long base, unsigned int reg, unsigned short val)
55 __asm__("str%?h %1, [%2] @ NET_RAP
56 str%?h %0, [%2, #-4] @ NET_RDP
57 " : : "r" (val), "r" (reg), "r" (0xf0000464));
60 static inline void
61 write_ireg (unsigned long base, unsigned int reg, unsigned short val)
63 __asm__("str%?h %1, [%2] @ NET_RAP
64 str%?h %0, [%2, #8] @ NET_RDP
65 " : : "r" (val), "r" (reg), "r" (0xf0000464));
68 #define am_writeword(dev,off,val)\
69 __asm__("str%?h %0, [%1]" : : \
70 "r" ((val) & 0xffff), "r" (0xe0000000 + ((off) << 1)));
72 static inline void
73 am_writebuffer(struct net_device *dev, unsigned int offset, unsigned char *buf, unsigned int length)
75 offset = 0xe0000000 + (offset << 1);
76 length = (length + 1) & ~1;
77 if ((int)buf & 2) {
78 __asm__ __volatile__("str%?h %2, [%0], #4"
79 : "=&r" (offset) : "0" (offset), "r" (buf[0] | (buf[1] << 8)));
80 buf += 2;
81 length -= 2;
83 while (length > 8) {
84 unsigned int tmp, tmp2;
85 __asm__ __volatile__("
86 ldm%?ia %1!, {%2, %3}
87 str%?h %2, [%0], #4
88 mov%? %2, %2, lsr #16
89 str%?h %2, [%0], #4
90 str%?h %3, [%0], #4
91 mov%? %3, %3, lsr #16
92 str%?h %3, [%0], #4
93 " : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2)
94 : "0" (offset), "1" (buf));
95 length -= 8;
97 while (length > 0) {
98 __asm__ __volatile__("str%?h %2, [%0], #4"
99 : "=&r" (offset) : "0" (offset), "r" (buf[0] | (buf[1] << 8)));
100 buf += 2;
101 length -= 2;
105 static inline unsigned short
106 read_rreg (unsigned int base_addr, unsigned int reg)
108 unsigned short v;
109 __asm__("str%?h %1, [%2] @ NET_RAP
110 ldr%?h %0, [%2, #-4] @ NET_IDP
111 " : "=r" (v): "r" (reg), "r" (0xf0000464));
112 return v;
115 static inline unsigned short
116 am_readword (struct net_device *dev, unsigned long off)
118 unsigned long address = 0xe0000000 + (off << 1);
119 unsigned short val;
121 __asm__("ldr%?h %0, [%1]" : "=r" (val): "r" (address));
122 return val;
125 static inline void
126 am_readbuffer(struct net_device *dev, unsigned int offset, unsigned char *buf, unsigned int length)
128 offset = 0xe0000000 + (offset << 1);
129 length = (length + 1) & ~1;
130 if ((int)buf & 2) {
131 unsigned int tmp;
132 __asm__ __volatile__("
133 ldr%?h %2, [%0], #4
134 str%?b %2, [%1], #1
135 mov%? %2, %2, lsr #8
136 str%?b %2, [%1], #1
137 " : "=&r" (offset), "=&r" (buf), "=r" (tmp): "0" (offset), "1" (buf));
138 length -= 2;
140 while (length > 8) {
141 unsigned int tmp, tmp2, tmp3;
142 __asm__ __volatile__("
143 ldr%?h %2, [%0], #4
144 ldr%?h %3, [%0], #4
145 orr%? %2, %2, %3, lsl #16
146 ldr%?h %3, [%0], #4
147 ldr%?h %4, [%0], #4
148 orr%? %3, %3, %4, lsl #16
149 stm%?ia %1!, {%2, %3}
150 " : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2), "=r" (tmp3)
151 : "0" (offset), "1" (buf));
152 length -= 8;
154 while (length > 0) {
155 unsigned int tmp;
156 __asm__ __volatile__("
157 ldr%?h %2, [%0], #4
158 str%?b %2, [%1], #1
159 mov%? %2, %2, lsr #8
160 str%?b %2, [%1], #1
161 " : "=&r" (offset), "=&r" (buf), "=r" (tmp) : "0" (offset), "1" (buf));
162 length -= 2;
165 #else
166 #error Not compatable
167 #endif
169 static int
170 am79c961_ramtest(struct net_device *dev, unsigned int val)
172 unsigned char *buffer = kmalloc (65536, GFP_KERNEL);
173 int i, error = 0, errorcount = 0;
175 if (!buffer)
176 return 0;
177 memset (buffer, val, 65536);
178 am_writebuffer(dev, 0, buffer, 65536);
179 memset (buffer, val ^ 255, 65536);
180 am_readbuffer(dev, 0, buffer, 65536);
181 for (i = 0; i < 65536; i++) {
182 if (buffer[i] != val && !error) {
183 printk ("%s: buffer error (%02X %02X) %05X - ", dev->name, val, buffer[i], i);
184 error = 1;
185 errorcount ++;
186 } else if (error && buffer[i] == val) {
187 printk ("%05X\n", i);
188 error = 0;
191 if (error)
192 printk ("10000\n");
193 kfree (buffer);
194 return errorcount;
197 static void
198 am79c961_init_for_open(struct net_device *dev)
200 struct dev_priv *priv = (struct dev_priv *)dev->priv;
201 unsigned long hdr_addr, first_free_addr;
202 unsigned long flags;
203 unsigned char *p;
204 int i;
206 save_flags_cli (flags);
208 write_ireg (dev->base_addr, 2, 0x4000); /* autoselect media */
209 write_rreg (dev->base_addr, CSR0, CSR0_BABL|CSR0_CERR|CSR0_MISS|CSR0_MERR|CSR0_TINT|CSR0_RINT|CSR0_STOP);
211 restore_flags (flags);
213 first_free_addr = RX_BUFFERS * 8 + TX_BUFFERS * 8 + 16;
214 hdr_addr = 0;
216 priv->rxhead = 0;
217 priv->rxtail = 0;
218 priv->rxhdr = hdr_addr;
220 for (i = 0; i < RX_BUFFERS; i++) {
221 priv->rxbuffer[i] = first_free_addr;
222 am_writeword (dev, hdr_addr, first_free_addr);
223 am_writeword (dev, hdr_addr + 2, RMD_OWN);
224 am_writeword (dev, hdr_addr + 4, (-1600));
225 am_writeword (dev, hdr_addr + 6, 0);
226 first_free_addr += 1600;
227 hdr_addr += 8;
229 priv->txhead = 0;
230 priv->txtail = 0;
231 priv->txhdr = hdr_addr;
232 for (i = 0; i < TX_BUFFERS; i++) {
233 priv->txbuffer[i] = first_free_addr;
234 am_writeword (dev, hdr_addr, first_free_addr);
235 am_writeword (dev, hdr_addr + 2, 0);
236 am_writeword (dev, hdr_addr + 4, 0);
237 am_writeword (dev, hdr_addr + 6, 0);
238 first_free_addr += 1600;
239 hdr_addr += 8;
242 for (i = LADRL; i <= LADRH; i++)
243 write_rreg (dev->base_addr, i, 0);
245 for (i = PADRL, p = dev->dev_addr; i <= PADRH; i++, p += 2)
246 write_rreg (dev->base_addr, i, p[0] | (p[1] << 8));
248 i = MODE_PORT0;
249 if (dev->flags & IFF_PROMISC)
250 i |= MODE_PROMISC;
252 write_rreg (dev->base_addr, MODE, i);
253 write_rreg (dev->base_addr, BASERXL, priv->rxhdr);
254 write_rreg (dev->base_addr, BASERXH, 0);
255 write_rreg (dev->base_addr, BASETXL, priv->txhdr);
256 write_rreg (dev->base_addr, BASERXH, 0);
257 write_rreg (dev->base_addr, POLLINT, 0);
258 write_rreg (dev->base_addr, SIZERXR, -RX_BUFFERS);
259 write_rreg (dev->base_addr, SIZETXR, -TX_BUFFERS);
260 write_rreg (dev->base_addr, CSR0, CSR0_STOP);
261 write_rreg (dev->base_addr, CSR3, CSR3_IDONM|CSR3_BABLM|CSR3_DXSUFLO);
262 write_rreg (dev->base_addr, CSR0, CSR0_IENA|CSR0_STRT);
266 * Open/initialize the board. This is called (in the current kernel)
267 * sometime after booting when the 'ifconfig' program is run.
269 * This routine should set everything up anew at each open, even
270 * registers that "should" only need to be set once at boot, so that
271 * there is non-reboot way to recover if something goes wrong.
273 static int
274 am79c961_open(struct net_device *dev)
276 struct dev_priv *priv = (struct dev_priv *)dev->priv;
278 MOD_INC_USE_COUNT;
280 memset (&priv->stats, 0, sizeof (priv->stats));
282 if (request_irq(dev->irq, am79c961_interrupt, 0, "am79c961", dev)) {
283 MOD_DEC_USE_COUNT;
284 return -EAGAIN;
287 am79c961_init_for_open(dev);
289 netif_start_queue(dev);
291 return 0;
295 * The inverse routine to am79c961_open().
297 static int
298 am79c961_close(struct net_device *dev)
300 unsigned long flags;
302 netif_stop_queue(dev);
304 save_flags_cli (flags);
306 write_ireg (dev->base_addr, 2, 0x4000); /* autoselect media */
307 write_rreg (dev->base_addr, CSR0, CSR0_STOP);
308 write_rreg (dev->base_addr, CSR3, CSR3_MASKALL);
310 restore_flags (flags);
312 free_irq (dev->irq, dev);
314 MOD_DEC_USE_COUNT;
315 return 0;
319 * Get the current statistics. This may be called with the card open or
320 * closed.
322 static struct enet_statistics *am79c961_getstats (struct net_device *dev)
324 struct dev_priv *priv = (struct dev_priv *)dev->priv;
325 return &priv->stats;
328 static inline u32 update_crc(u32 crc, u8 byte)
330 int i;
332 for (i = 8; i != 0; i--) {
333 byte ^= crc & 1;
334 crc >>= 1;
336 if (byte & 1)
337 crc ^= 0xedb88320;
339 byte >>= 1;
342 return crc;
345 static void am79c961_mc_hash(struct dev_mc_list *dmi, unsigned short *hash)
347 if (dmi->dmi_addrlen == ETH_ALEN && dmi->dmi_addr[0] & 0x01) {
348 int i, idx, bit;
349 u32 crc;
351 crc = 0xffffffff;
353 for (i = 0; i < ETH_ALEN; i++)
354 crc = update_crc(crc, dmi->dmi_addr[i]);
356 idx = crc >> 30;
357 bit = (crc >> 26) & 15;
359 hash[idx] |= 1 << bit;
364 * Set or clear promiscuous/multicast mode filter for this adaptor.
366 static void am79c961_setmulticastlist (struct net_device *dev)
368 unsigned long flags;
369 unsigned short multi_hash[4], mode;
370 int i, stopped;
372 mode = MODE_PORT0;
374 if (dev->flags & IFF_PROMISC) {
375 mode |= MODE_PROMISC;
376 } else if (dev->flags & IFF_ALLMULTI) {
377 memset(multi_hash, 0xff, sizeof(multi_hash));
378 } else {
379 struct dev_mc_list *dmi;
381 memset(multi_hash, 0x00, sizeof(multi_hash));
383 for (dmi = dev->mc_list; dmi; dmi = dmi->next)
384 am79c961_mc_hash(dmi, multi_hash);
387 save_flags_cli(flags);
389 stopped = read_rreg(dev->base_addr, CSR0) & CSR0_STOP;
391 if (!stopped) {
393 * Put the chip into suspend mode
395 write_rreg(dev->base_addr, CTRL1, CTRL1_SPND);
398 * Spin waiting for chip to report suspend mode
400 while ((read_rreg(dev->base_addr, CTRL1) & CTRL1_SPND) == 0) {
401 restore_flags(flags);
402 nop();
403 save_flags_cli(flags);
408 * Update the multicast hash table
410 for (i = 0; i < sizeof(multi_hash) / sizeof(multi_hash[0]); i++)
411 write_rreg(dev->base_addr, i + LADRL, multi_hash[i]);
414 * Write the mode register
416 write_rreg(dev->base_addr, MODE, mode);
418 if (!stopped) {
420 * Put the chip back into running mode
422 write_rreg(dev->base_addr, CTRL1, 0);
425 restore_flags(flags);
428 static void am79c961_timeout(struct net_device *dev)
430 printk(KERN_WARNING "%s: transmit timed out, network cable problem?\n",
431 dev->name);
434 * ought to do some setup of the tx side here
437 netif_wake_queue(dev);
441 * Transmit a packet
443 static int
444 am79c961_sendpacket(struct sk_buff *skb, struct net_device *dev)
446 struct dev_priv *priv = (struct dev_priv *)dev->priv;
447 unsigned int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
448 unsigned int hdraddr, bufaddr;
449 unsigned int head;
450 unsigned long flags;
452 head = priv->txhead;
453 hdraddr = priv->txhdr + (head << 3);
454 bufaddr = priv->txbuffer[head];
455 head += 1;
456 if (head >= TX_BUFFERS)
457 head = 0;
459 am_writebuffer (dev, bufaddr, skb->data, length);
460 am_writeword (dev, hdraddr + 4, -length);
461 am_writeword (dev, hdraddr + 2, TMD_OWN|TMD_STP|TMD_ENP);
462 priv->txhead = head;
464 save_flags_cli (flags);
465 write_rreg (dev->base_addr, CSR0, CSR0_TDMD|CSR0_IENA);
466 dev->trans_start = jiffies;
467 restore_flags (flags);
469 if (!(am_readword (dev, priv->txhdr + (priv->txhead << 3) + 2) & TMD_OWN))
470 netif_stop_queue(dev);
472 dev_kfree_skb(skb);
474 return 0;
477 static void
478 am79c961_interrupt(int irq, void *dev_id, struct pt_regs *regs)
480 struct net_device *dev = (struct net_device *)dev_id;
481 struct dev_priv *priv = (struct dev_priv *)dev->priv;
482 unsigned int status;
484 #if NET_DEBUG > 1
485 if(net_debug & DEBUG_INT)
486 printk(KERN_DEBUG "am79c961irq: %d ", irq);
487 #endif
489 status = read_rreg (dev->base_addr, CSR0);
490 write_rreg (dev->base_addr, CSR0, status & (CSR0_TINT|CSR0_RINT|CSR0_MISS|CSR0_IENA));
492 if (status & CSR0_RINT) /* Got a packet(s). */
493 am79c961_rx (dev, priv);
494 if (status & CSR0_TINT) /* Packets transmitted */
495 am79c961_tx (dev, priv);
496 if (status & CSR0_MISS)
497 priv->stats.rx_dropped ++;
499 #if NET_DEBUG > 1
500 if(net_debug & DEBUG_INT)
501 printk("done\n");
502 #endif
506 * If we have a good packet(s), get it/them out of the buffers.
508 static void
509 am79c961_rx(struct net_device *dev, struct dev_priv *priv)
511 unsigned long hdraddr;
512 unsigned long pktaddr;
514 do {
515 unsigned long status;
516 struct sk_buff *skb;
517 int len;
519 hdraddr = priv->rxhdr + (priv->rxtail << 3);
520 pktaddr = priv->rxbuffer[priv->rxtail];
522 status = am_readword (dev, hdraddr + 2);
523 if (status & RMD_OWN) /* do we own it? */
524 break;
526 priv->rxtail ++;
527 if (priv->rxtail >= RX_BUFFERS)
528 priv->rxtail = 0;
530 if ((status & (RMD_ERR|RMD_STP|RMD_ENP)) != (RMD_STP|RMD_ENP)) {
531 am_writeword (dev, hdraddr + 2, RMD_OWN);
532 priv->stats.rx_errors ++;
533 if (status & RMD_ERR) {
534 if (status & RMD_FRAM)
535 priv->stats.rx_frame_errors ++;
536 if (status & RMD_CRC)
537 priv->stats.rx_crc_errors ++;
538 } else if (status & RMD_STP)
539 priv->stats.rx_length_errors ++;
540 continue;
543 len = am_readword (dev, hdraddr + 6);
544 skb = dev_alloc_skb (len + 2);
546 if (skb) {
547 unsigned char *buf;
549 skb->dev = dev;
550 skb_reserve (skb, 2);
551 buf = skb_put (skb, len);
553 am_readbuffer (dev, pktaddr, buf, len);
554 am_writeword (dev, hdraddr + 2, RMD_OWN);
555 skb->protocol = eth_type_trans(skb, dev);
556 netif_rx (skb);
557 priv->stats.rx_packets ++;
558 } else {
559 am_writeword (dev, hdraddr + 2, RMD_OWN);
560 printk (KERN_WARNING "%s: memory squeeze, dropping packet.\n", dev->name);
561 priv->stats.rx_dropped ++;
562 break;
564 } while (1);
568 * Update stats for the transmitted packet
570 static void
571 am79c961_tx(struct net_device *dev, struct dev_priv *priv)
573 do {
574 unsigned long hdraddr;
575 unsigned long status;
577 hdraddr = priv->txhdr + (priv->txtail << 3);
578 status = am_readword (dev, hdraddr + 2);
579 if (status & TMD_OWN)
580 break;
582 priv->txtail ++;
583 if (priv->txtail >= TX_BUFFERS)
584 priv->txtail = 0;
586 if (status & TMD_ERR) {
587 unsigned long status2;
589 priv->stats.tx_errors ++;
591 status2 = am_readword (dev, hdraddr + 6);
592 am_writeword (dev, hdraddr + 6, 0);
594 if (status2 & TST_RTRY)
595 priv->stats.collisions += 16;
596 if (status2 & TST_LCOL)
597 priv->stats.tx_window_errors ++;
598 if (status2 & TST_LCAR)
599 priv->stats.tx_carrier_errors ++;
600 if (status2 & TST_UFLO)
601 priv->stats.tx_fifo_errors ++;
602 continue;
604 priv->stats.tx_packets ++;
605 } while (priv->txtail != priv->txhead);
607 netif_wake_queue(dev);
610 static int
611 am79c961_hw_init(struct net_device *dev)
613 unsigned long flags;
615 am79c961_ramtest(dev, 0x66);
616 am79c961_ramtest(dev, 0x99);
618 save_flags_cli (flags);
620 write_ireg (dev->base_addr, 2, 0x4000); /* autoselect media */
621 write_rreg (dev->base_addr, CSR0, CSR0_STOP);
622 write_rreg (dev->base_addr, CSR3, CSR3_MASKALL);
624 restore_flags (flags);
626 return 0;
629 static void __init am79c961_banner(void)
631 static unsigned version_printed = 0;
633 if (net_debug && version_printed++ == 0)
634 printk(KERN_INFO "%s", version);
637 static int __init am79c961_init(void)
639 struct net_device *dev;
640 struct dev_priv *priv;
641 int i, ret;
643 dev = init_etherdev(NULL, sizeof(struct dev_priv));
644 ret = -ENOMEM;
645 if (!dev)
646 goto out;
648 priv = (struct dev_priv *) dev->priv;
651 * Fixed address and IRQ lines here.
652 * The PNP initialisation should have been
653 * done by the ether bootp loader.
655 dev->base_addr = 0x220;
656 dev->irq = IRQ_EBSA110_ETHERNET;
659 * Reset the device.
661 inb((dev->base_addr + NET_RESET) >> 1);
662 udelay(5);
665 * Check the manufacturer part of the
666 * ether address.
668 ret = -ENODEV;
669 if (inb(dev->base_addr >> 1) != 0x08 ||
670 inb((dev->base_addr >> 1) + 1) != 00 ||
671 inb((dev->base_addr >> 1) + 2) != 0x2b)
672 goto nodev;
674 if (!request_region(dev->base_addr, 0x18, dev->name))
675 goto nodev;
677 am79c961_banner();
678 printk(KERN_INFO "%s: am79c961 found at %08lx, IRQ%d, ether address ",
679 dev->name, dev->base_addr, dev->irq);
681 /* Retrive and print the ethernet address. */
682 for (i = 0; i < 6; i++) {
683 dev->dev_addr[i] = inb((dev->base_addr >> 1) + i) & 0xff;
684 printk (i == 5 ? "%02x\n" : "%02x:", dev->dev_addr[i]);
687 if (am79c961_hw_init(dev))
688 goto release;
690 dev->open = am79c961_open;
691 dev->stop = am79c961_close;
692 dev->hard_start_xmit = am79c961_sendpacket;
693 dev->get_stats = am79c961_getstats;
694 dev->set_multicast_list = am79c961_setmulticastlist;
695 dev->tx_timeout = am79c961_timeout;
697 return 0;
699 release:
700 release_region(dev->base_addr, 0x18);
701 nodev:
702 unregister_netdev(dev);
703 kfree(dev);
704 out:
705 return ret;
708 module_init(am79c961_init);