|
|
1.1 ! root 1: /* ! 2: * net-3-driver for the NI5210 card (i82586 Ethernet chip) ! 3: * ! 4: * This is an extension to the Linux operating system, and is covered by the ! 5: * same Gnu Public License that covers that work. ! 6: * ! 7: * Alphacode 0.80 (96/02/19) for Linux 1.3.66 (or later) ! 8: * Copyrights (c) 1994,1995,1996 by M.Hipp ([email protected]) ! 9: * [feel free to mail ....] ! 10: * ! 11: * when using as module: (no autoprobing!) ! 12: * compile with: gcc -D__KERNEL__ -DMODULE -O2 -c ni52.c ! 13: * run with e.g: insmod ni52.o io=0x360 irq=9 memstart=0xd0000 memend=0xd4000 ! 14: * ! 15: * CAN YOU PLEASE REPORT ME YOUR PERFORMANCE EXPERIENCES !!. ! 16: * ! 17: * If you find a bug, please report me: ! 18: * The kernel panic output and any kmsg from the ni52 driver ! 19: * the ni5210-driver-version and the linux-kernel version ! 20: * how many shared memory (memsize) on the netcard, ! 21: * bootprom: yes/no, base_addr, mem_start ! 22: * maybe the ni5210-card revision and the i82586 version ! 23: * ! 24: * autoprobe for: base_addr: 0x300,0x280,0x360,0x320,0x340 ! 25: * mem_start: 0xd0000,0xd2000,0xc8000,0xca000,0xd4000,0xd6000, ! 26: * 0xd8000,0xcc000,0xce000,0xda000,0xdc000 ! 27: * ! 28: * sources: ! 29: * skeleton.c from Donald Becker ! 30: * ! 31: * I have also done a look in the following sources: (mail me if you need them) ! 32: * crynwr-packet-driver by Russ Nelson ! 33: * Garret A. Wollman's (fourth) i82586-driver for BSD ! 34: * (before getting an i82596 (yes 596 not 586) manual, the existing drivers helped ! 35: * me a lot to understand this tricky chip.) ! 36: * ! 37: * Known Problems: ! 38: * The internal sysbus seems to be slow. So we often lose packets because of ! 39: * overruns while receiving from a fast remote host. ! 40: * This can slow down TCP connections. Maybe the newer ni5210 cards are better. ! 41: * my experience is, that if a machine sends with more then about 500-600K/s ! 42: * the fifo/sysbus overflows. ! 43: * ! 44: * IMPORTANT NOTE: ! 45: * On fast networks, it's a (very) good idea to have 16K shared memory. With ! 46: * 8K, we can store only 4 receive frames, so it can (easily) happen that a remote ! 47: * machine 'overruns' our system. ! 48: * ! 49: * Known i82586/card problems (I'm sure, there are many more!): ! 50: * Running the NOP-mode, the i82586 sometimes seems to forget to report ! 51: * every xmit-interrupt until we restart the CU. ! 52: * Another MAJOR bug is, that the RU sometimes seems to ignore the EL-Bit ! 53: * in the RBD-Struct which indicates an end of the RBD queue. ! 54: * Instead, the RU fetches another (randomly selected and ! 55: * usually used) RBD and begins to fill it. (Maybe, this happens only if ! 56: * the last buffer from the previous RFD fits exact into the queue and ! 57: * the next RFD can't fetch an initial RBD. Anyone knows more? ) ! 58: * ! 59: * results from ftp performance tests with Linux 1.2.5 ! 60: * send and receive about 350-400 KByte/s (peak up to 460 kbytes/s) ! 61: * sending in NOP-mode: peak performance up to 530K/s (but better don't run this mode) ! 62: */ ! 63: ! 64: /* ! 65: * 19.Feb.96: more Mcast changes, module support (MH) ! 66: * ! 67: * 18.Nov.95: Mcast changes (AC). ! 68: * ! 69: * 23.April.95: fixed(?) receiving problems by configuring a RFD more ! 70: * than the number of RBD's. Can maybe cause other problems. ! 71: * 18.April.95: Added MODULE support (MH) ! 72: * 17.April.95: MC related changes in init586() and set_multicast_list(). ! 73: * removed use of 'jiffies' in init586() (MH) ! 74: * ! 75: * 19.Sep.94: Added Multicast support (not tested yet) (MH) ! 76: * ! 77: * 18.Sep.94: Workaround for 'EL-Bug'. Removed flexible RBD-handling. ! 78: * Now, every RFD has exact one RBD. (MH) ! 79: * ! 80: * 14.Sep.94: added promiscuous mode, a few cleanups (MH) ! 81: * ! 82: * 19.Aug.94: changed request_irq() parameter (MH) ! 83: * ! 84: * 20.July.94: removed cleanup bugs, removed a 16K-mem-probe-bug (MH) ! 85: * ! 86: * 19.July.94: lotsa cleanups .. (MH) ! 87: * ! 88: * 17.July.94: some patches ... verified to run with 1.1.29 (MH) ! 89: * ! 90: * 4.July.94: patches for Linux 1.1.24 (MH) ! 91: * ! 92: * 26.March.94: patches for Linux 1.0 and iomem-auto-probe (MH) ! 93: * ! 94: * 30.Sep.93: Added nop-chain .. driver now runs with only one Xmit-Buff, too (MH) ! 95: * ! 96: * < 30.Sep.93: first versions ! 97: */ ! 98: ! 99: static int debuglevel = 0; /* debug-printk 0: off 1: a few 2: more */ ! 100: static int automatic_resume = 0; /* experimental .. better should be zero */ ! 101: static int rfdadd = 0; /* rfdadd=1 may be better for 8K MEM cards */ ! 102: static int fifo=0x8; /* don't change */ ! 103: ! 104: /* #define REALLY_SLOW_IO */ ! 105: ! 106: #include <linux/module.h> ! 107: #include <linux/kernel.h> ! 108: #include <linux/string.h> ! 109: #include <linux/errno.h> ! 110: #include <linux/ioport.h> ! 111: #include <linux/malloc.h> ! 112: #include <linux/interrupt.h> ! 113: #include <linux/delay.h> ! 114: #include <asm/bitops.h> ! 115: #include <asm/io.h> ! 116: ! 117: #include <linux/netdevice.h> ! 118: #include <linux/etherdevice.h> ! 119: #include <linux/skbuff.h> ! 120: ! 121: #include "ni52.h" ! 122: ! 123: #define DEBUG /* debug on */ ! 124: #define SYSBUSVAL 1 /* 8 Bit */ ! 125: ! 126: #define ni_attn586() {outb(0,dev->base_addr+NI52_ATTENTION);} ! 127: #define ni_reset586() {outb(0,dev->base_addr+NI52_RESET);} ! 128: #define ni_disint() {outb(0,dev->base_addr+NI52_INTDIS);} ! 129: #define ni_enaint() {outb(0,dev->base_addr+NI52_INTENA);} ! 130: ! 131: #define make32(ptr16) (p->memtop + (short) (ptr16) ) ! 132: #define make24(ptr32) ((char *) (ptr32) - p->base) ! 133: #define make16(ptr32) ((unsigned short) ((unsigned long) (ptr32) - (unsigned long) p->memtop )) ! 134: ! 135: /******************* how to calculate the buffers ***************************** ! 136: ! 137: * IMPORTANT NOTE: if you configure only one NUM_XMIT_BUFFS, the driver works ! 138: * --------------- in a different (more stable?) mode. Only in this mode it's ! 139: * possible to configure the driver with 'NO_NOPCOMMANDS' ! 140: ! 141: sizeof(scp)=12; sizeof(scb)=16; sizeof(iscp)=8; ! 142: sizeof(scp)+sizeof(iscp)+sizeof(scb) = 36 = INIT ! 143: sizeof(rfd) = 24; sizeof(rbd) = 12; ! 144: sizeof(tbd) = 8; sizeof(transmit_cmd) = 16; ! 145: sizeof(nop_cmd) = 8; ! 146: ! 147: * if you don't know the driver, better do not change these values: */ ! 148: ! 149: #define RECV_BUFF_SIZE 1524 /* slightly oversized */ ! 150: #define XMIT_BUFF_SIZE 1524 /* slightly oversized */ ! 151: #define NUM_XMIT_BUFFS 1 /* config for both, 8K and 16K shmem */ ! 152: #define NUM_RECV_BUFFS_8 4 /* config for 8K shared mem */ ! 153: #define NUM_RECV_BUFFS_16 9 /* config for 16K shared mem */ ! 154: #define NO_NOPCOMMANDS /* only possible with NUM_XMIT_BUFFS=1 */ ! 155: ! 156: /**************************************************************************/ ! 157: ! 158: /* different DELAYs */ ! 159: #define DELAY(x) __delay((loops_per_sec>>5)*(x)); ! 160: #define DELAY_16(); { __delay( (loops_per_sec>>16)+1 ); } ! 161: #define DELAY_18(); { __delay( (loops_per_sec>>18)+1 ); } ! 162: ! 163: /* wait for command with timeout: */ ! 164: #define WAIT_4_SCB_CMD() { int i; \ ! 165: for(i=0;i<16384;i++) { \ ! 166: if(!p->scb->cmd_cuc) break; \ ! 167: DELAY_18(); \ ! 168: if(i == 16383) { \ ! 169: printk("%s: scb_cmd timed out: %04x,%04x .. disabling i82586!!\n",dev->name,p->scb->cmd_cuc,p->scb->cus); \ ! 170: if(!p->reseted) { p->reseted = 1; ni_reset586(); } } } } ! 171: ! 172: #define WAIT_4_SCB_CMD_RUC() { int i; \ ! 173: for(i=0;i<16384;i++) { \ ! 174: if(!p->scb->cmd_ruc) break; \ ! 175: DELAY_18(); \ ! 176: if(i == 16383) { \ ! 177: printk("%s: scb_cmd (ruc) timed out: %04x,%04x .. disabling i82586!!\n",dev->name,p->scb->cmd_ruc,p->scb->rus); \ ! 178: if(!p->reseted) { p->reseted = 1; ni_reset586(); } } } } ! 179: ! 180: #define WAIT_4_STAT_COMPL(addr) { int i; \ ! 181: for(i=0;i<32767;i++) { \ ! 182: if((addr)->cmd_status & STAT_COMPL) break; \ ! 183: DELAY_16(); DELAY_16(); } } ! 184: ! 185: #define NI52_TOTAL_SIZE 16 ! 186: #define NI52_ADDR0 0x02 ! 187: #define NI52_ADDR1 0x07 ! 188: #define NI52_ADDR2 0x01 ! 189: ! 190: static int ni52_probe1(struct device *dev,int ioaddr); ! 191: static void ni52_interrupt(int irq,void *dev_id,struct pt_regs *reg_ptr); ! 192: static int ni52_open(struct device *dev); ! 193: static int ni52_close(struct device *dev); ! 194: static int ni52_send_packet(struct sk_buff *,struct device *); ! 195: static struct enet_statistics *ni52_get_stats(struct device *dev); ! 196: static void set_multicast_list(struct device *dev); ! 197: #if 0 ! 198: static void ni52_dump(struct device *,void *); ! 199: #endif ! 200: ! 201: /* helper-functions */ ! 202: static int init586(struct device *dev); ! 203: static int check586(struct device *dev,char *where,unsigned size); ! 204: static void alloc586(struct device *dev); ! 205: static void startrecv586(struct device *dev); ! 206: static void *alloc_rfa(struct device *dev,void *ptr); ! 207: static void ni52_rcv_int(struct device *dev); ! 208: static void ni52_xmt_int(struct device *dev); ! 209: static void ni52_rnr_int(struct device *dev); ! 210: ! 211: struct priv ! 212: { ! 213: struct enet_statistics stats; ! 214: unsigned long base; ! 215: char *memtop; ! 216: int lock,reseted; ! 217: volatile struct rfd_struct *rfd_last,*rfd_top,*rfd_first; ! 218: volatile struct scp_struct *scp; /* volatile is important */ ! 219: volatile struct iscp_struct *iscp; /* volatile is important */ ! 220: volatile struct scb_struct *scb; /* volatile is important */ ! 221: volatile struct tbd_struct *xmit_buffs[NUM_XMIT_BUFFS]; ! 222: volatile struct transmit_cmd_struct *xmit_cmds[NUM_XMIT_BUFFS]; ! 223: #if (NUM_XMIT_BUFFS == 1) ! 224: volatile struct nop_cmd_struct *nop_cmds[2]; ! 225: #else ! 226: volatile struct nop_cmd_struct *nop_cmds[NUM_XMIT_BUFFS]; ! 227: #endif ! 228: volatile int nop_point,num_recv_buffs; ! 229: volatile char *xmit_cbuffs[NUM_XMIT_BUFFS]; ! 230: volatile int xmit_count,xmit_last; ! 231: }; ! 232: ! 233: /********************************************** ! 234: * close device ! 235: */ ! 236: static int ni52_close(struct device *dev) ! 237: { ! 238: free_irq(dev->irq, NULL); ! 239: irq2dev_map[dev->irq] = NULL; ! 240: ! 241: ni_reset586(); /* the hard way to stop the receiver */ ! 242: ! 243: dev->start = 0; ! 244: dev->tbusy = 0; ! 245: ! 246: MOD_DEC_USE_COUNT; ! 247: ! 248: return 0; ! 249: } ! 250: ! 251: /********************************************** ! 252: * open device ! 253: */ ! 254: static int ni52_open(struct device *dev) ! 255: { ! 256: ni_disint(); ! 257: alloc586(dev); ! 258: init586(dev); ! 259: startrecv586(dev); ! 260: ni_enaint(); ! 261: ! 262: if(request_irq(dev->irq, &ni52_interrupt,0,"ni5210",NULL)) ! 263: { ! 264: ni_reset586(); ! 265: return -EAGAIN; ! 266: } ! 267: irq2dev_map[dev->irq] = dev; ! 268: ! 269: dev->interrupt = 0; ! 270: dev->tbusy = 0; ! 271: dev->start = 1; ! 272: ! 273: MOD_INC_USE_COUNT; ! 274: ! 275: return 0; /* most done by init */ ! 276: } ! 277: ! 278: /********************************************** ! 279: * Check to see if there's an 82586 out there. ! 280: */ ! 281: static int check586(struct device *dev,char *where,unsigned size) ! 282: { ! 283: struct priv pb; ! 284: struct priv *p = /* (struct priv *) dev->priv*/ &pb; ! 285: char *iscp_addrs[2]; ! 286: int i; ! 287: ! 288: p->base = (unsigned long) where + size - 0x01000000; ! 289: p->memtop = where + size; ! 290: p->scp = (struct scp_struct *)(p->base + SCP_DEFAULT_ADDRESS); ! 291: memset((char *)p->scp,0, sizeof(struct scp_struct)); ! 292: for(i=0;i<sizeof(struct scp_struct);i++) /* memory was writeable? */ ! 293: if(((char *)p->scp)[i]) ! 294: return 0; ! 295: p->scp->sysbus = SYSBUSVAL; /* 1 = 8Bit-Bus, 0 = 16 Bit */ ! 296: if(p->scp->sysbus != SYSBUSVAL) ! 297: return 0; ! 298: ! 299: iscp_addrs[0] = where; ! 300: iscp_addrs[1]= (char *) p->scp - sizeof(struct iscp_struct); ! 301: ! 302: for(i=0;i<2;i++) ! 303: { ! 304: p->iscp = (struct iscp_struct *) iscp_addrs[i]; ! 305: memset((char *)p->iscp,0, sizeof(struct iscp_struct)); ! 306: ! 307: p->scp->iscp = make24(p->iscp); ! 308: p->iscp->busy = 1; ! 309: ! 310: ni_reset586(); ! 311: ni_attn586(); ! 312: DELAY(1); /* wait a while... */ ! 313: ! 314: if(p->iscp->busy) /* i82586 clears 'busy' after successful init */ ! 315: return 0; ! 316: } ! 317: return 1; ! 318: } ! 319: ! 320: /****************************************************************** ! 321: * set iscp at the right place, called by ni52_probe1 and open586. ! 322: */ ! 323: void alloc586(struct device *dev) ! 324: { ! 325: struct priv *p = (struct priv *) dev->priv; ! 326: ! 327: ni_reset586(); ! 328: DELAY(1); ! 329: ! 330: p->scp = (struct scp_struct *) (p->base + SCP_DEFAULT_ADDRESS); ! 331: p->scb = (struct scb_struct *) (dev->mem_start); ! 332: p->iscp = (struct iscp_struct *) ((char *)p->scp - sizeof(struct iscp_struct)); ! 333: ! 334: memset((char *) p->iscp,0,sizeof(struct iscp_struct)); ! 335: memset((char *) p->scp ,0,sizeof(struct scp_struct)); ! 336: ! 337: p->scp->iscp = make24(p->iscp); ! 338: p->scp->sysbus = SYSBUSVAL; ! 339: p->iscp->scb_offset = make16(p->scb); ! 340: ! 341: p->iscp->busy = 1; ! 342: ni_reset586(); ! 343: ni_attn586(); ! 344: ! 345: DELAY(1); ! 346: ! 347: if(p->iscp->busy) ! 348: printk("%s: Init-Problems (alloc).\n",dev->name); ! 349: ! 350: p->reseted = 0; ! 351: ! 352: memset((char *)p->scb,0,sizeof(struct scb_struct)); ! 353: } ! 354: ! 355: /********************************************** ! 356: * probe the ni5210-card ! 357: */ ! 358: int ni52_probe(struct device *dev) ! 359: { ! 360: #ifndef MODULE ! 361: int *port; ! 362: static int ports[] = {0x300, 0x280, 0x360 , 0x320 , 0x340, 0}; ! 363: #endif ! 364: int base_addr = dev->base_addr; ! 365: ! 366: if (base_addr > 0x1ff) /* Check a single specified location. */ ! 367: if( (inb(base_addr+NI52_MAGIC1) == NI52_MAGICVAL1) && ! 368: (inb(base_addr+NI52_MAGIC2) == NI52_MAGICVAL2)) ! 369: return ni52_probe1(dev, base_addr); ! 370: else if (base_addr > 0) /* Don't probe at all. */ ! 371: return ENXIO; ! 372: ! 373: #ifdef MODULE ! 374: printk("%s: no autoprobing allowed for modules.\n",dev->name); ! 375: #else ! 376: for (port = ports; *port; port++) { ! 377: int ioaddr = *port; ! 378: if (check_region(ioaddr, NI52_TOTAL_SIZE)) ! 379: continue; ! 380: if( !(inb(ioaddr+NI52_MAGIC1) == NI52_MAGICVAL1) || ! 381: !(inb(ioaddr+NI52_MAGIC2) == NI52_MAGICVAL2)) ! 382: continue; ! 383: ! 384: dev->base_addr = ioaddr; ! 385: if (ni52_probe1(dev, ioaddr) == 0) ! 386: return 0; ! 387: } ! 388: ! 389: #ifdef FULL_IO_PROBE ! 390: for(dev->base_addr=0x200;dev->base_addr<0x400;dev->base_addr+=8) ! 391: { ! 392: int ioaddr = dev->base_addr; ! 393: if (check_region(ioaddr, NI52_TOTAL_SIZE)) ! 394: continue; ! 395: if( !(inb(ioaddr+NI52_MAGIC1) == NI52_MAGICVAL1) || ! 396: !(inb(ioaddr+NI52_MAGIC2) == NI52_MAGICVAL2)) ! 397: continue; ! 398: if (ni52_probe1(dev, ioaddr) == 0) ! 399: return 0; ! 400: } ! 401: #endif ! 402: ! 403: #endif ! 404: ! 405: dev->base_addr = base_addr; ! 406: return ENODEV; ! 407: } ! 408: ! 409: static int ni52_probe1(struct device *dev,int ioaddr) ! 410: { ! 411: int i,size; ! 412: ! 413: for(i=0;i<ETH_ALEN;i++) ! 414: dev->dev_addr[i] = inb(dev->base_addr+i); ! 415: ! 416: if(dev->dev_addr[0] != NI52_ADDR0 || dev->dev_addr[1] != NI52_ADDR1 ! 417: || dev->dev_addr[2] != NI52_ADDR2) ! 418: return ENODEV; ! 419: ! 420: printk("%s: NI5210 found at %#3lx, ",dev->name,dev->base_addr); ! 421: ! 422: request_region(ioaddr,NI52_TOTAL_SIZE,"ni5210"); ! 423: ! 424: /* ! 425: * check (or search) IO-Memory, 8K and 16K ! 426: */ ! 427: #ifdef MODULE ! 428: size = dev->mem_end - dev->mem_start; ! 429: if(size != 0x2000 && size != 0x4000) ! 430: { ! 431: printk("\n%s: Illegal memory size %d. Allowed is 0x2000 or 0x4000 bytes.\n",dev->name,size); ! 432: return ENODEV; ! 433: } ! 434: if(!check586(dev,(char *) dev->mem_start,size)) ! 435: { ! 436: printk("?memcheck, Can't find memory at 0x%lx with size %d!\n",dev->mem_start,size); ! 437: return ENODEV; ! 438: } ! 439: #else ! 440: if(dev->mem_start != 0) /* no auto-mem-probe */ ! 441: { ! 442: size = 0x4000; /* check for 16K mem */ ! 443: if(!check586(dev,(char *) dev->mem_start,size)) { ! 444: size = 0x2000; /* check for 8K mem */ ! 445: if(!check586(dev,(char *) dev->mem_start,size)) { ! 446: printk("?memprobe, Can't find memory at 0x%lx!\n",dev->mem_start); ! 447: return ENODEV; ! 448: } ! 449: } ! 450: } ! 451: else ! 452: { ! 453: static long memaddrs[] = { 0xc8000,0xca000,0xcc000,0xce000,0xd0000,0xd2000, ! 454: 0xd4000,0xd6000,0xd8000,0xda000,0xdc000, 0 }; ! 455: for(i=0;;i++) ! 456: { ! 457: if(!memaddrs[i]) { ! 458: printk("?memprobe, Can't find io-memory!\n"); ! 459: return ENODEV; ! 460: } ! 461: dev->mem_start = memaddrs[i]; ! 462: size = 0x2000; /* check for 8K mem */ ! 463: if(check586(dev,(char *)dev->mem_start,size)) /* 8K-check */ ! 464: break; ! 465: size = 0x4000; /* check for 16K mem */ ! 466: if(check586(dev,(char *)dev->mem_start,size)) /* 16K-check */ ! 467: break; ! 468: } ! 469: } ! 470: dev->mem_end = dev->mem_start + size; /* set mem_end showed by 'ifconfig' */ ! 471: #endif ! 472: ! 473: dev->priv = (void *) kmalloc(sizeof(struct priv),GFP_KERNEL); ! 474: if(dev->priv == NULL) ! 475: { ! 476: printk("%s: Ooops .. can't allocate private driver memory.\n",dev->name); ! 477: return -ENOMEM; ! 478: } ! 479: /* warning: we don't free it on errors */ ! 480: memset((char *) dev->priv,0,sizeof(struct priv)); ! 481: ! 482: ((struct priv *) (dev->priv))->memtop = (char *) dev->mem_start + size; ! 483: ((struct priv *) (dev->priv))->base = dev->mem_start + size - 0x01000000; ! 484: alloc586(dev); ! 485: ! 486: /* set number of receive-buffs according to memsize */ ! 487: if(size == 0x2000) ! 488: ((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_8; ! 489: else ! 490: ((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_16; ! 491: ! 492: printk("Memaddr: 0x%lx, Memsize: %d, ",dev->mem_start,size); ! 493: ! 494: if(dev->irq < 2) ! 495: { ! 496: autoirq_setup(0); ! 497: ni_reset586(); ! 498: ni_attn586(); ! 499: if(!(dev->irq = autoirq_report(2))) ! 500: { ! 501: printk("?autoirq, Failed to detect IRQ line!\n"); ! 502: return 1; ! 503: } ! 504: printk("IRQ %d (autodetected).\n",dev->irq); ! 505: } ! 506: else { ! 507: if(dev->irq == 2) ! 508: dev->irq = 9; ! 509: printk("IRQ %d (assigned and not checked!).\n",dev->irq); ! 510: } ! 511: ! 512: dev->open = &ni52_open; ! 513: dev->stop = &ni52_close; ! 514: dev->get_stats = &ni52_get_stats; ! 515: dev->hard_start_xmit = &ni52_send_packet; ! 516: dev->set_multicast_list = &set_multicast_list; ! 517: ! 518: dev->if_port = 0; ! 519: ! 520: ether_setup(dev); ! 521: ! 522: dev->tbusy = 0; ! 523: dev->interrupt = 0; ! 524: dev->start = 0; ! 525: ! 526: return 0; ! 527: } ! 528: ! 529: /********************************************** ! 530: * init the chip (ni52-interrupt should be disabled?!) ! 531: * needs a correct 'allocated' memory ! 532: */ ! 533: ! 534: static int init586(struct device *dev) ! 535: { ! 536: void *ptr; ! 537: int i,result=0; ! 538: struct priv *p = (struct priv *) dev->priv; ! 539: volatile struct configure_cmd_struct *cfg_cmd; ! 540: volatile struct iasetup_cmd_struct *ias_cmd; ! 541: volatile struct tdr_cmd_struct *tdr_cmd; ! 542: volatile struct mcsetup_cmd_struct *mc_cmd; ! 543: struct dev_mc_list *dmi=dev->mc_list; ! 544: int num_addrs=dev->mc_count; ! 545: ! 546: ptr = (void *) ((char *)p->scb + sizeof(struct scb_struct)); ! 547: ! 548: cfg_cmd = (struct configure_cmd_struct *)ptr; /* configure-command */ ! 549: cfg_cmd->cmd_status = 0; ! 550: cfg_cmd->cmd_cmd = CMD_CONFIGURE | CMD_LAST; ! 551: cfg_cmd->cmd_link = 0xffff; ! 552: ! 553: cfg_cmd->byte_cnt = 0x0a; /* number of cfg bytes */ ! 554: cfg_cmd->fifo = fifo; /* fifo-limit (8=tx:32/rx:64) */ ! 555: cfg_cmd->sav_bf = 0x40; /* hold or discard bad recv frames (bit 7) */ ! 556: cfg_cmd->adr_len = 0x2e; /* addr_len |!src_insert |pre-len |loopback */ ! 557: cfg_cmd->priority = 0x00; ! 558: cfg_cmd->ifs = 0x60; ! 559: cfg_cmd->time_low = 0x00; ! 560: cfg_cmd->time_high = 0xf2; ! 561: cfg_cmd->promisc = 0; ! 562: if(dev->flags & IFF_ALLMULTI) { ! 563: int len = ((char *) p->iscp - (char *) ptr - 8) / 6; ! 564: if(num_addrs > len) { ! 565: printk("%s: switching to promisc. mode\n",dev->name); ! 566: dev->flags|=IFF_PROMISC; ! 567: } ! 568: } ! 569: if(dev->flags&IFF_PROMISC) ! 570: { ! 571: cfg_cmd->promisc=1; ! 572: dev->flags|=IFF_PROMISC; ! 573: } ! 574: cfg_cmd->carr_coll = 0x00; ! 575: ! 576: p->scb->cbl_offset = make16(cfg_cmd); ! 577: p->scb->cmd_ruc = 0; ! 578: ! 579: p->scb->cmd_cuc = CUC_START; /* cmd.-unit start */ ! 580: ni_attn586(); ! 581: ! 582: WAIT_4_STAT_COMPL(cfg_cmd); ! 583: ! 584: if((cfg_cmd->cmd_status & (STAT_OK|STAT_COMPL)) != (STAT_COMPL|STAT_OK)) ! 585: { ! 586: printk("%s: configure command failed: %x\n",dev->name,cfg_cmd->cmd_status); ! 587: return 1; ! 588: } ! 589: ! 590: /* ! 591: * individual address setup ! 592: */ ! 593: ias_cmd = (struct iasetup_cmd_struct *)ptr; ! 594: ! 595: ias_cmd->cmd_status = 0; ! 596: ias_cmd->cmd_cmd = CMD_IASETUP | CMD_LAST; ! 597: ias_cmd->cmd_link = 0xffff; ! 598: ! 599: memcpy((char *)&ias_cmd->iaddr,(char *) dev->dev_addr,ETH_ALEN); ! 600: ! 601: p->scb->cbl_offset = make16(ias_cmd); ! 602: ! 603: p->scb->cmd_cuc = CUC_START; /* cmd.-unit start */ ! 604: ni_attn586(); ! 605: ! 606: WAIT_4_STAT_COMPL(ias_cmd); ! 607: ! 608: if((ias_cmd->cmd_status & (STAT_OK|STAT_COMPL)) != (STAT_OK|STAT_COMPL)) { ! 609: printk("%s (ni52): individual address setup command failed: %04x\n",dev->name,ias_cmd->cmd_status); ! 610: return 1; ! 611: } ! 612: ! 613: /* ! 614: * TDR, wire check .. e.g. no resistor e.t.c ! 615: */ ! 616: tdr_cmd = (struct tdr_cmd_struct *)ptr; ! 617: ! 618: tdr_cmd->cmd_status = 0; ! 619: tdr_cmd->cmd_cmd = CMD_TDR | CMD_LAST; ! 620: tdr_cmd->cmd_link = 0xffff; ! 621: tdr_cmd->status = 0; ! 622: ! 623: p->scb->cbl_offset = make16(tdr_cmd); ! 624: p->scb->cmd_cuc = CUC_START; /* cmd.-unit start */ ! 625: ni_attn586(); ! 626: ! 627: WAIT_4_STAT_COMPL(tdr_cmd); ! 628: ! 629: if(!(tdr_cmd->cmd_status & STAT_COMPL)) ! 630: { ! 631: printk("%s: Problems while running the TDR.\n",dev->name); ! 632: } ! 633: else ! 634: { ! 635: DELAY_16(); /* wait for result */ ! 636: result = tdr_cmd->status; ! 637: ! 638: p->scb->cmd_cuc = p->scb->cus & STAT_MASK; ! 639: ni_attn586(); /* ack the interrupts */ ! 640: ! 641: if(result & TDR_LNK_OK) ! 642: ; ! 643: else if(result & TDR_XCVR_PRB) ! 644: printk("%s: TDR: Transceiver problem. Check the cable(s)!\n",dev->name); ! 645: else if(result & TDR_ET_OPN) ! 646: printk("%s: TDR: No correct termination %d clocks away.\n",dev->name,result & TDR_TIMEMASK); ! 647: else if(result & TDR_ET_SRT) ! 648: { ! 649: if (result & TDR_TIMEMASK) /* time == 0 -> strange :-) */ ! 650: printk("%s: TDR: Detected a short circuit %d clocks away.\n",dev->name,result & TDR_TIMEMASK); ! 651: } ! 652: else ! 653: printk("%s: TDR: Unknown status %04x\n",dev->name,result); ! 654: } ! 655: ! 656: /* ! 657: * Multicast setup ! 658: */ ! 659: if(num_addrs && !(dev->flags & IFF_PROMISC) ) ! 660: { ! 661: mc_cmd = (struct mcsetup_cmd_struct *) ptr; ! 662: mc_cmd->cmd_status = 0; ! 663: mc_cmd->cmd_cmd = CMD_MCSETUP | CMD_LAST; ! 664: mc_cmd->cmd_link = 0xffff; ! 665: mc_cmd->mc_cnt = num_addrs * 6; ! 666: ! 667: for(i=0;i<num_addrs;i++,dmi=dmi->next) ! 668: memcpy((char *) mc_cmd->mc_list[i], dmi->dmi_addr,6); ! 669: ! 670: p->scb->cbl_offset = make16(mc_cmd); ! 671: p->scb->cmd_cuc = CUC_START; ! 672: ni_attn586(); ! 673: ! 674: WAIT_4_STAT_COMPL(mc_cmd); ! 675: ! 676: if( (mc_cmd->cmd_status & (STAT_COMPL|STAT_OK)) != (STAT_COMPL|STAT_OK) ) ! 677: printk("%s: Can't apply multicast-address-list.\n",dev->name); ! 678: } ! 679: ! 680: /* ! 681: * alloc nop/xmit-cmds ! 682: */ ! 683: #if (NUM_XMIT_BUFFS == 1) ! 684: for(i=0;i<2;i++) ! 685: { ! 686: p->nop_cmds[i] = (struct nop_cmd_struct *)ptr; ! 687: p->nop_cmds[i]->cmd_cmd = CMD_NOP; ! 688: p->nop_cmds[i]->cmd_status = 0; ! 689: p->nop_cmds[i]->cmd_link = make16((p->nop_cmds[i])); ! 690: ptr = (char *) ptr + sizeof(struct nop_cmd_struct); ! 691: } ! 692: #else ! 693: for(i=0;i<NUM_XMIT_BUFFS;i++) ! 694: { ! 695: p->nop_cmds[i] = (struct nop_cmd_struct *)ptr; ! 696: p->nop_cmds[i]->cmd_cmd = CMD_NOP; ! 697: p->nop_cmds[i]->cmd_status = 0; ! 698: p->nop_cmds[i]->cmd_link = make16((p->nop_cmds[i])); ! 699: ptr = (char *) ptr + sizeof(struct nop_cmd_struct); ! 700: } ! 701: #endif ! 702: ! 703: ptr = alloc_rfa(dev,(void *)ptr); /* init receive-frame-area */ ! 704: ! 705: /* ! 706: * alloc xmit-buffs / init xmit_cmds ! 707: */ ! 708: for(i=0;i<NUM_XMIT_BUFFS;i++) ! 709: { ! 710: p->xmit_cmds[i] = (struct transmit_cmd_struct *)ptr; /*transmit cmd/buff 0*/ ! 711: ptr = (char *) ptr + sizeof(struct transmit_cmd_struct); ! 712: p->xmit_cbuffs[i] = (char *)ptr; /* char-buffs */ ! 713: ptr = (char *) ptr + XMIT_BUFF_SIZE; ! 714: p->xmit_buffs[i] = (struct tbd_struct *)ptr; /* TBD */ ! 715: ptr = (char *) ptr + sizeof(struct tbd_struct); ! 716: if((void *)ptr > (void *)p->iscp) ! 717: { ! 718: printk("%s: not enough shared-mem for your configuration!\n",dev->name); ! 719: return 1; ! 720: } ! 721: memset((char *)(p->xmit_cmds[i]) ,0, sizeof(struct transmit_cmd_struct)); ! 722: memset((char *)(p->xmit_buffs[i]),0, sizeof(struct tbd_struct)); ! 723: p->xmit_cmds[i]->cmd_link = make16(p->nop_cmds[(i+1)%NUM_XMIT_BUFFS]); ! 724: p->xmit_cmds[i]->cmd_status = STAT_COMPL; ! 725: p->xmit_cmds[i]->cmd_cmd = CMD_XMIT | CMD_INT; ! 726: p->xmit_cmds[i]->tbd_offset = make16((p->xmit_buffs[i])); ! 727: p->xmit_buffs[i]->next = 0xffff; ! 728: p->xmit_buffs[i]->buffer = make24((p->xmit_cbuffs[i])); ! 729: } ! 730: ! 731: p->xmit_count = 0; ! 732: p->xmit_last = 0; ! 733: #ifndef NO_NOPCOMMANDS ! 734: p->nop_point = 0; ! 735: #endif ! 736: ! 737: /* ! 738: * 'start transmitter' ! 739: */ ! 740: #ifndef NO_NOPCOMMANDS ! 741: p->scb->cbl_offset = make16(p->nop_cmds[0]); ! 742: p->scb->cmd_cuc = CUC_START; ! 743: ni_attn586(); ! 744: WAIT_4_SCB_CMD(); ! 745: #else ! 746: p->xmit_cmds[0]->cmd_link = make16(p->xmit_cmds[0]); ! 747: p->xmit_cmds[0]->cmd_cmd = CMD_XMIT | CMD_SUSPEND | CMD_INT; ! 748: #endif ! 749: ! 750: /* ! 751: * ack. interrupts ! 752: */ ! 753: p->scb->cmd_cuc = p->scb->cus & STAT_MASK; ! 754: ni_attn586(); ! 755: DELAY_16(); ! 756: ! 757: ni_enaint(); ! 758: ! 759: return 0; ! 760: } ! 761: ! 762: /****************************************************** ! 763: * This is a helper routine for ni52_rnr_int() and init586(). ! 764: * It sets up the Receive Frame Area (RFA). ! 765: */ ! 766: ! 767: static void *alloc_rfa(struct device *dev,void *ptr) ! 768: { ! 769: volatile struct rfd_struct *rfd = (struct rfd_struct *)ptr; ! 770: volatile struct rbd_struct *rbd; ! 771: int i; ! 772: struct priv *p = (struct priv *) dev->priv; ! 773: ! 774: memset((char *) rfd,0,sizeof(struct rfd_struct)*(p->num_recv_buffs+rfdadd)); ! 775: p->rfd_first = rfd; ! 776: ! 777: for(i = 0; i < (p->num_recv_buffs+rfdadd); i++) { ! 778: rfd[i].next = make16(rfd + (i+1) % (p->num_recv_buffs+rfdadd) ); ! 779: rfd[i].rbd_offset = 0xffff; ! 780: } ! 781: rfd[p->num_recv_buffs-1+rfdadd].last = RFD_SUSP; /* RU suspend */ ! 782: ! 783: ptr = (void *) (rfd + (p->num_recv_buffs + rfdadd) ); ! 784: ! 785: rbd = (struct rbd_struct *) ptr; ! 786: ptr = (void *) (rbd + p->num_recv_buffs); ! 787: ! 788: /* clr descriptors */ ! 789: memset((char *) rbd,0,sizeof(struct rbd_struct)*(p->num_recv_buffs)); ! 790: ! 791: for(i=0;i<p->num_recv_buffs;i++) ! 792: { ! 793: rbd[i].next = make16((rbd + (i+1) % p->num_recv_buffs)); ! 794: rbd[i].size = RECV_BUFF_SIZE; ! 795: rbd[i].buffer = make24(ptr); ! 796: ptr = (char *) ptr + RECV_BUFF_SIZE; ! 797: } ! 798: ! 799: p->rfd_top = p->rfd_first; ! 800: p->rfd_last = p->rfd_first + (p->num_recv_buffs - 1 + rfdadd); ! 801: ! 802: p->scb->rfa_offset = make16(p->rfd_first); ! 803: p->rfd_first->rbd_offset = make16(rbd); ! 804: ! 805: return ptr; ! 806: } ! 807: ! 808: ! 809: /************************************************** ! 810: * Interrupt Handler ... ! 811: */ ! 812: ! 813: static void ni52_interrupt(int irq,void *dev_id,struct pt_regs *reg_ptr) ! 814: { ! 815: struct device *dev = (struct device *) irq2dev_map[irq]; ! 816: unsigned short stat; ! 817: int cnt=0; ! 818: struct priv *p; ! 819: ! 820: if (!dev) { ! 821: printk ("ni5210-interrupt: irq %d for unknown device.\n",irq); ! 822: return; ! 823: } ! 824: p = (struct priv *) dev->priv; ! 825: ! 826: if(debuglevel > 1) ! 827: printk("I"); ! 828: ! 829: dev->interrupt = 1; ! 830: ! 831: WAIT_4_SCB_CMD(); /* wait for last command */ ! 832: ! 833: while((stat=p->scb->cus & STAT_MASK)) ! 834: { ! 835: p->scb->cmd_cuc = stat; ! 836: ni_attn586(); ! 837: ! 838: if(stat & STAT_FR) /* received a frame */ ! 839: ni52_rcv_int(dev); ! 840: ! 841: if(stat & STAT_RNR) /* RU went 'not ready' */ ! 842: { ! 843: printk("(R)"); ! 844: if(p->scb->rus & RU_SUSPEND) /* special case: RU_SUSPEND */ ! 845: { ! 846: WAIT_4_SCB_CMD(); ! 847: p->scb->cmd_ruc = RUC_RESUME; ! 848: ni_attn586(); ! 849: WAIT_4_SCB_CMD_RUC(); ! 850: } ! 851: else ! 852: { ! 853: printk("%s: Receiver-Unit went 'NOT READY': %04x/%02x.\n",dev->name,(int) stat,(int) p->scb->rus); ! 854: ni52_rnr_int(dev); ! 855: } ! 856: } ! 857: ! 858: if(stat & STAT_CX) /* command with I-bit set complete */ ! 859: ni52_xmt_int(dev); ! 860: ! 861: #ifndef NO_NOPCOMMANDS ! 862: if(stat & STAT_CNA) /* CU went 'not ready' */ ! 863: { ! 864: if(dev->start) ! 865: printk("%s: oops! CU has left active state. stat: %04x/%02x.\n",dev->name,(int) stat,(int) p->scb->cus); ! 866: } ! 867: #endif ! 868: ! 869: if(debuglevel > 1) ! 870: printk("%d",cnt++); ! 871: ! 872: WAIT_4_SCB_CMD(); /* wait for ack. (ni52_xmt_int can be faster than ack!!) */ ! 873: if(p->scb->cmd_cuc) /* timed out? */ ! 874: { ! 875: printk("%s: Acknowledge timed out.\n",dev->name); ! 876: ni_disint(); ! 877: break; ! 878: } ! 879: } ! 880: ! 881: if(debuglevel > 1) ! 882: printk("i"); ! 883: ! 884: dev->interrupt = 0; ! 885: } ! 886: ! 887: /******************************************************* ! 888: * receive-interrupt ! 889: */ ! 890: ! 891: static void ni52_rcv_int(struct device *dev) ! 892: { ! 893: int status,cnt=0; ! 894: unsigned short totlen; ! 895: struct sk_buff *skb; ! 896: struct rbd_struct *rbd; ! 897: struct priv *p = (struct priv *) dev->priv; ! 898: ! 899: if(debuglevel > 0) ! 900: printk("R"); ! 901: ! 902: for(;(status = p->rfd_top->stat_high) & RFD_COMPL;) ! 903: { ! 904: rbd = (struct rbd_struct *) make32(p->rfd_top->rbd_offset); ! 905: ! 906: if(status & RFD_OK) /* frame received without error? */ ! 907: { ! 908: if( (totlen = rbd->status) & RBD_LAST) /* the first and the last buffer? */ ! 909: { ! 910: totlen &= RBD_MASK; /* length of this frame */ ! 911: rbd->status = 0; ! 912: skb = (struct sk_buff *) dev_alloc_skb(totlen+2); ! 913: if(skb != NULL) ! 914: { ! 915: skb->dev = dev; ! 916: skb_reserve(skb,2); ! 917: skb_put(skb,totlen); ! 918: eth_copy_and_sum(skb,(char *) p->base+(unsigned long) rbd->buffer,totlen,0); ! 919: skb->protocol=eth_type_trans(skb,dev); ! 920: netif_rx(skb); ! 921: p->stats.rx_packets++; ! 922: } ! 923: else ! 924: p->stats.rx_dropped++; ! 925: } ! 926: else ! 927: { ! 928: int rstat; ! 929: /* free all RBD's until RBD_LAST is set */ ! 930: totlen = 0; ! 931: while(!((rstat=rbd->status) & RBD_LAST)) ! 932: { ! 933: totlen += rstat & RBD_MASK; ! 934: if(!rstat) ! 935: { ! 936: printk("%s: Whoops .. no end mark in RBD list\n",dev->name); ! 937: break; ! 938: } ! 939: rbd->status = 0; ! 940: rbd = (struct rbd_struct *) make32(rbd->next); ! 941: } ! 942: totlen += rstat & RBD_MASK; ! 943: rbd->status = 0; ! 944: printk("%s: received oversized frame! length: %d\n",dev->name,totlen); ! 945: p->stats.rx_dropped++; ! 946: } ! 947: } ! 948: else /* frame !(ok), only with 'save-bad-frames' */ ! 949: { ! 950: printk("%s: oops! rfd-error-status: %04x\n",dev->name,status); ! 951: p->stats.rx_errors++; ! 952: } ! 953: p->rfd_top->stat_high = 0; ! 954: p->rfd_top->last = RFD_SUSP; /* maybe exchange by RFD_LAST */ ! 955: p->rfd_top->rbd_offset = 0xffff; ! 956: p->rfd_last->last = 0; /* delete RFD_SUSP */ ! 957: p->rfd_last = p->rfd_top; ! 958: p->rfd_top = (struct rfd_struct *) make32(p->rfd_top->next); /* step to next RFD */ ! 959: p->scb->rfa_offset = make16(p->rfd_top); ! 960: ! 961: if(debuglevel > 0) ! 962: printk("%d",cnt++); ! 963: } ! 964: ! 965: if(automatic_resume) ! 966: { ! 967: WAIT_4_SCB_CMD(); ! 968: p->scb->cmd_ruc = RUC_RESUME; ! 969: ni_attn586(); ! 970: WAIT_4_SCB_CMD_RUC(); ! 971: } ! 972: ! 973: #ifdef WAIT_4_BUSY ! 974: { ! 975: int i; ! 976: for(i=0;i<1024;i++) ! 977: { ! 978: if(p->rfd_top->status) ! 979: break; ! 980: DELAY_16(); ! 981: if(i == 1023) ! 982: printk("%s: RU hasn't fetched next RFD (not busy/complete)\n",dev->name); ! 983: } ! 984: } ! 985: #endif ! 986: ! 987: #if 0 ! 988: if(!at_least_one) ! 989: { ! 990: int i; ! 991: volatile struct rfd_struct *rfds=p->rfd_top; ! 992: volatile struct rbd_struct *rbds; ! 993: printk("%s: received a FC intr. without having a frame: %04x %d\n",dev->name,status,old_at_least); ! 994: for(i=0;i< (p->num_recv_buffs+4);i++) ! 995: { ! 996: rbds = (struct rbd_struct *) make32(rfds->rbd_offset); ! 997: printk("%04x:%04x ",rfds->status,rbds->status); ! 998: rfds = (struct rfd_struct *) make32(rfds->next); ! 999: } ! 1000: printk("\nerrs: %04x %04x stat: %04x\n",(int)p->scb->rsc_errs,(int)p->scb->ovrn_errs,(int)p->scb->status); ! 1001: printk("\nerrs: %04x %04x rus: %02x, cus: %02x\n",(int)p->scb->rsc_errs,(int)p->scb->ovrn_errs,(int)p->scb->rus,(int)p->scb->cus); ! 1002: } ! 1003: old_at_least = at_least_one; ! 1004: #endif ! 1005: ! 1006: if(debuglevel > 0) ! 1007: printk("r"); ! 1008: } ! 1009: ! 1010: /********************************************************** ! 1011: * handle 'Receiver went not ready'. ! 1012: */ ! 1013: ! 1014: static void ni52_rnr_int(struct device *dev) ! 1015: { ! 1016: struct priv *p = (struct priv *) dev->priv; ! 1017: ! 1018: p->stats.rx_errors++; ! 1019: ! 1020: WAIT_4_SCB_CMD(); /* wait for the last cmd, WAIT_4_FULLSTAT?? */ ! 1021: p->scb->cmd_ruc = RUC_ABORT; /* usually the RU is in the 'no resource'-state .. abort it now. */ ! 1022: ni_attn586(); ! 1023: WAIT_4_SCB_CMD_RUC(); /* wait for accept cmd. */ ! 1024: ! 1025: alloc_rfa(dev,(char *)p->rfd_first); ! 1026: /* maybe add a check here, before restarting the RU */ ! 1027: startrecv586(dev); /* restart RU */ ! 1028: ! 1029: printk("%s: Receive-Unit restarted. Status: %04x\n",dev->name,p->scb->rus); ! 1030: ! 1031: } ! 1032: ! 1033: /********************************************************** ! 1034: * handle xmit - interrupt ! 1035: */ ! 1036: ! 1037: static void ni52_xmt_int(struct device *dev) ! 1038: { ! 1039: int status; ! 1040: struct priv *p = (struct priv *) dev->priv; ! 1041: ! 1042: if(debuglevel > 0) ! 1043: printk("X"); ! 1044: ! 1045: status = p->xmit_cmds[p->xmit_last]->cmd_status; ! 1046: if(!(status & STAT_COMPL)) ! 1047: printk("%s: strange .. xmit-int without a 'COMPLETE'\n",dev->name); ! 1048: ! 1049: if(status & STAT_OK) ! 1050: { ! 1051: p->stats.tx_packets++; ! 1052: p->stats.collisions += (status & TCMD_MAXCOLLMASK); ! 1053: } ! 1054: else ! 1055: { ! 1056: p->stats.tx_errors++; ! 1057: if(status & TCMD_LATECOLL) { ! 1058: printk("%s: late collision detected.\n",dev->name); ! 1059: p->stats.collisions++; ! 1060: } ! 1061: else if(status & TCMD_NOCARRIER) { ! 1062: p->stats.tx_carrier_errors++; ! 1063: printk("%s: no carrier detected.\n",dev->name); ! 1064: } ! 1065: else if(status & TCMD_LOSTCTS) ! 1066: printk("%s: loss of CTS detected.\n",dev->name); ! 1067: else if(status & TCMD_UNDERRUN) { ! 1068: p->stats.tx_fifo_errors++; ! 1069: printk("%s: DMA underrun detected.\n",dev->name); ! 1070: } ! 1071: else if(status & TCMD_MAXCOLL) { ! 1072: printk("%s: Max. collisions exceeded.\n",dev->name); ! 1073: p->stats.collisions += 16; ! 1074: } ! 1075: } ! 1076: ! 1077: #if (NUM_XMIT_BUFFS > 1) ! 1078: if( (++p->xmit_last) == NUM_XMIT_BUFFS) ! 1079: p->xmit_last = 0; ! 1080: #endif ! 1081: ! 1082: dev->tbusy = 0; ! 1083: mark_bh(NET_BH); ! 1084: } ! 1085: ! 1086: /*********************************************************** ! 1087: * (re)start the receiver ! 1088: */ ! 1089: ! 1090: static void startrecv586(struct device *dev) ! 1091: { ! 1092: struct priv *p = (struct priv *) dev->priv; ! 1093: ! 1094: WAIT_4_SCB_CMD(); ! 1095: WAIT_4_SCB_CMD_RUC(); ! 1096: p->scb->rfa_offset = make16(p->rfd_first); ! 1097: p->scb->cmd_ruc = RUC_START; ! 1098: ni_attn586(); /* start cmd. */ ! 1099: WAIT_4_SCB_CMD_RUC(); /* wait for accept cmd. (no timeout!!) */ ! 1100: } ! 1101: ! 1102: /****************************************************** ! 1103: * send frame ! 1104: */ ! 1105: ! 1106: static int ni52_send_packet(struct sk_buff *skb, struct device *dev) ! 1107: { ! 1108: int len,i; ! 1109: #ifndef NO_NOPCOMMANDS ! 1110: int next_nop; ! 1111: #endif ! 1112: struct priv *p = (struct priv *) dev->priv; ! 1113: ! 1114: if(dev->tbusy) ! 1115: { ! 1116: int tickssofar = jiffies - dev->trans_start; ! 1117: if (tickssofar < 5) ! 1118: return 1; ! 1119: ! 1120: #ifndef NO_NOPCOMMANDS ! 1121: if(p->scb->cus & CU_ACTIVE) /* COMMAND-UNIT active? */ ! 1122: { ! 1123: dev->tbusy = 0; ! 1124: #ifdef DEBUG ! 1125: printk("%s: strange ... timeout with CU active?!?\n",dev->name); ! 1126: printk("%s: X0: %04x N0: %04x N1: %04x %d\n",dev->name,(int)p->xmit_cmds[0]->cmd_status,(int)p->nop_cmds[0]->cmd_status,(int)p->nop_cmds[1]->cmd_status,(int)p->nop_point); ! 1127: #endif ! 1128: p->scb->cmd_cuc = CUC_ABORT; ! 1129: ni_attn586(); ! 1130: WAIT_4_SCB_CMD(); ! 1131: p->scb->cbl_offset = make16(p->nop_cmds[p->nop_point]); ! 1132: p->scb->cmd_cuc = CUC_START; ! 1133: ni_attn586(); ! 1134: WAIT_4_SCB_CMD(); ! 1135: dev->trans_start = jiffies; ! 1136: dev_kfree_skb(skb, FREE_WRITE); ! 1137: return 0; ! 1138: } ! 1139: else ! 1140: #endif ! 1141: { ! 1142: #ifdef DEBUG ! 1143: printk("%s: xmitter timed out, try to restart! stat: %02x\n",dev->name,p->scb->cus); ! 1144: printk("%s: command-stats: %04x %04x\n",dev->name,p->xmit_cmds[0]->cmd_status,p->xmit_cmds[1]->cmd_status); ! 1145: printk("%s: check, whether you set the right interrupt number!\n",dev->name); ! 1146: #endif ! 1147: ni52_close(dev); ! 1148: ni52_open(dev); ! 1149: } ! 1150: dev->trans_start = jiffies; ! 1151: return 0; ! 1152: } ! 1153: ! 1154: if(skb == NULL) ! 1155: { ! 1156: dev_tint(dev); ! 1157: return 0; ! 1158: } ! 1159: ! 1160: if (skb->len <= 0) ! 1161: return 0; ! 1162: if(skb->len > XMIT_BUFF_SIZE) ! 1163: { ! 1164: printk("%s: Sorry, max. framelength is %d bytes. The length of your frame is %ld bytes.\n",dev->name,XMIT_BUFF_SIZE,skb->len); ! 1165: return 0; ! 1166: } ! 1167: ! 1168: if (set_bit(0, (void*)&dev->tbusy)) { ! 1169: printk("%s: Transmitter access conflict.\n", dev->name); ! 1170: return 1; ! 1171: } ! 1172: #if(NUM_XMIT_BUFFS > 1) ! 1173: else if(set_bit(0,(void *) &p->lock)) { ! 1174: printk("%s: Queue was locked\n",dev->name); ! 1175: return 1; ! 1176: } ! 1177: #endif ! 1178: else ! 1179: { ! 1180: memcpy((char *)p->xmit_cbuffs[p->xmit_count],(char *)(skb->data),skb->len); ! 1181: len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN; ! 1182: ! 1183: #if (NUM_XMIT_BUFFS == 1) ! 1184: # ifdef NO_NOPCOMMANDS ! 1185: ! 1186: #ifdef DEBUG ! 1187: if(p->scb->cus & CU_ACTIVE) ! 1188: { ! 1189: printk("%s: Hmmm .. CU is still running and we wanna send a new packet.\n",dev->name); ! 1190: printk("%s: stat: %04x %04x\n",dev->name,p->scb->cus,p->xmit_cmds[0]->cmd_status); ! 1191: } ! 1192: #endif ! 1193: ! 1194: p->xmit_buffs[0]->size = TBD_LAST | len; ! 1195: for(i=0;i<16;i++) ! 1196: { ! 1197: p->xmit_cmds[0]->cmd_status = 0; ! 1198: WAIT_4_SCB_CMD(); ! 1199: if( (p->scb->cus & CU_STATUS) == CU_SUSPEND) ! 1200: p->scb->cmd_cuc = CUC_RESUME; ! 1201: else ! 1202: { ! 1203: p->scb->cbl_offset = make16(p->xmit_cmds[0]); ! 1204: p->scb->cmd_cuc = CUC_START; ! 1205: } ! 1206: ! 1207: ni_attn586(); ! 1208: dev->trans_start = jiffies; ! 1209: if(!i) ! 1210: dev_kfree_skb(skb,FREE_WRITE); ! 1211: WAIT_4_SCB_CMD(); ! 1212: if( (p->scb->cus & CU_ACTIVE)) /* test it, because CU sometimes doesn't start immediately */ ! 1213: break; ! 1214: if(p->xmit_cmds[0]->cmd_status) ! 1215: break; ! 1216: if(i==15) ! 1217: printk("%s: Can't start transmit-command.\n",dev->name); ! 1218: } ! 1219: # else ! 1220: next_nop = (p->nop_point + 1) & 0x1; ! 1221: p->xmit_buffs[0]->size = TBD_LAST | len; ! 1222: ! 1223: p->xmit_cmds[0]->cmd_link = p->nop_cmds[next_nop]->cmd_link ! 1224: = make16((p->nop_cmds[next_nop])); ! 1225: p->xmit_cmds[0]->cmd_status = p->nop_cmds[next_nop]->cmd_status = 0; ! 1226: ! 1227: p->nop_cmds[p->nop_point]->cmd_link = make16((p->xmit_cmds[0])); ! 1228: dev->trans_start = jiffies; ! 1229: p->nop_point = next_nop; ! 1230: dev_kfree_skb(skb,FREE_WRITE); ! 1231: # endif ! 1232: #else ! 1233: p->xmit_buffs[p->xmit_count]->size = TBD_LAST | len; ! 1234: if( (next_nop = p->xmit_count + 1) == NUM_XMIT_BUFFS ) ! 1235: next_nop = 0; ! 1236: ! 1237: p->xmit_cmds[p->xmit_count]->cmd_status = 0; ! 1238: /* linkpointer of xmit-command already points to next nop cmd */ ! 1239: p->nop_cmds[next_nop]->cmd_link = make16((p->nop_cmds[next_nop])); ! 1240: p->nop_cmds[next_nop]->cmd_status = 0; ! 1241: ! 1242: p->nop_cmds[p->xmit_count]->cmd_link = make16((p->xmit_cmds[p->xmit_count])); ! 1243: dev->trans_start = jiffies; ! 1244: p->xmit_count = next_nop; ! 1245: ! 1246: { ! 1247: long flags; ! 1248: save_flags(flags); ! 1249: cli(); ! 1250: if(p->xmit_count != p->xmit_last) ! 1251: dev->tbusy = 0; ! 1252: p->lock = 0; ! 1253: restore_flags(flags); ! 1254: } ! 1255: dev_kfree_skb(skb,FREE_WRITE); ! 1256: #endif ! 1257: } ! 1258: return 0; ! 1259: } ! 1260: ! 1261: /******************************************* ! 1262: * Someone wanna have the statistics ! 1263: */ ! 1264: ! 1265: static struct enet_statistics *ni52_get_stats(struct device *dev) ! 1266: { ! 1267: struct priv *p = (struct priv *) dev->priv; ! 1268: unsigned short crc,aln,rsc,ovrn; ! 1269: ! 1270: crc = p->scb->crc_errs; /* get error-statistic from the ni82586 */ ! 1271: p->scb->crc_errs = 0; ! 1272: aln = p->scb->aln_errs; ! 1273: p->scb->aln_errs = 0; ! 1274: rsc = p->scb->rsc_errs; ! 1275: p->scb->rsc_errs = 0; ! 1276: ovrn = p->scb->ovrn_errs; ! 1277: p->scb->ovrn_errs = 0; ! 1278: ! 1279: p->stats.rx_crc_errors += crc; ! 1280: p->stats.rx_fifo_errors += ovrn; ! 1281: p->stats.rx_frame_errors += aln; ! 1282: p->stats.rx_dropped += rsc; ! 1283: ! 1284: return &p->stats; ! 1285: } ! 1286: ! 1287: /******************************************************** ! 1288: * Set MC list .. ! 1289: */ ! 1290: static void set_multicast_list(struct device *dev) ! 1291: { ! 1292: if(!dev->start) ! 1293: { ! 1294: printk("%s: Can't apply promiscuous/multicastmode to a not running interface.\n",dev->name); ! 1295: return; ! 1296: } ! 1297: ! 1298: dev->start = 0; ! 1299: ! 1300: ni_disint(); ! 1301: alloc586(dev); ! 1302: init586(dev); ! 1303: startrecv586(dev); ! 1304: ni_enaint(); ! 1305: ! 1306: dev->start = 1; ! 1307: } ! 1308: ! 1309: #ifdef MODULE ! 1310: static struct device dev_ni52 = { ! 1311: " ", /* "ni5210": device name inserted by net_init.c */ ! 1312: 0, 0, 0, 0, ! 1313: 0x300, 9, /* I/O address, IRQ */ ! 1314: 0, 0, 0, NULL, ni52_probe }; ! 1315: ! 1316: /* set: io,irq,memstart,memend or set it when calling insmod */ ! 1317: int irq=9; ! 1318: int io=0x300; ! 1319: long memstart=0; /* e.g 0xd0000 */ ! 1320: long memend=0; /* e.g 0xd4000 */ ! 1321: ! 1322: int init_module(void) ! 1323: { ! 1324: if(io <= 0x0 || !memend || !memstart || irq < 2) { ! 1325: printk("ni52: Autoprobing not allowed for modules.\nni52: Set symbols 'io' 'irq' 'memstart' and 'memend'\n"); ! 1326: return -ENODEV; ! 1327: } ! 1328: dev_ni52.irq = irq; ! 1329: dev_ni52.base_addr = io; ! 1330: dev_ni52.mem_end = memend; ! 1331: dev_ni52.mem_start = memstart; ! 1332: if (register_netdev(&dev_ni52) != 0) ! 1333: return -EIO; ! 1334: return 0; ! 1335: } ! 1336: ! 1337: void cleanup_module(void) ! 1338: { ! 1339: release_region(dev_ni52.base_addr, NI52_TOTAL_SIZE); ! 1340: kfree(dev_ni52.priv); ! 1341: dev_ni52.priv = NULL; ! 1342: unregister_netdev(&dev_ni52); ! 1343: } ! 1344: #endif /* MODULE */ ! 1345: ! 1346: #if 0 ! 1347: /* ! 1348: * DUMP .. we expect a not running CMD unit and enough space ! 1349: */ ! 1350: void ni52_dump(struct device *dev,void *ptr) ! 1351: { ! 1352: struct priv *p = (struct priv *) dev->priv; ! 1353: struct dump_cmd_struct *dump_cmd = (struct dump_cmd_struct *) ptr; ! 1354: int i; ! 1355: ! 1356: p->scb->cmd_cuc = CUC_ABORT; ! 1357: ni_attn586(); ! 1358: WAIT_4_SCB_CMD(); ! 1359: WAIT_4_SCB_CMD_RUC(); ! 1360: ! 1361: dump_cmd->cmd_status = 0; ! 1362: dump_cmd->cmd_cmd = CMD_DUMP | CMD_LAST; ! 1363: dump_cmd->dump_offset = make16((dump_cmd + 1)); ! 1364: dump_cmd->cmd_link = 0xffff; ! 1365: ! 1366: p->scb->cbl_offset = make16(dump_cmd); ! 1367: p->scb->cmd_cuc = CUC_START; ! 1368: ni_attn586(); ! 1369: WAIT_4_STAT_COMPL(dump_cmd); ! 1370: ! 1371: if( (dump_cmd->cmd_status & (STAT_COMPL|STAT_OK)) != (STAT_COMPL|STAT_OK) ) ! 1372: printk("%s: Can't get dump information.\n",dev->name); ! 1373: ! 1374: for(i=0;i<170;i++) { ! 1375: printk("%02x ",(int) ((unsigned char *) (dump_cmd + 1))[i]); ! 1376: if(i % 24 == 23) ! 1377: printk("\n"); ! 1378: } ! 1379: printk("\n"); ! 1380: } ! 1381: #endif ! 1382: ! 1383: /* ! 1384: * END: linux/drivers/net/ni52.c ! 1385: */ ! 1386: ! 1387:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.