|
|
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)
1.1.1.2 ! root 846: printk("%s", version);
1.1 root 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.