OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [before_ORP/] [uclinux/] [uClinux-2.0.x/] [drivers/] [net/] [de620.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/*
2
 *      de620.c $Revision: 1.1.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 <bj0rn@blox.se>
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 <becker@super.org>
16
 *              (Now at <becker@cesdis.gsfc.nasa.gov>
17
 *
18
 *      Valuable assistance from:
19
 *              J. Joshua Kopper <kopper@rtsg.mot.com>
20
 *              Olav Kvittem <Olav.Kvittem@uninett.no>
21
 *              Germano Caronni <caronni@nessie.cs.id.ethz.ch>
22
 *              Jeremy Fitzhardinge <jeremy@suite.sw.oz.au>
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.1.1 $,  Bjorn Ekwall <bj0rn@blox.se>\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
 */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.