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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [net/] [3c507.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
/* 3c507.c: An EtherLink16 device driver for Linux. */
2
/*
3
        Written 1993,1994 by Donald Becker.
4
 
5
        Copyright 1993 United States Government as represented by the
6
        Director, National Security Agency.
7
 
8
        This software may be used and distributed according to the terms
9
        of the GNU Public License, incorporated herein by reference.
10
 
11
        The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
12
        Center of Excellence in Space Data and Information Sciences
13
           Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
14
 
15
        Thanks go to jennings@Montrouge.SMR.slb.com ( Patrick Jennings)
16
        and jrs@world.std.com (Rick Sladkey) for testing and bugfixes.
17
        Mark Salazar <leslie@access.digex.net> made the changes for cards with
18
        only 16K packet buffers.
19
 
20
        Things remaining to do:
21
        Verify that the tx and rx buffers don't have fencepost errors.
22
        Move the theory of operation and memory map documentation.
23
        The statistics need to be updated correctly.
24
*/
25
 
26
static const char *version =
27
        "3c507.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
28
 
29
 
30
#include <linux/module.h>
31
 
32
/*
33
  Sources:
34
        This driver wouldn't have been written with the availability of the
35
        Crynwr driver source code.      It provided a known-working implementation
36
        that filled in the gaping holes of the Intel documentation.  Three cheers
37
        for Russ Nelson.
38
 
39
        Intel Microcommunications Databook, Vol. 1, 1990.  It provides just enough
40
        info that the casual reader might think that it documents the i82586 :-<.
41
*/
42
 
43
#include <linux/kernel.h>
44
#include <linux/sched.h>
45
#include <linux/types.h>
46
#include <linux/fcntl.h>
47
#include <linux/interrupt.h>
48
#include <linux/ptrace.h>
49
#include <linux/ioport.h>
50
#include <linux/in.h>
51
#include <linux/string.h>
52
#include <asm/system.h>
53
#include <asm/bitops.h>
54
#include <asm/io.h>
55
#include <asm/dma.h>
56
#include <linux/errno.h>
57
 
58
#include <linux/netdevice.h>
59
#include <linux/etherdevice.h>
60
#include <linux/skbuff.h>
61
#include <linux/malloc.h>
62
 
63
 
64
/* use 0 for production, 1 for verification, 2..7 for debug */
65
#ifndef NET_DEBUG
66
#define NET_DEBUG 1
67
#endif
68
static unsigned int net_debug = NET_DEBUG;
69
 
70
/* A zero-terminated list of common I/O addresses to be probed. */
71
static unsigned int netcard_portlist[] =
72
        { 0x300, 0x320, 0x340, 0x280, 0};
73
 
74
/*
75
                        Details of the i82586.
76
 
77
   You'll really need the databook to understand the details of this part,
78
   but the outline is that the i82586 has two separate processing units.
79
   Both are started from a list of three configuration tables, of which only
80
   the last, the System Control Block (SCB), is used after reset-time.  The SCB
81
   has the following fields:
82
                Status word
83
                Command word
84
                Tx/Command block addr.
85
                Rx block addr.
86
   The command word accepts the following controls for the Tx and Rx units:
87
  */
88
 
89
#define  CUC_START       0x0100
90
#define  CUC_RESUME      0x0200
91
#define  CUC_SUSPEND 0x0300
92
#define  RX_START        0x0010
93
#define  RX_RESUME       0x0020
94
#define  RX_SUSPEND      0x0030
95
 
96
/* The Rx unit uses a list of frame descriptors and a list of data buffer
97
   descriptors.  We use full-sized (1518 byte) data buffers, so there is
98
   a one-to-one pairing of frame descriptors to buffer descriptors.
99
 
100
   The Tx ("command") unit executes a list of commands that look like:
101
                Status word             Written by the 82586 when the command is done.
102
                Command word    Command in lower 3 bits, post-command action in upper 3
103
                Link word               The address of the next command.
104
                Parameters              (as needed).
105
 
106
        Some definitions related to the Command Word are:
107
 */
108
#define CMD_EOL         0x8000                  /* The last command of the list, stop. */
109
#define CMD_SUSP        0x4000                  /* Suspend after doing cmd. */
110
#define CMD_INTR        0x2000                  /* Interrupt after doing cmd. */
111
 
112
enum commands {
113
        CmdNOp = 0, CmdSASetup = 1, CmdConfigure = 2, CmdMulticastList = 3,
114
        CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7};
115
 
116
/* Information that need to be kept for each board. */
117
struct net_local {
118
        struct enet_statistics stats;
119
        int last_restart;
120
        ushort rx_head;
121
        ushort rx_tail;
122
        ushort tx_head;
123
        ushort tx_cmd_link;
124
        ushort tx_reap;
125
};
126
 
127
/*
128
                Details of the EtherLink16 Implementation
129
  The 3c507 is a generic shared-memory i82586 implementation.
130
  The host can map 16K, 32K, 48K, or 64K of the 64K memory into
131
  0x0[CD][08]0000, or all 64K into 0xF[02468]0000.
132
  */
133
 
134
/* Offsets from the base I/O address. */
135
#define SA_DATA         0        /* Station address data, or 3Com signature. */
136
#define MISC_CTRL       6       /* Switch the SA_DATA banks, and bus config bits. */
137
#define RESET_IRQ       10      /* Reset the latched IRQ line. */
138
#define SIGNAL_CA       11      /* Frob the 82586 Channel Attention line. */
139
#define ROM_CONFIG      13
140
#define MEM_CONFIG      14
141
#define IRQ_CONFIG      15
142
#define EL16_IO_EXTENT 16
143
 
144
/* The ID port is used at boot-time to locate the ethercard. */
145
#define ID_PORT         0x100
146
 
147
/* Offsets to registers in the mailbox (SCB). */
148
#define iSCB_STATUS     0x8
149
#define iSCB_CMD                0xA
150
#define iSCB_CBL                0xC     /* Command BLock offset. */
151
#define iSCB_RFA                0xE     /* Rx Frame Area offset. */
152
 
153
/*  Since the 3c507 maps the shared memory window so that the last byte is
154
        at 82586 address FFFF, the first byte is at 82586 address 0, 16K, 32K, or
155
        48K corresponding to window sizes of 64K, 48K, 32K and 16K respectively.
156
        We can account for this be setting the 'SBC Base' entry in the ISCP table
157
        below for all the 16 bit offset addresses, and also adding the 'SCB Base'
158
        value to all 24 bit physical addresses (in the SCP table and the TX and RX
159
        Buffer Descriptors).
160
                                        -Mark
161
        */
162
#define SCB_BASE                ((unsigned)64*1024 - (dev->mem_end - dev->mem_start))
163
 
164
/*
165
  What follows in 'init_words[]' is the "program" that is downloaded to the
166
  82586 memory.  It's mostly tables and command blocks, and starts at the
167
  reset address 0xfffff6.  This is designed to be similar to the EtherExpress,
168
  thus the unusual location of the SCB at 0x0008.
169
 
170
  Even with the additional "don't care" values, doing it this way takes less
171
  program space than initializing the individual tables, and I feel it's much
172
  cleaner.
173
 
174
  The databook is particularly useless for the first two structures, I had
175
  to use the Crynwr driver as an example.
176
 
177
   The memory setup is as follows:
178
   */
179
 
180
#define CONFIG_CMD      0x0018
181
#define SET_SA_CMD      0x0024
182
#define SA_OFFSET       0x002A
183
#define IDLELOOP        0x30
184
#define TDR_CMD         0x38
185
#define TDR_TIME        0x3C
186
#define DUMP_CMD        0x40
187
#define DIAG_CMD        0x48
188
#define SET_MC_CMD      0x4E
189
#define DUMP_DATA       0x56    /* A 170 byte buffer for dump and Set-MC into. */
190
 
191
#define TX_BUF_START    0x0100
192
#define NUM_TX_BUFS     4
193
#define TX_BUF_SIZE     (1518+14+20+16) /* packet+header+TBD */
194
 
195
#define RX_BUF_START    0x2000
196
#define RX_BUF_SIZE     (1518+14+18)    /* packet+header+RBD */
197
#define RX_BUF_END              (dev->mem_end - dev->mem_start)
198
 
199
/*
200
  That's it: only 86 bytes to set up the beast, including every extra
201
  command available.  The 170 byte buffer at DUMP_DATA is shared between the
202
  Dump command (called only by the diagnostic program) and the SetMulticastList
203
  command.
204
 
205
  To complete the memory setup you only have to write the station address at
206
  SA_OFFSET and create the Tx & Rx buffer lists.
207
 
208
  The Tx command chain and buffer list is setup as follows:
209
  A Tx command table, with the data buffer pointing to...
210
  A Tx data buffer descriptor.  The packet is in a single buffer, rather than
211
        chaining together several smaller buffers.
212
  A NoOp command, which initially points to itself,
213
  And the packet data.
214
 
215
  A transmit is done by filling in the Tx command table and data buffer,
216
  re-writing the NoOp command, and finally changing the offset of the last
217
  command to point to the current Tx command.  When the Tx command is finished,
218
  it jumps to the NoOp, when it loops until the next Tx command changes the
219
  "link offset" in the NoOp.  This way the 82586 never has to go through the
220
  slow restart sequence.
221
 
222
  The Rx buffer list is set up in the obvious ring structure.  We have enough
223
  memory (and low enough interrupt latency) that we can avoid the complicated
224
  Rx buffer linked lists by alway associating a full-size Rx data buffer with
225
  each Rx data frame.
226
 
227
  I current use four transmit buffers starting at TX_BUF_START (0x0100), and
228
  use the rest of memory, from RX_BUF_START to RX_BUF_END, for Rx buffers.
229
 
230
  */
231
 
232
unsigned short init_words[] = {
233
        /*      System Configuration Pointer (SCP). */
234
        0x0000,                                 /* Set bus size to 16 bits. */
235
        0,0,                                      /* pad words. */
236
        0x0000,0x0000,                  /* ISCP phys addr, set in init_82586_mem(). */
237
 
238
        /*      Intermediate System Configuration Pointer (ISCP). */
239
        0x0001,                                 /* Status word that's cleared when init is done. */
240
        0x0008,0,0,                               /* SCB offset, (skip, skip) */
241
 
242
        /* System Control Block (SCB). */
243
        0,0xf000|RX_START|CUC_START,     /* SCB status and cmd. */
244
        CONFIG_CMD,                             /* Command list pointer, points to Configure. */
245
        RX_BUF_START,                           /* Rx block list. */
246
        0,0,0,0,                            /* Error count: CRC, align, buffer, overrun. */
247
 
248
        /* 0x0018: Configure command.  Change to put MAC data with packet. */
249
        0, CmdConfigure,         /* Status, command.             */
250
        SET_SA_CMD,                             /* Next command is Set Station Addr. */
251
        0x0804,                                 /* "4" bytes of config data, 8 byte FIFO. */
252
        0x2e40,                                 /* Magic values, including MAC data location. */
253
        0,                                               /* Unused pad word. */
254
 
255
        /* 0x0024: Setup station address command. */
256
        0, CmdSASetup,
257
        SET_MC_CMD,                             /* Next command. */
258
        0xaa00,0xb000,0x0bad,   /* Station address (to be filled in) */
259
 
260
        /* 0x0030: NOP, looping back to itself.  Point to first Tx buffer to Tx. */
261
        0, CmdNOp, IDLELOOP, 0 /* pad */,
262
 
263
        /* 0x0038: A unused Time-Domain Reflectometer command. */
264
        0, CmdTDR, IDLELOOP, 0,
265
 
266
        /* 0x0040: An unused Dump State command. */
267
        0, CmdDump, IDLELOOP, DUMP_DATA,
268
 
269
        /* 0x0048: An unused Diagnose command. */
270
        0, CmdDiagnose, IDLELOOP,
271
 
272
        /* 0x004E: An empty set-multicast-list command. */
273
        0, CmdMulticastList, IDLELOOP, 0,
274
};
275
 
276
/* Index to functions, as function prototypes. */
277
 
278
extern int el16_probe(struct device *dev);      /* Called from Space.c */
279
 
280
static int      el16_probe1(struct device *dev, int ioaddr);
281
static int      el16_open(struct device *dev);
282
static int      el16_send_packet(struct sk_buff *skb, struct device *dev);
283
static void     el16_interrupt(int irq, void *dev_id, struct pt_regs *regs);
284
static void el16_rx(struct device *dev);
285
static int      el16_close(struct device *dev);
286
static struct enet_statistics *el16_get_stats(struct device *dev);
287
 
288
static void hardware_send_packet(struct device *dev, void *buf, short length);
289
void init_82586_mem(struct device *dev);
290
 
291
 
292
#ifdef HAVE_DEVLIST
293
struct netdev_entry netcard_drv =
294
{"3c507", el16_probe1, EL16_IO_EXTENT, netcard_portlist};
295
#endif
296
 
297
/* Check for a network adaptor of this type, and return '0' iff one exists.
298
        If dev->base_addr == 0, probe all likely locations.
299
        If dev->base_addr == 1, always return failure.
300
        If dev->base_addr == 2, (detachable devices only) allocate space for the
301
        device and return success.
302
        */
303
int
304
el16_probe(struct device *dev)
305
{
306
        int base_addr = dev ? dev->base_addr : 0;
307
        int i;
308
 
309
        if (base_addr > 0x1ff)  /* Check a single specified location. */
310
                return el16_probe1(dev, base_addr);
311
        else if (base_addr != 0)
312
                return ENXIO;           /* Don't probe at all. */
313
 
314
        for (i = 0; netcard_portlist[i]; i++) {
315
                int ioaddr = netcard_portlist[i];
316
                if (check_region(ioaddr, EL16_IO_EXTENT))
317
                        continue;
318
                if (el16_probe1(dev, ioaddr) == 0)
319
                        return 0;
320
        }
321
 
322
        return ENODEV;
323
}
324
 
325
int el16_probe1(struct device *dev, int ioaddr)
326
{
327
        static unsigned char init_ID_done = 0, version_printed = 0;
328
        int i, irq, irqval;
329
 
330
        if (init_ID_done == 0) {
331
                ushort lrs_state = 0xff;
332
                /* Send the ID sequence to the ID_PORT to enable the board(s). */
333
                outb(0x00, ID_PORT);
334
                for(i = 0; i < 255; i++) {
335
                        outb(lrs_state, ID_PORT);
336
                        lrs_state <<= 1;
337
                        if (lrs_state & 0x100)
338
                                lrs_state ^= 0xe7;
339
                }
340
                outb(0x00, ID_PORT);
341
                init_ID_done = 1;
342
        }
343
 
344
        if (inb(ioaddr) == '*' && inb(ioaddr+1) == '3'
345
                && inb(ioaddr+2) == 'C' && inb(ioaddr+3) == 'O')
346
                ;
347
        else
348
                return ENODEV;
349
 
350
        /* Allocate a new 'dev' if needed. */
351
        if (dev == NULL)
352
                dev = init_etherdev(0, sizeof(struct net_local));
353
 
354
        if (net_debug  &&  version_printed++ == 0)
355
                printk(version);
356
 
357
        printk("%s: 3c507 at %#x,", dev->name, ioaddr);
358
 
359
        /* We should make a few more checks here, like the first three octets of
360
           the S.A. for the manufacturer's code. */
361
 
362
        irq = inb(ioaddr + IRQ_CONFIG) & 0x0f;
363
 
364
        irqval = request_irq(irq, &el16_interrupt, 0, "3c507", NULL);
365
        if (irqval) {
366
                printk ("unable to get IRQ %d (irqval=%d).\n", irq, irqval);
367
                return EAGAIN;
368
        }
369
 
370
        /* We've committed to using the board, and can start filling in *dev. */
371
        request_region(ioaddr, EL16_IO_EXTENT, "3c507");
372
        dev->base_addr = ioaddr;
373
 
374
        outb(0x01, ioaddr + MISC_CTRL);
375
        for (i = 0; i < 6; i++) {
376
                dev->dev_addr[i] = inb(ioaddr + i);
377
                printk(" %02x", dev->dev_addr[i]);
378
        }
379
 
380
        if ((dev->mem_start & 0xf) > 0)
381
                net_debug = dev->mem_start & 7;
382
 
383
#ifdef MEM_BASE
384
        dev->mem_start = MEM_BASE;
385
        dev->mem_end = dev->mem_start + 0x10000;
386
#else
387
        {
388
                int base;
389
                int size;
390
                char mem_config = inb(ioaddr + MEM_CONFIG);
391
                if (mem_config & 0x20) {
392
                        size = 64*1024;
393
                        base = 0xf00000 + (mem_config & 0x08 ? 0x080000
394
                                                           : ((mem_config & 3) << 17));
395
                } else {
396
                        size = ((mem_config & 3) + 1) << 14;
397
                        base = 0x0c0000 + ( (mem_config & 0x18) << 12);
398
                }
399
                dev->mem_start = base;
400
                dev->mem_end = base + size;
401
        }
402
#endif
403
 
404
        dev->if_port = (inb(ioaddr + ROM_CONFIG) & 0x80) ? 1 : 0;
405
        dev->irq = inb(ioaddr + IRQ_CONFIG) & 0x0f;
406
 
407
        printk(", IRQ %d, %sternal xcvr, memory %#lx-%#lx.\n", dev->irq,
408
                   dev->if_port ? "ex" : "in", dev->mem_start, dev->mem_end-1);
409
 
410
        if (net_debug)
411
                printk(version);
412
 
413
        /* Initialize the device structure. */
414
        dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
415
        if (dev->priv == NULL)
416
                return -ENOMEM;
417
        memset(dev->priv, 0, sizeof(struct net_local));
418
 
419
        dev->open               = el16_open;
420
        dev->stop               = el16_close;
421
        dev->hard_start_xmit = el16_send_packet;
422
        dev->get_stats  = el16_get_stats;
423
 
424
        ether_setup(dev);       /* Generic ethernet behaviour */
425
 
426
        dev->flags&=~IFF_MULTICAST;     /* Multicast doesn't work */
427
 
428
        return 0;
429
}
430
 
431
 
432
 
433
static int
434
el16_open(struct device *dev)
435
{
436
        irq2dev_map[dev->irq] = dev;
437
 
438
        /* Initialize the 82586 memory and start it. */
439
        init_82586_mem(dev);
440
 
441
        dev->tbusy = 0;
442
        dev->interrupt = 0;
443
        dev->start = 1;
444
 
445
        MOD_INC_USE_COUNT;
446
 
447
        return 0;
448
}
449
 
450
static int
451
el16_send_packet(struct sk_buff *skb, struct device *dev)
452
{
453
        struct net_local *lp = (struct net_local *)dev->priv;
454
        int ioaddr = dev->base_addr;
455
        short *shmem = (short*)dev->mem_start;
456
 
457
        if (dev->tbusy) {
458
                /* If we get here, some higher level has decided we are broken.
459
                   There should really be a "kick me" function call instead. */
460
                int tickssofar = jiffies - dev->trans_start;
461
                if (tickssofar < 5)
462
                        return 1;
463
                if (net_debug > 1)
464
                        printk("%s: transmit timed out, %s?  ", dev->name,
465
                                   shmem[iSCB_STATUS>>1] & 0x8000 ? "IRQ conflict" :
466
                                   "network cable problem");
467
                /* Try to restart the adaptor. */
468
                if (lp->last_restart == lp->stats.tx_packets) {
469
                        if (net_debug > 1) printk("Resetting board.\n");
470
                        /* Completely reset the adaptor. */
471
                        init_82586_mem(dev);
472
                } else {
473
                        /* Issue the channel attention signal and hope it "gets better". */
474
                        if (net_debug > 1) printk("Kicking board.\n");
475
                        shmem[iSCB_CMD>>1] = 0xf000|CUC_START|RX_START;
476
                        outb(0, ioaddr + SIGNAL_CA);                     /* Issue channel-attn. */
477
                        lp->last_restart = lp->stats.tx_packets;
478
                }
479
                dev->tbusy=0;
480
                dev->trans_start = jiffies;
481
        }
482
 
483
        /* If some higher layer thinks we've missed an tx-done interrupt
484
           we are passed NULL. Caution: dev_tint() handles the cli()/sti()
485
           itself. */
486
        if (skb == NULL) {
487
                dev_tint(dev);
488
                return 0;
489
        }
490
 
491
        /* Block a timer-based transmit from overlapping. */
492
        if (set_bit(0, (void*)&dev->tbusy) != 0)
493
                printk("%s: Transmitter access conflict.\n", dev->name);
494
        else {
495
                short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
496
                unsigned char *buf = skb->data;
497
 
498
                /* Disable the 82586's input to the interrupt line. */
499
                outb(0x80, ioaddr + MISC_CTRL);
500
                hardware_send_packet(dev, buf, length);
501
                dev->trans_start = jiffies;
502
                /* Enable the 82586 interrupt input. */
503
                outb(0x84, ioaddr + MISC_CTRL);
504
        }
505
 
506
        dev_kfree_skb (skb, FREE_WRITE);
507
 
508
        /* You might need to clean up and record Tx statistics here. */
509
 
510
        return 0;
511
}
512
 
513
/*      The typical workload of the driver:
514
        Handle the network interface interrupts. */
515
static void
516
el16_interrupt(int irq, void *dev_id, struct pt_regs *regs)
517
{
518
        struct device *dev = (struct device *)(irq2dev_map[irq]);
519
        struct net_local *lp;
520
        int ioaddr, status, boguscount = 0;
521
        ushort ack_cmd = 0;
522
        ushort *shmem;
523
 
524
        if (dev == NULL) {
525
                printk ("net_interrupt(): irq %d for unknown device.\n", irq);
526
                return;
527
        }
528
        dev->interrupt = 1;
529
 
530
        ioaddr = dev->base_addr;
531
        lp = (struct net_local *)dev->priv;
532
        shmem = ((ushort*)dev->mem_start);
533
 
534
        status = shmem[iSCB_STATUS>>1];
535
 
536
        if (net_debug > 4) {
537
                printk("%s: 3c507 interrupt, status %4.4x.\n", dev->name, status);
538
        }
539
 
540
        /* Disable the 82586's input to the interrupt line. */
541
        outb(0x80, ioaddr + MISC_CTRL);
542
 
543
        /* Reap the Tx packet buffers. */
544
        while (lp->tx_reap != lp->tx_head) {
545
          unsigned short tx_status = shmem[lp->tx_reap>>1];
546
 
547
          if (tx_status == 0) {
548
                if (net_debug > 5)  printk("Couldn't reap %#x.\n", lp->tx_reap);
549
                break;
550
          }
551
          if (tx_status & 0x2000) {
552
                lp->stats.tx_packets++;
553
                lp->stats.collisions += tx_status & 0xf;
554
                dev->tbusy = 0;
555
                mark_bh(NET_BH);                /* Inform upper layers. */
556
          } else {
557
                lp->stats.tx_errors++;
558
                if (tx_status & 0x0600)  lp->stats.tx_carrier_errors++;
559
                if (tx_status & 0x0100)  lp->stats.tx_fifo_errors++;
560
                if (!(tx_status & 0x0040))  lp->stats.tx_heartbeat_errors++;
561
                if (tx_status & 0x0020)  lp->stats.tx_aborted_errors++;
562
          }
563
          if (net_debug > 5)
564
                  printk("Reaped %x, Tx status %04x.\n" , lp->tx_reap, tx_status);
565
          lp->tx_reap += TX_BUF_SIZE;
566
          if (lp->tx_reap > RX_BUF_START - TX_BUF_SIZE)
567
                lp->tx_reap = TX_BUF_START;
568
          if (++boguscount > 4)
569
                break;
570
        }
571
 
572
        if (status & 0x4000) { /* Packet received. */
573
                if (net_debug > 5)
574
                        printk("Received packet, rx_head %04x.\n", lp->rx_head);
575
                el16_rx(dev);
576
        }
577
 
578
        /* Acknowledge the interrupt sources. */
579
        ack_cmd = status & 0xf000;
580
 
581
        if ((status & 0x0700) != 0x0200 && dev->start) {
582
                if (net_debug)
583
                        printk("%s: Command unit stopped, status %04x, restarting.\n",
584
                                   dev->name, status);
585
                /* If this ever occurs we should really re-write the idle loop, reset
586
                   the Tx list, and do a complete restart of the command unit.
587
                   For now we rely on the Tx timeout if the resume doesn't work. */
588
                ack_cmd |= CUC_RESUME;
589
        }
590
 
591
        if ((status & 0x0070) != 0x0040  &&  dev->start) {
592
          static void init_rx_bufs(struct device *);
593
                /* The Rx unit is not ready, it must be hung.  Restart the receiver by
594
                   initializing the rx buffers, and issuing an Rx start command. */
595
                if (net_debug)
596
                        printk("%s: Rx unit stopped, status %04x, restarting.\n",
597
                                   dev->name, status);
598
                init_rx_bufs(dev);
599
                shmem[iSCB_RFA >> 1] = RX_BUF_START;
600
                ack_cmd |= RX_START;
601
        }
602
 
603
        shmem[iSCB_CMD>>1] = ack_cmd;
604
        outb(0, ioaddr + SIGNAL_CA);                     /* Issue channel-attn. */
605
 
606
        /* Clear the latched interrupt. */
607
        outb(0, ioaddr + RESET_IRQ);
608
 
609
        /* Enable the 82586's interrupt input. */
610
        outb(0x84, ioaddr + MISC_CTRL);
611
 
612
        return;
613
}
614
 
615
static int
616
el16_close(struct device *dev)
617
{
618
        int ioaddr = dev->base_addr;
619
        ushort *shmem = (short*)dev->mem_start;
620
 
621
        dev->tbusy = 1;
622
        dev->start = 0;
623
 
624
        /* Flush the Tx and disable Rx. */
625
        shmem[iSCB_CMD >> 1] = RX_SUSPEND | CUC_SUSPEND;
626
        outb(0, ioaddr + SIGNAL_CA);
627
 
628
        /* Disable the 82586's input to the interrupt line. */
629
        outb(0x80, ioaddr + MISC_CTRL);
630
 
631
        /* We always physically use the IRQ line, so we don't do free_irq().
632
           We do remove ourselves from the map. */
633
 
634
        irq2dev_map[dev->irq] = 0;
635
 
636
        /* Update the statistics here. */
637
 
638
        MOD_DEC_USE_COUNT;
639
 
640
        return 0;
641
}
642
 
643
/* Get the current statistics.  This may be called with the card open or
644
   closed. */
645
static struct enet_statistics *
646
el16_get_stats(struct device *dev)
647
{
648
        struct net_local *lp = (struct net_local *)dev->priv;
649
 
650
        /* ToDo: decide if there are any useful statistics from the SCB. */
651
 
652
        return &lp->stats;
653
}
654
 
655
/* Initialize the Rx-block list. */
656
static void
657
init_rx_bufs(struct device *dev)
658
{
659
        struct net_local *lp = (struct net_local *)dev->priv;
660
        unsigned short *write_ptr;
661
        unsigned short SCB_base = SCB_BASE;
662
 
663
        int cur_rxbuf = lp->rx_head = RX_BUF_START;
664
 
665
        /* Initialize each Rx frame + data buffer. */
666
        do {    /* While there is room for one more. */
667
 
668
          write_ptr = (unsigned short *)(dev->mem_start + cur_rxbuf);
669
 
670
                *write_ptr++ = 0x0000;                          /* Status */
671
                *write_ptr++ = 0x0000;                          /* Command */
672
                *write_ptr++ = cur_rxbuf + RX_BUF_SIZE; /* Link */
673
                *write_ptr++ = cur_rxbuf + 22;          /* Buffer offset */
674
                *write_ptr++ = 0x0000;                          /* Pad for dest addr. */
675
                *write_ptr++ = 0x0000;
676
                *write_ptr++ = 0x0000;
677
                *write_ptr++ = 0x0000;                          /* Pad for source addr. */
678
                *write_ptr++ = 0x0000;
679
                *write_ptr++ = 0x0000;
680
                *write_ptr++ = 0x0000;                          /* Pad for protocol. */
681
 
682
                *write_ptr++ = 0x0000;                          /* Buffer: Actual count */
683
                *write_ptr++ = -1;                                      /* Buffer: Next (none). */
684
                *write_ptr++ = cur_rxbuf + 0x20 + SCB_base;     /* Buffer: Address low */
685
                *write_ptr++ = 0x0000;
686
                /* Finally, the number of bytes in the buffer. */
687
                *write_ptr++ = 0x8000 + RX_BUF_SIZE-0x20;
688
 
689
                lp->rx_tail = cur_rxbuf;
690
                cur_rxbuf += RX_BUF_SIZE;
691
        } while (cur_rxbuf <= RX_BUF_END - RX_BUF_SIZE);
692
 
693
        /* Terminate the list by setting the EOL bit, and wrap the pointer to make
694
           the list a ring. */
695
        write_ptr = (unsigned short *)
696
          (dev->mem_start + lp->rx_tail + 2);
697
        *write_ptr++ = 0xC000;                                  /* Command, mark as last. */
698
        *write_ptr++ = lp->rx_head;                             /* Link */
699
 
700
}
701
 
702
void
703
init_82586_mem(struct device *dev)
704
{
705
        struct net_local *lp = (struct net_local *)dev->priv;
706
        short ioaddr = dev->base_addr;
707
        ushort *shmem = (short*)dev->mem_start;
708
 
709
        /* Enable loopback to protect the wire while starting up,
710
           and hold the 586 in reset during the memory initialization. */
711
        outb(0x20, ioaddr + MISC_CTRL);
712
 
713
        /* Fix the ISCP address and base. */
714
        init_words[3] = SCB_BASE;
715
        init_words[7] = SCB_BASE;
716
 
717
        /* Write the words at 0xfff6 (address-aliased to 0xfffff6). */
718
        memcpy((void*)dev->mem_end-10, init_words, 10);
719
 
720
        /* Write the words at 0x0000. */
721
        memcpy((char*)dev->mem_start, init_words + 5, sizeof(init_words) - 10);
722
 
723
        /* Fill in the station address. */
724
        memcpy((char*)dev->mem_start+SA_OFFSET, dev->dev_addr,
725
                   sizeof(dev->dev_addr));
726
 
727
        /* The Tx-block list is written as needed.  We just set up the values. */
728
        lp->tx_cmd_link = IDLELOOP + 4;
729
        lp->tx_head = lp->tx_reap = TX_BUF_START;
730
 
731
        init_rx_bufs(dev);
732
 
733
        /* Start the 586 by releasing the reset line, but leave loopback. */
734
        outb(0xA0, ioaddr + MISC_CTRL);
735
 
736
        /* This was time consuming to track down: you need to give two channel
737
           attention signals to reliably start up the i82586. */
738
        outb(0, ioaddr + SIGNAL_CA);
739
 
740
        {
741
                int boguscnt = 50;
742
                while (shmem[iSCB_STATUS>>1] == 0)
743
                        if (--boguscnt == 0) {
744
                                printk("%s: i82586 initialization timed out with status %04x,"
745
                                           "cmd %04x.\n", dev->name,
746
                                           shmem[iSCB_STATUS>>1], shmem[iSCB_CMD>>1]);
747
                                break;
748
                        }
749
                /* Issue channel-attn -- the 82586 won't start. */
750
                outb(0, ioaddr + SIGNAL_CA);
751
        }
752
 
753
        /* Disable loopback and enable interrupts. */
754
        outb(0x84, ioaddr + MISC_CTRL);
755
        if (net_debug > 4)
756
                printk("%s: Initialized 82586, status %04x.\n", dev->name,
757
                           shmem[iSCB_STATUS>>1]);
758
        return;
759
}
760
 
761
static void
762
hardware_send_packet(struct device *dev, void *buf, short length)
763
{
764
        struct net_local *lp = (struct net_local *)dev->priv;
765
        short ioaddr = dev->base_addr;
766
        ushort tx_block = lp->tx_head;
767
        ushort *write_ptr =       (ushort *)(dev->mem_start + tx_block);
768
 
769
        /* Set the write pointer to the Tx block, and put out the header. */
770
        *write_ptr++ = 0x0000;                          /* Tx status */
771
        *write_ptr++ = CMD_INTR|CmdTx;          /* Tx command */
772
        *write_ptr++ = tx_block+16;                     /* Next command is a NoOp. */
773
        *write_ptr++ = tx_block+8;                      /* Data Buffer offset. */
774
 
775
        /* Output the data buffer descriptor. */
776
        *write_ptr++ = length | 0x8000;         /* Byte count parameter. */
777
        *write_ptr++ = -1;                                      /* No next data buffer. */
778
        *write_ptr++ = tx_block+22+SCB_BASE;/* Buffer follows the NoOp command. */
779
        *write_ptr++ = 0x0000;                          /* Buffer address high bits (always zero). */
780
 
781
        /* Output the Loop-back NoOp command. */
782
        *write_ptr++ = 0x0000;                          /* Tx status */
783
        *write_ptr++ = CmdNOp;                          /* Tx command */
784
        *write_ptr++ = tx_block+16;                     /* Next is myself. */
785
 
786
        /* Output the packet at the write pointer. */
787
        memcpy(write_ptr, buf, length);
788
 
789
        /* Set the old command link pointing to this send packet. */
790
        *(ushort*)(dev->mem_start + lp->tx_cmd_link) = tx_block;
791
        lp->tx_cmd_link = tx_block + 20;
792
 
793
        /* Set the next free tx region. */
794
        lp->tx_head = tx_block + TX_BUF_SIZE;
795
        if (lp->tx_head > RX_BUF_START - TX_BUF_SIZE)
796
                lp->tx_head = TX_BUF_START;
797
 
798
        if (net_debug > 4) {
799
                printk("%s: 3c507 @%x send length = %d, tx_block %3x, next %3x.\n",
800
                           dev->name, ioaddr, length, tx_block, lp->tx_head);
801
        }
802
 
803
        if (lp->tx_head != lp->tx_reap)
804
                dev->tbusy = 0;
805
}
806
 
807
static void
808
el16_rx(struct device *dev)
809
{
810
        struct net_local *lp = (struct net_local *)dev->priv;
811
        short *shmem = (short*)dev->mem_start;
812
        ushort rx_head = lp->rx_head;
813
        ushort rx_tail = lp->rx_tail;
814
        ushort boguscount = 10;
815
        short frame_status;
816
 
817
        while ((frame_status = shmem[rx_head>>1]) < 0) {   /* Command complete */
818
                ushort *read_frame =  (short *)(dev->mem_start + rx_head);
819
                ushort rfd_cmd = read_frame[1];
820
                ushort next_rx_frame = read_frame[2];
821
                ushort data_buffer_addr = read_frame[3];
822
                ushort *data_frame = (short *)(dev->mem_start + data_buffer_addr);
823
                ushort pkt_len = data_frame[0];
824
 
825
                if (rfd_cmd != 0 || data_buffer_addr != rx_head + 22
826
                        || (pkt_len & 0xC000) != 0xC000) {
827
                        printk("%s: Rx frame at %#x corrupted, status %04x cmd %04x"
828
                                   "next %04x data-buf @%04x %04x.\n", dev->name, rx_head,
829
                                   frame_status, rfd_cmd, next_rx_frame, data_buffer_addr,
830
                                   pkt_len);
831
                } else if ((frame_status & 0x2000) == 0) {
832
                        /* Frame Rxed, but with error. */
833
                        lp->stats.rx_errors++;
834
                        if (frame_status & 0x0800) lp->stats.rx_crc_errors++;
835
                        if (frame_status & 0x0400) lp->stats.rx_frame_errors++;
836
                        if (frame_status & 0x0200) lp->stats.rx_fifo_errors++;
837
                        if (frame_status & 0x0100) lp->stats.rx_over_errors++;
838
                        if (frame_status & 0x0080) lp->stats.rx_length_errors++;
839
                } else {
840
                        /* Malloc up new buffer. */
841
                        struct sk_buff *skb;
842
 
843
                        pkt_len &= 0x3fff;
844
                        skb = dev_alloc_skb(pkt_len+2);
845
                        if (skb == NULL) {
846
                                printk("%s: Memory squeeze, dropping packet.\n", dev->name);
847
                                lp->stats.rx_dropped++;
848
                                break;
849
                        }
850
 
851
                        skb_reserve(skb,2);
852
                        skb->dev = dev;
853
 
854
                        /* 'skb->data' points to the start of sk_buff data area. */
855
                        memcpy(skb_put(skb,pkt_len), data_frame + 5, pkt_len);
856
 
857
                        skb->protocol=eth_type_trans(skb,dev);
858
                        netif_rx(skb);
859
                        lp->stats.rx_packets++;
860
                }
861
 
862
                /* Clear the status word and set End-of-List on the rx frame. */
863
                read_frame[0] = 0;
864
                read_frame[1] = 0xC000;
865
                /* Clear the end-of-list on the prev. RFD. */
866
                *(short*)(dev->mem_start + rx_tail + 2) = 0x0000;
867
 
868
                rx_tail = rx_head;
869
                rx_head = next_rx_frame;
870
                if (--boguscount == 0)
871
                        break;
872
        }
873
 
874
        lp->rx_head = rx_head;
875
        lp->rx_tail = rx_tail;
876
}
877
#ifdef MODULE
878
static char devicename[9] = { 0, };
879
static struct device dev_3c507 = {
880
        devicename, /* device name is inserted by linux/drivers/net/net_init.c */
881
        0, 0, 0, 0,
882
        0, 0,
883
        0, 0, 0, NULL, el16_probe
884
};
885
 
886
static int io = 0x300;
887
static int irq = 0;
888
 
889
int init_module(void)
890
{
891
        if (io == 0)
892
                printk("3c507: You should not use auto-probing with insmod!\n");
893
        dev_3c507.base_addr = io;
894
        dev_3c507.irq       = irq;
895
        if (register_netdev(&dev_3c507) != 0) {
896
                printk("3c507: register_netdev() returned non-zero.\n");
897
                return -EIO;
898
        }
899
        return 0;
900
}
901
 
902
void
903
cleanup_module(void)
904
{
905
        unregister_netdev(&dev_3c507);
906
        kfree(dev_3c507.priv);
907
        dev_3c507.priv = NULL;
908
 
909
        /* If we don't do this, we can't re-insmod it later. */
910
        free_irq(dev_3c507.irq, NULL);
911
        release_region(dev_3c507.base_addr, EL16_IO_EXTENT);
912
}
913
#endif /* MODULE */
914
 
915
/*
916
 * Local variables:
917
 *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -I/usr/src/linux/drivers/net -Wall -Wstrict-prototypes -O6 -m486 -c 3c507.c"
918
 *  version-control: t
919
 *  kept-new-versions: 5
920
 *  tab-width: 4
921
 *  c-indent-level: 4
922
 * End:
923
 */

powered by: WebSVN 2.1.0

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