blob: b5d0f4e973f70cbb9fa68eff005b4ff594104f11 [file] [log] [blame]
Jeff Garzikd7fbeba2006-05-24 01:31:14 -04001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002net-3-driver for the IBM LAN Adapter/A
3
4This is an extension to the Linux operating system, and is covered by the
5same GNU General Public License that covers that work.
6
7Copyright 1999 by Alfred Arnold (alfred@ccac.rwth-aachen.de,
8 alfred.arnold@lancom.de)
9
10This driver is based both on the SK_MCA driver, which is itself based on the
11SK_G16 and 3C523 driver.
12
13paper sources:
Jeff Garzikd7fbeba2006-05-24 01:31:14 -040014 'PC Hardware: Aufbau, Funktionsweise, Programmierung' by
Linus Torvalds1da177e2005-04-16 15:20:36 -070015 Hans-Peter Messmer for the basic Microchannel stuff
Jeff Garzikd7fbeba2006-05-24 01:31:14 -040016
Linus Torvalds1da177e2005-04-16 15:20:36 -070017 'Linux Geraetetreiber' by Allesandro Rubini, Kalle Dalheimer
18 for help on Ethernet driver programming
19
20 'DP83934CVUL-20/25 MHz SONIC-T Ethernet Controller Datasheet' by National
21 Semiconductor for info on the MAC chip
22
23 'LAN Technical Reference Ethernet Adapter Interface Version 1 Release 1.0
24 Document Number SC30-3661-00' by IBM for info on the adapter itself
25
26 Also see http://www.natsemi.com/
27
28special acknowledgements to:
29 - Bob Eager for helping me out with documentation from IBM
Jeff Garzikd7fbeba2006-05-24 01:31:14 -040030 - Jim Shorney for his endless patience with me while I was using
Linus Torvalds1da177e2005-04-16 15:20:36 -070031 him as a beta tester to trace down the address filter bug ;-)
32
33 Missing things:
34
35 -> set debug level via ioctl instead of compile-time switches
36 -> I didn't follow the development of the 2.1.x kernels, so my
Jeff Garzikd7fbeba2006-05-24 01:31:14 -040037 assumptions about which things changed with which kernel version
Linus Torvalds1da177e2005-04-16 15:20:36 -070038 are probably nonsense
39
40History:
41 Nov 6th, 1999
42 startup from SK_MCA driver
43 Dec 6th, 1999
44 finally got docs about the card. A big thank you to Bob Eager!
45 Dec 12th, 1999
46 first packet received
47 Dec 13th, 1999
48 recv queue done, tcpdump works
49 Dec 15th, 1999
50 transmission part works
51 Dec 28th, 1999
52 added usage of the isa_functions for Linux 2.3 . Things should
53 still work with 2.0.x....
54 Jan 28th, 2000
55 in Linux 2.2.13, the version.h file mysteriously didn't get
56 included. Added a workaround for this. Futhermore, it now
57 not only compiles as a modules ;-)
58 Jan 30th, 2000
59 newer kernels automatically probe more than one board, so the
60 'startslot' as a variable is also needed here
61 Apr 12th, 2000
62 the interrupt mask register is not set 'hard' instead of individually
63 setting registers, since this seems to set bits that shouldn't be
64 set
65 May 21st, 2000
66 reset interrupt status immediately after CAM load
67 add a recovery delay after releasing the chip's reset line
68 May 24th, 2000
69 finally found the bug in the address filter setup - damned signed
70 chars!
71 June 1st, 2000
72 corrected version codes, added support for the latest 2.3 changes
73 Oct 28th, 2002
Alan Cox113aa832008-10-13 19:01:08 -070074 cleaned up for the 2.5 tree <alan@lxorguk.ukuu.org.uk>
Linus Torvalds1da177e2005-04-16 15:20:36 -070075
76 *************************************************************************/
77
78#include <linux/kernel.h>
79#include <linux/string.h>
80#include <linux/errno.h>
81#include <linux/ioport.h>
82#include <linux/slab.h>
83#include <linux/interrupt.h>
84#include <linux/delay.h>
85#include <linux/time.h>
Jeff Garzik3df59202007-11-04 21:53:26 -050086#include <linux/mca.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070087#include <linux/module.h>
88#include <linux/netdevice.h>
89#include <linux/etherdevice.h>
Daniel Drake1f044932009-12-24 08:11:24 +000090#include <linux/if_ether.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070091#include <linux/skbuff.h>
92#include <linux/bitops.h>
93
94#include <asm/processor.h>
95#include <asm/io.h>
96
97#define _IBM_LANA_DRIVER_
98#include "ibmlana.h"
99
100#undef DEBUG
101
102#define DRV_NAME "ibmlana"
103
104/* ------------------------------------------------------------------------
105 * global static data - not more since we can handle multiple boards and
106 * have to pack all state info into the device struct!
107 * ------------------------------------------------------------------------ */
108
109static char *MediaNames[Media_Count] = {
110 "10BaseT", "10Base5", "Unknown", "10Base2"
111};
112
113/* ------------------------------------------------------------------------
114 * private subfunctions
115 * ------------------------------------------------------------------------ */
116
117#ifdef DEBUG
118 /* dump all registers */
119
120static void dumpregs(struct net_device *dev)
121{
122 int z;
123
124 for (z = 0; z < 160; z += 2) {
125 if (!(z & 15))
126 printk("REGS: %04x:", z);
127 printk(" %04x", inw(dev->base_addr + z));
128 if ((z & 15) == 14)
129 printk("\n");
130 }
131}
132
133/* dump parts of shared memory - only needed during debugging */
134
135static void dumpmem(struct net_device *dev, u32 start, u32 len)
136{
137 ibmlana_priv *priv = netdev_priv(dev);
138 int z;
139
140 printk("Address %04x:\n", start);
141 for (z = 0; z < len; z++) {
142 if ((z & 15) == 0)
143 printk("%04x:", z);
144 printk(" %02x", readb(priv->base + start + z));
145 if ((z & 15) == 15)
146 printk("\n");
147 }
148 if ((z & 15) != 0)
149 printk("\n");
150}
151
152/* print exact time - ditto */
153
154static void PrTime(void)
155{
156 struct timeval tv;
157
158 do_gettimeofday(&tv);
159 printk("%9d:%06d: ", (int) tv.tv_sec, (int) tv.tv_usec);
160}
161#endif /* DEBUG */
162
163/* deduce resources out of POS registers */
164
Jeff Garzik3df59202007-11-04 21:53:26 -0500165static void getaddrs(struct mca_device *mdev, int *base, int *memlen,
166 int *iobase, int *irq, ibmlana_medium *medium)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167{
168 u_char pos0, pos1;
169
Jeff Garzik3df59202007-11-04 21:53:26 -0500170 pos0 = mca_device_read_stored_pos(mdev, 2);
171 pos1 = mca_device_read_stored_pos(mdev, 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172
173 *base = 0xc0000 + ((pos1 & 0xf0) << 9);
174 *memlen = (pos1 & 0x01) ? 0x8000 : 0x4000;
175 *iobase = (pos0 & 0xe0) << 7;
176 switch (pos0 & 0x06) {
177 case 0:
178 *irq = 5;
179 break;
180 case 2:
181 *irq = 15;
182 break;
183 case 4:
184 *irq = 10;
185 break;
186 case 6:
187 *irq = 11;
188 break;
189 }
190 *medium = (pos0 & 0x18) >> 3;
191}
192
193/* wait on register value with mask and timeout */
194
195static int wait_timeout(struct net_device *dev, int regoffs, u16 mask,
196 u16 value, int timeout)
197{
198 unsigned long fin = jiffies + timeout;
199
200 while (time_before(jiffies,fin))
201 if ((inw(dev->base_addr + regoffs) & mask) == value)
202 return 1;
203
204 return 0;
205}
206
207
208/* reset the whole board */
209
210static void ResetBoard(struct net_device *dev)
211{
212 unsigned char bcmval;
213
214 /* read original board control value */
215
216 bcmval = inb(dev->base_addr + BCMREG);
217
218 /* set reset bit for a while */
219
220 bcmval |= BCMREG_RESET;
221 outb(bcmval, dev->base_addr + BCMREG);
222 udelay(10);
223 bcmval &= ~BCMREG_RESET;
224 outb(bcmval, dev->base_addr + BCMREG);
225
226 /* switch over to RAM again */
227
228 bcmval |= BCMREG_RAMEN | BCMREG_RAMWIN;
229 outb(bcmval, dev->base_addr + BCMREG);
230}
231
232/* calculate RAM layout & set up descriptors in RAM */
233
234static void InitDscrs(struct net_device *dev)
235{
236 ibmlana_priv *priv = netdev_priv(dev);
237 u32 addr, baddr, raddr;
238 int z;
239 tda_t tda;
240 rda_t rda;
241 rra_t rra;
242
243 /* initialize RAM */
244
245 memset_io(priv->base, 0xaa,
246 dev->mem_start - dev->mem_start); /* XXX: typo? */
247
248 /* setup n TX descriptors - independent of RAM size */
249
250 priv->tdastart = addr = 0;
251 priv->txbufstart = baddr = sizeof(tda_t) * TXBUFCNT;
252 for (z = 0; z < TXBUFCNT; z++) {
253 tda.status = 0;
254 tda.config = 0;
255 tda.length = 0;
256 tda.fragcount = 1;
257 tda.startlo = baddr;
258 tda.starthi = 0;
259 tda.fraglength = 0;
260 if (z == TXBUFCNT - 1)
261 tda.link = priv->tdastart;
262 else
263 tda.link = addr + sizeof(tda_t);
264 tda.link |= 1;
265 memcpy_toio(priv->base + addr, &tda, sizeof(tda_t));
266 addr += sizeof(tda_t);
267 baddr += PKTSIZE;
268 }
269
270 /* calculate how many receive buffers fit into remaining memory */
271
272 priv->rxbufcnt = (dev->mem_end - dev->mem_start - baddr) / (sizeof(rra_t) + sizeof(rda_t) + PKTSIZE);
273
274 /* calculate receive addresses */
275
276 priv->rrastart = raddr = priv->txbufstart + (TXBUFCNT * PKTSIZE);
277 priv->rdastart = addr = priv->rrastart + (priv->rxbufcnt * sizeof(rra_t));
278 priv->rxbufstart = baddr = priv->rdastart + (priv->rxbufcnt * sizeof(rda_t));
Jeff Garzikd7fbeba2006-05-24 01:31:14 -0400279
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 for (z = 0; z < priv->rxbufcnt; z++) {
281 rra.startlo = baddr;
282 rra.starthi = 0;
283 rra.cntlo = PKTSIZE >> 1;
284 rra.cnthi = 0;
285 memcpy_toio(priv->base + raddr, &rra, sizeof(rra_t));
286
287 rda.status = 0;
288 rda.length = 0;
289 rda.startlo = 0;
290 rda.starthi = 0;
291 rda.seqno = 0;
292 if (z < priv->rxbufcnt - 1)
293 rda.link = addr + sizeof(rda_t);
294 else
295 rda.link = 1;
296 rda.inuse = 1;
297 memcpy_toio(priv->base + addr, &rda, sizeof(rda_t));
298
299 baddr += PKTSIZE;
300 raddr += sizeof(rra_t);
301 addr += sizeof(rda_t);
302 }
303
304 /* initialize current pointers */
305
306 priv->nextrxdescr = 0;
307 priv->lastrxdescr = priv->rxbufcnt - 1;
308 priv->nexttxdescr = 0;
309 priv->currtxdescr = 0;
310 priv->txusedcnt = 0;
311 memset(priv->txused, 0, sizeof(priv->txused));
312}
313
314/* set up Rx + Tx descriptors in SONIC */
315
316static int InitSONIC(struct net_device *dev)
317{
318 ibmlana_priv *priv = netdev_priv(dev);
319
320 /* set up start & end of resource area */
321
322 outw(0, SONIC_URRA);
323 outw(priv->rrastart, dev->base_addr + SONIC_RSA);
324 outw(priv->rrastart + (priv->rxbufcnt * sizeof(rra_t)), dev->base_addr + SONIC_REA);
325 outw(priv->rrastart, dev->base_addr + SONIC_RRP);
326 outw(priv->rrastart, dev->base_addr + SONIC_RWP);
327
328 /* set EOBC so that only one packet goes into one buffer */
329
330 outw((PKTSIZE - 4) >> 1, dev->base_addr + SONIC_EOBC);
331
332 /* let SONIC read the first RRA descriptor */
333
334 outw(CMDREG_RRRA, dev->base_addr + SONIC_CMDREG);
335 if (!wait_timeout(dev, SONIC_CMDREG, CMDREG_RRRA, 0, 2)) {
336 printk(KERN_ERR "%s: SONIC did not respond on RRRA command - giving up.", dev->name);
337 return 0;
338 }
339
340 /* point SONIC to the first RDA */
341
342 outw(0, dev->base_addr + SONIC_URDA);
343 outw(priv->rdastart, dev->base_addr + SONIC_CRDA);
344
345 /* set upper half of TDA address */
346
347 outw(0, dev->base_addr + SONIC_UTDA);
348
349 return 1;
350}
351
352/* stop SONIC so we can reinitialize it */
353
354static void StopSONIC(struct net_device *dev)
355{
356 /* disable interrupts */
357
358 outb(inb(dev->base_addr + BCMREG) & (~BCMREG_IEN), dev->base_addr + BCMREG);
359 outb(0, dev->base_addr + SONIC_IMREG);
360
361 /* reset the SONIC */
362
363 outw(CMDREG_RST, dev->base_addr + SONIC_CMDREG);
364 udelay(10);
365 outw(CMDREG_RST, dev->base_addr + SONIC_CMDREG);
366}
367
368/* initialize card and SONIC for proper operation */
369
370static void putcam(camentry_t * cams, int *camcnt, char *addr)
371{
372 camentry_t *pcam = cams + (*camcnt);
373 u8 *uaddr = (u8 *) addr;
374
375 pcam->index = *camcnt;
376 pcam->addr0 = (((u16) uaddr[1]) << 8) | uaddr[0];
377 pcam->addr1 = (((u16) uaddr[3]) << 8) | uaddr[2];
378 pcam->addr2 = (((u16) uaddr[5]) << 8) | uaddr[4];
379 (*camcnt)++;
380}
381
382static void InitBoard(struct net_device *dev)
383{
384 ibmlana_priv *priv = netdev_priv(dev);
385 int camcnt;
386 camentry_t cams[16];
387 u32 cammask;
388 struct dev_mc_list *mcptr;
389 u16 rcrval;
390
391 /* reset the SONIC */
392
393 outw(CMDREG_RST, dev->base_addr + SONIC_CMDREG);
394 udelay(10);
395
396 /* clear all spurious interrupts */
397
398 outw(inw(dev->base_addr + SONIC_ISREG), dev->base_addr + SONIC_ISREG);
399
400 /* set up the SONIC's bus interface - constant for this adapter -
401 must be done while the SONIC is in reset */
402
403 outw(DCREG_USR1 | DCREG_USR0 | DCREG_WC1 | DCREG_DW32, dev->base_addr + SONIC_DCREG);
404 outw(0, dev->base_addr + SONIC_DCREG2);
405
406 /* remove reset form the SONIC */
407
408 outw(0, dev->base_addr + SONIC_CMDREG);
409 udelay(10);
410
411 /* data sheet requires URRA to be programmed before setting up the CAM contents */
412
413 outw(0, dev->base_addr + SONIC_URRA);
414
415 /* program the CAM entry 0 to the device address */
416
417 camcnt = 0;
418 putcam(cams, &camcnt, dev->dev_addr);
419
420 /* start putting the multicast addresses into the CAM list. Stop if
421 it is full. */
422
Jiri Pirko48e2f182010-02-22 09:22:26 +0000423 netdev_for_each_mc_addr(mcptr, dev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 putcam(cams, &camcnt, mcptr->dmi_addr);
425 if (camcnt == 16)
426 break;
427 }
428
429 /* calculate CAM mask */
430
431 cammask = (1 << camcnt) - 1;
432
433 /* feed CDA into SONIC, initialize RCR value (always get broadcasts) */
434
435 memcpy_toio(priv->base, cams, sizeof(camentry_t) * camcnt);
436 memcpy_toio(priv->base + (sizeof(camentry_t) * camcnt), &cammask, sizeof(cammask));
437
438#ifdef DEBUG
439 printk("CAM setup:\n");
440 dumpmem(dev, 0, sizeof(camentry_t) * camcnt + sizeof(cammask));
441#endif
442
443 outw(0, dev->base_addr + SONIC_CAMPTR);
444 outw(camcnt, dev->base_addr + SONIC_CAMCNT);
445 outw(CMDREG_LCAM, dev->base_addr + SONIC_CMDREG);
446 if (!wait_timeout(dev, SONIC_CMDREG, CMDREG_LCAM, 0, 2)) {
447 printk(KERN_ERR "%s:SONIC did not respond on LCAM command - giving up.", dev->name);
448 return;
449 } else {
450 /* clear interrupt condition */
451
452 outw(ISREG_LCD, dev->base_addr + SONIC_ISREG);
453
454#ifdef DEBUG
455 printk("Loading CAM done, address pointers %04x:%04x\n",
456 inw(dev->base_addr + SONIC_URRA),
457 inw(dev->base_addr + SONIC_CAMPTR));
458 {
459 int z;
460
461 printk("\n-->CAM: PTR %04x CNT %04x\n",
462 inw(dev->base_addr + SONIC_CAMPTR),
463 inw(dev->base_addr + SONIC_CAMCNT));
464 outw(CMDREG_RST, dev->base_addr + SONIC_CMDREG);
465 for (z = 0; z < camcnt; z++) {
466 outw(z, dev->base_addr + SONIC_CAMEPTR);
467 printk("Entry %d: %04x %04x %04x\n", z,
468 inw(dev->base_addr + SONIC_CAMADDR0),
469 inw(dev->base_addr + SONIC_CAMADDR1),
470 inw(dev->base_addr + SONIC_CAMADDR2));
471 }
472 outw(0, dev->base_addr + SONIC_CMDREG);
473 }
474#endif
475 }
476
477 rcrval = RCREG_BRD | RCREG_LB_NONE;
478
479 /* if still multicast addresses left or ALLMULTI is set, set the multicast
480 enable bit */
481
482 if ((dev->flags & IFF_ALLMULTI) || (mcptr != NULL))
483 rcrval |= RCREG_AMC;
484
485 /* promiscous mode ? */
486
487 if (dev->flags & IFF_PROMISC)
488 rcrval |= RCREG_PRO;
489
490 /* program receive mode */
491
492 outw(rcrval, dev->base_addr + SONIC_RCREG);
493#ifdef DEBUG
494 printk("\nRCRVAL: %04x\n", rcrval);
495#endif
496
497 /* set up descriptors in shared memory + feed them into SONIC registers */
498
499 InitDscrs(dev);
500 if (!InitSONIC(dev))
501 return;
502
503 /* reset all pending interrupts */
504
505 outw(0xffff, dev->base_addr + SONIC_ISREG);
506
507 /* enable transmitter + receiver interrupts */
508
509 outw(CMDREG_RXEN, dev->base_addr + SONIC_CMDREG);
510 outw(IMREG_PRXEN | IMREG_RBEEN | IMREG_PTXEN | IMREG_TXEREN, dev->base_addr + SONIC_IMREG);
511
512 /* turn on card interrupts */
513
514 outb(inb(dev->base_addr + BCMREG) | BCMREG_IEN, dev->base_addr + BCMREG);
515
516#ifdef DEBUG
517 printk("Register dump after initialization:\n");
518 dumpregs(dev);
519#endif
520}
521
522/* start transmission of a descriptor */
523
524static void StartTx(struct net_device *dev, int descr)
525{
526 ibmlana_priv *priv = netdev_priv(dev);
527 int addr;
528
529 addr = priv->tdastart + (descr * sizeof(tda_t));
530
531 /* put descriptor address into SONIC */
532
533 outw(addr, dev->base_addr + SONIC_CTDA);
534
535 /* trigger transmitter */
536
537 priv->currtxdescr = descr;
538 outw(CMDREG_TXP, dev->base_addr + SONIC_CMDREG);
539}
540
541/* ------------------------------------------------------------------------
542 * interrupt handler(s)
543 * ------------------------------------------------------------------------ */
544
545/* receive buffer area exhausted */
546
547static void irqrbe_handler(struct net_device *dev)
548{
549 ibmlana_priv *priv = netdev_priv(dev);
550
551 /* point the SONIC back to the RRA start */
552
553 outw(priv->rrastart, dev->base_addr + SONIC_RRP);
554 outw(priv->rrastart, dev->base_addr + SONIC_RWP);
555}
556
557/* receive interrupt */
558
559static void irqrx_handler(struct net_device *dev)
560{
561 ibmlana_priv *priv = netdev_priv(dev);
562 rda_t rda;
563 u32 rdaaddr, lrdaaddr;
564
565 /* loop until ... */
566
567 while (1) {
568 /* read descriptor that was next to be filled by SONIC */
569
570 rdaaddr = priv->rdastart + (priv->nextrxdescr * sizeof(rda_t));
571 lrdaaddr = priv->rdastart + (priv->lastrxdescr * sizeof(rda_t));
572 memcpy_fromio(&rda, priv->base + rdaaddr, sizeof(rda_t));
573
Jeff Garzikd7fbeba2006-05-24 01:31:14 -0400574 /* iron out upper word halves of fields we use - SONIC will duplicate
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575 bits 0..15 to 16..31 */
576
577 rda.status &= 0xffff;
578 rda.length &= 0xffff;
579 rda.startlo &= 0xffff;
580
581 /* stop if the SONIC still owns it, i.e. there is no data for us */
582
583 if (rda.inuse)
584 break;
585
586 /* good packet? */
587
588 else if (rda.status & RCREG_PRX) {
589 struct sk_buff *skb;
590
591 /* fetch buffer */
592
593 skb = dev_alloc_skb(rda.length + 2);
594 if (skb == NULL)
Jeff Garzik09f75cd2007-10-03 17:41:50 -0700595 dev->stats.rx_dropped++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596 else {
597 /* copy out data */
598
599 memcpy_fromio(skb_put(skb, rda.length),
600 priv->base +
601 rda.startlo, rda.length);
602
603 /* set up skb fields */
604
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605 skb->protocol = eth_type_trans(skb, dev);
606 skb->ip_summed = CHECKSUM_NONE;
607
608 /* bookkeeping */
Jeff Garzik09f75cd2007-10-03 17:41:50 -0700609 dev->stats.rx_packets++;
610 dev->stats.rx_bytes += rda.length;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611
612 /* pass to the upper layers */
613 netif_rx(skb);
614 }
615 }
616
617 /* otherwise check error status bits and increase statistics */
618
619 else {
Jeff Garzik09f75cd2007-10-03 17:41:50 -0700620 dev->stats.rx_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621 if (rda.status & RCREG_FAER)
Jeff Garzik09f75cd2007-10-03 17:41:50 -0700622 dev->stats.rx_frame_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 if (rda.status & RCREG_CRCR)
Jeff Garzik09f75cd2007-10-03 17:41:50 -0700624 dev->stats.rx_crc_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 }
626
627 /* descriptor processed, will become new last descriptor in queue */
628
629 rda.link = 1;
630 rda.inuse = 1;
631 memcpy_toio(priv->base + rdaaddr, &rda,
632 sizeof(rda_t));
633
634 /* set up link and EOL = 0 in currently last descriptor. Only write
635 the link field since the SONIC may currently already access the
636 other fields. */
637
638 memcpy_toio(priv->base + lrdaaddr + 20, &rdaaddr, 4);
639
640 /* advance indices */
641
642 priv->lastrxdescr = priv->nextrxdescr;
643 if ((++priv->nextrxdescr) >= priv->rxbufcnt)
644 priv->nextrxdescr = 0;
645 }
646}
647
648/* transmit interrupt */
649
650static void irqtx_handler(struct net_device *dev)
651{
652 ibmlana_priv *priv = netdev_priv(dev);
653 tda_t tda;
654
655 /* fetch descriptor (we forgot the size ;-) */
656 memcpy_fromio(&tda, priv->base + priv->tdastart + (priv->currtxdescr * sizeof(tda_t)), sizeof(tda_t));
657
658 /* update statistics */
Jeff Garzik09f75cd2007-10-03 17:41:50 -0700659 dev->stats.tx_packets++;
660 dev->stats.tx_bytes += tda.length;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661
662 /* update our pointers */
663 priv->txused[priv->currtxdescr] = 0;
664 priv->txusedcnt--;
665
666 /* if there are more descriptors present in RAM, start them */
667 if (priv->txusedcnt > 0)
668 StartTx(dev, (priv->currtxdescr + 1) % TXBUFCNT);
669
670 /* tell the upper layer we can go on transmitting */
671 netif_wake_queue(dev);
672}
673
674static void irqtxerr_handler(struct net_device *dev)
675{
676 ibmlana_priv *priv = netdev_priv(dev);
677 tda_t tda;
678
679 /* fetch descriptor to check status */
680 memcpy_fromio(&tda, priv->base + priv->tdastart + (priv->currtxdescr * sizeof(tda_t)), sizeof(tda_t));
681
682 /* update statistics */
Jeff Garzik09f75cd2007-10-03 17:41:50 -0700683 dev->stats.tx_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 if (tda.status & (TCREG_NCRS | TCREG_CRSL))
Jeff Garzik09f75cd2007-10-03 17:41:50 -0700685 dev->stats.tx_carrier_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686 if (tda.status & TCREG_EXC)
Jeff Garzik09f75cd2007-10-03 17:41:50 -0700687 dev->stats.tx_aborted_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688 if (tda.status & TCREG_OWC)
Jeff Garzik09f75cd2007-10-03 17:41:50 -0700689 dev->stats.tx_window_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 if (tda.status & TCREG_FU)
Jeff Garzik09f75cd2007-10-03 17:41:50 -0700691 dev->stats.tx_fifo_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692
693 /* update our pointers */
694 priv->txused[priv->currtxdescr] = 0;
695 priv->txusedcnt--;
696
697 /* if there are more descriptors present in RAM, start them */
698 if (priv->txusedcnt > 0)
699 StartTx(dev, (priv->currtxdescr + 1) % TXBUFCNT);
700
701 /* tell the upper layer we can go on transmitting */
702 netif_wake_queue(dev);
703}
704
705/* general interrupt entry */
706
Jeff Garzik28fc1f52007-10-29 05:46:16 -0400707static irqreturn_t irq_handler(int dummy, void *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708{
Jeff Garzik28fc1f52007-10-29 05:46:16 -0400709 struct net_device *dev = device;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710 u16 ival;
711
712 /* in case we're not meant... */
713 if (!(inb(dev->base_addr + BCMREG) & BCMREG_IPEND))
714 return IRQ_NONE;
715
716 /* loop through the interrupt bits until everything is clear */
717 while (1) {
718 ival = inw(dev->base_addr + SONIC_ISREG);
719
720 if (ival & ISREG_RBE) {
721 irqrbe_handler(dev);
722 outw(ISREG_RBE, dev->base_addr + SONIC_ISREG);
723 }
724 if (ival & ISREG_PKTRX) {
725 irqrx_handler(dev);
726 outw(ISREG_PKTRX, dev->base_addr + SONIC_ISREG);
727 }
728 if (ival & ISREG_TXDN) {
729 irqtx_handler(dev);
730 outw(ISREG_TXDN, dev->base_addr + SONIC_ISREG);
731 }
732 if (ival & ISREG_TXER) {
733 irqtxerr_handler(dev);
734 outw(ISREG_TXER, dev->base_addr + SONIC_ISREG);
735 }
736 break;
737 }
738 return IRQ_HANDLED;
739}
740
741/* ------------------------------------------------------------------------
742 * driver methods
743 * ------------------------------------------------------------------------ */
744
745/* MCA info */
746
Jeff Garzik3df59202007-11-04 21:53:26 -0500747#if 0 /* info available elsewhere, but this is kept for reference */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748static int ibmlana_getinfo(char *buf, int slot, void *d)
749{
750 int len = 0, i;
751 struct net_device *dev = (struct net_device *) d;
752 ibmlana_priv *priv;
753
754 /* can't say anything about an uninitialized device... */
755
756 if (dev == NULL)
757 return len;
758 priv = netdev_priv(dev);
759
760 /* print info */
761
762 len += sprintf(buf + len, "IRQ: %d\n", priv->realirq);
763 len += sprintf(buf + len, "I/O: %#lx\n", dev->base_addr);
764 len += sprintf(buf + len, "Memory: %#lx-%#lx\n", dev->mem_start, dev->mem_end - 1);
765 len += sprintf(buf + len, "Transceiver: %s\n", MediaNames[priv->medium]);
766 len += sprintf(buf + len, "Device: %s\n", dev->name);
767 len += sprintf(buf + len, "MAC address:");
768 for (i = 0; i < 6; i++)
769 len += sprintf(buf + len, " %02x", dev->dev_addr[i]);
770 buf[len++] = '\n';
771 buf[len] = 0;
772
773 return len;
774}
Jeff Garzik3df59202007-11-04 21:53:26 -0500775#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776
777/* open driver. Means also initialization and start of LANCE */
778
779static int ibmlana_open(struct net_device *dev)
780{
781 int result;
782 ibmlana_priv *priv = netdev_priv(dev);
783
784 /* register resources - only necessary for IRQ */
785
Thomas Gleixner1fb9df52006-07-01 19:29:39 -0700786 result = request_irq(priv->realirq, irq_handler, IRQF_SHARED | IRQF_SAMPLE_RANDOM, dev->name, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 if (result != 0) {
788 printk(KERN_ERR "%s: failed to register irq %d\n", dev->name, dev->irq);
789 return result;
790 }
791 dev->irq = priv->realirq;
792
793 /* set up the card and SONIC */
794 InitBoard(dev);
795
796 /* initialize operational flags */
797 netif_start_queue(dev);
798 return 0;
799}
800
801/* close driver. Shut down board and free allocated resources */
802
803static int ibmlana_close(struct net_device *dev)
804{
805 /* turn off board */
806
807 /* release resources */
808 if (dev->irq != 0)
809 free_irq(dev->irq, dev);
810 dev->irq = 0;
811 return 0;
812}
813
814/* transmit a block. */
815
Stephen Hemminger613573252009-08-31 19:50:58 +0000816static netdev_tx_t ibmlana_tx(struct sk_buff *skb, struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817{
818 ibmlana_priv *priv = netdev_priv(dev);
Patrick McHardy3790c8c2009-06-12 03:00:35 +0000819 int tmplen, addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820 unsigned long flags;
821 tda_t tda;
822 int baddr;
823
824 /* find out if there are free slots for a frame to transmit. If not,
825 the upper layer is in deep desperation and we simply ignore the frame. */
826
827 if (priv->txusedcnt >= TXBUFCNT) {
Jeff Garzik09f75cd2007-10-03 17:41:50 -0700828 dev->stats.tx_dropped++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 goto tx_done;
830 }
831
832 /* copy the frame data into the next free transmit buffer - fillup missing */
833 tmplen = skb->len;
834 if (tmplen < 60)
835 tmplen = 60;
836 baddr = priv->txbufstart + (priv->nexttxdescr * PKTSIZE);
837 memcpy_toio(priv->base + baddr, skb->data, skb->len);
838
Jeff Garzikd7fbeba2006-05-24 01:31:14 -0400839 /* copy filler into RAM - in case we're filling up...
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 we're filling a bit more than necessary, but that doesn't harm
Jeff Garzikd7fbeba2006-05-24 01:31:14 -0400841 since the buffer is far larger...
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 Sorry Linus for the filler string but I couldn't resist ;-) */
843
844 if (tmplen > skb->len) {
845 char *fill = "NetBSD is a nice OS too! ";
846 unsigned int destoffs = skb->len, l = strlen(fill);
847
848 while (destoffs < tmplen) {
849 memcpy_toio(priv->base + baddr + destoffs, fill, l);
850 destoffs += l;
851 }
852 }
853
854 /* set up the new frame descriptor */
855 addr = priv->tdastart + (priv->nexttxdescr * sizeof(tda_t));
856 memcpy_fromio(&tda, priv->base + addr, sizeof(tda_t));
857 tda.length = tda.fraglength = tmplen;
858 memcpy_toio(priv->base + addr, &tda, sizeof(tda_t));
859
860 /* if there were no active descriptors, trigger the SONIC */
861 spin_lock_irqsave(&priv->lock, flags);
862
863 priv->txusedcnt++;
864 priv->txused[priv->nexttxdescr] = 1;
865
866 /* are all transmission slots used up ? */
867 if (priv->txusedcnt >= TXBUFCNT)
868 netif_stop_queue(dev);
869
870 if (priv->txusedcnt == 1)
871 StartTx(dev, priv->nexttxdescr);
872 priv->nexttxdescr = (priv->nexttxdescr + 1) % TXBUFCNT;
873
874 spin_unlock_irqrestore(&priv->lock, flags);
875tx_done:
876 dev_kfree_skb(skb);
Patrick McHardy3790c8c2009-06-12 03:00:35 +0000877 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878}
879
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880/* switch receiver mode. */
881
882static void ibmlana_set_multicast_list(struct net_device *dev)
883{
884 /* first stop the SONIC... */
885 StopSONIC(dev);
886 /* ...then reinit it with the new flags */
887 InitBoard(dev);
888}
889
890/* ------------------------------------------------------------------------
891 * hardware check
892 * ------------------------------------------------------------------------ */
893
Jeff Garzikfbe02d62007-11-04 21:52:49 -0500894static int ibmlana_irq;
895static int ibmlana_io;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896static int startslot; /* counts through slots when probing multiple devices */
897
Jeff Garzik3df59202007-11-04 21:53:26 -0500898static short ibmlana_adapter_ids[] __initdata = {
899 IBM_LANA_ID,
900 0x0000
901};
902
Adrian Bunk976006f2008-01-30 22:02:10 +0200903static char *ibmlana_adapter_names[] __devinitdata = {
Jeff Garzik3df59202007-11-04 21:53:26 -0500904 "IBM LAN Adapter/A",
905 NULL
906};
907
Stephen Hemmingerd9c6d502009-03-26 15:11:33 +0000908
909static const struct net_device_ops ibmlana_netdev_ops = {
910 .ndo_open = ibmlana_open,
911 .ndo_stop = ibmlana_close,
912 .ndo_start_xmit = ibmlana_tx,
913 .ndo_set_multicast_list = ibmlana_set_multicast_list,
914 .ndo_change_mtu = eth_change_mtu,
915 .ndo_set_mac_address = eth_mac_addr,
916 .ndo_validate_addr = eth_validate_addr,
917};
918
Adrian Bunkb54e4f82008-01-30 22:02:08 +0200919static int __devinit ibmlana_init_one(struct device *kdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920{
Jeff Garzik3df59202007-11-04 21:53:26 -0500921 struct mca_device *mdev = to_mca_device(kdev);
Jeff Garzikfbe02d62007-11-04 21:52:49 -0500922 struct net_device *dev;
Jeff Garzik3df59202007-11-04 21:53:26 -0500923 int slot = mdev->slot, z, rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 int base = 0, irq = 0, iobase = 0, memlen = 0;
925 ibmlana_priv *priv;
926 ibmlana_medium medium;
927
Jeff Garzikfbe02d62007-11-04 21:52:49 -0500928 dev = alloc_etherdev(sizeof(ibmlana_priv));
929 if (!dev)
930 return -ENOMEM;
931
932 dev->irq = ibmlana_irq;
933 dev->base_addr = ibmlana_io;
934
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 base = dev->mem_start;
936 irq = dev->irq;
937
Jeff Garzik3df59202007-11-04 21:53:26 -0500938 /* deduce card addresses */
939 getaddrs(mdev, &base, &memlen, &iobase, &irq, &medium);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940
Jeff Garzik3df59202007-11-04 21:53:26 -0500941 /* were we looking for something different ? */
942 if (dev->irq && dev->irq != irq) {
943 rc = -ENODEV;
944 goto err_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 }
Jeff Garzik3df59202007-11-04 21:53:26 -0500946 if (dev->mem_start && dev->mem_start != base) {
947 rc = -ENODEV;
Jeff Garzikfbe02d62007-11-04 21:52:49 -0500948 goto err_out;
949 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950
951 /* announce success */
952 printk(KERN_INFO "%s: IBM LAN Adapter/A found in slot %d\n", dev->name, slot + 1);
953
954 /* try to obtain I/O range */
955 if (!request_region(iobase, IBM_LANA_IORANGE, DRV_NAME)) {
956 printk(KERN_ERR "%s: cannot allocate I/O range at %#x!\n", DRV_NAME, iobase);
957 startslot = slot + 1;
Jeff Garzikfbe02d62007-11-04 21:52:49 -0500958 rc = -EBUSY;
959 goto err_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 }
961
962 priv = netdev_priv(dev);
963 priv->slot = slot;
Jeff Garzik3df59202007-11-04 21:53:26 -0500964 priv->realirq = mca_device_transform_irq(mdev, irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 priv->medium = medium;
966 spin_lock_init(&priv->lock);
Jeff Garzikd7fbeba2006-05-24 01:31:14 -0400967
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 /* set base + irq for this device (irq not allocated so far) */
969
970 dev->irq = 0;
971 dev->mem_start = base;
972 dev->mem_end = base + memlen;
973 dev->base_addr = iobase;
974
975 priv->base = ioremap(base, memlen);
976 if (!priv->base) {
977 printk(KERN_ERR "%s: cannot remap memory!\n", DRV_NAME);
978 startslot = slot + 1;
Jeff Garzikfbe02d62007-11-04 21:52:49 -0500979 rc = -EBUSY;
980 goto err_out_reg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 }
982
Jeff Garzik3df59202007-11-04 21:53:26 -0500983 mca_device_set_name(mdev, ibmlana_adapter_names[mdev->index]);
984 mca_device_set_claim(mdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985
986 /* set methods */
Stephen Hemmingerd9c6d502009-03-26 15:11:33 +0000987 dev->netdev_ops = &ibmlana_netdev_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 dev->flags |= IFF_MULTICAST;
989
990 /* copy out MAC address */
991
Daniel Drake1f044932009-12-24 08:11:24 +0000992 for (z = 0; z < ETH_ALEN; z++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 dev->dev_addr[z] = inb(dev->base_addr + MACADDRPROM + z);
994
995 /* print config */
996
997 printk(KERN_INFO "%s: IRQ %d, I/O %#lx, memory %#lx-%#lx, "
Johannes Berge1749612008-10-27 15:59:26 -0700998 "MAC address %pM.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999 dev->name, priv->realirq, dev->base_addr,
1000 dev->mem_start, dev->mem_end - 1,
Johannes Berge1749612008-10-27 15:59:26 -07001001 dev->dev_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002 printk(KERN_INFO "%s: %s medium\n", dev->name, MediaNames[priv->medium]);
1003
1004 /* reset board */
1005
1006 ResetBoard(dev);
1007
1008 /* next probe will start at next slot */
1009
1010 startslot = slot + 1;
1011
Jeff Garzikfbe02d62007-11-04 21:52:49 -05001012 rc = register_netdev(dev);
1013 if (rc)
1014 goto err_out_claimed;
1015
Jeff Garzik3df59202007-11-04 21:53:26 -05001016 dev_set_drvdata(kdev, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 return 0;
Jeff Garzikfbe02d62007-11-04 21:52:49 -05001018
1019err_out_claimed:
Jeff Garzik3df59202007-11-04 21:53:26 -05001020 mca_device_set_claim(mdev, 0);
Jeff Garzikfbe02d62007-11-04 21:52:49 -05001021 iounmap(priv->base);
1022err_out_reg:
1023 release_region(iobase, IBM_LANA_IORANGE);
1024err_out:
1025 free_netdev(dev);
1026 return rc;
1027}
1028
Jeff Garzik3df59202007-11-04 21:53:26 -05001029static int ibmlana_remove_one(struct device *kdev)
Jeff Garzikfbe02d62007-11-04 21:52:49 -05001030{
Jeff Garzik3df59202007-11-04 21:53:26 -05001031 struct mca_device *mdev = to_mca_device(kdev);
1032 struct net_device *dev = dev_get_drvdata(kdev);
Jeff Garzikfbe02d62007-11-04 21:52:49 -05001033 ibmlana_priv *priv = netdev_priv(dev);
1034
1035 unregister_netdev(dev);
1036 /*DeinitBoard(dev); */
1037 release_region(dev->base_addr, IBM_LANA_IORANGE);
Jeff Garzik3df59202007-11-04 21:53:26 -05001038 mca_device_set_claim(mdev, 0);
Jeff Garzikfbe02d62007-11-04 21:52:49 -05001039 iounmap(priv->base);
1040 free_netdev(dev);
Jeff Garzik3df59202007-11-04 21:53:26 -05001041 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042}
1043
1044/* ------------------------------------------------------------------------
1045 * modularization support
1046 * ------------------------------------------------------------------------ */
1047
Jeff Garzikfbe02d62007-11-04 21:52:49 -05001048module_param_named(irq, ibmlana_irq, int, 0);
1049module_param_named(io, ibmlana_io, int, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050MODULE_PARM_DESC(irq, "IBM LAN/A IRQ number");
1051MODULE_PARM_DESC(io, "IBM LAN/A I/O base address");
1052MODULE_LICENSE("GPL");
1053
Jeff Garzik3df59202007-11-04 21:53:26 -05001054static struct mca_driver ibmlana_driver = {
1055 .id_table = ibmlana_adapter_ids,
1056 .driver = {
1057 .name = "ibmlana",
1058 .bus = &mca_bus_type,
1059 .probe = ibmlana_init_one,
1060 .remove = ibmlana_remove_one,
1061 },
1062};
1063
Jeff Garzikfbe02d62007-11-04 21:52:49 -05001064static int __init ibmlana_init_module(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065{
Jeff Garzik3df59202007-11-04 21:53:26 -05001066 return mca_register_driver(&ibmlana_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067}
1068
Jeff Garzikfbe02d62007-11-04 21:52:49 -05001069static void __exit ibmlana_cleanup_module(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070{
Jeff Garzik3df59202007-11-04 21:53:26 -05001071 mca_unregister_driver(&ibmlana_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072}
Jeff Garzikfbe02d62007-11-04 21:52:49 -05001073
1074module_init(ibmlana_init_module);
1075module_exit(ibmlana_cleanup_module);