|
|
1.1 ! root 1: /* ! 2: * de620.c $Revision: 1.1 $ BETA ! 3: * ! 4: * ! 5: * Linux driver for the D-Link DE-620 Ethernet pocket adapter. ! 6: * ! 7: * Portions (C) Copyright 1993, 1994 by Bjorn Ekwall <[email protected]> ! 8: * ! 9: * Based on adapter information gathered from DOS packetdriver ! 10: * sources from D-Link Inc: (Special thanks to Henry Ngai of D-Link.) ! 11: * Portions (C) Copyright D-Link SYSTEM Inc. 1991, 1992 ! 12: * Copyright, 1988, Russell Nelson, Crynwr Software ! 13: * ! 14: * Adapted to the sample network driver core for linux, ! 15: * written by: Donald Becker <[email protected]> ! 16: * (Now at <[email protected]> ! 17: * ! 18: * Valuable assistance from: ! 19: * J. Joshua Kopper <[email protected]> ! 20: * Olav Kvittem <[email protected]> ! 21: * Germano Caronni <[email protected]> ! 22: * Jeremy Fitzhardinge <[email protected]> ! 23: * ! 24: *****************************************************************************/ ! 25: /* ! 26: * This program is free software; you can redistribute it and/or modify ! 27: * it under the terms of the GNU General Public License as published by ! 28: * the Free Software Foundation; either version 2, or (at your option) ! 29: * any later version. ! 30: * ! 31: * This program is distributed in the hope that it will be useful, ! 32: * but WITHOUT ANY WARRANTY; without even the implied warranty of ! 33: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 34: * GNU General Public License for more details. ! 35: * ! 36: * You should have received a copy of the GNU General Public License ! 37: * along with this program; if not, write to the Free Software ! 38: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ! 39: * ! 40: *****************************************************************************/ ! 41: static const char *version = ! 42: "de620.c: $Revision: 1.1 $, Bjorn Ekwall <[email protected]>\n"; ! 43: ! 44: /*********************************************************************** ! 45: * ! 46: * "Tuning" section. ! 47: * ! 48: * Compile-time options: (see below for descriptions) ! 49: * -DDE620_IO=0x378 (lpt1) ! 50: * -DDE620_IRQ=7 (lpt1) ! 51: * -DDE602_DEBUG=... ! 52: * -DSHUTDOWN_WHEN_LOST ! 53: * -DCOUNT_LOOPS ! 54: * -DLOWSPEED ! 55: * -DREAD_DELAY ! 56: * -DWRITE_DELAY ! 57: */ ! 58: ! 59: /* ! 60: * This driver assumes that the printer port is a "normal", ! 61: * dumb, uni-directional port! ! 62: * If your port is "fancy" in any way, please try to set it to "normal" ! 63: * with your BIOS setup. I have no access to machines with bi-directional ! 64: * ports, so I can't test such a driver :-( ! 65: * (Yes, I _know_ it is possible to use DE620 with bidirectional ports...) ! 66: * ! 67: * There are some clones of DE620 out there, with different names. ! 68: * If the current driver does not recognize a clone, try to change ! 69: * the following #define to: ! 70: * ! 71: * #define DE620_CLONE 1 ! 72: */ ! 73: #define DE620_CLONE 0 ! 74: ! 75: /* ! 76: * If the adapter has problems with high speeds, enable this #define ! 77: * otherwise full printerport speed will be attempted. ! 78: * ! 79: * You can tune the READ_DELAY/WRITE_DELAY below if you enable LOWSPEED ! 80: * ! 81: #define LOWSPEED ! 82: */ ! 83: ! 84: #ifndef READ_DELAY ! 85: #define READ_DELAY 100 /* adapter internal read delay in 100ns units */ ! 86: #endif ! 87: ! 88: #ifndef WRITE_DELAY ! 89: #define WRITE_DELAY 100 /* adapter internal write delay in 100ns units */ ! 90: #endif ! 91: ! 92: /* ! 93: * Enable this #define if you want the adapter to do a "ifconfig down" on ! 94: * itself when we have detected that something is possibly wrong with it. ! 95: * The default behaviour is to retry with "adapter_init()" until success. ! 96: * This should be used for debugging purposes only. ! 97: * ! 98: #define SHUTDOWN_WHEN_LOST ! 99: */ ! 100: ! 101: /* ! 102: * Enable debugging by "-DDE620_DEBUG=3" when compiling, ! 103: * OR in "./CONFIG" ! 104: * OR by enabling the following #define ! 105: * ! 106: * use 0 for production, 1 for verification, >2 for debug ! 107: * ! 108: #define DE620_DEBUG 3 ! 109: */ ! 110: ! 111: #ifdef LOWSPEED ! 112: /* ! 113: * Enable this #define if you want to see debugging output that show how long ! 114: * we have to wait before the DE-620 is ready for the next read/write/command. ! 115: * ! 116: #define COUNT_LOOPS ! 117: */ ! 118: #endif ! 119: ! 120: #include <linux/module.h> ! 121: ! 122: #include <linux/kernel.h> ! 123: #include <linux/sched.h> ! 124: #include <linux/types.h> ! 125: #include <linux/fcntl.h> ! 126: #include <linux/string.h> ! 127: #include <linux/interrupt.h> ! 128: #include <linux/ioport.h> ! 129: #include <asm/io.h> ! 130: #include <linux/in.h> ! 131: #include <linux/ptrace.h> ! 132: #include <asm/system.h> ! 133: #include <linux/errno.h> ! 134: ! 135: #include <linux/inet.h> ! 136: #include <linux/netdevice.h> ! 137: #include <linux/etherdevice.h> ! 138: #include <linux/skbuff.h> ! 139: ! 140: /* Constant definitions for the DE-620 registers, commands and bits */ ! 141: #include "de620.h" ! 142: ! 143: #define netstats enet_statistics ! 144: typedef unsigned char byte; ! 145: ! 146: /******************************************************* ! 147: * * ! 148: * Definition of D-Link DE-620 Ethernet Pocket adapter * ! 149: * See also "de620.h" * ! 150: * * ! 151: *******************************************************/ ! 152: #ifndef DE620_IO /* Compile-time configurable */ ! 153: #define DE620_IO 0x378 ! 154: #endif ! 155: ! 156: #ifndef DE620_IRQ /* Compile-time configurable */ ! 157: #define DE620_IRQ 7 ! 158: #endif ! 159: ! 160: #define DATA_PORT (dev->base_addr) ! 161: #define STATUS_PORT (dev->base_addr + 1) ! 162: #define COMMAND_PORT (dev->base_addr + 2) ! 163: ! 164: #define RUNT 60 /* Too small Ethernet packet */ ! 165: #define GIANT 1514 /* largest legal size packet, no fcs */ ! 166: ! 167: #ifdef DE620_DEBUG /* Compile-time configurable */ ! 168: #define PRINTK(x) if (de620_debug >= 2) printk x ! 169: #else ! 170: #define DE620_DEBUG 0 ! 171: #define PRINTK(x) /**/ ! 172: #endif ! 173: ! 174: ! 175: /* ! 176: * Force media with insmod: ! 177: * insmod de620.o bnc=1 ! 178: * or ! 179: * insmod de620.o utp=1 ! 180: * ! 181: * Force io and/or irq with insmod: ! 182: * insmod de620.o io=0x378 irq=7 ! 183: * ! 184: * Make a clone skip the Ethernet-address range check: ! 185: * insmod de620.o clone=1 ! 186: */ ! 187: static int bnc = 0; ! 188: static int utp = 0; ! 189: static int io = DE620_IO; ! 190: static int irq = DE620_IRQ; ! 191: static int clone = DE620_CLONE; ! 192: ! 193: static unsigned int de620_debug = DE620_DEBUG; ! 194: ! 195: /*********************************************** ! 196: * * ! 197: * Index to functions, as function prototypes. * ! 198: * * ! 199: ***********************************************/ ! 200: ! 201: /* ! 202: * Routines used internally. (See also "convenience macros.. below") ! 203: */ ! 204: ! 205: /* Put in the device structure. */ ! 206: static int de620_open(struct device *); ! 207: static int de620_close(struct device *); ! 208: static struct netstats *get_stats(struct device *); ! 209: static void de620_set_multicast_list(struct device *); ! 210: static int de620_start_xmit(struct sk_buff *, struct device *); ! 211: ! 212: /* Dispatch from interrupts. */ ! 213: static void de620_interrupt(int, void *, struct pt_regs *); ! 214: static int de620_rx_intr(struct device *); ! 215: ! 216: /* Initialization */ ! 217: static int adapter_init(struct device *); ! 218: int de620_probe(struct device *); ! 219: static int read_eeprom(struct device *); ! 220: ! 221: ! 222: /* ! 223: * D-Link driver variables: ! 224: */ ! 225: #define SCR_DEF NIBBLEMODE |INTON | SLEEP | AUTOTX ! 226: #define TCR_DEF RXPB /* not used: | TXSUCINT | T16INT */ ! 227: #define DE620_RX_START_PAGE 12 /* 12 pages (=3k) reserved for tx */ ! 228: #define DEF_NIC_CMD IRQEN | ICEN | DS1 ! 229: ! 230: static volatile byte NIC_Cmd; ! 231: static volatile byte next_rx_page; ! 232: static byte first_rx_page; ! 233: static byte last_rx_page; ! 234: static byte EIPRegister; ! 235: ! 236: static struct nic { ! 237: byte NodeID[6]; ! 238: byte RAM_Size; ! 239: byte Model; ! 240: byte Media; ! 241: byte SCR; ! 242: } nic_data; ! 243: ! 244: /********************************************************** ! 245: * * ! 246: * Convenience macros/functions for D-Link DE-620 adapter * ! 247: * * ! 248: **********************************************************/ ! 249: #define de620_tx_buffs(dd) (inb(STATUS_PORT) & (TXBF0 | TXBF1)) ! 250: #define de620_flip_ds(dd) NIC_Cmd ^= DS0 | DS1; outb(NIC_Cmd, COMMAND_PORT); ! 251: ! 252: /* Check for ready-status, and return a nibble (high 4 bits) for data input */ ! 253: #ifdef COUNT_LOOPS ! 254: static int tot_cnt; ! 255: #endif ! 256: static inline byte ! 257: de620_ready(struct device *dev) ! 258: { ! 259: byte value; ! 260: register short int cnt = 0; ! 261: ! 262: while ((((value = inb(STATUS_PORT)) & READY) == 0) && (cnt <= 1000)) ! 263: ++cnt; ! 264: ! 265: #ifdef COUNT_LOOPS ! 266: tot_cnt += cnt; ! 267: #endif ! 268: return value & 0xf0; /* nibble */ ! 269: } ! 270: ! 271: static inline void ! 272: de620_send_command(struct device *dev, byte cmd) ! 273: { ! 274: de620_ready(dev); ! 275: if (cmd == W_DUMMY) ! 276: outb(NIC_Cmd, COMMAND_PORT); ! 277: ! 278: outb(cmd, DATA_PORT); ! 279: ! 280: outb(NIC_Cmd ^ CS0, COMMAND_PORT); ! 281: de620_ready(dev); ! 282: outb(NIC_Cmd, COMMAND_PORT); ! 283: } ! 284: ! 285: static inline void ! 286: de620_put_byte(struct device *dev, byte value) ! 287: { ! 288: /* The de620_ready() makes 7 loops, on the average, on a DX2/66 */ ! 289: de620_ready(dev); ! 290: outb(value, DATA_PORT); ! 291: de620_flip_ds(dev); ! 292: } ! 293: ! 294: static inline byte ! 295: de620_read_byte(struct device *dev) ! 296: { ! 297: byte value; ! 298: ! 299: /* The de620_ready() makes 7 loops, on the average, on a DX2/66 */ ! 300: value = de620_ready(dev); /* High nibble */ ! 301: de620_flip_ds(dev); ! 302: value |= de620_ready(dev) >> 4; /* Low nibble */ ! 303: return value; ! 304: } ! 305: ! 306: static inline void ! 307: de620_write_block(struct device *dev, byte *buffer, int count) ! 308: { ! 309: #ifndef LOWSPEED ! 310: byte uflip = NIC_Cmd ^ (DS0 | DS1); ! 311: byte dflip = NIC_Cmd; ! 312: #else /* LOWSPEED */ ! 313: #ifdef COUNT_LOOPS ! 314: int bytes = count; ! 315: #endif /* COUNT_LOOPS */ ! 316: #endif /* LOWSPEED */ ! 317: ! 318: #ifdef LOWSPEED ! 319: #ifdef COUNT_LOOPS ! 320: tot_cnt = 0; ! 321: #endif /* COUNT_LOOPS */ ! 322: /* No further optimization useful, the limit is in the adapter. */ ! 323: for ( ; count > 0; --count, ++buffer) { ! 324: de620_put_byte(dev,*buffer); ! 325: } ! 326: de620_send_command(dev,W_DUMMY); ! 327: #ifdef COUNT_LOOPS ! 328: /* trial debug output: loops per byte in de620_ready() */ ! 329: printk("WRITE(%d)\n", tot_cnt/((bytes?bytes:1))); ! 330: #endif /* COUNT_LOOPS */ ! 331: #else /* not LOWSPEED */ ! 332: for ( ; count > 0; count -=2) { ! 333: outb(*buffer++, DATA_PORT); ! 334: outb(uflip, COMMAND_PORT); ! 335: outb(*buffer++, DATA_PORT); ! 336: outb(dflip, COMMAND_PORT); ! 337: } ! 338: de620_send_command(dev,W_DUMMY); ! 339: #endif /* LOWSPEED */ ! 340: } ! 341: ! 342: static inline void ! 343: de620_read_block(struct device *dev, byte *data, int count) ! 344: { ! 345: #ifndef LOWSPEED ! 346: byte value; ! 347: byte uflip = NIC_Cmd ^ (DS0 | DS1); ! 348: byte dflip = NIC_Cmd; ! 349: #else /* LOWSPEED */ ! 350: #ifdef COUNT_LOOPS ! 351: int bytes = count; ! 352: ! 353: tot_cnt = 0; ! 354: #endif /* COUNT_LOOPS */ ! 355: #endif /* LOWSPEED */ ! 356: ! 357: #ifdef LOWSPEED ! 358: /* No further optimization useful, the limit is in the adapter. */ ! 359: while (count-- > 0) { ! 360: *data++ = de620_read_byte(dev); ! 361: de620_flip_ds(dev); ! 362: } ! 363: #ifdef COUNT_LOOPS ! 364: /* trial debug output: loops per byte in de620_ready() */ ! 365: printk("READ(%d)\n", tot_cnt/(2*(bytes?bytes:1))); ! 366: #endif /* COUNT_LOOPS */ ! 367: #else /* not LOWSPEED */ ! 368: while (count-- > 0) { ! 369: value = inb(STATUS_PORT) & 0xf0; /* High nibble */ ! 370: outb(uflip, COMMAND_PORT); ! 371: *data++ = value | inb(STATUS_PORT) >> 4; /* Low nibble */ ! 372: outb(dflip , COMMAND_PORT); ! 373: } ! 374: #endif /* LOWSPEED */ ! 375: } ! 376: ! 377: static inline void ! 378: de620_set_delay(struct device *dev) ! 379: { ! 380: de620_ready(dev); ! 381: outb(W_DFR, DATA_PORT); ! 382: outb(NIC_Cmd ^ CS0, COMMAND_PORT); ! 383: ! 384: de620_ready(dev); ! 385: #ifdef LOWSPEED ! 386: outb(WRITE_DELAY, DATA_PORT); ! 387: #else ! 388: outb(0, DATA_PORT); ! 389: #endif ! 390: de620_flip_ds(dev); ! 391: ! 392: de620_ready(dev); ! 393: #ifdef LOWSPEED ! 394: outb(READ_DELAY, DATA_PORT); ! 395: #else ! 396: outb(0, DATA_PORT); ! 397: #endif ! 398: de620_flip_ds(dev); ! 399: } ! 400: ! 401: static inline void ! 402: de620_set_register(struct device *dev, byte reg, byte value) ! 403: { ! 404: de620_ready(dev); ! 405: outb(reg, DATA_PORT); ! 406: outb(NIC_Cmd ^ CS0, COMMAND_PORT); ! 407: ! 408: de620_put_byte(dev, value); ! 409: } ! 410: ! 411: static inline byte ! 412: de620_get_register(struct device *dev, byte reg) ! 413: { ! 414: byte value; ! 415: ! 416: de620_send_command(dev,reg); ! 417: value = de620_read_byte(dev); ! 418: de620_send_command(dev,W_DUMMY); ! 419: ! 420: return value; ! 421: } ! 422: ! 423: /********************************************************************* ! 424: * ! 425: * Open/initialize the board. ! 426: * ! 427: * This routine should set everything up anew at each open, even ! 428: * registers that "should" only need to be set once at boot, so that ! 429: * there is a non-reboot way to recover if something goes wrong. ! 430: * ! 431: */ ! 432: static int ! 433: de620_open(struct device *dev) ! 434: { ! 435: if (request_irq(dev->irq, de620_interrupt, 0, "de620", NULL)) { ! 436: printk ("%s: unable to get IRQ %d\n", dev->name, dev->irq); ! 437: return 1; ! 438: } ! 439: irq2dev_map[dev->irq] = dev; ! 440: ! 441: MOD_INC_USE_COUNT; ! 442: if (adapter_init(dev)) { ! 443: return 1; ! 444: } ! 445: dev->start = 1; ! 446: return 0; ! 447: } ! 448: ! 449: /************************************************ ! 450: * ! 451: * The inverse routine to de620_open(). ! 452: * ! 453: */ ! 454: static int ! 455: de620_close(struct device *dev) ! 456: { ! 457: /* disable recv */ ! 458: de620_set_register(dev, W_TCR, RXOFF); ! 459: ! 460: free_irq(dev->irq, NULL); ! 461: irq2dev_map[dev->irq] = NULL; ! 462: ! 463: dev->start = 0; ! 464: MOD_DEC_USE_COUNT; ! 465: return 0; ! 466: } ! 467: ! 468: /********************************************* ! 469: * ! 470: * Return current statistics ! 471: * ! 472: */ ! 473: static struct netstats * ! 474: get_stats(struct device *dev) ! 475: { ! 476: return (struct netstats *)(dev->priv); ! 477: } ! 478: ! 479: /********************************************* ! 480: * ! 481: * Set or clear the multicast filter for this adaptor. ! 482: * (no real multicast implemented for the DE-620, but she can be promiscuous...) ! 483: * ! 484: */ ! 485: ! 486: static void de620_set_multicast_list(struct device *dev) ! 487: { ! 488: if (dev->mc_count || dev->flags&(IFF_ALLMULTI|IFF_PROMISC)) ! 489: { /* Enable promiscuous mode */ ! 490: /* ! 491: * We must make the kernel realise we had to move ! 492: * into promisc mode or we start all out war on ! 493: * the cable. - AC ! 494: */ ! 495: dev->flags|=IFF_PROMISC; ! 496: ! 497: de620_set_register(dev, W_TCR, (TCR_DEF & ~RXPBM) | RXALL); ! 498: } ! 499: else ! 500: { /* Disable promiscuous mode, use normal mode */ ! 501: de620_set_register(dev, W_TCR, TCR_DEF); ! 502: } ! 503: } ! 504: ! 505: /******************************************************* ! 506: * ! 507: * Copy a buffer to the adapter transmit page memory. ! 508: * Start sending. ! 509: */ ! 510: static int ! 511: de620_start_xmit(struct sk_buff *skb, struct device *dev) ! 512: { ! 513: unsigned long flags; ! 514: int len; ! 515: int tickssofar; ! 516: byte *buffer = skb->data; ! 517: byte using_txbuf; ! 518: ! 519: /* ! 520: * If some higher layer thinks we've missed a ! 521: * tx-done interrupt we are passed NULL. ! 522: * Caution: dev_tint() handles the cli()/sti() itself. ! 523: */ ! 524: ! 525: if (skb == NULL) { ! 526: dev_tint(dev); ! 527: return 0; ! 528: } ! 529: ! 530: using_txbuf = de620_tx_buffs(dev); /* Peek at the adapter */ ! 531: dev->tbusy = (using_txbuf == (TXBF0 | TXBF1)); /* Boolean! */ ! 532: ! 533: if (dev->tbusy) { /* Do timeouts, to avoid hangs. */ ! 534: tickssofar = jiffies - dev->trans_start; ! 535: ! 536: if (tickssofar < 5) ! 537: return 1; ! 538: ! 539: /* else */ ! 540: printk("%s: transmit timed out (%d), %s?\n", ! 541: dev->name, ! 542: tickssofar, ! 543: "network cable problem" ! 544: ); ! 545: /* Restart the adapter. */ ! 546: if (adapter_init(dev)) /* maybe close it */ ! 547: return 1; ! 548: } ! 549: ! 550: if ((len = skb->len) < RUNT) ! 551: len = RUNT; ! 552: if (len & 1) /* send an even number of bytes */ ! 553: ++len; ! 554: ! 555: /* Start real output */ ! 556: save_flags(flags); ! 557: cli(); ! 558: ! 559: PRINTK(("de620_start_xmit: len=%d, bufs 0x%02x\n", ! 560: (int)skb->len, using_txbuf)); ! 561: ! 562: /* select a free tx buffer. if there is one... */ ! 563: switch (using_txbuf) { ! 564: default: /* both are free: use TXBF0 */ ! 565: case TXBF1: /* use TXBF0 */ ! 566: de620_send_command(dev,W_CR | RW0); ! 567: using_txbuf |= TXBF0; ! 568: break; ! 569: ! 570: case TXBF0: /* use TXBF1 */ ! 571: de620_send_command(dev,W_CR | RW1); ! 572: using_txbuf |= TXBF1; ! 573: break; ! 574: ! 575: case (TXBF0 | TXBF1): /* NONE!!! */ ! 576: printk("de620: Ouch! No tx-buffer available!\n"); ! 577: restore_flags(flags); ! 578: return 1; ! 579: break; ! 580: } ! 581: de620_write_block(dev, buffer, len); ! 582: ! 583: dev->trans_start = jiffies; ! 584: dev->tbusy = (using_txbuf == (TXBF0 | TXBF1)); /* Boolean! */ ! 585: ! 586: ((struct netstats *)(dev->priv))->tx_packets++; ! 587: ! 588: restore_flags(flags); /* interrupts maybe back on */ ! 589: ! 590: dev_kfree_skb (skb, FREE_WRITE); ! 591: ! 592: return 0; ! 593: } ! 594: ! 595: /***************************************************** ! 596: * ! 597: * Handle the network interface interrupts. ! 598: * ! 599: */ ! 600: static void ! 601: de620_interrupt(int irq_in, void *dev_id, struct pt_regs *regs) ! 602: { ! 603: struct device *dev = irq2dev_map[irq_in]; ! 604: byte irq_status; ! 605: int bogus_count = 0; ! 606: int again = 0; ! 607: ! 608: /* This might be deleted now, no crummy drivers present :-) Or..? */ ! 609: if ((dev == NULL) || (irq != irq_in)) { ! 610: printk("%s: bogus interrupt %d\n", dev?dev->name:"de620", irq_in); ! 611: return; ! 612: } ! 613: ! 614: cli(); ! 615: dev->interrupt = 1; ! 616: ! 617: /* Read the status register (_not_ the status port) */ ! 618: irq_status = de620_get_register(dev, R_STS); ! 619: ! 620: PRINTK(("de620_interrupt (%2.2X)\n", irq_status)); ! 621: ! 622: if (irq_status & RXGOOD) { ! 623: do { ! 624: again = de620_rx_intr(dev); ! 625: PRINTK(("again=%d\n", again)); ! 626: } ! 627: while (again && (++bogus_count < 100)); ! 628: } ! 629: ! 630: dev->tbusy = (de620_tx_buffs(dev) == (TXBF0 | TXBF1)); /* Boolean! */ ! 631: ! 632: dev->interrupt = 0; ! 633: sti(); ! 634: return; ! 635: } ! 636: ! 637: /************************************** ! 638: * ! 639: * Get a packet from the adapter ! 640: * ! 641: * Send it "upstairs" ! 642: * ! 643: */ ! 644: static int ! 645: de620_rx_intr(struct device *dev) ! 646: { ! 647: struct header_buf { ! 648: byte status; ! 649: byte Rx_NextPage; ! 650: unsigned short Rx_ByteCount; ! 651: } header_buf; ! 652: struct sk_buff *skb; ! 653: int size; ! 654: byte *buffer; ! 655: byte pagelink; ! 656: byte curr_page; ! 657: ! 658: PRINTK(("de620_rx_intr: next_rx_page = %d\n", next_rx_page)); ! 659: ! 660: /* Tell the adapter that we are going to read data, and from where */ ! 661: de620_send_command(dev, W_CR | RRN); ! 662: de620_set_register(dev, W_RSA1, next_rx_page); ! 663: de620_set_register(dev, W_RSA0, 0); ! 664: ! 665: /* Deep breath, and away we goooooo */ ! 666: de620_read_block(dev, (byte *)&header_buf, sizeof(struct header_buf)); ! 667: PRINTK(("page status=0x%02x, nextpage=%d, packetsize=%d\n", ! 668: header_buf.status, header_buf.Rx_NextPage, header_buf.Rx_ByteCount)); ! 669: ! 670: /* Plausible page header? */ ! 671: pagelink = header_buf.Rx_NextPage; ! 672: if ((pagelink < first_rx_page) || (last_rx_page < pagelink)) { ! 673: /* Ouch... Forget it! Skip all and start afresh... */ ! 674: printk("%s: Ring overrun? Restoring...\n", dev->name); ! 675: /* You win some, you loose some. And sometimes plenty... */ ! 676: adapter_init(dev); ! 677: ((struct netstats *)(dev->priv))->rx_over_errors++; ! 678: return 0; ! 679: } ! 680: ! 681: /* OK, this look good, so far. Let's see if it's consistent... */ ! 682: /* Let's compute the start of the next packet, based on where we are */ ! 683: pagelink = next_rx_page + ! 684: ((header_buf.Rx_ByteCount + (4 - 1 + 0x100)) >> 8); ! 685: ! 686: /* Are we going to wrap around the page counter? */ ! 687: if (pagelink > last_rx_page) ! 688: pagelink -= (last_rx_page - first_rx_page + 1); ! 689: ! 690: /* Is the _computed_ next page number equal to what the adapter says? */ ! 691: if (pagelink != header_buf.Rx_NextPage) { ! 692: /* Naah, we'll skip this packet. Probably bogus data as well */ ! 693: printk("%s: Page link out of sync! Restoring...\n", dev->name); ! 694: next_rx_page = header_buf.Rx_NextPage; /* at least a try... */ ! 695: de620_send_command(dev, W_DUMMY); ! 696: de620_set_register(dev, W_NPRF, next_rx_page); ! 697: ((struct netstats *)(dev->priv))->rx_over_errors++; ! 698: return 0; ! 699: } ! 700: next_rx_page = pagelink; ! 701: ! 702: size = header_buf.Rx_ByteCount - 4; ! 703: if ((size < RUNT) || (GIANT < size)) { ! 704: printk("%s: Illegal packet size: %d!\n", dev->name, size); ! 705: } ! 706: else { /* Good packet? */ ! 707: skb = dev_alloc_skb(size+2); ! 708: if (skb == NULL) { /* Yeah, but no place to put it... */ ! 709: printk("%s: Couldn't allocate a sk_buff of size %d.\n", ! 710: dev->name, size); ! 711: ((struct netstats *)(dev->priv))->rx_dropped++; ! 712: } ! 713: else { /* Yep! Go get it! */ ! 714: skb_reserve(skb,2); /* Align */ ! 715: skb->dev = dev; ! 716: skb->free = 1; ! 717: /* skb->data points to the start of sk_buff data area */ ! 718: buffer = skb_put(skb,size); ! 719: /* copy the packet into the buffer */ ! 720: de620_read_block(dev, buffer, size); ! 721: PRINTK(("Read %d bytes\n", size)); ! 722: skb->protocol=eth_type_trans(skb,dev); ! 723: netif_rx(skb); /* deliver it "upstairs" */ ! 724: /* count all receives */ ! 725: ((struct netstats *)(dev->priv))->rx_packets++; ! 726: } ! 727: } ! 728: ! 729: /* Let's peek ahead to see if we have read the last current packet */ ! 730: /* NOTE! We're _not_ checking the 'EMPTY'-flag! This seems better... */ ! 731: curr_page = de620_get_register(dev, R_CPR); ! 732: de620_set_register(dev, W_NPRF, next_rx_page); ! 733: PRINTK(("next_rx_page=%d CPR=%d\n", next_rx_page, curr_page)); ! 734: ! 735: return (next_rx_page != curr_page); /* That was slightly tricky... */ ! 736: } ! 737: ! 738: /********************************************* ! 739: * ! 740: * Reset the adapter to a known state ! 741: * ! 742: */ ! 743: static int ! 744: adapter_init(struct device *dev) ! 745: { ! 746: int i; ! 747: static int was_down = 0; ! 748: ! 749: if ((nic_data.Model == 3) || (nic_data.Model == 0)) { /* CT */ ! 750: EIPRegister = NCTL0; ! 751: if (nic_data.Media != 1) ! 752: EIPRegister |= NIS0; /* not BNC */ ! 753: } ! 754: else if (nic_data.Model == 2) { /* UTP */ ! 755: EIPRegister = NCTL0 | NIS0; ! 756: } ! 757: ! 758: if (utp) ! 759: EIPRegister = NCTL0 | NIS0; ! 760: if (bnc) ! 761: EIPRegister = NCTL0; ! 762: ! 763: de620_send_command(dev, W_CR | RNOP | CLEAR); ! 764: de620_send_command(dev, W_CR | RNOP); ! 765: ! 766: de620_set_register(dev, W_SCR, SCR_DEF); ! 767: /* disable recv to wait init */ ! 768: de620_set_register(dev, W_TCR, RXOFF); ! 769: ! 770: /* Set the node ID in the adapter */ ! 771: for (i = 0; i < 6; ++i) { /* W_PARn = 0xaa + n */ ! 772: de620_set_register(dev, W_PAR0 + i, dev->dev_addr[i]); ! 773: } ! 774: ! 775: de620_set_register(dev, W_EIP, EIPRegister); ! 776: ! 777: next_rx_page = first_rx_page = DE620_RX_START_PAGE; ! 778: if (nic_data.RAM_Size) ! 779: last_rx_page = nic_data.RAM_Size - 1; ! 780: else /* 64k RAM */ ! 781: last_rx_page = 255; ! 782: ! 783: de620_set_register(dev, W_SPR, first_rx_page); /* Start Page Register*/ ! 784: de620_set_register(dev, W_EPR, last_rx_page); /* End Page Register */ ! 785: de620_set_register(dev, W_CPR, first_rx_page);/*Current Page Register*/ ! 786: de620_send_command(dev, W_NPR | first_rx_page); /* Next Page Register*/ ! 787: de620_send_command(dev, W_DUMMY); ! 788: de620_set_delay(dev); ! 789: ! 790: /* Final sanity check: Anybody out there? */ ! 791: /* Let's hope some bits from the statusregister make a good check */ ! 792: #define CHECK_MASK ( 0 | TXSUC | T16 | 0 | RXCRC | RXSHORT | 0 | 0 ) ! 793: #define CHECK_OK ( 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 ) ! 794: /* success: X 0 0 X 0 0 X X */ ! 795: /* ignore: EEDI RXGOOD COLS LNKS*/ ! 796: ! 797: if (((i = de620_get_register(dev, R_STS)) & CHECK_MASK) != CHECK_OK) { ! 798: printk("Something has happened to the DE-620! Please check it" ! 799: #ifdef SHUTDOWN_WHEN_LOST ! 800: " and do a new ifconfig" ! 801: #endif ! 802: "! (%02x)\n", i); ! 803: #ifdef SHUTDOWN_WHEN_LOST ! 804: /* Goodbye, cruel world... */ ! 805: dev->flags &= ~IFF_UP; ! 806: de620_close(dev); ! 807: #endif ! 808: was_down = 1; ! 809: return 1; /* failed */ ! 810: } ! 811: if (was_down) { ! 812: printk("Thanks, I feel much better now!\n"); ! 813: was_down = 0; ! 814: } ! 815: ! 816: /* All OK, go ahead... */ ! 817: de620_set_register(dev, W_TCR, TCR_DEF); ! 818: ! 819: return 0; /* all ok */ ! 820: } ! 821: ! 822: /****************************************************************************** ! 823: * ! 824: * Only start-up code below ! 825: * ! 826: */ ! 827: /**************************************** ! 828: * ! 829: * Check if there is a DE-620 connected ! 830: */ ! 831: int ! 832: de620_probe(struct device *dev) ! 833: { ! 834: static struct netstats de620_netstats; ! 835: int i; ! 836: byte checkbyte = 0xa5; ! 837: ! 838: /* ! 839: * This is where the base_addr and irq gets set. ! 840: * Tunable at compile-time and insmod-time ! 841: */ ! 842: dev->base_addr = io; ! 843: dev->irq = irq; ! 844: ! 845: if (de620_debug) ! 846: printk(version); ! 847: ! 848: printk("D-Link DE-620 pocket adapter"); ! 849: ! 850: /* Initially, configure basic nibble mode, so we can read the EEPROM */ ! 851: NIC_Cmd = DEF_NIC_CMD; ! 852: de620_set_register(dev, W_EIP, EIPRegister); ! 853: ! 854: /* Anybody out there? */ ! 855: de620_set_register(dev, W_CPR, checkbyte); ! 856: checkbyte = de620_get_register(dev, R_CPR); ! 857: ! 858: if ((checkbyte != 0xa5) || (read_eeprom(dev) != 0)) { ! 859: printk(" not identified in the printer port\n"); ! 860: return ENODEV; ! 861: } ! 862: ! 863: #if 0 /* Not yet */ ! 864: if (check_region(dev->base_addr, 3)) { ! 865: printk(", port 0x%x busy\n", dev->base_addr); ! 866: return EBUSY; ! 867: } ! 868: #endif ! 869: request_region(dev->base_addr, 3, "de620"); ! 870: ! 871: /* else, got it! */ ! 872: printk(", Ethernet Address: %2.2X", ! 873: dev->dev_addr[0] = nic_data.NodeID[0]); ! 874: for (i = 1; i < ETH_ALEN; i++) { ! 875: printk(":%2.2X", dev->dev_addr[i] = nic_data.NodeID[i]); ! 876: dev->broadcast[i] = 0xff; ! 877: } ! 878: ! 879: printk(" (%dk RAM,", ! 880: (nic_data.RAM_Size) ? (nic_data.RAM_Size >> 2) : 64); ! 881: ! 882: if (nic_data.Media == 1) ! 883: printk(" BNC)\n"); ! 884: else ! 885: printk(" UTP)\n"); ! 886: ! 887: /* Initialize the device structure. */ ! 888: /*dev->priv = kmalloc(sizeof(struct netstats), GFP_KERNEL);*/ ! 889: dev->priv = &de620_netstats; ! 890: ! 891: memset(dev->priv, 0, sizeof(struct netstats)); ! 892: dev->get_stats = get_stats; ! 893: dev->open = de620_open; ! 894: dev->stop = de620_close; ! 895: dev->hard_start_xmit = &de620_start_xmit; ! 896: dev->set_multicast_list = &de620_set_multicast_list; ! 897: /* base_addr and irq are already set, see above! */ ! 898: ! 899: ether_setup(dev); ! 900: ! 901: /* dump eeprom */ ! 902: if (de620_debug) { ! 903: printk("\nEEPROM contents:\n"); ! 904: printk("RAM_Size = 0x%02X\n", nic_data.RAM_Size); ! 905: printk("NodeID = %02X:%02X:%02X:%02X:%02X:%02X\n", ! 906: nic_data.NodeID[0], nic_data.NodeID[1], ! 907: nic_data.NodeID[2], nic_data.NodeID[3], ! 908: nic_data.NodeID[4], nic_data.NodeID[5]); ! 909: printk("Model = %d\n", nic_data.Model); ! 910: printk("Media = %d\n", nic_data.Media); ! 911: printk("SCR = 0x%02x\n", nic_data.SCR); ! 912: } ! 913: ! 914: return 0; ! 915: } ! 916: ! 917: /********************************** ! 918: * ! 919: * Read info from on-board EEPROM ! 920: * ! 921: * Note: Bitwise serial I/O to/from the EEPROM vi the status _register_! ! 922: */ ! 923: #define sendit(dev,data) de620_set_register(dev, W_EIP, data | EIPRegister); ! 924: ! 925: static unsigned short ! 926: ReadAWord(struct device *dev, int from) ! 927: { ! 928: unsigned short data; ! 929: int nbits; ! 930: ! 931: /* cs [__~~] SET SEND STATE */ ! 932: /* di [____] */ ! 933: /* sck [_~~_] */ ! 934: sendit(dev, 0); sendit(dev, 1); sendit(dev, 5); sendit(dev, 4); ! 935: ! 936: /* Send the 9-bit address from where we want to read the 16-bit word */ ! 937: for (nbits = 9; nbits > 0; --nbits, from <<= 1) { ! 938: if (from & 0x0100) { /* bit set? */ ! 939: /* cs [~~~~] SEND 1 */ ! 940: /* di [~~~~] */ ! 941: /* sck [_~~_] */ ! 942: sendit(dev, 6); sendit(dev, 7); sendit(dev, 7); sendit(dev, 6); ! 943: } ! 944: else { ! 945: /* cs [~~~~] SEND 0 */ ! 946: /* di [____] */ ! 947: /* sck [_~~_] */ ! 948: sendit(dev, 4); sendit(dev, 5); sendit(dev, 5); sendit(dev, 4); ! 949: } ! 950: } ! 951: ! 952: /* Shift in the 16-bit word. The bits appear serially in EEDI (=0x80) */ ! 953: for (data = 0, nbits = 16; nbits > 0; --nbits) { ! 954: /* cs [~~~~] SEND 0 */ ! 955: /* di [____] */ ! 956: /* sck [_~~_] */ ! 957: sendit(dev, 4); sendit(dev, 5); sendit(dev, 5); sendit(dev, 4); ! 958: data = (data << 1) | ((de620_get_register(dev, R_STS) & EEDI) >> 7); ! 959: } ! 960: /* cs [____] RESET SEND STATE */ ! 961: /* di [____] */ ! 962: /* sck [_~~_] */ ! 963: sendit(dev, 0); sendit(dev, 1); sendit(dev, 1); sendit(dev, 0); ! 964: ! 965: return data; ! 966: } ! 967: ! 968: static int ! 969: read_eeprom(struct device *dev) ! 970: { ! 971: unsigned short wrd; ! 972: ! 973: /* D-Link Ethernet addresses are in the series 00:80:c8:7X:XX:XX:XX */ ! 974: wrd = ReadAWord(dev, 0x1aa); /* bytes 0 + 1 of NodeID */ ! 975: if (!clone && (wrd != htons(0x0080))) /* Valid D-Link ether sequence? */ ! 976: return -1; /* Nope, not a DE-620 */ ! 977: nic_data.NodeID[0] = wrd & 0xff; ! 978: nic_data.NodeID[1] = wrd >> 8; ! 979: ! 980: wrd = ReadAWord(dev, 0x1ab); /* bytes 2 + 3 of NodeID */ ! 981: if (!clone && ((wrd & 0xff) != 0xc8)) /* Valid D-Link ether sequence? */ ! 982: return -1; /* Nope, not a DE-620 */ ! 983: nic_data.NodeID[2] = wrd & 0xff; ! 984: nic_data.NodeID[3] = wrd >> 8; ! 985: ! 986: wrd = ReadAWord(dev, 0x1ac); /* bytes 4 + 5 of NodeID */ ! 987: nic_data.NodeID[4] = wrd & 0xff; ! 988: nic_data.NodeID[5] = wrd >> 8; ! 989: ! 990: wrd = ReadAWord(dev, 0x1ad); /* RAM size in pages (256 bytes). 0 = 64k */ ! 991: nic_data.RAM_Size = (wrd >> 8); ! 992: ! 993: wrd = ReadAWord(dev, 0x1ae); /* hardware model (CT = 3) */ ! 994: nic_data.Model = (wrd & 0xff); ! 995: ! 996: wrd = ReadAWord(dev, 0x1af); /* media (indicates BNC/UTP) */ ! 997: nic_data.Media = (wrd & 0xff); ! 998: ! 999: wrd = ReadAWord(dev, 0x1a8); /* System Configuration Register */ ! 1000: nic_data.SCR = (wrd >> 8); ! 1001: ! 1002: return 0; /* no errors */ ! 1003: } ! 1004: ! 1005: /****************************************************************************** ! 1006: * ! 1007: * Loadable module skeleton ! 1008: * ! 1009: */ ! 1010: #ifdef MODULE ! 1011: static char nullname[8] = ""; ! 1012: static struct device de620_dev = { ! 1013: nullname, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, de620_probe }; ! 1014: ! 1015: int ! 1016: init_module(void) ! 1017: { ! 1018: if (register_netdev(&de620_dev) != 0) ! 1019: return -EIO; ! 1020: return 0; ! 1021: } ! 1022: ! 1023: void ! 1024: cleanup_module(void) ! 1025: { ! 1026: unregister_netdev(&de620_dev); ! 1027: release_region(de620_dev.base_addr, 3); ! 1028: } ! 1029: #endif /* MODULE */ ! 1030: ! 1031: /* ! 1032: * (add '-DMODULE' when compiling as loadable module) ! 1033: * ! 1034: * compile-command: ! 1035: * gcc -D__KERNEL__ -Wall -Wstrict-prototypes -O2 \ ! 1036: * -fomit-frame-pointer -m486 \ ! 1037: * -I/usr/src/linux/include -I../../net/inet -c de620.c ! 1038: */ ! 1039: /* ! 1040: * Local variables: ! 1041: * kernel-compile-command: "gcc -D__KERNEL__ -Ilinux/include -I../../net/inet -Wall -Wstrict-prototypes -O2 -m486 -c de620.c" ! 1042: * module-compile-command: "gcc -D__KERNEL__ -DMODULE -Ilinux/include -I../../net/inet -Wall -Wstrict-prototypes -O2 -m486 -c de620.c" ! 1043: * compile-command: "gcc -D__KERNEL__ -DMODULE -Ilinux/include -I../../net/inet -Wall -Wstrict-prototypes -O2 -m486 -c de620.c" ! 1044: * End: ! 1045: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.