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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [uClinux-2.0.x/] [arch/] [armnommu/] [drivers/] [net/] [etherh.c] - Blame information for rev 1775

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

Line No. Rev Author Line
1 199 simons
/*
2
 * linux/drivers/net/etherh.c
3
 *
4
 * NS8390 ANT etherh specific driver
5
 *  For Acorn machines
6
 *
7
 * Thanks to I-Cubed for information on their cards.
8
 *
9
 * By Russell King.
10
 *
11
 * Changelog:
12
 *  08-12-1996  RMK     1.00    Created
13
 *              RMK     1.03    Added support for EtherLan500 cards
14
 *  23-11-1997  RMK     1.04    Added media autodetection
15
 *  16-04-1998  RMK     1.05    Improved media autodetection
16
 *
17
 * Insmod Module Parameters
18
 * ------------------------
19
 *   io=<io_base>
20
 *   irq=<irqno>
21
 */
22
 
23
#include <linux/module.h>
24
#include <linux/kernel.h>
25
#include <linux/sched.h>
26
#include <linux/types.h>
27
#include <linux/fcntl.h>
28
#include <linux/interrupt.h>
29
#include <linux/ptrace.h>
30
#include <linux/ioport.h>
31
#include <linux/in.h>
32
#include <linux/malloc.h>
33
#include <linux/string.h>
34
#include <linux/errno.h>
35
#include <linux/netdevice.h>
36
#include <linux/etherdevice.h>
37
#include <linux/skbuff.h>
38
 
39
#include <asm/system.h>
40
#include <asm/bitops.h>
41
#include <asm/ecard.h>
42
#include <asm/delay.h>
43
#include <asm/io.h>
44
#include <asm/irq.h>
45
 
46
#include "8390.h"
47
 
48
struct eh_priv {
49
        unsigned int    product;
50
        unsigned int    control_copy;
51
        unsigned int    ctrl_port;
52
        unsigned int    dma_port;
53
};
54
 
55
struct eh_device {
56
        struct ei_device ei_local;
57
        struct eh_priv   eh_local;
58
};
59
 
60
#define eh_status (((struct eh_device *)(dev->priv))->eh_local)
61
 
62
#define NET_DEBUG  0
63
#define DEBUG_INIT 2
64
 
65
static unsigned int net_debug = NET_DEBUG;
66
static const card_ids etherh_cids[] = {
67
        { MANU_I3, PROD_I3_ETHERLAN500 },
68
        { MANU_I3, PROD_I3_ETHERLAN600 },
69
        { MANU_I3, PROD_I3_ETHERLAN600A },
70
        { 0xffff, 0xffff }
71
};
72
 
73
static char *version = "etherh [500/600/600A] ethernet driver (c) 1998 R.M.King v1.05\n";
74
 
75
#define ETHERH500_NS8390        0x000   /* MEMC */
76
#define ETHERH500_DATAPORT      0x200   /* MEMC */
77
#define ETHERH500_CTRLPORT      0x200   /* IOC  */
78
 
79
#define ETHERH600_NS8390        0x200   /* MEMC */
80
#define ETHERH600_DATAPORT      0x210   /* MEMC */
81
#define ETHERH600_CTRLPORT      0x280   /* MEMC */
82
 
83
#define ETHERH_CP_IE            1
84
#define ETHERH_CP_IF            2
85
#define ETHERH_CP_HEARTBEAT     2
86
 
87
#define ETHERH_TX_START_PAGE    1
88
#define ETHERH_STOP_PAGE        0x7f
89
 
90
/* --------------------------------------------------------------------------- */
91
 
92
static void etherh_irq_enable(ecard_t *ec, int irqnr)
93
{
94
        struct eh_priv *priv = (struct eh_priv *)ec->irq_data;
95
 
96
        priv->control_copy |= ETHERH_CP_IE;
97
        outb(priv->control_copy, priv->ctrl_port);
98
}
99
 
100
static void etherh_irq_disable(ecard_t *ec, int irqnr)
101
{
102
        struct eh_priv *priv = (struct eh_priv *)ec->irq_data;
103
 
104
        priv->control_copy &= ~ETHERH_CP_IE;
105
        outb(priv->control_copy, priv->ctrl_port);
106
}
107
 
108
static expansioncard_ops_t etherh_ops = {
109
        etherh_irq_enable,
110
        etherh_irq_disable,
111
        NULL,
112
        NULL,
113
        NULL,
114
        NULL
115
};
116
 
117
static void
118
etherh_setif(struct device *dev)
119
{
120
        unsigned long addr;
121
        unsigned long flags;
122
 
123
        save_flags_cli(flags);
124
 
125
        /* set the interface type */
126
        switch (eh_status.product) {
127
        case PROD_I3_ETHERLAN600:
128
        case PROD_I3_ETHERLAN600A:
129
                addr = dev->base_addr + EN0_RCNTHI;
130
 
131
                if (ei_status.interface_num)    /* 10b2 */
132
                        outb((inb(addr) & 0xf8) | 1, addr);
133
                else                            /* 10bT */
134
                        outb((inb(addr) & 0xf8), addr);
135
                break;
136
 
137
        case PROD_I3_ETHERLAN500:
138
                if (ei_status.interface_num)    /* 10b2 */
139
                        eh_status.control_copy &= ~ETHERH_CP_IF;
140
                else                            /* 10bT */
141
                        eh_status.control_copy |= ETHERH_CP_IF;
142
                outb(eh_status.control_copy, eh_status.ctrl_port);
143
                break;
144
 
145
        default:
146
                break;
147
        }
148
 
149
        restore_flags(flags);
150
}
151
 
152
static int
153
etherh_getifstat(struct device *dev)
154
{
155
        int stat;
156
 
157
        switch (eh_status.product) {
158
        case PROD_I3_ETHERLAN600:
159
        case PROD_I3_ETHERLAN600A:
160
                if (ei_status.interface_num)    /* 10b2 */
161
                        stat = 1;
162
                else                            /* 10bT */
163
                        stat = inb(dev->base_addr+EN0_RCNTHI) & 4;
164
                break;
165
 
166
        case PROD_I3_ETHERLAN500:
167
                if (ei_status.interface_num)    /* 10b2 */
168
                        stat = 1;
169
                else                            /* 10bT */
170
                        stat = inb(eh_status.ctrl_port) & ETHERH_CP_HEARTBEAT;
171
                break;
172
 
173
        default:
174
                stat = 0;
175
                break;
176
        }
177
 
178
        return stat != 0;
179
}
180
 
181
/*
182
 * Reset the 8390 (hard reset)
183
 */
184
static void
185
etherh_reset(struct device *dev)
186
{
187
        outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, dev->base_addr);
188
 
189
        etherh_setif(dev);
190
}
191
 
192
/*
193
 * Write a block of data out to the 8390
194
 */
195
static void
196
etherh_block_output (struct device *dev, int count, const unsigned char *buf, int start_page)
197
{
198
        unsigned int addr, dma_addr;
199
        unsigned long dma_start;
200
 
201
        if (ei_status.dmaing) {
202
                printk ("%s: DMAing conflict in etherh_block_input: "
203
                        " DMAstat %d irqlock %d intr %d\n", dev->name,
204
                        ei_status.dmaing, ei_status.irqlock, dev->interrupt);
205
                return;
206
        }
207
 
208
        ei_status.dmaing |= 1;
209
 
210
        addr = dev->base_addr;
211
        dma_addr = eh_status.dma_port;
212
 
213
        count = (count + 1) & ~1;
214
        outb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
215
 
216
        outb (0x42, addr + EN0_RCNTLO);
217
        outb (0x00, addr + EN0_RCNTHI);
218
        outb (0x42, addr + EN0_RSARLO);
219
        outb (0x00, addr + EN0_RSARHI);
220
        outb (E8390_RREAD | E8390_START, addr + E8390_CMD);
221
 
222
        udelay (1);
223
 
224
        outb (ENISR_RDC, addr + EN0_ISR);
225
        outb (count, addr + EN0_RCNTLO);
226
        outb (count >> 8, addr + EN0_RCNTHI);
227
        outb (0, addr + EN0_RSARLO);
228
        outb (start_page, addr + EN0_RSARHI);
229
        outb (E8390_RWRITE | E8390_START, addr + E8390_CMD);
230
 
231
        if (ei_status.word16)
232
                outsw (dma_addr, buf, count >> 1);
233
#ifdef BIT8
234
        else
235
                outsb (dma_addr, buf, count);
236
#endif
237
 
238
        dma_start = jiffies;
239
 
240
        while ((inb (addr + EN0_ISR) & ENISR_RDC) == 0)
241
                if (jiffies - dma_start > 2*HZ/100) { /* 20ms */
242
                        printk ("%s: timeout waiting for TX RDC\n", dev->name);
243
                        etherh_reset (dev);
244
                        NS8390_init (dev, 1);
245
                        break;
246
                }
247
 
248
        outb (ENISR_RDC, addr + EN0_ISR);
249
        ei_status.dmaing &= ~1;
250
}
251
 
252
/*
253
 * Read a block of data from the 8390
254
 */
255
static void
256
etherh_block_input (struct device *dev, int count, struct sk_buff *skb, int ring_offset)
257
{
258
        unsigned int addr, dma_addr;
259
        unsigned char *buf;
260
 
261
        if (ei_status.dmaing) {
262
                printk ("%s: DMAing conflict in etherh_block_input: "
263
                        " DMAstat %d irqlock %d intr %d\n", dev->name,
264
                        ei_status.dmaing, ei_status.irqlock, dev->interrupt);
265
                return;
266
        }
267
 
268
        ei_status.dmaing |= 1;
269
 
270
        addr = dev->base_addr;
271
        dma_addr = eh_status.dma_port;
272
 
273
        buf = skb->data;
274
        outb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
275
        outb (count, addr + EN0_RCNTLO);
276
        outb (count >> 8, addr + EN0_RCNTHI);
277
        outb (ring_offset, addr + EN0_RSARLO);
278
        outb (ring_offset >> 8, addr + EN0_RSARHI);
279
        outb (E8390_RREAD | E8390_START, addr + E8390_CMD);
280
 
281
        if (ei_status.word16) {
282
                insw (dma_addr, buf, count >> 1);
283
                if (count & 1)
284
                        buf[count - 1] = inb (dma_addr);
285
        }
286
#ifdef BIT8
287
        else
288
                insb (dma_addr, buf, count);
289
#endif
290
 
291
        outb (ENISR_RDC, addr + EN0_ISR);
292
        ei_status.dmaing &= ~1;
293
}
294
 
295
/*
296
 * Read a header from the 8390
297
 */
298
static void
299
etherh_get_header (struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
300
{
301
        unsigned int addr, dma_addr;
302
 
303
        if (ei_status.dmaing) {
304
                printk ("%s: DMAing conflict in etherh_get_header: "
305
                        " DMAstat %d irqlock %d intr %d\n", dev->name,
306
                        ei_status.dmaing, ei_status.irqlock, dev->interrupt);
307
                return;
308
        }
309
 
310
        ei_status.dmaing |= 1;
311
 
312
        addr = dev->base_addr;
313
        dma_addr = eh_status.dma_port;
314
 
315
        outb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
316
        outb (sizeof (*hdr), addr + EN0_RCNTLO);
317
        outb (0, addr + EN0_RCNTHI);
318
        outb (0, addr + EN0_RSARLO);
319
        outb (ring_page, addr + EN0_RSARHI);
320
        outb (E8390_RREAD | E8390_START, addr + E8390_CMD);
321
 
322
        if (ei_status.word16)
323
                insw (dma_addr, hdr, sizeof (*hdr) >> 1);
324
#ifdef BIT8
325
        else
326
                insb (dma_addr, hdr, sizeof (*hdr));
327
#endif
328
 
329
        outb (ENISR_RDC, addr + EN0_ISR);
330
        ei_status.dmaing &= ~1;
331
}
332
 
333
/*
334
 * Open/initialize the board.  This is called (in the current kernel)
335
 * sometime after booting when the 'ifconfig' program is run.
336
 *
337
 * This routine should set everything up anew at each open, even
338
 * registers that "should" only need to be set once at boot, so that
339
 * there is non-reboot way to recover if something goes wrong.
340
 */
341
static int
342
etherh_open(struct device *dev)
343
{
344
        MOD_INC_USE_COUNT;
345
 
346
        if (request_irq(dev->irq, ei_interrupt, 0, "etherh", dev)) {
347
                MOD_DEC_USE_COUNT;
348
                return -EAGAIN;
349
        }
350
 
351
        etherh_reset(dev);
352
        ei_open(dev);
353
        return 0;
354
}
355
 
356
/*
357
 * The inverse routine to etherh_open().
358
 */
359
static int
360
etherh_close(struct device *dev)
361
{
362
        ei_close (dev);
363
        free_irq (dev->irq, dev);
364
 
365
        MOD_DEC_USE_COUNT;
366
        return 0;
367
}
368
 
369
/*
370
 * detect presence of NS8390 compatible chip
371
 */
372
static int
373
etherh_check_ns8390(struct device *dev, unsigned int addr)
374
{
375
        unsigned int reg0, tmp;
376
 
377
        reg0 = inb(addr);
378
        if (reg0 == 0xff) {
379
                if (net_debug & DEBUG_INIT)
380
                        printk("%s: etherh error: NS8390 command register wrong\n", dev->name);
381
                return -ENODEV;
382
        }
383
 
384
        outb(E8390_NODMA | E8390_PAGE1 | E8390_STOP, addr + E8390_CMD);
385
        tmp = inb(addr + 13);
386
        outb(0xff, addr + 13);
387
        outb(E8390_NODMA | E8390_PAGE0, addr + E8390_CMD);
388
        inb(addr + EN0_COUNTER0);
389
        if (inb(addr + EN0_COUNTER0) != 0) {
390
                if (net_debug & DEBUG_INIT)
391
                        printk ("%s: etherh error: NS8390 not found\n", dev->name);
392
                outb(reg0, addr);
393
                outb(tmp, addr + 13);
394
                return -ENODEV;
395
        }
396
        return 0;
397
}
398
 
399
/*
400
 * autodetect the media type
401
 */
402
static void
403
etherh_autodetect_media(struct device *dev)
404
{
405
        ei_status.interface_num = 0;     /* select 10bT */
406
        etherh_setif(dev);
407
        udelay(1000);
408
 
409
        if (!etherh_getifstat(dev)) {
410
                ei_status.interface_num = 1;
411
                etherh_setif(dev);
412
        }
413
 
414
        if (!etherh_getifstat(dev))
415
                ei_status.interface_num = 2;
416
}
417
 
418
/*
419
 * This is the real probe routine.
420
 */
421
static int
422
etherh_probe1(struct device *dev)
423
{
424
        static int version_printed;
425
        struct expansion_card *ec;
426
        unsigned int addr, i, memc_base, io_base;
427
        const char *dev_type, *if_type[] = { "10BaseT", "10Base2", "UNKNOWN" };
428
 
429
        if (net_debug && version_printed++ == 0)
430
                printk(version);
431
 
432
        if (!dev->priv)
433
                return -ENODEV;
434
 
435
        ec        = (struct expansion_card *)dev->priv;
436
        memc_base = ecard_address(ec, ECARD_MEMC, 0);
437
        io_base   = ecard_address(ec, ECARD_IOC, ECARD_FAST);
438
 
439
        switch (ec->cid.product) {
440
        case PROD_I3_ETHERLAN500:
441
                dev_type = "500";
442
                addr = memc_base + ETHERH500_NS8390;
443
                break;
444
        case PROD_I3_ETHERLAN600:
445
                dev_type = "600";
446
                addr = memc_base + ETHERH600_NS8390;
447
                break;
448
        case PROD_I3_ETHERLAN600A:
449
                dev_type = "600A";
450
                addr = memc_base + ETHERH600_NS8390;
451
                break;
452
        default:
453
                dev_type = "*unknown*";
454
                addr = memc_base + ETHERH600_NS8390;
455
        }
456
 
457
        /*
458
         * check to make sure that this region isn't already in use,
459
         * and make absolutely sure that we've got a real NS8390
460
         * compatible controller here.
461
         */
462
        if (check_region(addr, 16) || etherh_check_ns8390(dev, addr))
463
                return -ENODEV;
464
 
465
        /*
466
         * Allocate our structure on top of 8390's private structure
467
         */
468
        dev->priv = kmalloc(sizeof(struct eh_device), GFP_KERNEL);
469
        if (dev->priv == NULL)
470
                return -ENOMEM;
471
        memset(dev->priv, 0, sizeof(struct eh_device));
472
 
473
        /*
474
         * Initialise the 8390 driver core.  We've already claimed the
475
         * memory for the driver, so this won't fail.
476
         */
477
        ethdev_init(dev);
478
 
479
        dev->mem_start  = 0;
480
        dev->mem_end    = 0;
481
        dev->rmem_start = 0;
482
        dev->rmem_end   = 0;
483
        dev->open       = etherh_open;
484
        dev->stop       = etherh_close;
485
 
486
        request_region (addr, 16, "etherh");
487
 
488
        /*
489
         * Setup ec->irq_data and ec->ops to point to the correct thing
490
         * so that we can enable/disable the interrupts.
491
         */
492
        ec->irq_data    = &eh_status;
493
        ec->ops         = &etherh_ops;
494
        ecard_claim(ec);
495
 
496
        ei_status.name          = "etherh";
497
        ei_status.word16        = 1;
498
        ei_status.tx_start_page = ETHERH_TX_START_PAGE;
499
        ei_status.rx_start_page = ei_status.tx_start_page + TX_PAGES;
500
        ei_status.stop_page     = ETHERH_STOP_PAGE;
501
        ei_status.reset_8390    = etherh_reset;
502
        ei_status.block_input   = etherh_block_input;
503
        ei_status.block_output  = etherh_block_output;
504
        ei_status.get_8390_hdr  = etherh_get_header;
505
        eh_status.product       = ec->cid.product;
506
 
507
        switch(ec->cid.product) {
508
        case PROD_I3_ETHERLAN500:
509
                dev->base_addr      = memc_base + ETHERH500_NS8390;
510
                eh_status.dma_port  = memc_base + ETHERH500_DATAPORT;
511
                eh_status.ctrl_port = io_base   + ETHERH500_CTRLPORT;
512
                break;
513
        case PROD_I3_ETHERLAN600:
514
        case PROD_I3_ETHERLAN600A:
515
                dev->base_addr      = memc_base + ETHERH600_NS8390;
516
                eh_status.dma_port  = memc_base + ETHERH600_DATAPORT;
517
                eh_status.ctrl_port = memc_base + ETHERH600_CTRLPORT;
518
                break;
519
        }
520
 
521
        /*
522
         * Now, autodetect media
523
         */
524
        etherh_autodetect_media(dev);
525
 
526
        /*
527
         * Tell the user what we found
528
         */
529
        printk("%s: etherh %s found at %lx, IRQ%d, ether address ",
530
                dev->name, dev_type, dev->base_addr, dev->irq);
531
        for (i = 0; i < 6; i++)
532
                printk (i == 5 ? "%2.2x " : "%2.2x:", dev->dev_addr[i]);
533
        printk("%s\n", if_type[ei_status.interface_num]);
534
 
535
        etherh_reset(dev);
536
        NS8390_init(dev, 0);
537
 
538
        return 0;
539
}
540
 
541
/*
542
 * Read the ethernet address string from the on board rom.
543
 * This is an ascii string...
544
 */
545
static int
546
etherh_addr(char *addr, struct expansion_card *ec)
547
{
548
        struct in_chunk_dir cd;
549
        char *s;
550
 
551
        if (ecard_readchunk(&cd, ec, 0xf5, 0) && (s = strchr(cd.d.string, '('))) {
552
                int i;
553
                for (i = 0; i < 6; i++) {
554
                        addr[i] = simple_strtoul(s + 1, &s, 0x10);
555
                        if (*s != (i == 5? ')' : ':'))
556
                                break;
557
                }
558
                if (i == 6)
559
                        return 0;
560
        }
561
        return ENODEV;
562
}
563
 
564
static void
565
etherh_initdev(ecard_t *ec, struct device *dev)
566
{
567
        dev->base_addr = 0;              /* 'autoprobe' */
568
        dev->irq       = ec->irq;
569
        dev->priv      = ec;
570
 
571
        etherh_addr (dev->dev_addr, ec);
572
}
573
 
574
#ifndef MODULE
575
int
576
etherh_probe(struct device *dev)
577
{
578
        if (!dev)
579
                return ENODEV;
580
 
581
        ecard_startfind();
582
 
583
        if (!dev->base_addr) {
584
                struct expansion_card *ec;
585
 
586
                if ((ec = ecard_find(0, etherh_cids)) == NULL)
587
                        return ENODEV;
588
 
589
                etherh_initdev(ec, dev);
590
        }
591
        return etherh_probe1(dev);
592
}
593
#endif
594
 
595
#ifdef MODULE
596
#define MAX_ETHERH_CARDS 2
597
 
598
static int io[MAX_ETHERH_CARDS];
599
static int irq[MAX_ETHERH_CARDS];
600
static char ethernames[MAX_ETHERH_CARDS][9];
601
static struct device *my_ethers[MAX_ETHERH_CARDS];
602
static struct expansion_card *ec[MAX_ETHERH_CARDS];
603
 
604
int
605
init_module(void)
606
{
607
        struct device *dev = NULL;
608
        struct expansion_card *boguscards[MAX_ETHERH_CARDS];
609
        int i, found = 0;
610
 
611
        for (i = 0; i < MAX_ETHERH_CARDS; i++) {
612
                my_ethers[i] = NULL;
613
                boguscards[i] = NULL;
614
                ec[i] = NULL;
615
                strcpy (ethernames[i], "        ");
616
        }
617
 
618
        ecard_startfind();
619
 
620
        for (i = 0; i < MAX_ETHERH_CARDS; i++) {
621
                if (!dev)
622
                        dev = (struct device *)kmalloc (sizeof (struct device), GFP_KERNEL);
623
                if (dev)
624
                        memset (dev, 0, sizeof (struct device));
625
 
626
                if (!io[i]) {
627
                        if ((ec[i] = ecard_find (0, etherh_cids)) == NULL)
628
                                continue;
629
                        if (!dev)
630
                                return -ENOMEM;
631
 
632
                        etherh_initdev (ec[i], dev);
633
                } else {
634
                        ec[i] = NULL;
635
                        if (!dev)
636
                                return -ENOMEM;
637
                        dev->base_addr = io[i];
638
                        dev->irq = irq[i];
639
                }
640
 
641
                dev->init = etherh_probe1;
642
                dev->name = ethernames[i];
643
 
644
                my_ethers[i] = dev;
645
 
646
                if (register_netdev (my_ethers[i]) != 0) {
647
                        printk (KERN_WARNING "No etherh card found at %08lX\n", dev->base_addr);
648
                        if (ec[i]) {
649
                                boguscards[i] = ec[i];
650
                                ec[i] = NULL;
651
                        }
652
                        continue;
653
                }
654
                found ++;
655
                dev = NULL;
656
        }
657
        if (dev)
658
                kfree (dev);
659
        for (i = 0; i < MAX_ETHERH_CARDS; i++)
660
                if (boguscards[i]) {
661
                        boguscards[i]->ops = NULL;
662
                        ecard_release (boguscards[i]);
663
                }
664
        if (!found)
665
                return -ENODEV;
666
        return 0;
667
}
668
 
669
void
670
cleanup_module(void)
671
{
672
        int i;
673
        for (i = 0; i < MAX_ETHERH_CARDS; i++) {
674
                if (my_ethers[i]) {
675
                        unregister_netdev(my_ethers[i]);
676
                        release_region (my_ethers[i]->base_addr, 16);
677
                        kfree (my_ethers[i]);
678
                        my_ethers[i] = NULL;
679
                }
680
                if (ec[i]) {
681
                        ec[i]->ops = NULL;
682
                        ecard_release(ec[i]);
683
                        ec[i] = NULL;
684
                }
685
        }
686
}
687
#endif /* MODULE */

powered by: WebSVN 2.1.0

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