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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [net/] [de620.c] - Blame information for rev 62

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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