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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [x86_64/] [kernel/] [pci-irq.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *      Low-Level PCI Support for PC -- Routing of Interrupts
3
 *
4
 *      (c) 1999--2000 Martin Mares <mj@ucw.cz>
5
 */
6
 
7
#include <linux/config.h>
8
#include <linux/types.h>
9
#include <linux/kernel.h>
10
#include <linux/pci.h>
11
#include <linux/init.h>
12
#include <linux/slab.h>
13
#include <linux/interrupt.h>
14
#include <linux/irq.h>
15
 
16
#include <asm/io.h>
17
#include <asm/smp.h>
18
#include <asm/io_apic.h>
19
 
20
#include "pci-x86_64.h"
21
 
22
#define PIRQ_SIGNATURE  (('$' << 0) + ('P' << 8) + ('I' << 16) + ('R' << 24))
23
#define PIRQ_VERSION 0x0100
24
 
25
static struct irq_routing_table *pirq_table;
26
 
27
/*
28
 * Never use: 0, 1, 2 (timer, keyboard, and cascade)
29
 * Avoid using: 13, 14 and 15 (FP error and IDE).
30
 * Penalize: 3, 4, 6, 7, 12 (known ISA uses: serial, floppy, parallel and mouse)
31
 */
32
unsigned int pcibios_irq_mask = 0xfff8;
33
 
34
static int pirq_penalty[16] = {
35
        1000000, 1000000, 1000000, 1000, 1000, 0, 1000, 1000,
36
        0, 0, 0, 0, 1000, 100000, 100000, 100000
37
};
38
 
39
struct irq_router {
40
        char *name;
41
        u16 vendor, device;
42
        int (*get)(struct pci_dev *router, struct pci_dev *dev, int pirq);
43
        int (*set)(struct pci_dev *router, struct pci_dev *dev, int pirq, int new);
44
};
45
 
46
/*
47
 *  Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table.
48
 */
49
 
50
static struct irq_routing_table * __init pirq_find_routing_table(void)
51
{
52
        u8 *addr;
53
        struct irq_routing_table *rt;
54
        int i;
55
        u8 sum;
56
 
57
        for(addr = (u8 *) __va(0xf0000); addr < (u8 *) __va(0x100000); addr += 16) {
58
                rt = (struct irq_routing_table *) addr;
59
                if (rt->signature != PIRQ_SIGNATURE ||
60
                    rt->version != PIRQ_VERSION ||
61
                    rt->size % 16 ||
62
                    rt->size < sizeof(struct irq_routing_table))
63
                        continue;
64
                sum = 0;
65
                for(i=0; i<rt->size; i++)
66
                        sum += addr[i];
67
                if (!sum) {
68
                        DBG("PCI: Interrupt Routing Table found at 0x%p\n", rt);
69
                        return rt;
70
                }
71
        }
72
        return NULL;
73
}
74
 
75
/*
76
 *  If we have a IRQ routing table, use it to search for peer host
77
 *  bridges.  It's a gross hack, but since there are no other known
78
 *  ways how to get a list of buses, we have to go this way.
79
 *
80
 *  [maybe x86-64 architecture should define way to query this info in
81
 more reasonable way?]
82
 */
83
 
84
static void __init pirq_peer_trick(void)
85
{
86
        struct irq_routing_table *rt = pirq_table;
87
        u8 busmap[256];
88
        int i;
89
        struct irq_info *e;
90
 
91
        memset(busmap, 0, sizeof(busmap));
92
        for(i=0; i < (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info); i++) {
93
                e = &rt->slots[i];
94
#ifdef DEBUG
95
                {
96
                        int j;
97
                        DBG("%02x:%02x slot=%02x", e->bus, e->devfn/8, e->slot);
98
                        for(j=0; j<4; j++)
99
                                DBG(" %d:%02x/%04x", j, e->irq[j].link, e->irq[j].bitmap);
100
                        DBG("\n");
101
                }
102
#endif
103
                busmap[e->bus] = 1;
104
        }
105
        for(i=1; i<256; i++)
106
                /*
107
                 *  It might be a secondary bus, but in this case its parent is already
108
                 *  known (ascending bus order) and therefore pci_scan_bus returns immediately.
109
                 */
110
                if (busmap[i] && pci_scan_bus(i, pci_root_bus->ops, NULL))
111
                        printk(KERN_INFO "PCI: Discovered primary peer bus %02x [IRQ]\n", i);
112
        pcibios_last_bus = -1;
113
}
114
 
115
/*
116
 *  Code for querying and setting of IRQ routes on various interrupt routers.
117
 */
118
 
119
void eisa_set_level_irq(unsigned int irq)
120
{
121
        unsigned char mask = 1 << (irq & 7);
122
        unsigned int port = 0x4d0 + (irq >> 3);
123
        unsigned char val = inb(port);
124
 
125
        if (!(val & mask)) {
126
                DBG(" -> edge");
127
                outb(val | mask, port);
128
        }
129
}
130
 
131
/*
132
 * Common IRQ routing practice: nybbles in config space,
133
 * offset by some magic constant.
134
 */
135
static unsigned int read_config_nybble(struct pci_dev *router, unsigned offset, unsigned nr)
136
{
137
        u8 x;
138
        unsigned reg = offset + (nr >> 1);
139
 
140
        pci_read_config_byte(router, reg, &x);
141
        return (nr & 1) ? (x >> 4) : (x & 0xf);
142
}
143
 
144
static void write_config_nybble(struct pci_dev *router, unsigned offset, unsigned nr, unsigned int val)
145
{
146
        u8 x;
147
        unsigned reg = offset + (nr >> 1);
148
 
149
        pci_read_config_byte(router, reg, &x);
150
        x = (nr & 1) ? ((x & 0x0f) | (val << 4)) : ((x & 0xf0) | val);
151
        pci_write_config_byte(router, reg, x);
152
}
153
 
154
/*
155
 * ALI pirq entries are damn ugly, and completely undocumented.
156
 * This has been figured out from pirq tables, and it's not a pretty
157
 * picture.
158
 */
159
static int pirq_ali_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
160
{
161
        static unsigned char irqmap[16] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 };
162
 
163
        return irqmap[read_config_nybble(router, 0x48, pirq-1)];
164
}
165
 
166
static int pirq_ali_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
167
{
168
        static unsigned char irqmap[16] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 };
169
        unsigned int val = irqmap[irq];
170
 
171
        if (val) {
172
                write_config_nybble(router, 0x48, pirq-1, val);
173
                return 1;
174
        }
175
        return 0;
176
}
177
 
178
/*
179
 * The Intel PIIX4 pirq rules are fairly simple: "pirq" is
180
 * just a pointer to the config space.
181
 */
182
static int pirq_piix_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
183
{
184
        u8 x;
185
 
186
        pci_read_config_byte(router, pirq, &x);
187
        return (x < 16) ? x : 0;
188
}
189
 
190
static int pirq_piix_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
191
{
192
        pci_write_config_byte(router, pirq, irq);
193
        return 1;
194
}
195
 
196
/*
197
 * The VIA pirq rules are nibble-based, like ALI,
198
 * but without the ugly irq number munging.
199
 */
200
static int pirq_via_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
201
{
202
        return read_config_nybble(router, 0x55, pirq);
203
}
204
 
205
static int pirq_via_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
206
{
207
        write_config_nybble(router, 0x55, pirq, irq);
208
        return 1;
209
}
210
 
211
/*
212
 * OPTI: high four bits are nibble pointer..
213
 * I wonder what the low bits do?
214
 */
215
static int pirq_opti_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
216
{
217
        return read_config_nybble(router, 0xb8, pirq >> 4);
218
}
219
 
220
static int pirq_opti_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
221
{
222
        write_config_nybble(router, 0xb8, pirq >> 4, irq);
223
        return 1;
224
}
225
 
226
/*
227
 * Cyrix: nibble offset 0x5C
228
 */
229
static int pirq_cyrix_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
230
{
231
        return read_config_nybble(router, 0x5C, pirq-1);
232
}
233
 
234
static int pirq_cyrix_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
235
{
236
        write_config_nybble(router, 0x5C, pirq-1, irq);
237
        return 1;
238
}
239
 
240
/*
241
 *      PIRQ routing for SiS 85C503 router used in several SiS chipsets
242
 *      According to the SiS 5595 datasheet (preliminary V1.0, 12/24/1997)
243
 *      the related registers work as follows:
244
 *
245
 *      general: one byte per re-routable IRQ,
246
 *               bit 7      IRQ mapping enabled (0) or disabled (1)
247
 *               bits [6:4] reserved
248
 *               bits [3:0] IRQ to map to
249
 *                   allowed: 3-7, 9-12, 14-15
250
 *                   reserved: 0, 1, 2, 8, 13
251
 *
252
 *      individual registers in device config space:
253
 *
254
 *      0x41/0x42/0x43/0x44:    PCI INT A/B/C/D - bits as in general case
255
 *
256
 *      0x61:                   IDEIRQ: bits as in general case - but:
257
 *                              bits [6:5] must be written 01
258
 *                              bit 4 channel-select primary (0), secondary (1)
259
 *
260
 *      0x62:                   USBIRQ: bits as in general case - but:
261
 *                              bit 4 OHCI function disabled (0), enabled (1)
262
 *
263
 *      0x6a:                   ACPI/SCI IRQ - bits as in general case
264
 *
265
 *      0x7e:                   Data Acq. Module IRQ - bits as in general case
266
 *
267
 *      Apparently there are systems implementing PCI routing table using both
268
 *      link values 0x01-0x04 and 0x41-0x44 for PCI INTA..D, but register offsets
269
 *      like 0x62 as link values for USBIRQ e.g. So there is no simple
270
 *      "register = offset + pirq" relation.
271
 *      Currently we support PCI INTA..D and USBIRQ and try our best to handle
272
 *      both link mappings.
273
 *      IDE/ACPI/DAQ mapping is currently unsupported (left untouched as set by BIOS).
274
 */
275
 
276
static int pirq_sis_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
277
{
278
        u8 x;
279
        int reg = pirq;
280
 
281
        switch(pirq) {
282
                case 0x01:
283
                case 0x02:
284
                case 0x03:
285
                case 0x04:
286
                        reg += 0x40;
287
                case 0x41:
288
                case 0x42:
289
                case 0x43:
290
                case 0x44:
291
                case 0x62:
292
        pci_read_config_byte(router, reg, &x);
293
                        if (reg != 0x62)
294
                                break;
295
                        if (!(x & 0x40))
296
                                return 0;
297
                        break;
298
                case 0x61:
299
                case 0x6a:
300
                case 0x7e:
301
                        printk(KERN_INFO "SiS pirq: advanced IDE/ACPI/DAQ mapping not yet implemented\n");
302
                        return 0;
303
                default:
304
                        printk(KERN_INFO "SiS router pirq escape (%d)\n", pirq);
305
                        return 0;
306
        }
307
        return (x & 0x80) ? 0 : (x & 0x0f);
308
}
309
 
310
static int pirq_sis_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
311
{
312
        u8 x;
313
        int reg = pirq;
314
 
315
        switch(pirq) {
316
                case 0x01:
317
                case 0x02:
318
                case 0x03:
319
                case 0x04:
320
                        reg += 0x40;
321
                case 0x41:
322
                case 0x42:
323
                case 0x43:
324
                case 0x44:
325
                case 0x62:
326
                        x = (irq&0x0f) ? (irq&0x0f) : 0x80;
327
                        if (reg != 0x62)
328
                                break;
329
                        /* always mark OHCI enabled, as nothing else knows about this */
330
                        x |= 0x40;
331
                        break;
332
                case 0x61:
333
                case 0x6a:
334
                case 0x7e:
335
                        printk(KERN_INFO "advanced SiS pirq mapping not yet implemented\n");
336
                        return 0;
337
                default:
338
                        printk(KERN_INFO "SiS router pirq escape (%d)\n", pirq);
339
                        return 0;
340
        }
341
        pci_write_config_byte(router, reg, x);
342
 
343
        return 1;
344
}
345
 
346
/*
347
 * VLSI: nibble offset 0x74 - educated guess due to routing table and
348
 *       config space of VLSI 82C534 PCI-bridge/router (1004:0102)
349
 *       Tested on HP OmniBook 800 covering PIRQ 1, 2, 4, 8 for onboard
350
 *       devices, PIRQ 3 for non-pci(!) soundchip and (untested) PIRQ 6
351
 *       for the busbridge to the docking station.
352
 */
353
 
354
static int pirq_vlsi_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
355
{
356
        if (pirq > 8) {
357
                printk(KERN_INFO "VLSI router pirq escape (%d)\n", pirq);
358
                return 0;
359
        }
360
        return read_config_nybble(router, 0x74, pirq-1);
361
}
362
 
363
static int pirq_vlsi_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
364
{
365
        if (pirq > 8) {
366
                printk(KERN_INFO "VLSI router pirq escape (%d)\n", pirq);
367
                return 0;
368
        }
369
        write_config_nybble(router, 0x74, pirq-1, irq);
370
        return 1;
371
}
372
 
373
/*
374
 * ServerWorks: PCI interrupts mapped to system IRQ lines through Index
375
 * and Redirect I/O registers (0x0c00 and 0x0c01).  The Index register
376
 * format is (PCIIRQ## | 0x10), e.g.: PCIIRQ10=0x1a.  The Redirect
377
 * register is a straight binary coding of desired PIC IRQ (low nibble).
378
 *
379
 * The 'link' value in the PIRQ table is already in the correct format
380
 * for the Index register.  There are some special index values:
381
 * 0x00 for ACPI (SCI), 0x01 for USB, 0x02 for IDE0, 0x04 for IDE1,
382
 * and 0x03 for SMBus.
383
 */
384
static int pirq_serverworks_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
385
{
386
        outb_p(pirq, 0xc00);
387
        return inb(0xc01) & 0xf;
388
}
389
 
390
static int pirq_serverworks_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
391
{
392
        outb_p(pirq, 0xc00);
393
        outb_p(irq, 0xc01);
394
        return 1;
395
}
396
 
397
/* Support for AMD756 PCI IRQ Routing
398
 * Jhon H. Caicedo <jhcaiced@osso.org.co>
399
 * Jun/21/2001 0.2.0 Release, fixed to use "nybble" functions... (jhcaiced)
400
 * Jun/19/2001 Alpha Release 0.1.0 (jhcaiced)
401
 * The AMD756 pirq rules are nibble-based
402
 * offset 0x56 0-3 PIRQA  4-7  PIRQB
403
 * offset 0x57 0-3 PIRQC  4-7  PIRQD
404
 */
405
static int pirq_amd756_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
406
{
407
        u8 irq;
408
        irq = 0;
409
        if (pirq <= 4)
410
        {
411
                irq = read_config_nybble(router, 0x56, pirq - 1);
412
        }
413
        printk(KERN_INFO "AMD756: dev %04x:%04x, router pirq : %d get irq : %2d\n",
414
                dev->vendor, dev->device, pirq, irq);
415
        return irq;
416
}
417
 
418
static int pirq_amd756_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
419
{
420
        printk(KERN_INFO "AMD756: dev %04x:%04x, router pirq : %d SET irq : %2d\n",
421
                dev->vendor, dev->device, pirq, irq);
422
        if (pirq <= 4)
423
        {
424
                write_config_nybble(router, 0x56, pirq - 1, irq);
425
        }
426
        return 1;
427
}
428
 
429
#ifdef CONFIG_PCI_BIOS
430
 
431
static int pirq_bios_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
432
{
433
        struct pci_dev *bridge;
434
        int pin = pci_get_interrupt_pin(dev, &bridge);
435
        return pcibios_set_irq_routing(bridge, pin, irq);
436
}
437
 
438
static struct irq_router pirq_bios_router =
439
        { "BIOS", 0, 0, NULL, pirq_bios_set };
440
 
441
#endif
442
 
443
static struct irq_router pirq_routers[] = {
444
        { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_0, pirq_piix_get, pirq_piix_set },
445
        { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, pirq_piix_get, pirq_piix_set },
446
        { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, pirq_piix_get, pirq_piix_set },
447
        { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371MX,   pirq_piix_get, pirq_piix_set },
448
        { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_0, pirq_piix_get, pirq_piix_set },
449
        { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, pirq_piix_get, pirq_piix_set },
450
 
451
        { "ALI", PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, pirq_ali_get, pirq_ali_set },
452
 
453
        { "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, pirq_via_get, pirq_via_set },
454
        { "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596, pirq_via_get, pirq_via_set },
455
        { "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, pirq_via_get, pirq_via_set },
456
 
457
        { "OPTI", PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C700, pirq_opti_get, pirq_opti_set },
458
 
459
        { "NatSemi", PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520, pirq_cyrix_get, pirq_cyrix_set },
460
        { "SIS", PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, pirq_sis_get, pirq_sis_set },
461
        { "VLSI 82C534", PCI_VENDOR_ID_VLSI, PCI_DEVICE_ID_VLSI_82C534, pirq_vlsi_get, pirq_vlsi_set },
462
        { "ServerWorks", PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4,
463
          pirq_serverworks_get, pirq_serverworks_set },
464
        { "AMD756 VIPER", PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_740B,
465
                pirq_amd756_get, pirq_amd756_set },
466
        { "AMD766", PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413,
467
                pirq_amd756_get, pirq_amd756_set },
468
        { "AMD768", PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7443,
469
                pirq_amd756_get, pirq_amd756_set },
470
 
471
        { "default", 0, 0, NULL, NULL }
472
};
473
 
474
static struct irq_router *pirq_router;
475
static struct pci_dev *pirq_router_dev;
476
 
477
static void __init pirq_find_router(void)
478
{
479
        struct irq_routing_table *rt = pirq_table;
480
        struct irq_router *r;
481
 
482
#ifdef CONFIG_PCI_BIOS
483
        if (!rt->signature) {
484
                printk(KERN_INFO "PCI: Using BIOS for IRQ routing\n");
485
                pirq_router = &pirq_bios_router;
486
                return;
487
        }
488
#endif
489
 
490
        DBG("PCI: Attempting to find IRQ router for %04x:%04x\n",
491
            rt->rtr_vendor, rt->rtr_device);
492
 
493
        /* fall back to default router if nothing else found */
494
        pirq_router = &pirq_routers[ARRAY_SIZE(pirq_routers) - 1];
495
 
496
        pirq_router_dev = pci_find_slot(rt->rtr_bus, rt->rtr_devfn);
497
        if (!pirq_router_dev) {
498
                DBG("PCI: Interrupt router not found at %02x:%02x\n", rt->rtr_bus, rt->rtr_devfn);
499
                return;
500
        }
501
 
502
        for(r=pirq_routers; r->vendor; r++) {
503
                /* Exact match against router table entry? Use it! */
504
                if (r->vendor == rt->rtr_vendor && r->device == rt->rtr_device) {
505
                        pirq_router = r;
506
                        break;
507
                }
508
                /* Match against router device entry? Use it as a fallback */
509
                if (r->vendor == pirq_router_dev->vendor && r->device == pirq_router_dev->device) {
510
        pirq_router = r;
511
                }
512
        }
513
        printk(KERN_INFO "PCI: Using IRQ router %s [%04x/%04x] at %s\n",
514
                pirq_router->name,
515
                pirq_router_dev->vendor,
516
                pirq_router_dev->device,
517
                pirq_router_dev->slot_name);
518
}
519
 
520
static struct irq_info *pirq_get_info(struct pci_dev *dev)
521
{
522
        struct irq_routing_table *rt = pirq_table;
523
        int entries = (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
524
        struct irq_info *info;
525
 
526
        for (info = rt->slots; entries--; info++)
527
                if (info->bus == dev->bus->number && PCI_SLOT(info->devfn) == PCI_SLOT(dev->devfn))
528
                        return info;
529
        return NULL;
530
}
531
 
532
static void pcibios_test_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
533
{
534
}
535
 
536
static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
537
{
538
        u8 pin;
539
        struct irq_info *info;
540
        int i, pirq, newirq;
541
        int irq = 0;
542
        u32 mask;
543
        struct irq_router *r = pirq_router;
544
        struct pci_dev *dev2;
545
        char *msg = NULL;
546
 
547
        if (!pirq_table)
548
                return 0;
549
 
550
        /* Find IRQ routing entry */
551
        pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
552
        if (!pin) {
553
                DBG(" -> no interrupt pin\n");
554
                return 0;
555
        }
556
        pin = pin - 1;
557
 
558
        DBG("IRQ for %s:%d", dev->slot_name, pin);
559
        info = pirq_get_info(dev);
560
        if (!info) {
561
                DBG(" -> not found in routing table\n");
562
                return 0;
563
        }
564
        pirq = info->irq[pin].link;
565
        mask = info->irq[pin].bitmap;
566
        if (!pirq) {
567
                DBG(" -> not routed\n");
568
                return 0;
569
        }
570
        DBG(" -> PIRQ %02x, mask %04x, excl %04x", pirq, mask, pirq_table->exclusive_irqs);
571
        mask &= pcibios_irq_mask;
572
 
573
        /*
574
         * Find the best IRQ to assign: use the one
575
         * reported by the device if possible.
576
         */
577
        newirq = dev->irq;
578
        if (!newirq && assign) {
579
                for (i = 0; i < 16; i++) {
580
                        if (!(mask & (1 << i)))
581
                                continue;
582
                        if (pirq_penalty[i] < pirq_penalty[newirq] &&
583
                            !request_irq(i, pcibios_test_irq_handler, SA_SHIRQ, "pci-test", dev)) {
584
                                free_irq(i, dev);
585
                                newirq = i;
586
                        }
587
                }
588
        }
589
        DBG(" -> newirq=%d", newirq);
590
 
591
        /* Check if it is hardcoded */
592
        if ((pirq & 0xf0) == 0xf0) {
593
                irq = pirq & 0xf;
594
                DBG(" -> hardcoded IRQ %d\n", irq);
595
                msg = "Hardcoded";
596
        } else if (r->get && (irq = r->get(pirq_router_dev, dev, pirq))) {
597
                DBG(" -> got IRQ %d\n", irq);
598
                msg = "Found";
599
        } else if (newirq && r->set && (dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) {
600
                DBG(" -> assigning IRQ %d", newirq);
601
                if (r->set(pirq_router_dev, dev, pirq, newirq)) {
602
                        eisa_set_level_irq(newirq);
603
                        DBG(" ... OK\n");
604
                        msg = "Assigned";
605
                        irq = newirq;
606
                }
607
        }
608
 
609
        if (!irq) {
610
                DBG(" ... failed\n");
611
                if (newirq && mask == (1 << newirq)) {
612
                        msg = "Guessed";
613
                        irq = newirq;
614
                } else
615
                        return 0;
616
        }
617
        printk(KERN_INFO "PCI: %s IRQ %d for device %s\n", msg, irq, dev->slot_name);
618
 
619
        /* Update IRQ for all devices with the same pirq value */
620
        pci_for_each_dev(dev2) {
621
                pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin);
622
                if (!pin)
623
                        continue;
624
                pin--;
625
                info = pirq_get_info(dev2);
626
                if (!info)
627
                        continue;
628
                if (info->irq[pin].link == pirq) {
629
                        /* We refuse to override the dev->irq information. Give a warning! */
630
                        if (dev2->irq && dev2->irq != irq) {
631
                                printk(KERN_INFO "IRQ routing conflict for %s, have irq %d, want irq %d\n",
632
                                       dev2->slot_name, dev2->irq, irq);
633
                                continue;
634
                        }
635
                        dev2->irq = irq;
636
                        pirq_penalty[irq]++;
637
                        if (dev != dev2)
638
                                printk(KERN_INFO "PCI: Sharing IRQ %d with %s\n", irq, dev2->slot_name);
639
                }
640
        }
641
        return 1;
642
}
643
 
644
void __init pcibios_irq_init(void)
645
{
646
        DBG("PCI: IRQ init\n");
647
        pirq_table = pirq_find_routing_table();
648
#ifdef CONFIG_PCI_BIOS
649
        if (!pirq_table && (pci_probe & PCI_BIOS_IRQ_SCAN))
650
                pirq_table = pcibios_get_irq_routing_table();
651
#endif
652
        if (pirq_table) {
653
                pirq_peer_trick();
654
                pirq_find_router();
655
                if (pirq_table->exclusive_irqs) {
656
                        int i;
657
                        for (i=0; i<16; i++)
658
                                if (!(pirq_table->exclusive_irqs & (1 << i)))
659
                                        pirq_penalty[i] += 100;
660
                }
661
                /* If we're using the I/O APIC, avoid using the PCI IRQ routing table */
662
                if (io_apic_assign_pci_irqs)
663
                        pirq_table = NULL;
664
        }
665
}
666
 
667
void __init pcibios_fixup_irqs(void)
668
{
669
        struct pci_dev *dev;
670
        u8 pin;
671
 
672
        DBG("PCI: IRQ fixup\n");
673
        pci_for_each_dev(dev) {
674
                /*
675
                 * If the BIOS has set an out of range IRQ number, just ignore it.
676
                 * Also keep track of which IRQ's are already in use.
677
                 */
678
                if (dev->irq >= 16) {
679
                        DBG("%s: ignoring bogus IRQ %d\n", dev->slot_name, dev->irq);
680
                        dev->irq = 0;
681
                }
682
                /* If the IRQ is already assigned to a PCI device, ignore its ISA use penalty */
683
                if (pirq_penalty[dev->irq] >= 100 && pirq_penalty[dev->irq] < 100000)
684
                        pirq_penalty[dev->irq] = 0;
685
                pirq_penalty[dev->irq]++;
686
        }
687
 
688
        pci_for_each_dev(dev) {
689
                pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
690
#ifdef CONFIG_X86_IO_APIC
691
                /*
692
                 * Recalculate IRQ numbers if we use the I/O APIC.
693
                 */
694
                if (io_apic_assign_pci_irqs)
695
                {
696
                        int irq;
697
 
698
                        if (pin) {
699
                                pin--;          /* interrupt pins are numbered starting from 1 */
700
                                irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin);
701
        /*
702
         * Busses behind bridges are typically not listed in the MP-table.
703
         * In this case we have to look up the IRQ based on the parent bus,
704
         * parent slot, and pin number. The SMP code detects such bridged
705
         * busses itself so we should get into this branch reliably.
706
         */
707
                                if (irq < 0 && dev->bus->parent) { /* go back to the bridge */
708
                                        struct pci_dev * bridge = dev->bus->self;
709
 
710
                                        pin = (pin + PCI_SLOT(dev->devfn)) % 4;
711
                                        irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number,
712
                                                        PCI_SLOT(bridge->devfn), pin);
713
                                        if (irq >= 0)
714
                                                printk(KERN_WARNING "PCI: using PPB(B%d,I%d,P%d) to get irq %d\n",
715
                                                        bridge->bus->number, PCI_SLOT(bridge->devfn), pin, irq);
716
                                }
717
                                if (irq >= 0) {
718
                                        printk(KERN_INFO "PCI->APIC IRQ transform: (B%d,I%d,P%d) -> %d\n",
719
                                                dev->bus->number, PCI_SLOT(dev->devfn), pin, irq);
720
                                        dev->irq = irq;
721
                                }
722
                        }
723
                }
724
#endif
725
                /*
726
                 * Still no IRQ? Try to lookup one...
727
                 */
728
                if (pin && !dev->irq)
729
                        pcibios_lookup_irq(dev, 0);
730
        }
731
}
732
 
733
void pcibios_penalize_isa_irq(int irq)
734
{
735
        /*
736
         *  If any ISAPnP device reports an IRQ in its list of possible
737
         *  IRQ's, we try to avoid assigning it to PCI devices.
738
         */
739
        pirq_penalty[irq] += 100;
740
}
741
 
742
void pcibios_enable_irq(struct pci_dev *dev)
743
{
744
                u8 pin;
745
        extern int interrupt_line_quirk;
746
 
747
                pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
748
        if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) {
749
                        char *msg;
750
                /* With IDE legacy devices the IRQ lookup failure is not a problem.. */
751
                if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE && !(dev->class & 0x5))
752
                        return;
753
 
754
                        if (io_apic_assign_pci_irqs)
755
                                msg = " Probably buggy MP table.";
756
                        else if (pci_probe & PCI_BIOS_IRQ_SCAN)
757
                                msg = "";
758
                        else
759
                                msg = " Please try using pci=biosirq.";
760
                        printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n",
761
                               'A' + pin - 1, dev->slot_name, msg);
762
        }
763
        /* VIA bridges use interrupt line for apic/pci steering across
764
           the V-Link */
765
        else if (interrupt_line_quirk)
766
                pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
767
}

powered by: WebSVN 2.1.0

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