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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [net/] [de620.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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