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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [net/] [ariadne.c] - Blame information for rev 1777

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1626 jcastillo
/*
2
 *  Amiga Linux/m68k Ariadne Ethernet Driver
3
 *
4
 *  © Copyright 1995 by Geert Uytterhoeven
5
 *                     (Geert.Uytterhoeven@cs.kuleuven.ac.be)
6
 *                      Peter De Schrijver
7
 *                     (Peter.DeSchrijver@linux.cc.kuleuven.ac.be)
8
 *
9
 *  ----------------------------------------------------------------------------------
10
 *
11
 *  This program is based on
12
 *
13
 *      lance.c:        An AMD LANCE ethernet driver for linux.
14
 *                      Written 1993-94 by Donald Becker.
15
 *
16
 *      Am79C960:       PCnet(tm)-ISA Single-Chip Ethernet Controller
17
 *                      Advanced Micro Devices
18
 *                      Publication #16907, Rev. B, Amendment/0, May 1994
19
 *
20
 *      MC68230:        Parallel Interface/Timer (PI/T)
21
 *                      Motorola Semiconductors, December, 1983
22
 *
23
 *  ----------------------------------------------------------------------------------
24
 *
25
 *  This file is subject to the terms and conditions of the GNU General Public
26
 *  License.  See the file COPYING in the main directory of the Linux
27
 *  distribution for more details.
28
 *
29
 *  ----------------------------------------------------------------------------------
30
 *
31
 *  The Ariadne is a Zorro-II board made by Village Tronic. It contains:
32
 *
33
 *      - an Am79C960 PCnet-ISA Single-Chip Ethernet Controller with both
34
 *        10BASE-2 (thin coax) and 10BASE-T (UTP) connectors
35
 *
36
 *      - an MC68230 Parallel Interface/Timer configured as 2 parallel ports
37
 */
38
 
39
#include <linux/module.h>
40
#include <linux/stddef.h>
41
#include <linux/kernel.h>
42
#include <linux/sched.h>
43
#include <linux/string.h>
44
#include <linux/ptrace.h>
45
#include <linux/errno.h>
46
#include <linux/ioport.h>
47
#include <linux/malloc.h>
48
#include <linux/netdevice.h>
49
#include <linux/etherdevice.h>
50
#include <linux/interrupt.h>
51
#include <linux/skbuff.h>
52
 
53
#include <asm/bitops.h>
54
#include <asm/amigaints.h>
55
#include <asm/amigahw.h>
56
#include <asm/zorro.h>
57
#include <asm/bootinfo.h>
58
#include <asm/io.h>
59
#include <asm/irq.h>
60
 
61
#include "ariadne.h"
62
 
63
 
64
#ifdef ARIADNE_DEBUG
65
int ariadne_debug = ARIADNE_DEBUG;
66
#else
67
int ariadne_debug = 1;
68
#endif
69
 
70
 
71
    /*
72
     *  Macros to Fix Endianness problems
73
     */
74
 
75
                                /* Swap the Bytes in a WORD */
76
#define swapw(x)        (((x>>8)&0x00ff)|((x<<8)&0xff00))
77
                                /* Get the Low BYTE in a WORD */
78
#define lowb(x)         (x&0xff)
79
                                /* Get the Swapped High WORD in a LONG */
80
#define swhighw(x)      ((((x)>>8)&0xff00)|(((x)>>24)&0x00ff))
81
                                /* Get the Swapped Low WORD in a LONG */
82
#define swloww(x)       ((((x)<<8)&0xff00)|(((x)>>8)&0x00ff))
83
 
84
 
85
    /*
86
     *  Transmit/Receive Ring Definitions
87
     */
88
 
89
#define TX_RING_SIZE    5
90
#define RX_RING_SIZE    16
91
 
92
#define PKT_BUF_SIZE    1520
93
 
94
 
95
    /*
96
     *  Private Device Data
97
     */
98
 
99
struct ariadne_private {
100
    struct AriadneBoard *board;
101
    struct TDRE *tx_ring[TX_RING_SIZE];
102
    struct RDRE *rx_ring[RX_RING_SIZE];
103
    u_short *tx_buff[TX_RING_SIZE];
104
    u_short *rx_buff[RX_RING_SIZE];
105
    int cur_tx, cur_rx;                 /* The next free ring entry */
106
    int dirty_tx;                       /* The ring entries to be free()ed. */
107
    struct enet_statistics stats;
108
    char tx_full;
109
    unsigned long lock;
110
    int key;
111
};
112
 
113
 
114
    /*
115
     *  Structure Created in the Ariadne's RAM Buffer
116
     */
117
 
118
struct lancedata {
119
    struct TDRE tx_ring[TX_RING_SIZE];
120
    struct RDRE rx_ring[RX_RING_SIZE];
121
    u_short tx_buff[TX_RING_SIZE][PKT_BUF_SIZE/sizeof(u_short)];
122
    u_short rx_buff[RX_RING_SIZE][PKT_BUF_SIZE/sizeof(u_short)];
123
};
124
 
125
 
126
static int ariadne_open(struct device *dev);
127
static void ariadne_init_ring(struct device *dev);
128
static int ariadne_start_xmit(struct sk_buff *skb, struct device *dev);
129
static int ariadne_rx(struct device *dev);
130
static void ariadne_interrupt(int irq, struct pt_regs *fp, void *data);
131
static int ariadne_close(struct device *dev);
132
static struct enet_statistics *ariadne_get_stats(struct device *dev);
133
#ifdef HAVE_MULTICAST
134
static void set_multicast_list(struct device *dev);
135
#endif
136
 
137
 
138
static void memcpyw(u_short *dest, u_short *src, int len)
139
{
140
    while (len >= 2) {
141
        *(dest++) = *(src++);
142
        len -= 2;
143
    }
144
    if (len == 1)
145
        *dest = (*(u_char *)src)<<8;
146
}
147
 
148
 
149
int ariadne_probe(struct device *dev)
150
{
151
    int key;
152
    struct ConfigDev *cd;
153
    u_long board;
154
    struct ariadne_private *priv;
155
 
156
    /* Ethernet is part 0, Parallel is part 1 */
157
    if ((key = zorro_find(MANUF_VILLAGE_TRONIC, PROD_ARIADNE, 0, 0))) {
158
        cd = zorro_get_board(key);
159
        if ((board = (u_long)cd->cd_BoardAddr)) {
160
            dev->dev_addr[0] = 0x00;
161
            dev->dev_addr[1] = 0x60;
162
            dev->dev_addr[2] = 0x30;
163
            dev->dev_addr[3] = (cd->cd_Rom.er_SerialNumber>>16)&0xff;
164
            dev->dev_addr[4] = (cd->cd_Rom.er_SerialNumber>>8)&0xff;
165
            dev->dev_addr[5] = cd->cd_Rom.er_SerialNumber&0xff;
166
            printk("%s: Ariadne at 0x%08lx, Ethernet Address "
167
                   "%02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, board,
168
                   dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
169
                   dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
170
 
171
            init_etherdev(dev, 0);
172
 
173
            dev->priv = kmalloc(sizeof(struct ariadne_private), GFP_KERNEL);
174
            priv = (struct ariadne_private *)dev->priv;
175
            memset(priv, 0, sizeof(struct ariadne_private));
176
 
177
            priv->board = (struct AriadneBoard *)ZTWO_VADDR(board);
178
            priv->key = key;
179
 
180
            dev->open = &ariadne_open;
181
            dev->stop = &ariadne_close;
182
            dev->hard_start_xmit = &ariadne_start_xmit;
183
            dev->get_stats = &ariadne_get_stats;
184
            dev->set_multicast_list = &set_multicast_list;
185
 
186
            zorro_config_board(key, 0);
187
            return(0);
188
        }
189
    }
190
    return(ENODEV);
191
}
192
 
193
 
194
static int ariadne_open(struct device *dev)
195
{
196
    struct ariadne_private *priv = (struct ariadne_private *)dev->priv;
197
    struct AriadneBoard *board = priv->board;
198
    struct lancedata *lancedata;
199
    u_short in;
200
    u_long version;
201
 
202
    /* Reset the LANCE */
203
    in = board->Lance.Reset;
204
 
205
    /* Stop the LANCE */
206
    board->Lance.RAP = CSR0;    /* PCnet-ISA Controller Status */
207
    board->Lance.RDP = STOP;
208
 
209
    /* Check the LANCE version */
210
    board->Lance.RAP = CSR88;   /* Chip ID */
211
    version = swapw(board->Lance.RDP);
212
    board->Lance.RAP = CSR89;   /* Chip ID */
213
    version |= swapw(board->Lance.RDP)<<16;
214
    if ((version & 0x00000fff) != 0x00000003) {
215
        printk("ariadne_open: Couldn't find AMD Ethernet Chip\n");
216
        return(-EAGAIN);
217
    }
218
    if ((version & 0x0ffff000) != 0x00003000) {
219
        printk("ariadne_open: Couldn't find Am79C960 (Wrong part number = %ld)\n",
220
               (version & 0x0ffff000)>>12);
221
        return(-EAGAIN);
222
    }
223
#if 0
224
    printk("ariadne_open: Am79C960 (PCnet-ISA) Revision %ld\n",
225
           (version & 0xf0000000)>>28);
226
#endif
227
 
228
    ariadne_init_ring(dev);
229
 
230
    /* Miscellaneous Stuff */
231
    board->Lance.RAP = CSR3;    /* Interrupt Masks and Deferral Control */
232
    board->Lance.RDP = 0x0000;
233
    board->Lance.RAP = CSR4;    /* Test and Features Control */
234
    board->Lance.RDP = DPOLL|APAD_XMT|MFCOM|RCVCCOM|TXSTRTM|JABM;
235
 
236
    /* Set the Multicast Table */
237
    board->Lance.RAP = CSR8;    /* Logical Address Filter, LADRF[15:0] */
238
    board->Lance.RDP = 0x0000;
239
    board->Lance.RAP = CSR9;    /* Logical Address Filter, LADRF[31:16] */
240
    board->Lance.RDP = 0x0000;
241
    board->Lance.RAP = CSR10;   /* Logical Address Filter, LADRF[47:32] */
242
    board->Lance.RDP = 0x0000;
243
    board->Lance.RAP = CSR11;   /* Logical Address Filter, LADRF[63:48] */
244
    board->Lance.RDP = 0x0000;
245
 
246
    /* Set the Ethernet Hardware Address */
247
    board->Lance.RAP = CSR12;   /* Physical Address Register, PADR[15:0] */
248
    board->Lance.RDP = ((u_short *)&dev->dev_addr[0])[0];
249
    board->Lance.RAP = CSR13;   /* Physical Address Register, PADR[31:16] */
250
    board->Lance.RDP = ((u_short *)&dev->dev_addr[0])[1];
251
    board->Lance.RAP = CSR14;   /* Physical Address Register, PADR[47:32] */
252
    board->Lance.RDP = ((u_short *)&dev->dev_addr[0])[2];
253
 
254
    /* Set the Init Block Mode */
255
    board->Lance.RAP = CSR15;   /* Mode Register */
256
    board->Lance.RDP = 0x0000;
257
 
258
    lancedata = (struct lancedata *)offsetof(struct AriadneBoard, RAM);
259
 
260
    /* Set the Transmit Descriptor Ring Pointer */
261
    board->Lance.RAP = CSR30;   /* Base Address of Transmit Ring */
262
    board->Lance.RDP = swloww((u_long)&lancedata->tx_ring);
263
    board->Lance.RAP = CSR31;   /* Base Address of transmit Ring */
264
    board->Lance.RDP = swhighw((u_long)&lancedata->tx_ring);
265
 
266
    /* Set the Receive Descriptor Ring Pointer */
267
    board->Lance.RAP = CSR24;   /* Base Address of Receive Ring */
268
    board->Lance.RDP = swloww((u_long)&lancedata->rx_ring);
269
    board->Lance.RAP = CSR25;   /* Base Address of Receive Ring */
270
    board->Lance.RDP = swhighw((u_long)&lancedata->rx_ring);
271
 
272
    /* Set the Number of RX and TX Ring Entries */
273
    board->Lance.RAP = CSR76;   /* Receive Ring Length */
274
    board->Lance.RDP = swapw(((u_short)-RX_RING_SIZE));
275
    board->Lance.RAP = CSR78;   /* Transmit Ring Length */
276
    board->Lance.RDP = swapw(((u_short)-TX_RING_SIZE));
277
 
278
    /* Enable Media Interface Port Auto Select (10BASE-2/10BASE-T) */
279
    board->Lance.RAP = ISACSR2; /* Miscellaneous Configuration */
280
    board->Lance.IDP = ASEL;
281
 
282
    /* LED Control */
283
    board->Lance.RAP = ISACSR5; /* LED1 Status */
284
    board->Lance.IDP = PSE|XMTE;
285
    board->Lance.RAP = ISACSR6; /* LED2 Status */
286
    board->Lance.IDP = PSE|COLE;
287
    board->Lance.RAP = ISACSR7; /* LED3 Status */
288
    board->Lance.IDP = PSE|RCVE;
289
 
290
    dev->tbusy = 0;
291
    dev->interrupt = 0;
292
    dev->start = 1;
293
 
294
    if (!add_isr(IRQ_AMIGA_PORTS, ariadne_interrupt, 0, dev,
295
                 "Ariadne Ethernet"))
296
        return(-EAGAIN);
297
 
298
    board->Lance.RAP = CSR0;    /* PCnet-ISA Controller Status */
299
    board->Lance.RDP = INEA|STRT;
300
 
301
    MOD_INC_USE_COUNT;
302
 
303
    return(0);
304
}
305
 
306
 
307
static void ariadne_init_ring(struct device *dev)
308
{
309
    struct ariadne_private *priv = (struct ariadne_private *)dev->priv;
310
    struct AriadneBoard *board = priv->board;
311
    struct lancedata *lancedata;        /* LANCE point of view */
312
    struct lancedata *alancedata;       /* Amiga point of view */
313
    int i;
314
 
315
    priv->lock = 0, priv->tx_full = 0;
316
    priv->cur_rx = priv->cur_tx = 0;
317
    priv->dirty_tx = 0;
318
 
319
    lancedata = (struct lancedata *)offsetof(struct AriadneBoard, RAM);
320
    alancedata = (struct lancedata *)board->RAM;
321
 
322
    /* Set up TX Ring */
323
    for (i = 0; i < TX_RING_SIZE; i++) {
324
        alancedata->tx_ring[i].TMD0 = swloww((u_long)lancedata->tx_buff[i]);
325
        alancedata->tx_ring[i].TMD1 = swhighw((u_long)lancedata->tx_buff[i])|TF_STP|TF_ENP;
326
        alancedata->tx_ring[i].TMD2 = swapw((u_short)-PKT_BUF_SIZE);
327
        alancedata->tx_ring[i].TMD3 = 0;
328
        priv->tx_ring[i] = &alancedata->tx_ring[i];
329
        priv->tx_buff[i] = alancedata->tx_buff[i];
330
#if 0
331
        printk("TX Entry %2d @ 0x%08x (LANCE 0x%08x), Buf @ 0x%08x (LANCE 0x%08x)\n",
332
               i, (int)&alancedata->tx_ring[i], (int)&lancedata->tx_ring[i],
333
               (int)alancedata->tx_buff[i], (int)lancedata->tx_buff[i]);
334
#endif
335
    }
336
 
337
    /* Set up RX Ring */
338
    for (i = 0; i < RX_RING_SIZE; i++) {
339
        alancedata->rx_ring[i].RMD0 = swloww((u_long)lancedata->rx_buff[i]);
340
        alancedata->rx_ring[i].RMD1 = swhighw((u_long)lancedata->rx_buff[i])|RF_OWN;
341
        alancedata->rx_ring[i].RMD2 = swapw((u_short)-PKT_BUF_SIZE);
342
        alancedata->rx_ring[i].RMD3 = 0x0000;
343
        priv->rx_ring[i] = &alancedata->rx_ring[i];
344
        priv->rx_buff[i] = alancedata->rx_buff[i];
345
#if 0
346
        printk("RX Entry %2d @ 0x%08x (LANCE 0x%08x), Buf @ 0x%08x (LANCE 0x%08x)\n",
347
               i, (int)&alancedata->rx_ring[i], (int)&lancedata->rx_ring[i],
348
               (int)alancedata->rx_buff[i], (int)lancedata->rx_buff[i]);
349
#endif
350
    }
351
}
352
 
353
 
354
static int ariadne_close(struct device *dev)
355
{
356
    struct ariadne_private *priv = (struct ariadne_private *)dev->priv;
357
    struct AriadneBoard *board = priv->board;
358
 
359
    dev->start = 0;
360
    dev->tbusy = 1;
361
 
362
    board->Lance.RAP = CSR112;  /* Missed Frame Count */
363
    priv->stats.rx_missed_errors = swapw(board->Lance.RDP);
364
    board->Lance.RAP = CSR0;    /* PCnet-ISA Controller Status */
365
 
366
    if (ariadne_debug > 1) {
367
        printk("%s: Shutting down ethercard, status was %2.2x.\n", dev->name,
368
               board->Lance.RDP);
369
        printk("%s: %d packets missed\n", dev->name,
370
               priv->stats.rx_missed_errors);
371
    }
372
 
373
    /* We stop the LANCE here -- it occasionally polls memory if we don't. */
374
    board->Lance.RDP = STOP;
375
 
376
    remove_isr(IRQ_AMIGA_PORTS, ariadne_interrupt, dev);
377
 
378
    MOD_DEC_USE_COUNT;
379
 
380
    return(0);
381
}
382
 
383
 
384
static void ariadne_interrupt(int irq, struct pt_regs *fp, void *data)
385
{
386
    struct device *dev = (struct device *)data;
387
    struct ariadne_private *priv;
388
    struct AriadneBoard *board;
389
    int csr0, boguscnt = 10;
390
 
391
    if (dev == NULL) {
392
        printk("ariadne_interrupt(): irq for unknown device.\n");
393
        return;
394
    }
395
 
396
    priv = (struct ariadne_private *)dev->priv;
397
    board = priv->board;
398
 
399
    board->Lance.RAP = CSR0;    /* PCnet-ISA Controller Status */
400
 
401
    if (!(board->Lance.RDP & INTR))     /* Check if any interrupt has been
402
        return;                            generated by the board. */
403
 
404
    if (dev->interrupt)
405
        printk("%s: Re-entering the interrupt handler.\n", dev->name);
406
 
407
    dev->interrupt = 1;
408
 
409
    while ((csr0 = board->Lance.RDP) & (ERR|RINT|TINT) && --boguscnt >= 0) {
410
        /* Acknowledge all of the current interrupt sources ASAP. */
411
        board->Lance.RDP = csr0 & ~(INEA|TDMD|STOP|STRT|INIT);
412
 
413
#if 0
414
        if (ariadne_debug > 5) {
415
            printk("%s: interrupt  csr0=%#2.2x new csr=%#2.2x.", dev->name,
416
                   csr0, board->Lance.RDP);
417
            printk("[");
418
            if (csr0 & INTR)
419
                printk(" INTR");
420
            if (csr0 & INEA)
421
                printk(" INEA");
422
            if (csr0 & RXON)
423
                printk(" RXON");
424
            if (csr0 & TXON)
425
                printk(" TXON");
426
            if (csr0 & TDMD)
427
                printk(" TDMD");
428
            if (csr0 & STOP)
429
                printk(" STOP");
430
            if (csr0 & STRT)
431
                printk(" STRT");
432
            if (csr0 & INIT)
433
                printk(" INIT");
434
            if (csr0 & ERR)
435
                printk(" ERR");
436
            if (csr0 & BABL)
437
                printk(" BABL");
438
            if (csr0 & CERR)
439
                printk(" CERR");
440
            if (csr0 & MISS)
441
                printk(" MISS");
442
            if (csr0 & MERR)
443
                printk(" MERR");
444
            if (csr0 & RINT)
445
                printk(" RINT");
446
            if (csr0 & TINT)
447
                printk(" TINT");
448
            if (csr0 & IDON)
449
                printk(" IDON");
450
            printk(" ]\n");
451
        }
452
#endif
453
 
454
        if (csr0 & RINT)        /* Rx interrupt */
455
            ariadne_rx(dev);
456
 
457
        if (csr0 & TINT) {      /* Tx-done interrupt */
458
            int dirty_tx = priv->dirty_tx;
459
 
460
            while (dirty_tx < priv->cur_tx) {
461
                int entry = dirty_tx % TX_RING_SIZE;
462
                int status = lowb(priv->tx_ring[entry]->TMD1);
463
 
464
                if (status & TF_OWN)
465
                    break;      /* It still hasn't been Txed */
466
 
467
                priv->tx_ring[entry]->TMD1 &= 0xff00;
468
 
469
                if (status & TF_ERR) {
470
                    /* There was an major error, log it. */
471
                    int err_status = priv->tx_ring[entry]->TMD3;
472
                    priv->stats.tx_errors++;
473
                    if (err_status & EF_RTRY)
474
                        priv->stats.tx_aborted_errors++;
475
                    if (err_status & EF_LCAR)
476
                        priv->stats.tx_carrier_errors++;
477
                    if (err_status & EF_LCOL)
478
                        priv->stats.tx_window_errors++;
479
                    if (err_status & EF_UFLO) {
480
                        /* Ackk!  On FIFO errors the Tx unit is turned off! */
481
                        priv->stats.tx_fifo_errors++;
482
                        /* Remove this verbosity later! */
483
                        printk("%s: Tx FIFO error! Status %4.4x.\n", dev->name,
484
                               csr0);
485
                        /* Restart the chip. */
486
                        board->Lance.RDP = STRT;
487
                    }
488
                } else {
489
                    if (status & (TF_MORE|TF_ONE))
490
                        priv->stats.collisions++;
491
                    priv->stats.tx_packets++;
492
                }
493
                dirty_tx++;
494
            }
495
 
496
#ifndef final_version
497
            if (priv->cur_tx - dirty_tx >= TX_RING_SIZE) {
498
                printk("out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
499
                       dirty_tx, priv->cur_tx, priv->tx_full);
500
                dirty_tx += TX_RING_SIZE;
501
            }
502
#endif
503
 
504
            if (priv->tx_full && dev->tbusy &&
505
                dirty_tx > priv->cur_tx - TX_RING_SIZE + 2) {
506
                /* The ring is no longer full, clear tbusy. */
507
                priv->tx_full = 0;
508
                dev->tbusy = 0;
509
                mark_bh(NET_BH);
510
            }
511
 
512
            priv->dirty_tx = dirty_tx;
513
        }
514
 
515
        /* Log misc errors. */
516
        if (csr0 & BABL)
517
            priv->stats.tx_errors++;    /* Tx babble. */
518
        if (csr0 & MISS)
519
            priv->stats.rx_errors++;    /* Missed a Rx frame. */
520
        if (csr0 & MERR) {
521
            printk("%s: Bus master arbitration failure, status %4.4x.\n",
522
                   dev->name, csr0);
523
            /* Restart the chip. */
524
            board->Lance.RDP = STRT;
525
        }
526
    }
527
 
528
    /* Clear any other interrupt, and set interrupt enable. */
529
    board->Lance.RAP = CSR0;    /* PCnet-ISA Controller Status */
530
    board->Lance.RDP = INEA|BABL|CERR|MISS|MERR|IDON;
531
 
532
#if 0
533
    if (ariadne_debug > 4)
534
        printk("%s: exiting interrupt, csr%d=%#4.4x.\n", dev->name,
535
               board->Lance.RAP, board->Lance.RDP);
536
#endif
537
 
538
    dev->interrupt = 0;
539
    return;
540
}
541
 
542
 
543
static int ariadne_start_xmit(struct sk_buff *skb, struct device *dev)
544
{
545
    struct ariadne_private *priv = (struct ariadne_private *)dev->priv;
546
    struct AriadneBoard *board = priv->board;
547
    int entry;
548
 
549
    /* Transmitter timeout, serious problems. */
550
    if (dev->tbusy) {
551
        int tickssofar = jiffies - dev->trans_start;
552
        if (tickssofar < 20)
553
            return(1);
554
        board->Lance.RAP = CSR0;        /* PCnet-ISA Controller Status */
555
        printk("%s: transmit timed out, status %4.4x, resetting.\n", dev->name,
556
               board->Lance.RDP);
557
        board->Lance.RDP = STOP;
558
        priv->stats.tx_errors++;
559
#ifndef final_version
560
        {
561
            int i;
562
            printk(" Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d.",
563
                   priv->dirty_tx, priv->cur_tx, priv->tx_full ? " (full)" : "",
564
                   priv->cur_rx);
565
            for (i = 0 ; i < RX_RING_SIZE; i++)
566
                printk("%s %08x %04x %04x", i & 0x3 ? "" : "\n ",
567
                       (swapw((priv->rx_ring[i]->RMD1))<<16)|swapw(priv->rx_ring[i]->RMD0),
568
                       swapw(-priv->rx_ring[i]->RMD2), swapw(priv->rx_ring[i]->RMD3));
569
            for (i = 0 ; i < TX_RING_SIZE; i++)
570
                printk("%s %08x %04x %04x", i & 0x3 ? "" : "\n ",
571
                       (swapw((priv->tx_ring[i]->TMD1))<<16)|swapw(priv->tx_ring[i]->TMD0),
572
                       swapw(-priv->tx_ring[i]->TMD2), priv->tx_ring[i]->TMD3);
573
            printk("\n");
574
        }
575
#endif
576
        ariadne_init_ring(dev);
577
        board->Lance.RDP = INEA|STRT;
578
 
579
        dev->tbusy = 0;
580
        dev->trans_start = jiffies;
581
        dev_kfree_skb(skb, FREE_WRITE);
582
        return(0);
583
    }
584
 
585
    if (skb == NULL) {
586
        dev_tint(dev);
587
        return(0);
588
    }
589
 
590
    if (skb->len <= 0)
591
        return(0);
592
 
593
#if 0
594
    if (ariadne_debug > 3) {
595
        board->Lance.RAP = CSR0;        /* PCnet-ISA Controller Status */
596
        printk("%s: ariadne_start_xmit() called, csr0 %4.4x.\n", dev->name,
597
               board->Lance.RDP);
598
        board->Lance.RDP = 0x0000;
599
    }
600
#endif
601
 
602
    /* Block a timer-based transmit from overlapping.  This could better be
603
        done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
604
    if (set_bit(0, (void*)&dev->tbusy) != 0) {
605
        printk("%s: Transmitter access conflict.\n", dev->name);
606
        return(1);
607
    }
608
 
609
    if (set_bit(0, (void*)&priv->lock) != 0) {
610
        if (ariadne_debug > 0)
611
            printk("%s: tx queue lock!.\n", dev->name);
612
        /* don't clear dev->tbusy flag. */
613
        return(1);
614
    }
615
 
616
    /* Fill in a Tx ring entry */
617
 
618
#if 0
619
    printk("TX pkt type 0x%04x from ", ((u_short *)skb->data)[6]);
620
    {
621
        int i;
622
        u_char *ptr = &((u_char *)skb->data)[6];
623
        for (i = 0; i < 6; i++)
624
            printk("%02x", ptr[i]);
625
    }
626
    printk(" to ");
627
    {
628
        int i;
629
        u_char *ptr = (u_char *)skb->data;
630
        for (i = 0; i < 6; i++)
631
            printk("%02x", ptr[i]);
632
    }
633
    printk(" data 0x%08x len %d\n", (int)skb->data, (int)skb->len);
634
#endif
635
 
636
    entry = priv->cur_tx % TX_RING_SIZE;
637
 
638
    /* Caution: the write order is important here, set the base address with
639
                the "ownership" bits last. */
640
 
641
    priv->tx_ring[entry]->TMD2 = swapw((u_short)-skb->len);
642
    priv->tx_ring[entry]->TMD3 = 0x0000;
643
    memcpyw(priv->tx_buff[entry], (u_short *)skb->data, skb->len);
644
 
645
#if 0
646
    {
647
        int i, len;
648
 
649
        len = skb->len > 64 ? 64 : skb->len;
650
        len >>= 1;
651
        for (i = 0; i < len; i += 8) {
652
            int j;
653
            printk("%04x:", i);
654
            for (j = 0; (j < 8) && ((i+j) < len); j++) {
655
                if (!(j & 1))
656
                    printk(" ");
657
                printk("%04x", priv->tx_buff[entry][i+j]);
658
            }
659
            printk("\n");
660
        }
661
    }
662
#endif
663
 
664
    priv->tx_ring[entry]->TMD1 = (priv->tx_ring[entry]->TMD1&0xff00)|TF_OWN|TF_STP|TF_ENP;
665
 
666
    dev_kfree_skb(skb, FREE_WRITE);
667
 
668
    priv->cur_tx++;
669
    if ((priv->cur_tx >= TX_RING_SIZE) && (priv->dirty_tx >= TX_RING_SIZE)) {
670
 
671
#if 0
672
        printk("*** Subtracting TX_RING_SIZE from cur_tx (%d) and dirty_tx (%d)\n",
673
               priv->cur_tx, priv->dirty_tx);
674
#endif
675
 
676
        priv->cur_tx -= TX_RING_SIZE;
677
        priv->dirty_tx -= TX_RING_SIZE;
678
    }
679
 
680
    /* Trigger an immediate send poll. */
681
    board->Lance.RAP = CSR0;    /* PCnet-ISA Controller Status */
682
    board->Lance.RDP = INEA|TDMD;
683
 
684
    dev->trans_start = jiffies;
685
 
686
    cli();
687
    priv->lock = 0;
688
    if (lowb(priv->tx_ring[(entry+1) % TX_RING_SIZE]->TMD1) == 0)
689
        dev->tbusy = 0;
690
    else
691
        priv->tx_full = 1;
692
    sti();
693
 
694
    return(0);
695
}
696
 
697
 
698
static int ariadne_rx(struct device *dev)
699
{
700
    struct ariadne_private *priv = (struct ariadne_private *)dev->priv;
701
    int entry = priv->cur_rx % RX_RING_SIZE;
702
    int i;
703
 
704
    /* If we own the next entry, it's a new packet. Send it up. */
705
    while (!(lowb(priv->rx_ring[entry]->RMD1) & RF_OWN)) {
706
        int status = lowb(priv->rx_ring[entry]->RMD1);
707
 
708
        if (status != (RF_STP|RF_ENP)) {        /* There was an error. */
709
            /* There is a tricky error noted by John Murphy,
710
                <murf@perftech.com> to Russ Nelson: Even with full-sized
711
                buffers it's possible for a jabber packet to use two
712
                buffers, with only the last correctly noting the error. */
713
            if (status & RF_ENP)
714
                /* Only count a general error at the end of a packet.*/
715
                priv->stats.rx_errors++;
716
            if (status & RF_FRAM)
717
                priv->stats.rx_frame_errors++;
718
            if (status & RF_OFLO)
719
                priv->stats.rx_over_errors++;
720
            if (status & RF_CRC)
721
                priv->stats.rx_crc_errors++;
722
            if (status & RF_BUFF)
723
                priv->stats.rx_fifo_errors++;
724
            priv->rx_ring[entry]->RMD1 &= 0xff00|RF_STP|RF_ENP;
725
        } else {
726
            /* Malloc up new buffer, compatible with net-3. */
727
            short pkt_len = swapw(priv->rx_ring[entry]->RMD3);
728
            struct sk_buff *skb;
729
 
730
            skb = dev_alloc_skb(pkt_len+2);
731
            if (skb == NULL) {
732
                printk("%s: Memory squeeze, deferring packet.\n", dev->name);
733
                for (i = 0; i < RX_RING_SIZE; i++)
734
                    if (lowb(priv->rx_ring[(entry+i) % RX_RING_SIZE]->RMD1) & RF_OWN)
735
                        break;
736
 
737
                if (i > RX_RING_SIZE-2) {
738
                    priv->stats.rx_dropped++;
739
                    priv->rx_ring[entry]->RMD1 |= RF_OWN;
740
                    priv->cur_rx++;
741
                }
742
                break;
743
            }
744
 
745
 
746
            skb->dev = dev;
747
            skb_reserve(skb,2);         /* 16 byte align */
748
            skb_put(skb,pkt_len);       /* Make room */
749
            eth_copy_and_sum(skb, (char *)priv->rx_buff[entry], pkt_len,0);
750
            skb->protocol=eth_type_trans(skb,dev);
751
#if 0
752
            printk("RX pkt type 0x%04x from ", ((u_short *)skb->data)[6]);
753
            {
754
                int i;
755
                u_char *ptr = &((u_char *)skb->data)[6];
756
                for (i = 0; i < 6; i++)
757
                    printk("%02x", ptr[i]);
758
            }
759
            printk(" to ");
760
            {
761
                int i;
762
                u_char *ptr = (u_char *)skb->data;
763
                for (i = 0; i < 6; i++)
764
                    printk("%02x", ptr[i]);
765
            }
766
            printk(" data 0x%08x len %d\n", (int)skb->data, (int)skb->len);
767
#endif
768
 
769
            netif_rx(skb);
770
            priv->stats.rx_packets++;
771
        }
772
 
773
        priv->rx_ring[entry]->RMD1 |= RF_OWN;
774
        entry = (++priv->cur_rx) % RX_RING_SIZE;
775
    }
776
 
777
    priv->cur_rx = priv->cur_rx % RX_RING_SIZE;
778
 
779
    /* We should check that at least two ring entries are free.  If not,
780
       we should free one and mark stats->rx_dropped++. */
781
 
782
    return(0);
783
}
784
 
785
 
786
static struct enet_statistics *ariadne_get_stats(struct device *dev)
787
{
788
    struct ariadne_private *priv = (struct ariadne_private *)dev->priv;
789
    struct AriadneBoard *board = priv->board;
790
    short saved_addr;
791
 
792
    cli();
793
    saved_addr = board->Lance.RAP;
794
    board->Lance.RAP = CSR112;  /* Missed Frame Count */
795
    priv->stats.rx_missed_errors = swapw(board->Lance.RDP);
796
    board->Lance.RAP = saved_addr;
797
    sti();
798
 
799
    return(&priv->stats);
800
}
801
 
802
 
803
/* Set or clear the multicast filter for this adaptor.
804
    num_addrs == -1     Promiscuous mode, receive all packets
805
    num_addrs == 0      Normal mode, clear multicast list
806
    num_addrs > 0       Multicast mode, receive normal and MC packets, and do
807
                        best-effort filtering.
808
 */
809
static void set_multicast_list(struct device *dev)
810
{
811
    struct ariadne_private *priv = (struct ariadne_private *)dev->priv;
812
    struct AriadneBoard *board = priv->board;
813
 
814
    /* We take the simple way out and always enable promiscuous mode. */
815
    board->Lance.RAP = CSR0;    /* PCnet-ISA Controller Status */
816
    board->Lance.RDP = STOP;    /* Temporarily stop the lance. */
817
 
818
    if (dev->flags & IFF_PROMISC) {
819
        /* Log any net taps. */
820
        printk("%s: Promiscuous mode enabled.\n", dev->name);
821
        board->Lance.RAP = CSR15;       /* Mode Register */
822
        board->Lance.RDP = PROM;        /* Set promiscuous mode */
823
    } else {
824
        short multicast_table[4];
825
        int num_addrs = dev->mc_count;
826
        int i;
827
        /* We don't use the multicast table, but rely on upper-layer filtering. */
828
        memset(multicast_table, (num_addrs == 0) ? 0 : -1,
829
               sizeof(multicast_table));
830
        for (i = 0; i < 4; i++) {
831
            board->Lance.RAP = CSR8+(i<<8);     /* Logical Address Filter */
832
            board->Lance.RDP = swapw(multicast_table[i]);
833
        }
834
        board->Lance.RAP = CSR15;       /* Mode Register */
835
        board->Lance.RDP = 0x0000;      /* Unset promiscuous mode */
836
    }
837
 
838
    board->Lance.RAP = CSR0;            /* PCnet-ISA Controller Status */
839
    board->Lance.RDP = INEA|STRT|IDON;  /* Resume normal operation. */
840
}
841
 
842
 
843
#ifdef MODULE
844
static char devicename[9] = { 0, };
845
 
846
static struct device ariadne_dev =
847
{
848
    devicename,                         /* filled in by register_netdev() */
849
    0, 0, 0, 0,                             /* memory */
850
    0, 0,                         /* base, irq */
851
    0, 0, 0, NULL, ariadne_probe,
852
};
853
 
854
int init_module(void)
855
{
856
    int err;
857
 
858
    if ((err = register_netdev(&ariadne_dev))) {
859
        if (err == -EIO)
860
            printk("No Ariadne board found. Module not loaded.\n");
861
        return(err);
862
    }
863
    return(0);
864
}
865
 
866
void cleanup_module(void)
867
{
868
    struct ariadne_private *priv = (struct ariadne_private *)ariadne_dev.priv;
869
 
870
    unregister_netdev(&ariadne_dev);
871
    zorro_unconfig_board(priv->key, 0);
872
    kfree(priv);
873
}
874
 
875
#endif /* MODULE */

powered by: WebSVN 2.1.0

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