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

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [arch/] [or32/] [drivers/] [open_eth.c] - Blame information for rev 11

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 7 xianfeng
/*
2
 * Ethernet driver for Open Ethernet Controller (www.opencores.org).
3
 *      Copyright (c) 2002 Simon Srot (simons@opencores.org) and OpenCores.org
4
 *
5
 * Changes:
6 11 xianfeng
 * 11.26, 2009: Xianfeng Zeng (Xianfeng.Zeng@SierraAtlantic.com)
7
 *   as MMU is enbale, make this driver accessed virtual address
8
 *
9 7 xianfeng
 * 10. 02. 2004: Matjaz Breskvar (phoenix@bsemi.com)
10
 *   port to linux-2.4, workaround for next tx bd number.
11
 *
12
 * Based on:
13
 *
14
 * Ethernet driver for Motorola MPC8xx.
15
 *      Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
16
 *
17
 * mcen302.c: A Linux network driver for Mototrola 68EN302 MCU
18
 *
19
 *      Copyright (C) 1999 Aplio S.A. Written by Vadim Lebedev
20
 *
21
 * Rigt now XXBUFF_PREALLOC must be used, bacause MAC does not
22
 * handle unaligned buffers yet.  Also the cache inhibit calls
23
 * should be used some day.
24
 *
25
 */
26
 
27
#include <linux/kernel.h>
28
#include <linux/sched.h>
29
#include <linux/string.h>
30
#include <linux/ptrace.h>
31
#include <linux/errno.h>
32
#include <linux/ioport.h>
33
#include <linux/slab.h>
34
#include <linux/interrupt.h>
35
#include <linux/pci.h>
36
#include <linux/init.h>
37
#include <linux/delay.h>
38
#include <linux/netdevice.h>
39
#include <linux/etherdevice.h>
40
#include <linux/skbuff.h>
41
#include <linux/spinlock.h>
42
 
43
#include <asm/irq.h>
44
#include <asm/pgtable.h>
45
#include <asm/bitops.h>
46
#include <asm/uaccess.h>
47
 
48 9 xianfeng
#include <asm/io.h>
49
 
50 7 xianfeng
/* __PHX__ :: clean up :: for ETH_BASE_ADDR and MAXADDR? */
51
#include <asm/board.h>
52
#include "open_eth.h"
53
 
54
#define __clear_user(add,len) memset((add),0,(len))
55
 
56 10 xianfeng
//#define DEBUG 1
57
#undef DEBUG
58 7 xianfeng
#define _print printk
59
 
60
#ifdef DEBUG
61
#define D(x) x
62
#else
63
#define D(x)
64
#endif
65
 
66
#define RXBUFF_PREALLOC 1
67
#define TXBUFF_PREALLOC 1
68
//#undef RXBUFF_PREALLOC
69
//#undef TXBUFF_PREALLOC
70
 
71
/* The transmitter timeout
72
 */
73
#define TX_TIMEOUT      (2*HZ)
74
 
75
/* Buffer number (must be 2^n)
76
 */
77
#define OETH_RXBD_NUM           8
78
#define OETH_TXBD_NUM           8
79
#define OETH_RXBD_NUM_MASK      (OETH_RXBD_NUM-1)
80
#define OETH_TXBD_NUM_MASK      (OETH_TXBD_NUM-1)
81
 
82
/* Buffer size
83
 */
84
#define OETH_RX_BUFF_SIZE       2048
85
#define OETH_TX_BUFF_SIZE       2048
86
 
87
/* How many buffers per page
88
 */
89
#define OETH_RX_BUFF_PPGAE      (PAGE_SIZE/OETH_RX_BUFF_SIZE)
90
#define OETH_TX_BUFF_PPGAE      (PAGE_SIZE/OETH_TX_BUFF_SIZE)
91
 
92
/* How many pages is needed for buffers
93
 */
94
#define OETH_RX_BUFF_PAGE_NUM   (OETH_RXBD_NUM/OETH_RX_BUFF_PPGAE)
95
#define OETH_TX_BUFF_PAGE_NUM   (OETH_TXBD_NUM/OETH_TX_BUFF_PPGAE)
96
 
97
/* Buffer size  (if not XXBUF_PREALLOC
98
 */
99
#define MAX_FRAME_SIZE          1518
100
 
101 9 xianfeng
void *oeth_vaddr;
102
 
103
#define OETH_BD_BASE            (oeth_vaddr + 0x400)
104
 
105
 
106 7 xianfeng
/* The buffer descriptors track the ring buffers.
107
 */
108
struct oeth_private {
109
        struct  sk_buff* rx_skbuff[OETH_RXBD_NUM];
110
        struct  sk_buff* tx_skbuff[OETH_TXBD_NUM];
111
 
112
        ushort  tx_next;                        /* Next buffer to be sent */
113
        ushort  tx_last;                        /* Next buffer to be checked if packet sent */
114
        ushort  tx_full;                        /* Buffer ring fuul indicator */
115
        ushort  rx_cur;                         /* Next buffer to be checked if packet received */
116
 
117
        oeth_regs       *regs;                  /* Address of controller registers. */
118
        oeth_bd         *rx_bd_base;            /* Address of Rx BDs. */
119
        oeth_bd         *tx_bd_base;            /* Address of Tx BDs. */
120
 
121
        struct net_device_stats stats;
122
};
123
 
124
static int oeth_open(struct net_device *dev);
125
static int oeth_start_xmit(struct sk_buff *skb, struct net_device *dev);
126
static void oeth_rx(struct net_device *dev);
127
static void oeth_tx(struct net_device *dev);
128
static irqreturn_t oeth_interrupt(int irq, void *dev_id, struct pt_regs *regs);
129
static int oeth_close(struct net_device *dev);
130
static struct net_device_stats *oeth_get_stats(struct net_device *dev);
131
static void oeth_set_multicast_list(struct net_device *dev);
132
static int oeth_set_mac_add(struct net_device *dev, void *addr);
133
static int calc_crc(char *mac_addr);
134
 
135
/* __PHX__ fixme for more ehternet drivers */
136
#ifdef CONFIG_OETH_UNKNOWN_TX_NEXT
137
static int tx_next = -1;
138
#endif
139
 
140
 
141
#ifdef DEBUG
142
static void
143
oeth_print_packet(unsigned long add, int len)
144
{
145
        int i;
146
 
147
        _print("ipacket: add = %lx len = %d\n", add, len);
148
        for(i = 0; i < len; i++) {
149
                if(!(i % 16))
150
                        _print("\n");
151
                _print(" %.2x", *(((unsigned char *)add) + i));
152
        }
153
        _print("\n");
154
}
155
#endif
156
 
157
static int
158
oeth_open(struct net_device *dev)
159
{
160
#ifdef CONFIG_OETH_UNKNOWN_TX_NEXT
161
        struct oeth_private *cep = (struct oeth_private *)dev->priv;
162
#endif
163
 
164
        oeth_regs *regs = (oeth_regs *)dev->base_addr;
165
        D(printk("OPEN: net_device %p\n", dev));
166
 
167
#ifdef CONFIG_OETH_UNKNOWN_TX_NEXT
168
        if (tx_next != -1) {
169
                cep->tx_next = tx_next;
170
        }
171
#endif
172
 
173
 
174
#ifndef RXBUFF_PREALLOC
175
        struct oeth_private *cep = (struct oeth_private *)dev->priv;
176
        struct  sk_buff *skb;
177
        volatile oeth_bd *rx_bd;
178
        int i;
179
 
180
        rx_bd = cep->rx_bd_base;
181
 
182
        for(i = 0; i < OETH_RXBD_NUM; i++) {
183
 
184
                skb = dev_alloc_skb(MAX_FRAME_SIZE);
185
 
186
                if (skb == NULL)
187
                        rx_bd[i].len_status = (0 << 16) | OETH_RX_BD_IRQ;
188
                else
189
                        rx_bd[i].len_status = (0 << 16) | OETH_RX_BD_EMPTY | OETH_RX_BD_IRQ;
190
 
191
                cep->rx_skbuff[i] = skb;
192
 
193
                rx_bd[i].addr = (unsigned long)skb->tail;
194
        }
195
        rx_bd[OETH_RXBD_NUM - 1].len_status |= OETH_RX_BD_WRAP;
196
#endif
197
 
198
        /* Install our interrupt handler.
199
         */
200
        request_irq(IRQ_ETH_0, oeth_interrupt, 0, "eth", (void *)dev);
201
 
202
        /* Enable receiver and transmiter
203
         */
204
        regs->moder |= OETH_MODER_RXEN | OETH_MODER_TXEN;
205
 
206
        return 0;
207
}
208
 
209
static int
210
oeth_close(struct net_device *dev)
211
{
212
#ifdef CONFIG_OETH_UNKNOWN_TX_NEXT
213
        struct oeth_private *cep = (struct oeth_private *)dev->priv;
214
#endif
215
        oeth_regs *regs = (oeth_regs *)dev->base_addr;
216
 
217
        D(printk("CLOSE: net_device %p\n", dev));
218
 
219
        /* Free interrupt hadler
220
         */
221
        free_irq(IRQ_ETH_0, (void *)dev);
222
 
223
        /* Disable receiver and transmitesr
224
         */
225
        regs->moder &= ~(OETH_MODER_RXEN | OETH_MODER_TXEN);
226
 
227
#ifndef RXBUFF_PREALLOC
228
        {
229
                int i;
230
 
231
                /* Free all alocated rx buffers
232
                 */
233
                for (i = 0; i < OETH_RXBD_NUM; i++) {
234
 
235
                        if (cep->rx_skbuff[i] != NULL)
236
                                dev_kfree_skb(cep->rx_skbuff[i]);
237
 
238
                }
239
        }
240
#endif
241
#ifndef TXBUFF_PREALLOC
242
        {
243
                int i;
244
                /* Free all alocated tx buffers
245
                 */
246
                for (i = 0; i < OETH_TXBD_NUM; i++) {
247
 
248
                        if (cep->tx_skbuff[i] != NULL)
249
                                dev_kfree_skb(cep->tx_skbuff[i]);
250
                }
251
        }
252
#endif
253
 
254
#ifdef CONFIG_OETH_UNKNOWN_TX_NEXT      
255
        tx_next = cep->tx_next;
256
#endif
257
 
258
        return 0;
259
}
260
 
261
static int
262
oeth_start_xmit(struct sk_buff *skb, struct net_device *dev)
263
{
264
        struct oeth_private *cep = (struct oeth_private *)dev->priv;
265
        volatile oeth_bd *bdp;
266
        unsigned long flags;
267
 
268
        D(printk("X"));
269
 
270
        /* Fill in a Tx ring entry
271
         */
272
        bdp = cep->tx_bd_base + cep->tx_next;
273
 
274
        if (cep->tx_full) {
275
 
276
                /* All transmit buffers are full.  Bail out.
277
                 */
278
                printk("%s: tx queue full!.\n", dev->name);
279
                return 1;
280
        }
281
 
282
        /* Clear all of the status flags.
283
         */
284
        bdp->len_status &= ~OETH_TX_BD_STATS;
285
 
286
        /* If the frame is short, tell CPM to pad it.
287
         */
288
        if (skb->len <= ETH_ZLEN)
289
                bdp->len_status |= OETH_TX_BD_PAD;
290
        else
291
                bdp->len_status &= ~OETH_TX_BD_PAD;
292
 
293
#ifdef DEBUG
294
        _print("TX\n");
295
        oeth_print_packet((unsigned long)skb->data, skb->len);
296
#endif
297
 
298
#ifdef TXBUFF_PREALLOC
299
 
300
        /* Copy data in preallocated buffer */
301
        if (skb->len > OETH_TX_BUFF_SIZE) {
302
                printk("%s: tx frame too long!.\n", dev->name);
303
                return 1;
304
        }
305
        else
306
                memcpy((unsigned char *)__va(bdp->addr), skb->data, skb->len);
307
 
308
        bdp->len_status = (bdp->len_status & 0x0000ffff) | (skb->len << 16);
309
 
310
        dev_kfree_skb(skb);
311
#else
312
        /* Set buffer length and buffer pointer.
313
         */
314
        bdp->len_status = (bdp->len_status & 0x0000ffff) | (skb->len << 16);
315
        bdp->addr = (uint)__pa(skb->data);
316
 
317
        /* Save skb pointer.
318
         */
319
        cep->tx_skbuff[cep->tx_next] = skb;
320
#endif
321
 
322
        cep->tx_next = (cep->tx_next + 1) & OETH_TXBD_NUM_MASK;
323
 
324
        local_irq_save(flags);
325
 
326
        if (cep->tx_next == cep->tx_last)
327
                cep->tx_full = 1;
328
 
329
        /* Send it on its way.  Tell controller its ready, interrupt when done,
330
         * and to put the CRC on the end.
331
         */
332
        bdp->len_status |= (OETH_TX_BD_READY | OETH_TX_BD_IRQ | OETH_TX_BD_CRC);
333
 
334
        dev->trans_start = jiffies;
335
 
336
        local_irq_restore(flags);
337
 
338
        return 0;
339
}
340
 
341
/* The interrupt handler.
342
 */
343
static irqreturn_t
344
oeth_interrupt(int irq, void *dev_id, struct pt_regs *regs)
345
{
346
        struct  net_device *dev = dev_id;
347
        volatile struct oeth_private *cep;
348
        uint    int_events;
349
        int serviced;
350
 
351
        serviced = 0;
352
 
353
#ifdef DEBUG
354
        printk(".");
355
 
356
        printk("\n=tx_ | %x | %x | %x | %x | %x | %x | %x | %x\n",
357
               ((oeth_bd *)(OETH_BD_BASE))->len_status,
358
               ((oeth_bd *)(OETH_BD_BASE+8))->len_status,
359
               ((oeth_bd *)(OETH_BD_BASE+16))->len_status,
360
               ((oeth_bd *)(OETH_BD_BASE+24))->len_status,
361
               ((oeth_bd *)(OETH_BD_BASE+32))->len_status,
362
               ((oeth_bd *)(OETH_BD_BASE+40))->len_status,
363
               ((oeth_bd *)(OETH_BD_BASE+48))->len_status,
364
               ((oeth_bd *)(OETH_BD_BASE+56))->len_status);
365
 
366
        printk("=rx_ | %x | %x | %x | %x | %x | %x | %x | %x\n",
367
               ((oeth_bd *)(OETH_BD_BASE+64))->len_status,
368
               ((oeth_bd *)(OETH_BD_BASE+64+8))->len_status,
369
               ((oeth_bd *)(OETH_BD_BASE+64+16))->len_status,
370
               ((oeth_bd *)(OETH_BD_BASE+64+24))->len_status,
371
               ((oeth_bd *)(OETH_BD_BASE+64+32))->len_status,
372
               ((oeth_bd *)(OETH_BD_BASE+64+40))->len_status,
373
               ((oeth_bd *)(OETH_BD_BASE+64+48))->len_status,
374
               ((oeth_bd *)(OETH_BD_BASE+64+56))->len_status);
375
#endif
376
 
377
        cep = (struct oeth_private *)dev->priv;
378
 
379
        /* Get the interrupt events that caused us to be here.
380
         */
381
        int_events = cep->regs->int_src;
382
        cep->regs->int_src = int_events;
383
 
384
        /* Handle receive event in its own function.
385
         */
386
        if (int_events & (OETH_INT_RXF | OETH_INT_RXE)) {
387
                D(serviced |= 0x1);
388
                oeth_rx(dev_id);
389
        }
390
 
391
        /* Handle transmit event in its own function.
392
         */
393
        if (int_events & (OETH_INT_TXB | OETH_INT_TXE)) {
394
                D(serviced |= 0x2);
395
 
396
                oeth_tx(dev_id);
397
                if (netif_queue_stopped(dev)) {
398
                        D(printk("n"));
399
                        netif_wake_queue(dev);
400
                }
401
        }
402
 
403
        /* Check for receive busy, i.e. packets coming but no place to
404
         * put them.
405
         */
406
        if (int_events & OETH_INT_BUSY) {
407
                D(serviced |= 0x4);
408
                D(printk("b"));
409
                if (!(int_events & (OETH_INT_RXF | OETH_INT_RXE)))
410
                        oeth_rx(dev_id);
411
        }
412
 
413
 
414
#if 0
415
        if (serviced == 0) {
416
                void die(const char * str, struct pt_regs * regs, long err);
417
                int show_stack(unsigned long *esp);
418
                printk("!");
419
//              printk("unserviced irq\n");
420
//              show_stack(NULL);
421
//              die("unserviced irq\n", regs, 801);
422
        }
423
#endif
424
 
425
#ifdef DEBUG
426
        if (serviced == 0)
427
                printk("\nnot serviced: events 0x%x, irq %d, dev %p\n",
428
                       int_events, irq, dev_id);
429
        else
430
                printk(" | serviced 0x%x, events 0x%x, irq %d, dev %p\n",
431
                       serviced, int_events, irq, dev_id);
432
#endif
433
 
434
        return IRQ_HANDLED;
435
}
436
 
437
 
438
static void
439
oeth_tx(struct net_device *dev)
440
{
441
        struct  oeth_private *cep;
442
        volatile oeth_bd *bdp;
443
 
444
#ifndef TXBUFF_PREALLOC
445
        struct  sk_buff *skb;
446
#endif
447
        D(printk("T"));
448
 
449
        cep = (struct oeth_private *)dev->priv;
450
 
451
        for (;; cep->tx_last = (cep->tx_last + 1) & OETH_TXBD_NUM_MASK) {
452
 
453
                bdp = cep->tx_bd_base + cep->tx_last;
454
 
455
                if ((bdp->len_status & OETH_TX_BD_READY) ||
456
                        ((cep->tx_last == cep->tx_next) && !cep->tx_full))
457
                        break;
458
 
459
                /* Check status for errors
460
                 */
461
                if (bdp->len_status & OETH_TX_BD_LATECOL)
462
                        cep->stats.tx_window_errors++;
463
                if (bdp->len_status & OETH_TX_BD_RETLIM)
464
                        cep->stats.tx_aborted_errors++;
465
                if (bdp->len_status & OETH_TX_BD_UNDERRUN)
466
                        cep->stats.tx_fifo_errors++;
467
                if (bdp->len_status & OETH_TX_BD_CARRIER)
468
                        cep->stats.tx_carrier_errors++;
469
                if (bdp->len_status & (OETH_TX_BD_LATECOL | OETH_TX_BD_RETLIM | OETH_TX_BD_UNDERRUN))
470
                        cep->stats.tx_errors++;
471
 
472
                cep->stats.tx_packets++;
473
                cep->stats.collisions += (bdp->len_status >> 4) & 0x000f;
474
 
475
#ifndef TXBUFF_PREALLOC
476
                skb = cep->tx_skbuff[cep->tx_last];
477
 
478
                /* Free the sk buffer associated with this last transmit.
479
                */
480
                dev_kfree_skb(skb);
481
#endif
482
 
483
                if (cep->tx_full)
484
                        cep->tx_full = 0;
485
        }
486
}
487
 
488
static void
489
oeth_rx(struct net_device *dev)
490
{
491
        struct  oeth_private *cep;
492
        volatile oeth_bd *bdp;
493
        struct  sk_buff *skb;
494
        int     pkt_len;
495
        int     bad = 0;
496
#ifndef RXBUFF_PREALLOC
497
        struct  sk_buff *small_skb;
498
#endif
499
 
500
        D(printk("r"));
501
 
502
        cep = (struct oeth_private *)dev->priv;
503
 
504
        /* First, grab all of the stats for the incoming packet.
505
         * These get messed up if we get called due to a busy condition.
506
         */
507
        for (;;cep->rx_cur = (cep->rx_cur + 1) & OETH_RXBD_NUM_MASK) {
508
 
509
                bdp = cep->rx_bd_base + cep->rx_cur;
510
 
511
#ifndef RXBUFF_PREALLOC
512
                skb = cep->rx_skbuff[cep->rx_cur];
513
 
514
                if (skb == NULL) {
515
 
516
                        skb = dev_alloc_skb(MAX_FRAME_SIZE + 2);
517
 
518
                        if (skb != NULL)
519
                        {
520
                                bdp->addr = (unsigned long) skb->tail;
521
                                bdp->len_status |= OETH_RX_BD_EMPTY;
522
                        }
523
                        skb_reserve(skb, 2);
524
 
525
                        continue;
526
                }
527
#endif
528
 
529
                if (bdp->len_status & OETH_RX_BD_EMPTY)
530
                        break;
531
 
532
                /* Check status for errors.
533
                 */
534
                if (bdp->len_status & (OETH_RX_BD_TOOLONG | OETH_RX_BD_SHORT)) {
535
                        cep->stats.rx_length_errors++;
536
                        bad = 1;
537
                }
538
                if (bdp->len_status & OETH_RX_BD_DRIBBLE) {
539
                        cep->stats.rx_frame_errors++;
540
                        bad = 1;
541
                }
542
                if (bdp->len_status & OETH_RX_BD_CRCERR) {
543
                        cep->stats.rx_crc_errors++;
544
                        bad = 1;
545
                }
546
                if (bdp->len_status & OETH_RX_BD_OVERRUN) {
547
                        cep->stats.rx_crc_errors++;
548
                        bad = 1;
549
                }
550
                if (bdp->len_status & OETH_RX_BD_MISS) {
551
 
552
                }
553
                if (bdp->len_status & OETH_RX_BD_LATECOL) {
554
                        cep->stats.rx_frame_errors++;
555
                        bad = 1;
556
                }
557
 
558
 
559
                if (bad) {
560
                        bdp->len_status &= ~OETH_RX_BD_STATS;
561
                        bdp->len_status |= OETH_RX_BD_EMPTY;
562
 
563
                        continue;
564
                }
565
 
566
                /* Process the incoming frame.
567
                 */
568
                pkt_len = bdp->len_status >> 16;
569
 
570
#ifdef RXBUFF_PREALLOC
571
                skb = dev_alloc_skb(pkt_len + 2);
572
 
573
                if (skb == NULL) {
574
                        printk("%s: Memory squeeze, dropping packet.\n", dev->name);
575
                        cep->stats.rx_dropped++;
576
                }
577
                else {
578
                        skb_reserve(skb, 2); /* longword align L3 header */
579
                        skb->dev = dev;
580
#ifdef DEBUG
581
                        _print("RX\n");
582
                        oeth_print_packet((unsigned long)__va(bdp->addr), pkt_len);
583
#endif
584
                        memcpy(skb_put(skb, pkt_len), (unsigned char *)__va(bdp->addr), pkt_len);
585
                        skb->protocol = eth_type_trans(skb,dev);
586
                        netif_rx(skb);
587
                        cep->stats.rx_packets++;
588
                }
589
 
590
                bdp->len_status &= ~OETH_RX_BD_STATS;
591
                bdp->len_status |= OETH_RX_BD_EMPTY;
592
#else
593
 
594
                if (pkt_len < 128) {
595
 
596
                        small_skb = dev_alloc_skb(pkt_len);
597
 
598
                        if (small_skb) {
599
                                small_skb->dev = dev;
600
#if DEBUG
601
                                _print("RX short\n");
602
                                oeth_print_packet(__va(bdp->addr), bdp->len_status >> 16);
603
#endif
604
                                memcpy(skb_put(small_skb, pkt_len), (unsigned char *)__va(bdp->addr), pkt_len);
605
                                small_skb->protocol = eth_type_trans(small_skb,dev);
606
                                netif_rx(small_skb);
607
                                cep->stats.rx_packets++;
608
                        }
609
                        else {
610
                                printk("%s: Memory squeeze, dropping packet.\n", dev->name);
611
                                cep->stats.rx_dropped++;
612
                        }
613
 
614
                        bdp->len_status &= ~OETH_RX_BD_STATS;
615
                        bdp->len_status |= OETH_RX_BD_EMPTY;
616
                }
617
                else {
618
                        skb->dev = dev;
619
                        skb_put(skb, bdp->len_status >> 16);
620
                        skb->protocol = eth_type_trans(skb,dev);
621
                        netif_rx(skb);
622
                        cep->stats.rx_packets++;
623
#if DEBUG
624
                        _print("RX long\n");
625
                        oeth_print_packet(__va(bdp->addr), bdp->len_status >> 16);
626
#endif
627
 
628
                        skb = dev_alloc_skb(MAX_FRAME_SIZE);
629
 
630
                        bdp->len_status &= ~OETH_RX_BD_STATS;
631
 
632
                        if (skb) {
633
                                cep->rx_skbuff[cep->rx_cur] = skb;
634
 
635
                                bdp->addr = (unsigned long)skb->tail;
636
                                bdp->len_status |= OETH_RX_BD_EMPTY;
637
                        }
638
                        else {
639
                                cep->rx_skbuff[cep->rx_cur] = NULL;
640
                        }
641
                }
642
#endif
643
        }
644
}
645
 
646
static int calc_crc(char *mac_addr)
647
{
648
        int result = 0;
649
        return (result & 0x3f);
650
}
651
 
652
static struct net_device_stats *oeth_get_stats(struct net_device *dev)
653
{
654
        struct oeth_private *cep = (struct oeth_private *)dev->priv;
655
 
656
        return &cep->stats;
657
}
658
 
659
static void oeth_set_multicast_list(struct net_device *dev)
660
{
661
        struct  oeth_private *cep;
662
        struct  dev_mc_list *dmi;
663
        volatile oeth_regs *regs;
664
        int     i;
665
 
666
        cep = (struct oeth_private *)dev->priv;
667
 
668
        /* Get pointer of controller registers.
669
         */
670
        regs = (oeth_regs *)dev->base_addr;
671
 
672
        if (dev->flags & IFF_PROMISC) {
673
 
674
                /* Log any net taps.
675
                 */
676
                printk("%s: Promiscuous mode enabled.\n", dev->name);
677
                regs->moder |= OETH_MODER_PRO;
678
        } else {
679
 
680
                regs->moder &= ~OETH_MODER_PRO;
681
 
682
                if (dev->flags & IFF_ALLMULTI) {
683
 
684
                        /* Catch all multicast addresses, so set the
685
                         * filter to all 1's.
686
                         */
687
                        regs->hash_addr0 = 0xffffffff;
688
                        regs->hash_addr1 = 0xffffffff;
689
                }
690
                else if (dev->mc_count) {
691
 
692
                        /* Clear filter and add the addresses in the list.
693
                         */
694
                        regs->hash_addr0 = 0x00000000;
695
                        regs->hash_addr0 = 0x00000000;
696
 
697
                        dmi = dev->mc_list;
698
 
699
                        for (i = 0; i < dev->mc_count; i++) {
700
 
701
                                int hash_b;
702
 
703
                                /* Only support group multicast for now.
704
                                 */
705
                                if (!(dmi->dmi_addr[0] & 1))
706
                                        continue;
707
 
708
                                hash_b = calc_crc(dmi->dmi_addr);
709
                                if(hash_b >= 32)
710
                                        regs->hash_addr1 |= 1 << (hash_b - 32);
711
                                else
712
                                        regs->hash_addr0 |= 1 << hash_b;
713
                        }
714
                }
715
        }
716
}
717
 
718
static int oeth_set_mac_add(struct net_device *dev, void *p)
719
{
720
        struct sockaddr *addr=p;
721
        volatile oeth_regs *regs;
722
 
723
        memcpy(dev->dev_addr, addr->sa_data,dev->addr_len);
724
 
725
        regs = (oeth_regs *)dev->base_addr;
726
 
727
        regs->mac_addr1 =       addr->sa_data[0] << 8    |
728
                                addr->sa_data[1];
729
        regs->mac_addr0 =       addr->sa_data[2] << 24  |
730
                                addr->sa_data[3] << 16  |
731
                                addr->sa_data[4] << 8   |
732
                                addr->sa_data[5];
733
 
734
        return 0;
735
}
736
 
737
/* Initialize the Open Ethernet MAC.
738
 */
739
int __init oeth_init(void)
740
{
741
        struct net_device *dev;
742
        struct oeth_private *cep;
743
        volatile oeth_regs *regs;
744
        volatile oeth_bd *tx_bd, *rx_bd;
745
        int error, i, j, k;
746
#ifdef SRAM_BUFF
747
        unsigned long mem_addr = SRAM_BUFF_BASE;
748
#else
749
        unsigned long mem_addr;
750
#endif
751
 
752
        /* Create an Ethernet device instance.
753
         */
754
        dev = alloc_etherdev(sizeof(*cep));
755
        if (!dev)
756
                return -ENOMEM;
757
 
758
        cep = dev->priv;
759
//      spin_lock_init(&cep->lock);
760
 
761 9 xianfeng
 
762
        /* map oeth IO */
763
        oeth_vaddr = ioremap(OETH_REG_BASE, 0x2000);
764
 
765 7 xianfeng
        /* Get pointer ethernet controller configuration registers.
766
         */
767 9 xianfeng
        cep->regs = (oeth_regs *)(oeth_vaddr);
768
        regs = (oeth_regs *)(oeth_vaddr);
769 7 xianfeng
 
770
        /* Reset the controller.
771
         */
772
        regs->moder = OETH_MODER_RST;   /* Reset ON */
773
        regs->moder &= ~OETH_MODER_RST; /* Reset OFF */
774
 
775
        /* Setting TXBD base to OETH_TXBD_NUM.
776
         */
777
        regs->tx_bd_num = OETH_TXBD_NUM;
778
 
779
        /* Initialize TXBD pointer
780
         */
781
        cep->tx_bd_base = (oeth_bd *)OETH_BD_BASE;
782
        tx_bd = (volatile oeth_bd *)OETH_BD_BASE;
783
 
784
        /* Initialize RXBD pointer
785
         */
786
        cep->rx_bd_base = ((oeth_bd *)OETH_BD_BASE) + OETH_TXBD_NUM;
787
        rx_bd = ((volatile oeth_bd *)OETH_BD_BASE) + OETH_TXBD_NUM;
788
 
789
        /* Initialize transmit pointers.
790
         */
791
        cep->rx_cur = 0;
792
 
793
        /* workaround */
794
#ifdef CONFIG_OETH_UNKNOWN_TX_NEXT
795
        /* the first time use value passed by bootloader
796
         * __PHX__ fixme, this woun't work if you have this compiled as module
797
         */
798
        {
799
                int tmp_next = *((int *)(0xc0000000));
800
 
801
                /* sanity check */
802
                if ((tmp_next >= 0) && (tmp_next < OETH_TXBD_NUM))
803
                        cep->tx_next = tmp_next;
804
                else {
805
                        printk(KERN_WARNING "open_eth: illegal number of TX buffer descriptors passed (%d), using default (if you did not use ethernet before starting linux this is ok)\n",
806
                               tmp_next);
807
                        cep->tx_next = 0;
808
                }
809
        }
810
#else
811
        /* or read it from eth register, or set it to 0 in eth */
812
        cep->tx_next = 0;
813
#endif
814
        cep->tx_last = 0;
815
        cep->tx_full = 0;
816
 
817
        /* Set min/max packet length
818
         */
819
        regs->packet_len = 0x00400600;
820
 
821
        /* Set IPGT register to recomended value
822
         */
823
        regs->ipgt = 0x00000012;
824
 
825
        /* Set IPGR1 register to recomended value
826
         */
827
        regs->ipgr1 = 0x0000000c;
828
 
829
        /* Set IPGR2 register to recomended value
830
         */
831
        regs->ipgr2 = 0x00000012;
832
 
833
        /* Set COLLCONF register to recomended value
834
         */
835
        regs->collconf = 0x000f003f;
836
 
837
        /* Set control module mode
838
         */
839
#if 0
840
        regs->ctrlmoder = OETH_CTRLMODER_TXFLOW | OETH_CTRLMODER_RXFLOW;
841
#else
842
        regs->ctrlmoder = 0;
843
#endif
844
 
845
  /* Set PHY to show Tx status, Rx status and Link status */
846
  regs->miiaddress = 20<<8;
847
  regs->miitx_data = 0x1422;
848
  regs->miicommand = OETH_MIICOMMAND_WCTRLDATA;
849
 
850
#ifdef TXBUFF_PREALLOC
851
 
852
        /* Initialize TXBDs.
853
         */
854
        for(i = 0, k = 0; i < OETH_TX_BUFF_PAGE_NUM; i++) {
855
 
856
#ifndef SRAM_BUFF
857
                mem_addr = __get_free_page(GFP_KERNEL);
858
#endif
859
 
860
                for(j = 0; j < OETH_TX_BUFF_PPGAE; j++, k++) {
861
                        tx_bd[k].len_status = OETH_TX_BD_PAD | OETH_TX_BD_CRC | OETH_RX_BD_IRQ;
862
                        tx_bd[k].addr = __pa(mem_addr);
863
                        mem_addr += OETH_TX_BUFF_SIZE;
864
                }
865
        }
866
        tx_bd[OETH_TXBD_NUM - 1].len_status |= OETH_TX_BD_WRAP;
867
#else
868
 
869
        /* Initialize TXBDs.
870
         */
871
        for(i = 0; i < OETH_TXBD_NUM; i++) {
872
 
873
                cep->tx_skbuff[i] = NULL;
874
 
875
                tx_bd[i].len_status = (0 << 16) | OETH_TX_BD_PAD | OETH_TX_BD_CRC | OETH_RX_BD_IRQ;
876
                tx_bd[i].addr = 0;
877
        }
878
        tx_bd[OETH_TXBD_NUM - 1].len_status |= OETH_TX_BD_WRAP;
879
#endif
880
 
881
#ifdef RXBUFF_PREALLOC
882
 
883
        /* Initialize RXBDs.
884
         */
885
        for(i = 0, k = 0; i < OETH_RX_BUFF_PAGE_NUM; i++) {
886
 
887
#ifndef SRAM_BUFF
888
                mem_addr = __get_free_page(GFP_KERNEL);
889
#endif
890
 
891
                for(j = 0; j < OETH_RX_BUFF_PPGAE; j++, k++) {
892
                        rx_bd[k].len_status = OETH_RX_BD_EMPTY | OETH_RX_BD_IRQ;
893
                        rx_bd[k].addr = __pa(mem_addr);
894
                        mem_addr += OETH_RX_BUFF_SIZE;
895
                }
896
        }
897
        rx_bd[OETH_RXBD_NUM - 1].len_status |= OETH_RX_BD_WRAP;
898
 
899
#else
900
        /* Initialize RXBDs.
901
         */
902
        for(i = 0; i < OETH_RXBD_NUM; i++) {
903
 
904
 
905
                rx_bd[i].len_status = (0 << 16) | OETH_RX_BD_IRQ;
906
 
907
                cep->rx_skbuff[i] = NULL;
908
 
909
                rx_bd[i].addr = 0;
910
        }
911
        rx_bd[OETH_RXBD_NUM - 1].len_status |= OETH_RX_BD_WRAP;
912
 
913
#endif
914
 
915
        /* Set default ethernet station address.
916
         */
917
        dev->dev_addr[0] = MACADDR0;
918
        dev->dev_addr[1] = MACADDR1;
919
        dev->dev_addr[2] = MACADDR2;
920
        dev->dev_addr[3] = MACADDR3;
921
        dev->dev_addr[4] = MACADDR4;
922
        dev->dev_addr[5] = MACADDR5;
923
 
924
        regs->mac_addr1 = MACADDR0 << 8 | MACADDR1;
925
        regs->mac_addr0 = MACADDR2 << 24 | MACADDR3 << 16 | MACADDR4 << 8 | MACADDR5;
926
 
927
        /* Clear all pending interrupts
928
         */
929
        regs->int_src = 0xffffffff;
930
 
931
        /* Promisc, IFG, CRCEn
932
         */
933
        regs->moder |= OETH_MODER_PAD | OETH_MODER_IFG | OETH_MODER_CRCEN;
934
 
935
        /* Enable interrupt sources.
936
         */
937
        regs->int_mask = OETH_INT_MASK_TXB      |
938
                OETH_INT_MASK_TXE       |
939
                OETH_INT_MASK_RXF       |
940
                OETH_INT_MASK_RXE       |
941
                OETH_INT_MASK_BUSY      |
942
                OETH_INT_MASK_TXC       |
943
                OETH_INT_MASK_RXC;
944
 
945
        /* Fill in the fields of the device structure with ethernet values.
946
         */
947
        ether_setup(dev);
948
 
949 9 xianfeng
        dev->base_addr = (unsigned long)oeth_vaddr;
950 7 xianfeng
 
951
        /* The Open Ethernet specific entries in the device structure.
952
         */
953
        dev->open = oeth_open;
954
        dev->hard_start_xmit = oeth_start_xmit;
955
        dev->stop = oeth_close;
956
        dev->get_stats = oeth_get_stats;
957
        dev->set_multicast_list = oeth_set_multicast_list;
958
        dev->set_mac_address = oeth_set_mac_add;
959
 
960
        if ((error = register_netdev(dev))) {
961
                free_netdev(dev);
962
                return error;
963
        }
964
 
965
        printk("%s: Open Ethernet Core Version 1.0\n", dev->name);
966
 
967
        return 0;
968
}
969
 
970
module_init(oeth_init);

powered by: WebSVN 2.1.0

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