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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [armnommu/] [kernel/] [ecard.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1622 jcastillo
/*
2
 * linux/arch/arm/kernel/ecard.c
3
 *
4
 *  Find all installed expansion cards, and handle interrupts from them.
5
 *
6
 * Copyright 1995-1998 Russell King
7
 *
8
 * Created from information from Acorns RiscOS3 PRMs
9
 *
10
 * 08-Dec-1996  RMK     Added code for the 9'th expansion card - the ether
11
 *                      podule slot.
12
 * 06-May-1997  RMK     Added blacklist for cards whose loader doesn't work.
13
 * 12-Sep-1997  RMK     Created new handling of interrupt enables/disables
14
 *                      - cards can now register their own routine to control
15
 *                      interrupts (recommended).
16
 * 29-Sep-1997  RMK     Expansion card interrupt hardware not being re-enabled
17
 *                      on reset from Linux. (Caused cards not to respond
18
 *                      under RiscOS without hard reset).
19
 * 15-Feb-1998  RMK     Added DMA support
20
 * 12-Sep-1998  RMK     Added EASI support
21
 * 10-Jan-1999  RMK     Run loaders in a simulated RISC OS environment.
22
 */
23
 
24
#define ECARD_C
25
#define __KERNEL_SYSCALLS__
26
 
27
#include <linux/config.h>
28
#include <linux/kernel.h>
29
#include <linux/types.h>
30
#include <linux/sched.h>
31
#include <linux/interrupt.h>
32
#include <linux/mm.h>
33
#include <linux/malloc.h>
34
#include <linux/errno.h>
35
#include <linux/unistd.h>
36
 
37
#include <asm/dma.h>
38
#include <asm/ecard.h>
39
#include <asm/hardware.h>
40
#include <asm/io.h>
41
#include <asm/irq.h>
42
#include <asm/arch/irq.h>
43
#include <asm/pgtable.h>
44
 
45
#ifdef CONFIG_ARCH_ARC
46
#include <asm/arch/oldlatches.h>
47
#else
48
#define oldlatch_init()
49
#endif
50
 
51
enum req {
52
        req_readbytes,
53
        req_reset
54
};
55
 
56
struct ecard_request {
57
        enum req        req;
58
        ecard_t         *ec;
59
        unsigned int    address;
60
        unsigned int    length;
61
        unsigned int    use_loader;
62
        void            *buffer;
63
};
64
 
65
struct expcard_blacklist {
66
        unsigned short   manufacturer;
67
        unsigned short   product;
68
        const char      *type;
69
};
70
 
71
static pid_t ecard_pid;
72
static struct wait_queue *ecard_wait;
73
static struct wait_queue *ecard_done;
74
static struct ecard_request *ecard_req;
75
static struct task_struct *ecard_tsk;
76
static ecard_t *cards;
77
static ecard_t *slot_to_expcard[MAX_ECARDS];
78
#ifdef HAS_EXPMASK
79
static unsigned int have_expmask;
80
#endif
81
 
82
/* List of descriptions of cards which don't have an extended
83
 * identification, or chunk directories containing a description.
84
 */
85
static const struct expcard_blacklist blacklist[] = {
86
        { MANU_ACORN, PROD_ACORN_ETHER1, "Acorn Ether1" }
87
};
88
 
89
asmlinkage extern int ecard_loader_reset(volatile unsigned char *pa,
90
                                         loader_t loader);
91
asmlinkage extern int ecard_loader_read(int off, volatile unsigned char *pa,
92
                                        loader_t loader);
93
extern int setup_arm_irq(int, struct irqaction *);
94
extern void do_fast_IRQ(int irq);
95
 
96
 
97
static void
98
ecard_irq_noexpmask(int intr_no, void *dev_id, struct pt_regs *regs);
99
 
100
static struct irqaction irqexpansioncard = {
101
        ecard_irq_noexpmask, 0, 0, "expansion cards", NULL, NULL
102
};
103
 
104
static inline unsigned short
105
ecard_getu16(unsigned char *v)
106
{
107
        return v[0] | v[1] << 8;
108
}
109
 
110
static inline signed long
111
ecard_gets24(unsigned char *v)
112
{
113
        return v[0] | v[1] << 8 | v[2] << 16 | ((v[2] & 0x80) ? 0xff000000 : 0);
114
}
115
 
116
static inline ecard_t *
117
slot_to_ecard(unsigned int slot)
118
{
119
        return slot < MAX_ECARDS ? slot_to_expcard[slot] : NULL;
120
}
121
 
122
/* ===================== Expansion card daemon ======================== */
123
/*
124
 * Since the loader programs on the expansion cards need to be run
125
 * in a specific environment, create a separate task with this
126
 * environment up, and pass requests to this task as and when we
127
 * need to.
128
 *
129
 * This should allow 99% of loaders to be called from Linux.
130
 *
131
 * From a security standpoint, we trust the card vendors.  This
132
 * may be a misplaced trust.
133
 */
134
#define BUS_ADDR(x) ((((unsigned long)(x)) << 2) + IO_BASE)
135
#define POD_INT_ADDR(x) ((volatile unsigned char *)\
136
                         ((BUS_ADDR((x)) - IO_BASE) + IO_START))
137
 
138
static void
139
ecard_task_reset(struct ecard_request *req)
140
{
141
        if (req->ec == NULL) {
142
                ecard_t *ec;
143
 
144
                for (ec = cards; ec; ec = ec->next) {
145
                        printk(KERN_DEBUG "Resetting card %d\n",
146
                               ec->slot_no);
147
 
148
                        if (ec->loader)
149
                                ecard_loader_reset(POD_INT_ADDR(ec->podaddr),
150
                                                   ec->loader);
151
                }
152
                printk(KERN_DEBUG "All cards reset\n");
153
        } else if (req->ec->loader)
154
                ecard_loader_reset(POD_INT_ADDR(req->ec->podaddr),
155
                                   req->ec->loader);
156
}
157
 
158
static void
159
ecard_task_readbytes(struct ecard_request *req)
160
{
161
        unsigned char *buf = (unsigned char *)req->buffer;
162
        volatile unsigned char *base_addr =
163
                (volatile unsigned char *)POD_INT_ADDR(req->ec->podaddr);
164
        unsigned int len = req->length;
165
 
166
        if (req->ec->slot_no == 8) {
167
                /*
168
                 * The card maintains an index which
169
                 * increments the address into a 4096-byte
170
                 * page on each access.  We need to keep
171
                 * track of the counter.
172
                 */
173
                static unsigned int index;
174
                unsigned int offset, page;
175
                unsigned char byte = 0; /* keep gcc quiet */
176
 
177
                offset = req->address & 4095;
178
                page   = req->address >> 12;
179
 
180
                if (page > 256)
181
                        return;
182
 
183
                page *= 4;
184
 
185
                if (offset == 0 || index > offset) {
186
                        /*
187
                         * We need to reset the index counter.
188
                         */
189
                        *base_addr = 0;
190
                        index = 0;
191
                }
192
 
193
                while (index <= offset) {
194
                        byte = base_addr[page];
195
                        index += 1;
196
                }
197
 
198
                while (len--) {
199
                        *buf++ = byte;
200
                        if (len) {
201
                                byte = base_addr[page];
202
                                index += 1;
203
                        }
204
                }
205
        } else {
206
                unsigned int off = req->address;
207
 
208
                if (!req->use_loader || !req->ec->loader) {
209
                        off *= 4;
210
                        while (len--) {
211
                                *buf++ = base_addr[off];
212
                                off += 4;
213
                        }
214
                } else {
215
                        while(len--) {
216
                                /*
217
                                 * The following is required by some
218
                                 * expansion card loader programs.
219
                                 */
220
                                *(unsigned long *)0x108 = 0;
221
                                *buf++ = ecard_loader_read(off++, base_addr,
222
                                                           req->ec->loader);
223
                        }
224
                }
225
        }
226
 
227
}
228
 
229
#if !defined(CONFIG_CPU_ARM2) && !defined(CONFIG_CPU_ARM3)
230
/*
231
 * Set up the expansion card daemon's environment.
232
 */
233
static void
234
ecard_init_task(void)
235
{
236
        /* We want to set up the page tables for the following mapping:
237
         *  Virtual     Physical
238
         *  0x03000000  0x03000000
239
         *  0x03010000  unmapped
240
         *  0x03210000  0x03210000
241
         *  0x03400000  unmapped
242
         *  0x08000000  0x08000000
243
         *  0x10000000  unmapped
244
         *
245
         * FIXME: we don't follow this 100% yet.
246
         */
247
        pgd_t *src_pgd, *dst_pgd;
248
        unsigned int dst_addr = IO_START;
249
 
250
        src_pgd = pgd_offset(current->mm, IO_BASE);
251
        dst_pgd = pgd_offset(current->mm, dst_addr);
252
 
253
        while (dst_addr < IO_START + IO_SIZE) {
254
                *dst_pgd++ = *src_pgd++;
255
                dst_addr += PGDIR_SIZE;
256
        }
257
 
258
        flush_tlb_range(current->mm, IO_START, IO_START + IO_SIZE);
259
 
260
        dst_addr = EASI_START;
261
        src_pgd = pgd_offset(current->mm, EASI_BASE);
262
        dst_pgd = pgd_offset(current->mm, dst_addr);
263
 
264
        while (dst_addr < EASI_START + EASI_SIZE) {
265
                *dst_pgd++ = *src_pgd++;
266
                dst_addr += PGDIR_SIZE;
267
        }
268
 
269
        flush_tlb_range(current->mm, EASI_START, EASI_START + EASI_SIZE);
270
}
271
 
272
static int
273
ecard_task(void * unused)
274
{
275
        ecard_tsk = current;
276
 
277
        current->session = 1;
278
        current->pgrp = 1;
279
 
280
        /*
281
         * We don't want /any/ signals, not even SIGKILL
282
         */
283
        current->blocked = -1;
284
        current->signal = 0;
285
 
286
        strcpy(current->comm, "kecardd");
287
 
288
        /*
289
         * Set up the environment
290
         */
291
        ecard_init_task();
292
 
293
        while (1) {
294
                struct ecard_request *req;
295
 
296
                do {
297
                        req = xchg(&ecard_req, NULL);
298
 
299
                        if (req == NULL) {
300
                                current->signal = 0;
301
                                interruptible_sleep_on(&ecard_wait);
302
                        }
303
                } while (req == NULL);
304
 
305
                switch (req->req) {
306
                case req_readbytes:
307
                        ecard_task_readbytes(req);
308
                        break;
309
 
310
                case req_reset:
311
                        ecard_task_reset(req);
312
                        break;
313
                }
314
                wake_up(&ecard_done);
315
        }
316
}
317
 
318
/*
319
 * Wake the expansion card daemon to action our request.
320
 *
321
 * FIXME: The test here is not sufficient to detect if the
322
 * kcardd is running.
323
 */
324
static inline void
325
ecard_call(struct ecard_request *req)
326
{
327
        /*
328
         * If we're called from task 0, or from an
329
         * interrupt (will be keyboard interrupt),
330
         * we forcefully set up the memory map, and
331
         * call the loader.  We can't schedule, or
332
         * sleep for this call.
333
         */
334
        if ((current == task[0] || intr_count == 1) &&
335
            req->req == req_reset && req->ec == NULL) {
336
                ecard_init_task();
337
                ecard_task_reset(req);
338
        } else {
339
                if (ecard_pid <= 0)
340
                        ecard_pid = kernel_thread(ecard_task, NULL, 0);
341
 
342
                ecard_req = req;
343
 
344
                wake_up(&ecard_wait);
345
 
346
                sleep_on(&ecard_done);
347
        }
348
}
349
#else
350
/*
351
 * On 26-bit processors, we don't need the kcardd thread to access the
352
 * expansion card loaders.  We do it directly.
353
 */
354
static inline void
355
ecard_call(struct ecard_request *req)
356
{
357
        if (req->req == req_reset)
358
                ecard_task_reset(req);
359
        else
360
                ecard_task_readbytes(req);
361
}
362
#endif
363
 
364
/* ======================= Mid-level card control ===================== */
365
/*
366
 * This is called to reset the loaders for each expansion card on reboot.
367
 *
368
 * This is required to make sure that the card is in the correct state
369
 * that RiscOS expects it to be.
370
 */
371
void
372
ecard_reset(int slot)
373
{
374
        struct ecard_request req;
375
 
376
        req.req = req_reset;
377
 
378
        if (slot < 0)
379
                req.ec = NULL;
380
        else
381
                req.ec = slot_to_ecard(slot);
382
 
383
        ecard_call(&req);
384
 
385
#ifdef HAS_EXPMASK
386
        if (have_expmask && slot < 0) {
387
                have_expmask |= ~0;
388
                EXPMASK_ENABLE = have_expmask;
389
        }
390
#endif
391
}
392
 
393
static void
394
ecard_readbytes(void *addr, ecard_t *ec, int off, int len, int useld)
395
{
396
        struct ecard_request req;
397
 
398
        req.req         = req_readbytes;
399
        req.ec          = ec;
400
        req.address     = off;
401
        req.length      = len;
402
        req.use_loader  = useld;
403
        req.buffer      = addr;
404
 
405
        ecard_call(&req);
406
}
407
 
408
int ecard_readchunk(struct in_chunk_dir *cd, ecard_t *ec, int id, int num)
409
{
410
        struct ex_chunk_dir excd;
411
        int index = 16;
412
        int useld = 0;
413
 
414
        if (!ec->cid.cd)
415
                return 0;
416
 
417
        while(1) {
418
                ecard_readbytes(&excd, ec, index, 8, useld);
419
                index += 8;
420
                if (c_id(&excd) == 0) {
421
                        if (!useld && ec->loader) {
422
                                useld = 1;
423
                                index = 0;
424
                                continue;
425
                        }
426
                        return 0;
427
                }
428
                if (c_id(&excd) == 0xf0) { /* link */
429
                        index = c_start(&excd);
430
                        continue;
431
                }
432
                if (c_id(&excd) == 0x80) { /* loader */
433
                        if (!ec->loader) {
434
                                ec->loader = (loader_t)kmalloc(c_len(&excd),
435
                                                               GFP_KERNEL);
436
                                ecard_readbytes(ec->loader, ec,
437
                                                (int)c_start(&excd),
438
                                                c_len(&excd), useld);
439
                        }
440
                        continue;
441
                }
442
                if (c_id(&excd) == id && num-- == 0)
443
                        break;
444
        }
445
 
446
        if (c_id(&excd) & 0x80) {
447
                switch (c_id(&excd) & 0x70) {
448
                case 0x70:
449
                        ecard_readbytes((unsigned char *)excd.d.string, ec,
450
                                        (int)c_start(&excd), c_len(&excd),
451
                                        useld);
452
                        break;
453
                case 0x00:
454
                        break;
455
                }
456
        }
457
        cd->start_offset = c_start(&excd);
458
        memcpy(cd->d.string, excd.d.string, 256);
459
        return 1;
460
}
461
 
462
/* ======================= Interrupt control ============================ */
463
 
464
static void ecard_def_irq_enable(ecard_t *ec, int irqnr)
465
{
466
#ifdef HAS_EXPMASK
467
        if (irqnr < 4 && have_expmask) {
468
                have_expmask |= 1 << irqnr;
469
                EXPMASK_ENABLE = have_expmask;
470
        }
471
#endif
472
}
473
 
474
static void ecard_def_irq_disable(ecard_t *ec, int irqnr)
475
{
476
#ifdef HAS_EXPMASK
477
        if (irqnr < 4 && have_expmask) {
478
                have_expmask &= ~(1 << irqnr);
479
                EXPMASK_ENABLE = have_expmask;
480
        }
481
#endif
482
}
483
 
484
static int ecard_def_irq_pending(ecard_t *ec)
485
{
486
        return !ec->irqmask || ec->irqaddr[0] & ec->irqmask;
487
}
488
 
489
static void ecard_def_fiq_enable(ecard_t *ec, int fiqnr)
490
{
491
        panic("ecard_def_fiq_enable called - impossible");
492
}
493
 
494
static void ecard_def_fiq_disable(ecard_t *ec, int fiqnr)
495
{
496
        panic("ecard_def_fiq_disable called - impossible");
497
}
498
 
499
static int ecard_def_fiq_pending(ecard_t *ec)
500
{
501
        return !ec->fiqmask || ec->fiqaddr[0] & ec->fiqmask;
502
}
503
 
504
static expansioncard_ops_t ecard_default_ops = {
505
        ecard_def_irq_enable,
506
        ecard_def_irq_disable,
507
        ecard_def_irq_pending,
508
        ecard_def_fiq_enable,
509
        ecard_def_fiq_disable,
510
        ecard_def_fiq_pending
511
};
512
 
513
/*
514
 * Enable and disable interrupts from expansion cards.
515
 * (interrupts are disabled for these functions).
516
 *
517
 * They are not meant to be called directly, but via enable/disable_irq.
518
 */
519
void ecard_enableirq(unsigned int irqnr)
520
{
521
        ecard_t *ec = slot_to_ecard(irqnr);
522
 
523
        if (ec) {
524
                if (!ec->ops)
525
                        ec->ops = &ecard_default_ops;
526
 
527
                if (ec->claimed && ec->ops->irqenable)
528
                        ec->ops->irqenable(ec, irqnr);
529
                else
530
                        printk(KERN_ERR "ecard: rejecting request to "
531
                                "enable IRQs for %d\n", irqnr);
532
        }
533
}
534
 
535
void ecard_disableirq(unsigned int irqnr)
536
{
537
        ecard_t *ec = slot_to_ecard(irqnr);
538
 
539
        if (ec) {
540
                if (!ec->ops)
541
                        ec->ops = &ecard_default_ops;
542
 
543
                if (ec->ops && ec->ops->irqdisable)
544
                        ec->ops->irqdisable(ec, irqnr);
545
        }
546
}
547
 
548
void ecard_enablefiq(unsigned int fiqnr)
549
{
550
        ecard_t *ec = slot_to_ecard(fiqnr);
551
 
552
        if (ec) {
553
                if (!ec->ops)
554
                        ec->ops = &ecard_default_ops;
555
 
556
                if (ec->claimed && ec->ops->fiqenable)
557
                        ec->ops->fiqenable(ec, fiqnr);
558
                else
559
                        printk(KERN_ERR "ecard: rejecting request to "
560
                                "enable FIQs for %d\n", fiqnr);
561
        }
562
}
563
 
564
void ecard_disablefiq(unsigned int fiqnr)
565
{
566
        ecard_t *ec = slot_to_ecard(fiqnr);
567
 
568
        if (ec) {
569
                if (!ec->ops)
570
                        ec->ops = &ecard_default_ops;
571
 
572
                if (ec->ops->fiqdisable)
573
                        ec->ops->fiqdisable(ec, fiqnr);
574
        }
575
}
576
 
577
static void
578
ecard_dump_irq_state(ecard_t *ec)
579
{
580
        printk("  %d: %sclaimed, ",
581
               ec->slot_no,
582
               ec->claimed ? "" : "not ");
583
 
584
        if (ec->ops && ec->ops->irqpending &&
585
            ec->ops != &ecard_default_ops)
586
                printk("irq %spending\n",
587
                       ec->ops->irqpending(ec) ? "" : "not ");
588
        else
589
                printk("irqaddr %p, mask = %02X, status = %02X\n",
590
                       ec->irqaddr, ec->irqmask, *ec->irqaddr);
591
}
592
 
593
static void
594
ecard_check_lockup(void)
595
{
596
        static int last, lockup;
597
        ecard_t *ec;
598
 
599
        /*
600
         * If the timer interrupt has not run since the last million
601
         * unrecognised expansion card interrupts, then there is
602
         * something seriously wrong.  Disable the expansion card
603
         * interrupts so at least we can continue.
604
         *
605
         * Maybe we ought to start a timer to re-enable them some time
606
         * later?
607
         */
608
        if (last == jiffies) {
609
                lockup += 1;
610
                if (lockup > 1000000) {
611
                        printk(KERN_ERR "\nInterrupt lockup detected - "
612
                               "disabling all expansion card interrupts\n");
613
 
614
                        disable_irq(IRQ_EXPANSIONCARD);
615
 
616
                        printk("Expansion card IRQ state:\n");
617
 
618
                        for (ec = cards; ec; ec = ec->next)
619
                                ecard_dump_irq_state(ec);
620
                }
621
        } else
622
                lockup = 0;
623
 
624
        /*
625
         * If we did not recognise the source of this interrupt,
626
         * warn the user, but don't flood the user with these messages.
627
         */
628
        if (!last || last + 500 < jiffies) {
629
                last = jiffies;
630
                printk(KERN_WARNING "Unrecognised interrupt from backplane\n");
631
        }
632
}
633
 
634
static void
635
ecard_irq_noexpmask(int intr_no, void *dev_id, struct pt_regs *regs)
636
{
637
        ecard_t *ec;
638
        int called = 0;
639
 
640
        mask_irq(IRQ_EXPANSIONCARD);
641
        for (ec = cards; ec; ec = ec->next) {
642
                int pending;
643
 
644
                if (!ec->claimed || ec->irq == NO_IRQ || ec->slot_no == 8)
645
                        continue;
646
 
647
                if (ec->ops && ec->ops->irqpending)
648
                        pending = ec->ops->irqpending(ec);
649
                else
650
                        pending = ecard_default_ops.irqpending(ec);
651
 
652
                if (pending) {
653
                        do_fast_IRQ(ec->irq);
654
                        called ++;
655
                }
656
        }
657
        cli();
658
        unmask_irq(IRQ_EXPANSIONCARD);
659
 
660
        if (called == 0)
661
                ecard_check_lockup();
662
}
663
 
664
#ifdef HAS_EXPMASK
665
static unsigned char priority_masks[] =
666
{
667
        0xf0, 0xf1, 0xf3, 0xf7, 0xff, 0xff, 0xff, 0xff
668
};
669
 
670
static unsigned char first_set[] =
671
{
672
        0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
673
        0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00
674
};
675
 
676
static void
677
ecard_irq_expmask(int intr_no, void *dev_id, struct pt_regs *regs)
678
{
679
        const unsigned int statusmask = 15;
680
        unsigned int status;
681
 
682
        status = EXPMASK_STATUS & statusmask;
683
        if (status) {
684
                unsigned int slot;
685
                ecard_t *ec;
686
again:
687
                slot = first_set[status];
688
                ec = slot_to_ecard(slot);
689
                if (ec->claimed) {
690
                        unsigned int oldexpmask;
691
                        /*
692
                         * this ugly code is so that we can operate a
693
                         * prioritorising system:
694
                         *
695
                         * Card 0       highest priority
696
                         * Card 1
697
                         * Card 2
698
                         * Card 3       lowest priority
699
                         *
700
                         * Serial cards should go in 0/1, ethernet/scsi in 2/3
701
                         * otherwise you will lose serial data at high speeds!
702
                         */
703
                        oldexpmask = have_expmask;
704
                        EXPMASK_ENABLE = (have_expmask &= priority_masks[slot]);
705
                        sti();
706
                        do_fast_IRQ(ec->irq);
707
                        cli();
708
                        EXPMASK_ENABLE = have_expmask = oldexpmask;
709
                        status = EXPMASK_STATUS & statusmask;
710
                        if (status)
711
                                goto again;
712
                } else {
713
                        printk(KERN_WARNING "card%d: interrupt from unclaimed "
714
                               "card???\n", slot);
715
                        EXPMASK_ENABLE = (have_expmask &= ~(1 << slot));
716
                }
717
        } else
718
                printk(KERN_WARNING "Wild interrupt from backplane (masks)\n");
719
}
720
 
721
static void
722
ecard_probeirqhw(void)
723
{
724
        ecard_t *ec;
725
        int found;
726
 
727
        EXPMASK_ENABLE = 0x00;
728
        EXPMASK_STATUS = 0xff;
729
        found = ((EXPMASK_STATUS & 15) == 0);
730
        EXPMASK_ENABLE = 0xff;
731
 
732
        if (!found)
733
                return;
734
 
735
        printk(KERN_DEBUG "Expansion card interrupt "
736
               "management hardware found\n");
737
 
738
        irqexpansioncard.handler = ecard_irq_expmask;
739
 
740
        /* for each card present, set a bit to '1' */
741
        have_expmask = 0x80000000;
742
 
743
        for (ec = cards; ec; ec = ec->next)
744
                have_expmask |= 1 << ec->slot_no;
745
 
746
        EXPMASK_ENABLE = have_expmask;
747
}
748
#else
749
#define ecard_probeirqhw()
750
#endif
751
 
752
unsigned int ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed)
753
{
754
        switch (ec->slot_no) {
755
        case 0 ... 3:
756
                switch (type) {
757
                case ECARD_MEMC:
758
                        return IO_EC_MEMC_BASE + (ec->slot_no << 12);
759
 
760
                case ECARD_IOC:
761
                        return IO_EC_IOC_BASE + (speed << 17) +
762
                                (ec->slot_no << 12);
763
 
764
#ifdef IO_EC_EASI_BASE
765
                case ECARD_EASI:
766
                        return IO_EC_EASI_BASE + (ec->slot_no << 22);
767
#endif
768
                }
769
                break;
770
 
771
        case 4 ... 7:
772
                switch (type) {
773
#ifdef IO_EC_IOC4_BASE
774
                case ECARD_IOC:
775
                        return IO_EC_IOC4_BASE + (speed << 17) +
776
                                ((ec->slot_no - 4) << 12);
777
#endif
778
#ifdef IO_EC_EASI_BASE
779
                case ECARD_EASI:
780
                        return IO_EC_EASI_BASE + (ec->slot_no << 22);
781
#endif
782
                default:
783
                        break;
784
                }
785
                break;
786
 
787
#ifdef IO_EC_MEMC8_BASE
788
        case 8:
789
                return IO_EC_MEMC8_BASE;
790
#endif
791
        }
792
        return 0;
793
}
794
 
795
static int ecard_prints(char *buffer, ecard_t *ec)
796
{
797
        char *start = buffer;
798
 
799
        buffer += sprintf(buffer, "  %d: %s ", ec->slot_no,
800
                          ec->type == ECARD_EASI ? "EASI" : "    ");
801
 
802
        if (ec->cid.id == 0) {
803
                struct in_chunk_dir incd;
804
 
805
                buffer += sprintf(buffer, "[%04X:%04X] ",
806
                        ec->cid.manufacturer, ec->cid.product);
807
 
808
                if (!ec->card_desc && ec->cid.cd &&
809
                    ecard_readchunk(&incd, ec, 0xf5, 0))
810
                        ec->card_desc = incd.d.string;
811
 
812
                if (!ec->card_desc)
813
                        ec->card_desc = "*unknown*";
814
 
815
                buffer += sprintf(buffer, "%s\n", ec->card_desc);
816
        } else
817
                buffer += sprintf(buffer, "Simple card %d\n", ec->cid.id);
818
 
819
        return buffer - start;
820
}
821
 
822
/*
823
 * Probe for an expansion card.
824
 *
825
 * If bit 1 of the first byte of the card is set, then the
826
 * card does not exist.
827
 */
828
static int
829
ecard_probe(int slot, card_type_t type)
830
{
831
        ecard_t **ecp;
832
        ecard_t *ec;
833
        struct ex_ecid cid;
834
        char buffer[200];
835
        int i, rc = -ENOMEM;
836
 
837
        ec = kmalloc(sizeof(ecard_t), GFP_KERNEL);
838
 
839
        if (!ec)
840
                goto nodev;
841
 
842
        memset(ec, 0, sizeof(ecard_t));
843
 
844
        ec->slot_no     = slot;
845
        ec->type        = type;
846
        ec->irq         = NO_IRQ;
847
        ec->fiq         = NO_IRQ;
848
        ec->dma         = NO_DMA;
849
        ec->card_desc   = NULL;
850
        ec->ops         = &ecard_default_ops;
851
 
852
        rc = -ENODEV;
853
        if ((ec->podaddr = ecard_address(ec, type, ECARD_SYNC)) == 0)
854
                goto nodev;
855
 
856
        cid.r_zero = 1;
857
        ecard_readbytes(&cid, ec, 0, 16, 0);
858
        if (cid.r_zero)
859
                goto nodev;
860
 
861
        ec->cid.id      = cid.r_id;
862
        ec->cid.cd      = cid.r_cd;
863
        ec->cid.is      = cid.r_is;
864
        ec->cid.w       = cid.r_w;
865
        ec->cid.manufacturer = ecard_getu16(cid.r_manu);
866
        ec->cid.product = ecard_getu16(cid.r_prod);
867
        ec->cid.country = cid.r_country;
868
        ec->cid.irqmask = cid.r_irqmask;
869
        ec->cid.irqoff  = ecard_gets24(cid.r_irqoff);
870
        ec->cid.fiqmask = cid.r_fiqmask;
871
        ec->cid.fiqoff  = ecard_gets24(cid.r_fiqoff);
872
        ec->fiqaddr     =
873
        ec->irqaddr     = (unsigned char *)ioaddr(ec->podaddr);
874
 
875
        if (ec->cid.is) {
876
                ec->irqmask = ec->cid.irqmask;
877
                ec->irqaddr += ec->cid.irqoff;
878
                ec->fiqmask = ec->cid.fiqmask;
879
                ec->fiqaddr += ec->cid.fiqoff;
880
        } else {
881
                ec->irqmask = 1;
882
                ec->fiqmask = 4;
883
        }
884
 
885
        for (i = 0; i < sizeof(blacklist) / sizeof(*blacklist); i++)
886
                if (blacklist[i].manufacturer == ec->cid.manufacturer &&
887
                    blacklist[i].product == ec->cid.product) {
888
                        ec->card_desc = blacklist[i].type;
889
                        break;
890
                }
891
 
892
        ec->irq = 32 + slot;
893
#ifdef IO_EC_MEMC8_BASE
894
        if (slot == 8)
895
                ec->irq = 11;
896
#endif
897
#ifdef CONFIG_ARCH_RPC
898
        /* On RiscPC, only first two slots have DMA capability */
899
        if (slot < 2)
900
                ec->dma = 2 + slot;
901
#endif
902
#if 0   /* We don't support FIQs on expansion cards at the moment */
903
        ec->fiq = 96 + slot;
904
#endif
905
 
906
        rc = 0;
907
 
908
        for (ecp = &cards; *ecp; ecp = &(*ecp)->next);
909
 
910
        *ecp = ec;
911
 
912
nodev:
913
        if (rc && ec)
914
                kfree(ec);
915
        else {
916
                slot_to_expcard[slot] = ec;
917
 
918
                ecard_prints(buffer, ec);
919
                printk("%s", buffer);
920
        }
921
        return rc;
922
}
923
 
924
static ecard_t *finding_pos;
925
 
926
void ecard_startfind(void)
927
{
928
        finding_pos = NULL;
929
}
930
 
931
ecard_t *ecard_find(int cid, const card_ids *cids)
932
{
933
        if (!finding_pos)
934
                finding_pos = cards;
935
        else
936
                finding_pos = finding_pos->next;
937
 
938
        for (; finding_pos; finding_pos = finding_pos->next) {
939
                if (finding_pos->claimed)
940
                        continue;
941
 
942
                if (!cids) {
943
                        if ((finding_pos->cid.id ^ cid) == 0)
944
                                break;
945
                } else {
946
                        unsigned int manufacturer, product;
947
                        int i;
948
 
949
                        manufacturer = finding_pos->cid.manufacturer;
950
                        product = finding_pos->cid.product;
951
 
952
                        for (i = 0; cids[i].manufacturer != 65535; i++)
953
                                if (manufacturer == cids[i].manufacturer &&
954
                                    product == cids[i].product)
955
                                        break;
956
 
957
                        if (cids[i].manufacturer != 65535)
958
                                break;
959
                }
960
        }
961
 
962
        return finding_pos;
963
}
964
 
965
static void ecard_free_all(void)
966
{
967
        ecard_t *ec, *ecn;
968
 
969
        for (ec = cards; ec; ec = ecn) {
970
                ecn = ec->next;
971
 
972
                kfree(ec);
973
        }
974
 
975
        cards = NULL;
976
 
977
        memset(slot_to_expcard, 0, sizeof(slot_to_expcard));
978
}
979
 
980
/*
981
 * Initialise the expansion card system.
982
 * Locate all hardware - interrupt management and
983
 * actual cards.
984
 */
985
void ecard_init(void)
986
{
987
        int slot;
988
 
989
        oldlatch_init();
990
 
991
        printk("Probing expansion cards: (does not imply support)\n");
992
 
993
        for (slot = 0; slot < 8; slot ++) {
994
                if (ecard_probe(slot, ECARD_EASI) == -ENODEV)
995
                        ecard_probe(slot, ECARD_IOC);
996
        }
997
 
998
#ifdef IO_EC_MEMC8_BASE
999
        ecard_probe(8, ECARD_IOC);
1000
#endif
1001
 
1002
        ecard_probeirqhw();
1003
 
1004
        if (setup_arm_irq(IRQ_EXPANSIONCARD, &irqexpansioncard)) {
1005
                printk(KERN_ERR "Unable to claim IRQ%d for expansion cards\n",
1006
                       IRQ_EXPANSIONCARD);
1007
                ecard_free_all();
1008
        }
1009
}

powered by: WebSVN 2.1.0

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