pci-irq.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:22k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

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