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

Subversion Repositories or1k

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

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

Line No. Rev Author Line
1 1626 jcastillo
/* uCcs89x0.c: A Crystal Semiconductor CS89[02]0 driver for linux. */
2
/*
3
        Port for uCsimm 1999 D. Jeff Dionne, Rt-Control Inc.
4
 
5
        Written 1996 by Russell Nelson, with reference to skeleton.c
6
        written 1993-1994 by Donald Becker.
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 at nelson@crynwr.com, Crynwr
12
        Software, 11 Grant St., Potsdam, NY 13676
13
 
14
  Changelog:
15
 
16
  Mike Cruse        : mcruse@cti-ltd.com
17
                    : Changes for Linux 2.0 compatibility.
18
                    : Added dev_id parameter in net_interrupt(),
19
                    : request_irq() and free_irq(). Just NULL for now.
20
 
21
  Mike Cruse        : Added MOD_INC_USE_COUNT and MOD_DEC_USE_COUNT macros
22
                    : in net_open() and net_close() so kerneld would know
23
                    : that the module is in use and wouldn't eject the
24
                    : driver prematurely.
25
 
26
  Mike Cruse        : Rewrote init_module() and cleanup_module using 8390.c
27
                    : as an example. Disabled autoprobing in init_module(),
28
                    : not a good thing to do to other devices while Linux
29
                    : is running from all accounts.
30
*/
31
 
32
static char *version =
33
"cs89x0.c:v1.02 11/26/96 Russell Nelson <nelson@crynwr.com>\ncs89x0.c:68EZ328 support D. Jeff Dionne <jeff@rt-control.com> 1999\n";
34
 
35
/* ======================= configure the driver here ======================= */
36
 
37
 
38
/* use 0 for production, 1 for verification, >2 for debug */
39
#ifndef NET_DEBUG
40
#define NET_DEBUG 2
41
#endif
42
 
43
/* ======================= end of configuration ======================= */
44
 
45
 
46
/* Always include 'config.h' first in case the user wants to turn on
47
   or override something. */
48
#include <linux/config.h>
49
 
50
#define PRINTK(x) printk x
51
 
52
/*
53
  Sources:
54
 
55
        Crynwr packet driver epktisa.
56
 
57
        Crystal Semiconductor data sheets.
58
 
59
*/
60
 
61
#include <linux/kernel.h>
62
#include <linux/sched.h>
63
#include <linux/types.h>
64
#include <linux/fcntl.h>
65
#include <linux/interrupt.h>
66
#include <linux/ptrace.h>
67
#include <linux/ioport.h>
68
#include <linux/in.h>
69
#include <linux/malloc.h>
70
#include <linux/string.h>
71
#include <asm/system.h>
72
#include <asm/bitops.h>
73
 
74
#ifndef CONFIG_UCCS8900_HW_SWAP
75
#include <asm/io.h>
76
#else
77
#include <asm/io_hw_swap.h>
78
#endif
79
 
80
#include <asm/irq.h>
81
#include <linux/errno.h>
82
 
83
#include <linux/netdevice.h>
84
#include <linux/etherdevice.h>
85
#include <linux/skbuff.h>
86
#include "uCcs8900.h"
87
 
88
#ifdef CONFIG_M68328
89
#include <asm/MC68328.h>
90
#endif
91
 
92
#ifdef CONFIG_M68EZ328
93
#include <asm/MC68EZ328.h>
94
#endif
95
 
96
#ifdef CONFIG_UCSIMM
97
#define NET_BASE 0x10000300
98
#endif
99
 
100
#ifdef CONFIG_ALMA_ANS
101
#define NET_BASE 0x10200300
102
#endif
103
 
104
static unsigned int net_debug = NET_DEBUG;
105
 
106
/* The number of low I/O ports used by the ethercard. */
107
#define NETCARD_IO_EXTENT       16
108
 
109
void *irq2dev_map[1]; /* FIXME:  This does NOT go here */
110
 
111
/* Information that need to be kept for each board. */
112
struct net_local {
113
        struct enet_statistics stats;
114
        int chip_type;          /* one of: CS8900, CS8920, CS8920M */
115
        char chip_revision;     /* revision letter of the chip ('A'...) */
116
        int send_cmd;           /* the propercommand used to send a packet. */
117
        int auto_neg_cnf;
118
        int adapter_cnf;
119
        int isa_config;
120
        int irq_map;
121
        int rx_mode;
122
        int curr_rx_cfg;
123
        int linectl;
124
        int send_underrun;      /* keep track of how many underruns in a row we get */
125
        struct sk_buff *skb;
126
};
127
 
128
/* Index to functions, as function prototypes. */
129
 
130
extern int cs89x0_probe(struct device *dev);
131
 
132
static int cs89x0_probe1(struct device *dev, int ioaddr);
133
static int net_open(struct device *dev);
134
static int      net_send_packet(struct sk_buff *skb, struct device *dev);
135
static void cs8900_interrupt(int irq, void *dev_id, struct pt_regs *regs);
136
static void set_multicast_list(struct device *dev);
137
static void net_rx(struct device *dev);
138
static int net_close(struct device *dev);
139
static struct enet_statistics *net_get_stats(struct device *dev);
140
static void reset_chip(struct device *dev);
141
static int set_mac_address(struct device *dev, void *addr);
142
 
143
 
144
/* Example routines you must write ;->. */
145
#define tx_done(dev) 1
146
 
147
 
148
/* Check for a network adaptor of this type, and return '0' iff one exists.
149
   If dev->base_addr == 0, probe all likely locations.
150
   If dev->base_addr == 1, always return failure.
151
   If dev->base_addr == 2, allocate space for the device and return success
152
   (detachable devices only).
153
   */
154
 
155
int
156
cs89x0_probe(struct device *dev)
157
{
158
        int base_addr = NET_BASE;
159
 
160
        return cs89x0_probe1(dev, base_addr);
161
}
162
 
163
int inline
164
readreg(struct device *dev, int portno)
165
{
166
        outw(portno, dev->base_addr + ADD_PORT);
167
        return inw(dev->base_addr + DATA_PORT);
168
}
169
 
170
void inline
171
writereg(struct device *dev, int portno, int value)
172
{
173
        outw(portno, dev->base_addr + ADD_PORT);
174
        outw(value,  dev->base_addr + DATA_PORT);
175
}
176
 
177
int inline
178
readword(struct device *dev, int portno)
179
{
180
        return inw(dev->base_addr + portno);
181
}
182
 
183
void inline
184
writeword(struct device *dev, int portno, int value)
185
{
186
        outw(value, dev->base_addr + portno);
187
}
188
 
189
/* This is the real probe routine.  */
190
 
191
static int cs89x0_probe1(struct device *dev, int ioaddr)
192
{
193
        struct net_local *lp;
194
        static unsigned version_printed = 0;
195
        int i;
196
        unsigned rev_type = 0;
197
 
198
        irq2dev_map[0] = dev;
199
 
200
#ifdef CONFIG_UCSIMM
201
        /* set up the chip select */
202
        *(volatile unsigned  char *)0xfffff42b |= 0x01; /* output /sleep */
203
        *(volatile unsigned short *)0xfffff428 |= 0x0101; /* not sleeping */
204
 
205
        *(volatile unsigned  char *)0xfffff42b &= ~0x02; /* input irq5 */
206
        *(volatile unsigned short *)0xfffff428 &= ~0x0202; /* irq5 fcn on */
207
 
208
        *(volatile unsigned short *)0xfffff102 = 0x8000; /* 0x04000000 */
209
        *(volatile unsigned short *)0xfffff112 = 0x01e1; /* 128k, 2ws, FLASH, en */
210
#endif
211
 
212
#ifdef CONFIG_ALMA_ANS
213
        /*
214
         * Make sure the chip select (CSA1) is enabled
215
         * Note, that we don't have to program the base address, since
216
         * it is programmed once for both CSA0 and CSA1 in *-head.S
217
         */
218
        PFSEL &= ~PF_CSA1;
219
        PFDIR |= PF_CSA1;
220
 
221
        /* Make sure that interrupt line (irq3) is enabled too */
222
        PDSEL  &= ~PD_IRQ3;
223
        PDDIR  &= ~PD_IRQ3;
224
        PDKBEN |= PD_IRQ3;
225
#endif
226
 
227
        /* Initialize the device structure. */
228
        if (dev->priv == NULL) {
229
                dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
230
                memset(dev->priv, 0, sizeof(struct net_local));
231
        }
232
        dev->base_addr = ioaddr;
233
        lp = (struct net_local *)dev->priv;
234
 
235
        if (readreg(dev, PP_ChipID) != CHIP_EISA_ID_SIG) {
236
          printk("cs89x0.c: No CrystalLan device found.\n");
237
                return ENODEV;
238
        }
239
 
240
        /* get the chip type */
241
        rev_type = readreg(dev, PRODUCT_ID_ADD);
242
        lp->chip_type = rev_type &~ REVISON_BITS;
243
        lp->chip_revision = ((rev_type & REVISON_BITS) >> 8) + 'A';
244
 
245
        /* Check the chip type and revision in order to set the correct send command
246
        CS8920 revision C and CS8900 revision F can use the faster send. */
247
        lp->send_cmd = TX_AFTER_ALL;
248
#if 0
249
        if (lp->chip_type == CS8900 && lp->chip_revision >= 'F')
250
                lp->send_cmd = TX_NOW;
251
        if (lp->chip_type != CS8900 && lp->chip_revision >= 'C')
252
                lp->send_cmd = TX_NOW;
253
#endif
254
        if (net_debug  &&  version_printed++ == 0)
255
                printk(version);
256
 
257
        printk("%s: cs89%c0%s rev %c found at 0x%.8x %s",
258
               dev->name,
259
               lp->chip_type==CS8900?'0':'2',
260
               lp->chip_type==CS8920M?"M":"",
261
               lp->chip_revision,
262
               dev->base_addr,
263
               readreg(dev, PP_SelfST) & ACTIVE_33V ? "3.3Volts" : "5Volts");
264
 
265
        reset_chip(dev);
266
 
267
        /* Fill this in, we don't have an EEPROM */
268
        lp->adapter_cnf = A_CNF_10B_T | A_CNF_MEDIA_10B_T;
269
        lp->auto_neg_cnf = EE_AUTO_NEG_ENABLE;
270
 
271
        printk(" media %s%s%s",
272
               (lp->adapter_cnf & A_CNF_10B_T)?"RJ-45,":"",
273
               (lp->adapter_cnf & A_CNF_AUI)?"AUI,":"",
274
               (lp->adapter_cnf & A_CNF_10B_2)?"BNC,":"");
275
 
276
        lp->irq_map = 0xffff;
277
 
278
#ifdef CONFIG_ALMA_ANS
279
        /* Bad hack, has to be fixed, since we have the SEEPROM on board */
280
        dev->dev_addr[0] = 0x00;
281
        dev->dev_addr[1] = 0x00;
282
        dev->dev_addr[2] = 0xc0;
283
        dev->dev_addr[3] = 0xff;
284
        dev->dev_addr[4] = 0xee;
285
        dev->dev_addr[5] = 0x01;
286
#endif
287
 
288
#ifdef CONFIG_UCSIMM
289
        {
290
                extern unsigned char *cs8900a_hwaddr;
291
                memcpy(dev->dev_addr, cs8900a_hwaddr, 6);
292
        }
293
#endif
294
 
295
        /* print the ethernet address. */
296
        for (i = 0; i < ETH_ALEN; i++)
297
                printk(" %2.2x", dev->dev_addr[i]);
298
 
299
#ifdef FIXME
300
        /* Grab the region so we can find another board if autoIRQ fails. */
301
        request_region(ioaddr, NETCARD_IO_EXTENT,"cs89x0");
302
#endif
303
 
304
        dev->open               = net_open;
305
        dev->stop               = net_close;
306
        dev->hard_start_xmit = net_send_packet;
307
        dev->get_stats  = net_get_stats;
308
        dev->set_multicast_list = &set_multicast_list;
309
        dev->set_mac_address = &set_mac_address;
310
 
311
        /* Fill in the fields of the device structure with ethernet values. */
312
        ether_setup(dev);
313
 
314
        printk("\n");
315
        return 0;
316
}
317
 
318
 
319
 
320
void
321
reset_chip(struct device *dev)
322
{
323
        int reset_start_time;
324
 
325
        writereg(dev, PP_SelfCTL, readreg(dev, PP_SelfCTL) | POWER_ON_RESET);
326
 
327
        /* wait 30 ms */
328
        current->state = TASK_INTERRUPTIBLE;
329
        current->timeout = jiffies + 3;
330
        schedule();
331
 
332
        /* Wait until the chip is reset */
333
        reset_start_time = jiffies;
334
        while( (readreg(dev, PP_SelfST) & INIT_DONE) == 0 && jiffies - reset_start_time < 2)
335
                ;
336
}
337
 
338
static int
339
detect_tp(struct device *dev)
340
{
341
        struct net_local *lp = (struct net_local *)dev->priv;
342
        int timenow = jiffies;
343
 
344
        if (net_debug > 1) printk("%s: Attempting TP\n", dev->name);
345
 
346
        /* If connected to another full duplex capable 10-Base-T card the link pulses
347
           seem to be lost when the auto detect bit in the LineCTL is set.
348
           To overcome this the auto detect bit will be cleared whilst testing the
349
           10-Base-T interface.  This would not be necessary for the sparrow chip but
350
           is simpler to do it anyway. */
351
        writereg(dev, PP_LineCTL, lp->linectl &~ AUI_ONLY);
352
 
353
        /* Delay for the hardware to work out if the TP cable is present - 150ms */
354
        for (timenow = jiffies; jiffies - timenow < 15; )
355
                ;
356
        if ((readreg(dev, PP_LineST) & LINK_OK) == 0)
357
                return 0;
358
 
359
        return A_CNF_MEDIA_10B_T;
360
}
361
 
362
/* send a test packet - return true if carrier bits are ok */
363
int
364
send_test_pkt(struct device *dev)
365
{
366
        int ioaddr = dev->base_addr;
367
        char test_packet[] = { 0,0,0,0,0,0, 0,0,0,0,0,0,
368
                                 0, 46, /* A 46 in network order */
369
                                 0, 0, /* DSAP=0 & SSAP=0 fields */
370
                                 0xf3, 0 /* Control (Test Req + P bit set) */ };
371
        long timenow = jiffies;
372
        unsigned short event;
373
 
374
        writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) | SERIAL_TX_ON);
375
 
376
        memcpy(test_packet,          dev->dev_addr, ETH_ALEN);
377
        memcpy(test_packet+ETH_ALEN, dev->dev_addr, ETH_ALEN);
378
        outw(TX_AFTER_ALL, ioaddr + TX_CMD_PORT);
379
        outw(ETH_ZLEN, ioaddr + TX_LEN_PORT);
380
 
381
        /* Test to see if the chip has allocated memory for the packet */
382
        while (jiffies - timenow < 5)
383
                if (readreg(dev, PP_BusST) & READY_FOR_TX_NOW)
384
                        break;
385
        if (jiffies - timenow >= 5)
386
                return 0;        /* this shouldn't happen */
387
 
388
        /* Write the contents of the packet */
389
        outsw(ioaddr + TX_FRAME_PORT,test_packet,(ETH_ZLEN+1) >>1);
390
 
391
        if (net_debug > 1) printk("Sending test packet ");
392
        /* wait a couple of jiffies for packet to be received */
393
        for (timenow = jiffies; jiffies - timenow < 60; )
394
                ;
395
        if (((event = readreg(dev, PP_TxEvent)) & TX_SEND_OK_BITS) == TX_OK) {
396
                if (net_debug > 1) printk("succeeded\n");
397
                return 1;
398
        }
399
        if (net_debug > 1) printk("failed TxEvent 0x%.4x\n",event);
400
        return 0;
401
}
402
 
403
 
404
void
405
write_irq(struct device *dev, int chip_type, int irq)
406
{
407
  /* we only hooked up 0 :-) */
408
        writereg(dev, PP_CS8900_ISAINT, 0);
409
}
410
 
411
/* Open/initialize the board.  This is called (in the current kernel)
412
   sometime after booting when the 'ifconfig' program is run.
413
 
414
   This routine should set everything up anew at each open, even
415
   registers that "should" only need to be set once at boot, so that
416
   there is non-reboot way to recover if something goes wrong.
417
   */
418
static int
419
net_open(struct device *dev)
420
{
421
        struct net_local *lp = (struct net_local *)dev->priv;
422
        int result = 0;
423
        int i;
424
 
425
        write_irq(dev, lp->chip_type, 0);
426
 
427
        irq2dev_map[/* FIXME */ 0] = dev;
428
        writereg(dev, PP_BusCTL, 0); /* ints off! */
429
 
430
#ifdef CONFIG_UCSIMM
431
        *(volatile unsigned short *)0xfffff302 |= 0x0080; /* +ve pol irq */
432
 
433
        if (request_irq(IRQ_MACHSPEC | IRQ5_IRQ_NUM,
434
                        cs8900_interrupt,
435
                        IRQ_FLG_STD,
436
                        "CrystalLAN_cs8900a", NULL))
437
                panic("Unable to attach cs8900 intr\n");
438
#endif
439
 
440
#ifdef CONFIG_ALMA_ANS
441
        /* We use positive polarity IRQ3 as a network interrupt */
442
        ICR |= ICR_POL3;
443
 
444
        if (request_irq(IRQ_MACHSPEC | IRQ3_IRQ_NUM,
445
                        cs8900_interrupt,
446
                        IRQ_FLG_STD,
447
                        "CrystalLAN_cs8900a", NULL))
448
                panic("Unable to attach cs8900 intr\n");
449
#endif
450
 
451
        /* set the Ethernet address */
452
        set_mac_address(dev, dev->dev_addr);
453
 
454
        /* Set the LineCTL */
455
        lp->linectl = 0;
456
 
457
        /* check to make sure that they have the "right" hardware available */
458
        switch(lp->adapter_cnf & A_CNF_MEDIA_TYPE) {
459
        case A_CNF_MEDIA_10B_T:
460
                result = lp->adapter_cnf & A_CNF_10B_T;
461
                break;
462
        case A_CNF_MEDIA_AUI:
463
                result = lp->adapter_cnf & A_CNF_AUI;
464
                break;
465
        case A_CNF_MEDIA_10B_2:
466
                result = lp->adapter_cnf & A_CNF_10B_2;
467
                break;
468
        default:
469
                result = lp->adapter_cnf &
470
                         (A_CNF_10B_T | A_CNF_AUI | A_CNF_10B_2);
471
        }
472
        if (!result) {
473
                printk("%s: EEPROM is configured for unavailable media\n", dev->name);
474
        release_irq:
475
                writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) & ~(SERIAL_TX_ON | SERIAL_RX_ON));
476
                irq2dev_map[dev->irq] = 0;
477
                return -EAGAIN;
478
        }
479
 
480
        /* set the hardware to the configured choice */
481
        switch(lp->adapter_cnf & A_CNF_MEDIA_TYPE) {
482
        case A_CNF_MEDIA_10B_T:
483
                result = detect_tp(dev);
484
                if (!result) printk("%s: 10Base-T (RJ-45) has no cable\n", dev->name);
485
                if (lp->auto_neg_cnf & IMM_BIT) /* check "ignore missing media" bit */
486
                        result = A_CNF_MEDIA_10B_T; /* Yes! I don't care if I see a link pulse */
487
                break;
488
        case A_CNF_MEDIA_AUI:
489
          printk("AUI?  What stinking AUI?\n");
490
                break;
491
        case A_CNF_MEDIA_10B_2:
492
          printk("10Base2?  What stinking 10Base2?\n");
493
                break;
494
        case A_CNF_MEDIA_AUTO:
495
                writereg(dev, PP_LineCTL, lp->linectl | AUTO_AUI_10BASET);
496
                if (lp->adapter_cnf & A_CNF_10B_T)
497
                        if ((result = detect_tp(dev)) != 0)
498
                                break;
499
 
500
                printk("%s: no media detected\n", dev->name);
501
                goto release_irq;
502
        }
503
        switch(result) {
504
        case 0: printk("%s: no network cable attached to configured media\n", dev->name);
505
                goto release_irq;
506
        case A_CNF_MEDIA_10B_T: printk("%s: using 10Base-T (RJ-45)\n", dev->name);break;
507
        case A_CNF_MEDIA_AUI:   printk("%s: using 10Base-5 (AUI)\n", dev->name);break;
508
        case A_CNF_MEDIA_10B_2: printk("%s: using 10Base-2 (BNC)\n", dev->name);break;
509
        default: printk("%s: unexpected result was %x\n", dev->name, result); goto release_irq;
510
        }
511
 
512
        /* Turn on both receive and transmit operations */
513
        writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) | SERIAL_RX_ON | SERIAL_TX_ON);
514
 
515
        /* Receive only error free packets addressed to this card */
516
        lp->rx_mode = 0;
517
        writereg(dev, PP_RxCTL, DEF_RX_ACCEPT);
518
 
519
        lp->curr_rx_cfg = RX_OK_ENBL | RX_CRC_ERROR_ENBL;
520
        if (lp->isa_config & STREAM_TRANSFER)
521
                lp->curr_rx_cfg |= RX_STREAM_ENBL;
522
 
523
        writereg(dev, PP_RxCFG, lp->curr_rx_cfg);
524
 
525
        writereg(dev, PP_TxCFG, TX_LOST_CRS_ENBL | TX_SQE_ERROR_ENBL | TX_OK_ENBL |
526
               TX_LATE_COL_ENBL | TX_JBR_ENBL | TX_ANY_COL_ENBL | TX_16_COL_ENBL);
527
 
528
        writereg(dev, PP_BufCFG, READY_FOR_TX_ENBL | RX_MISS_COUNT_OVRFLOW_ENBL |
529
                 TX_COL_COUNT_OVRFLOW_ENBL | TX_UNDERRUN_ENBL);
530
 
531
        /* now that we've got our act together, enable everything */
532
        writereg(dev, PP_BusCTL, ENABLE_IRQ
533
                 );
534
        dev->tbusy = 0;
535
        dev->interrupt = 0;
536
        dev->start = 1;
537
        return 0;
538
}
539
 
540
static int
541
net_send_packet(struct sk_buff *skb, struct device *dev)
542
{
543
        if (dev->tbusy) {
544
                /* If we get here, some higher level has decided we are broken.
545
                   There should really be a "kick me" function call instead. */
546
                int tickssofar = jiffies - dev->trans_start;
547
                if (tickssofar < 5)
548
                        return 1;
549
                if (net_debug > 0) printk("%s: transmit timed out, %s?\n", dev->name,
550
                           tx_done(dev) ? "IRQ conflict" : "network cable problem");
551
                /* Try to restart the adaptor. */
552
                dev->tbusy=0;
553
                dev->trans_start = jiffies;
554
        }
555
 
556
        /* If some higher layer thinks we've missed an tx-done interrupt
557
           we are passed NULL. Caution: dev_tint() handles the cli()/sti()
558
           itself. */
559
        if (skb == NULL) {
560
                dev_tint(dev);
561
                return 0;
562
        }
563
 
564
        /* Block a timer-based transmit from overlapping.  This could better be
565
           done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
566
        if (set_bit(0, (void*)&dev->tbusy) != 0)
567
                printk("%s: Transmitter access conflict.\n", dev->name);
568
        else {
569
                struct net_local *lp = (struct net_local *)dev->priv;
570
                unsigned long ioaddr = dev->base_addr;
571
                unsigned long flags;
572
 
573
                if (net_debug > 3)printk("%s: sent %ld byte packet of type %x\n", dev->name, skb->len, (skb->data[ETH_ALEN+ETH_ALEN] << 8) | skb->data[ETH_ALEN+ETH_ALEN+1]);
574
 
575
                /* keep the upload from being interrupted, since we
576
                   ask the chip to start transmitting before the
577
                   whole packet has been completely uploaded. */
578
                save_flags(flags);
579
                cli();
580
 
581
                /* initiate a transmit sequence */
582
                outw(lp->send_cmd, ioaddr + TX_CMD_PORT);
583
                outw(skb->len, ioaddr + TX_LEN_PORT);
584
 
585
                /* Test to see if the chip has allocated memory for the packet */
586
                if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
587
                        /* Gasp!  It hasn't.  But that shouldn't happen since
588
                           we're waiting for TxOk, so return 1 and requeue this packet. */
589
                        restore_flags(flags);
590
                        printk("cs8900 did not allocate memory for tx!\n");
591
                        return 1;
592
                }
593
 
594
                /* Write the contents of the packet */
595
                outsw(ioaddr + TX_FRAME_PORT,skb->data,(skb->len+1) >>1);
596
 
597
                restore_flags(flags);
598
                dev->trans_start = jiffies;
599
        }
600
        dev_kfree_skb (skb, FREE_WRITE);
601
 
602
        return 0;
603
}
604
 
605
 
606
/* The typical workload of the driver:
607
   Handle the network interface interrupts. */
608
void
609
cs8900_interrupt(int irq, void *dev_id, struct pt_regs * regs)
610
{
611
        struct device *dev = (struct device *)(irq2dev_map[/* FIXME */0]);
612
        struct net_local *lp;
613
        int ioaddr, status;
614
 
615
        dev = irq2dev_map[0];
616
        if (dev == NULL) {
617
                printk ("net_interrupt(): irq %d for unknown device.\n", irq);
618
                return;
619
        }
620
        if (dev->interrupt)
621
                printk("%s: Re-entering the interrupt handler.\n", dev->name);
622
        dev->interrupt = 1;
623
 
624
        ioaddr = dev->base_addr;
625
        lp = (struct net_local *)dev->priv;
626
 
627
        /* we MUST read all the events out of the ISQ, otherwise we'll never
628
           get interrupted again.  As a consequence, we can't have any limit
629
           on the number of times we loop in the interrupt handler.  The
630
           hardware guarantees that eventually we'll run out of events.  Of
631
           course, if you're on a slow machine, and packets are arriving
632
           faster than you can read them off, you're screwed.  Hasta la
633
           vista, baby!  */
634
        while ((status = readword(dev, ISQ_PORT))) {
635
                if (net_debug > 4)printk("%s: event=%04x\n", dev->name, status);
636
                switch(status & ISQ_EVENT_MASK) {
637
                case ISQ_RECEIVER_EVENT:
638
                        /* Got a packet(s). */
639
                        net_rx(dev);
640
                        break;
641
                case ISQ_TRANSMITTER_EVENT:
642
                        lp->stats.tx_packets++;
643
                        dev->tbusy = 0;
644
                        mark_bh(NET_BH);        /* Inform upper layers. */
645
                        if ((status & TX_OK) == 0) lp->stats.tx_errors++;
646
                        if (status & TX_LOST_CRS) lp->stats.tx_carrier_errors++;
647
                        if (status & TX_SQE_ERROR) lp->stats.tx_heartbeat_errors++;
648
                        if (status & TX_LATE_COL) lp->stats.tx_window_errors++;
649
                        if (status & TX_16_COL) lp->stats.tx_aborted_errors++;
650
                        break;
651
                case ISQ_BUFFER_EVENT:
652
                        if (status & READY_FOR_TX) {
653
                                /* we tried to transmit a packet earlier,
654
                                   but inexplicably ran out of buffers.
655
                                   That shouldn't happen since we only ever
656
                                   load one packet.  Shrug.  Do the right
657
                                   thing anyway. */
658
                                dev->tbusy = 0;
659
                                mark_bh(NET_BH);        /* Inform upper layers. */
660
                        }
661
                        if (status & TX_UNDERRUN) {
662
                                if (net_debug > 0) printk("%s: transmit underrun\n", dev->name);
663
                                lp->send_underrun++;
664
                                if (lp->send_underrun > 3) lp->send_cmd = TX_AFTER_ALL;
665
                        }
666
                        break;
667
                case ISQ_RX_MISS_EVENT:
668
                        lp->stats.rx_missed_errors += (status >>6);
669
                        break;
670
                case ISQ_TX_COL_EVENT:
671
                        lp->stats.collisions += (status >>6);
672
                        break;
673
                }
674
        }
675
        dev->interrupt = 0;
676
        return;
677
}
678
 
679
/* We have a good packet(s), get it/them out of the buffers. */
680
static void
681
net_rx(struct device *dev)
682
{
683
        struct net_local *lp = (struct net_local *)dev->priv;
684
        int ioaddr = dev->base_addr;
685
        struct sk_buff *skb;
686
        int status, length;
687
 
688
        status = inw(ioaddr + RX_FRAME_PORT);
689
        length = inw(ioaddr + RX_FRAME_PORT);
690
        if ((status & RX_OK) == 0) {
691
                lp->stats.rx_errors++;
692
                if (status & RX_RUNT) lp->stats.rx_length_errors++;
693
                if (status & RX_EXTRA_DATA) lp->stats.rx_length_errors++;
694
                if (status & RX_CRC_ERROR) if (!(status & (RX_EXTRA_DATA|RX_RUNT)))
695
                        /* per str 172 */
696
                        lp->stats.rx_crc_errors++;
697
                if (status & RX_DRIBBLE) lp->stats.rx_frame_errors++;
698
                return;
699
        }
700
 
701
        /* Malloc up new buffer. */
702
        skb = alloc_skb(length, GFP_ATOMIC);
703
        if (skb == NULL) {
704
                printk("%s: Memory squeeze, dropping packet.\n", dev->name);
705
                lp->stats.rx_dropped++;
706
                return;
707
        }
708
        skb->len = length;
709
        skb->dev = dev;
710
 
711
        insw(ioaddr + RX_FRAME_PORT, skb->data, length >> 1);
712
        if (length & 1)
713
                skb->data[length-1] = inw(ioaddr + RX_FRAME_PORT);
714
 
715
        if (net_debug > 3)printk("%s: received %d byte packet of type %x\n",
716
                                 dev->name, length,
717
                                 (skb->data[ETH_ALEN+ETH_ALEN] << 8) | skb->data[ETH_ALEN+ETH_ALEN+1]);
718
        skb->protocol=eth_type_trans(skb,dev);
719
 
720
        netif_rx(skb);
721
        lp->stats.rx_packets++;
722
        return;
723
}
724
 
725
/* The inverse routine to net_open(). */
726
static int
727
net_close(struct device *dev)
728
{
729
        /* FIXME:  This needs to put the chip to sleep and turn off the irq */
730
        writereg(dev, PP_RxCFG, 0);
731
        writereg(dev, PP_TxCFG, 0);
732
        writereg(dev, PP_BufCFG, 0);
733
        writereg(dev, PP_BusCTL, 0);
734
 
735
        dev->start = 0;
736
 
737
#if 0
738
        free_irq(dev->irq, NULL);
739
#endif
740
 
741
        irq2dev_map[/* FIXME */ 0] = 0;
742
 
743
        /* Update the statistics here. */
744
 
745
        return 0;
746
}
747
 
748
/* Get the current statistics.  This may be called with the card open or
749
   closed. */
750
static struct enet_statistics *
751
net_get_stats(struct device *dev)
752
{
753
        struct net_local *lp = (struct net_local *)dev->priv;
754
 
755
        cli();
756
        /* Update the statistics from the device registers. */
757
        lp->stats.rx_missed_errors += (readreg(dev, PP_RxMiss) >> 6);
758
        lp->stats.collisions += (readreg(dev, PP_TxCol) >> 6);
759
        sti();
760
 
761
        return &lp->stats;
762
}
763
 
764
static void set_multicast_list(struct device *dev)
765
{
766
        struct net_local *lp = (struct net_local *)dev->priv;
767
 
768
        if(dev->flags&IFF_PROMISC)
769
        {
770
                lp->rx_mode = RX_ALL_ACCEPT;
771
        }
772
        else if((dev->flags&IFF_ALLMULTI)||dev->mc_list)
773
        {
774
                /* The multicast-accept list is initialized to accept-all, and we
775
                   rely on higher-level filtering for now. */
776
                lp->rx_mode = RX_MULTCAST_ACCEPT;
777
        }
778
        else
779
                lp->rx_mode = 0;
780
 
781
        writereg(dev, PP_RxCTL, DEF_RX_ACCEPT | lp->rx_mode);
782
 
783
        /* in promiscuous mode, we accept errored packets, so we have to enable interrupts on them also */
784
        writereg(dev, PP_RxCFG, lp->curr_rx_cfg |
785
             (lp->rx_mode == RX_ALL_ACCEPT? (RX_CRC_ERROR_ENBL|RX_RUNT_ENBL|RX_EXTRA_DATA_ENBL) : 0));
786
}
787
 
788
static int
789
set_mac_address(struct device *dev, void *addr)
790
{
791
        int i;
792
        if (dev->start)
793
                return -EBUSY;
794
        printk("%s: Setting MAC address to ", dev->name);
795
        for (i = 0; i < 6; i++)
796
                printk(" %2.2x", dev->dev_addr[i] = ((unsigned char *)addr)[i]);
797
        printk(".\n");
798
        /* set the Ethernet address */
799
        for (i=0; i < ETH_ALEN/2; i++)
800
                writereg(dev, PP_IA+i*2, dev->dev_addr[i*2] | (dev->dev_addr[i*2+1] << 8));
801
 
802
        return 0;
803
}
804
 
805
/*
806
 * Local variables:
807
 *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -DMODULE -DCONFIG_MODVERSIONS -c cs89x0.c"
808
 *  version-control: t
809
 *  kept-new-versions: 5
810
 *  c-indent-level: 8
811
 *  tab-width: 8
812
 * End:
813
 */

powered by: WebSVN 2.1.0

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