1 #include <linux/pci.h> 2 #include <linux/interrupt.h> 3 #include <linux/timer.h> 4 #include <linux/kernel.h> 5 6 static int __init 7 early_read_config_word(struct pci_channel *hose, 8 int top_bus, int bus, int devfn, int offset, u16 *value) 9 { 10 struct pci_dev fake_dev; 11 struct pci_bus fake_bus; 12 13 fake_dev.bus = &fake_bus; 14 fake_dev.sysdata = hose; 15 fake_dev.devfn = devfn; 16 fake_bus.number = bus; 17 fake_bus.sysdata = hose; 18 fake_bus.ops = hose->pci_ops; 19 20 if (bus != top_bus) 21 /* Fake a parent bus structure. */ 22 fake_bus.parent = &fake_bus; 23 else 24 fake_bus.parent = NULL; 25 26 return pci_read_config_word(&fake_dev, offset, value); 27 } 28 29 int __init pci_is_66mhz_capable(struct pci_channel *hose, 30 int top_bus, int current_bus) 31 { 32 u32 pci_devfn; 33 unsigned short vid; 34 int cap66 = -1; 35 u16 stat; 36 37 printk(KERN_INFO "PCI: Checking 66MHz capabilities...\n"); 38 39 for (pci_devfn = 0; pci_devfn < 0xff; pci_devfn++) { 40 if (PCI_FUNC(pci_devfn)) 41 continue; 42 if (early_read_config_word(hose, top_bus, current_bus, 43 pci_devfn, PCI_VENDOR_ID, &vid) != 44 PCIBIOS_SUCCESSFUL) 45 continue; 46 if (vid == 0xffff) 47 continue; 48 49 /* check 66MHz capability */ 50 if (cap66 < 0) 51 cap66 = 1; 52 if (cap66) { 53 early_read_config_word(hose, top_bus, current_bus, 54 pci_devfn, PCI_STATUS, &stat); 55 if (!(stat & PCI_STATUS_66MHZ)) { 56 printk(KERN_DEBUG 57 "PCI: %02x:%02x not 66MHz capable.\n", 58 current_bus, pci_devfn); 59 cap66 = 0; 60 break; 61 } 62 } 63 } 64 65 return cap66 > 0; 66 } 67 68 static void pcibios_enable_err(unsigned long __data) 69 { 70 struct pci_channel *hose = (struct pci_channel *)__data; 71 72 del_timer(&hose->err_timer); 73 printk(KERN_DEBUG "PCI: re-enabling error IRQ.\n"); 74 enable_irq(hose->err_irq); 75 } 76 77 static void pcibios_enable_serr(unsigned long __data) 78 { 79 struct pci_channel *hose = (struct pci_channel *)__data; 80 81 del_timer(&hose->serr_timer); 82 printk(KERN_DEBUG "PCI: re-enabling system error IRQ.\n"); 83 enable_irq(hose->serr_irq); 84 } 85 86 void pcibios_enable_timers(struct pci_channel *hose) 87 { 88 if (hose->err_irq) { 89 init_timer(&hose->err_timer); 90 hose->err_timer.data = (unsigned long)hose; 91 hose->err_timer.function = pcibios_enable_err; 92 } 93 94 if (hose->serr_irq) { 95 init_timer(&hose->serr_timer); 96 hose->serr_timer.data = (unsigned long)hose; 97 hose->serr_timer.function = pcibios_enable_serr; 98 } 99 } 100 101 /* 102 * A simple handler for the regular PCI status errors, called from IRQ 103 * context. 104 */ 105 unsigned int pcibios_handle_status_errors(unsigned long addr, 106 unsigned int status, 107 struct pci_channel *hose) 108 { 109 unsigned int cmd = 0; 110 111 if (status & PCI_STATUS_REC_MASTER_ABORT) { 112 printk(KERN_DEBUG "PCI: master abort, pc=0x%08lx\n", addr); 113 cmd |= PCI_STATUS_REC_MASTER_ABORT; 114 } 115 116 if (status & PCI_STATUS_REC_TARGET_ABORT) { 117 printk(KERN_DEBUG "PCI: target abort: "); 118 pcibios_report_status(PCI_STATUS_REC_TARGET_ABORT | 119 PCI_STATUS_SIG_TARGET_ABORT | 120 PCI_STATUS_REC_MASTER_ABORT, 1); 121 printk("\n"); 122 123 cmd |= PCI_STATUS_REC_TARGET_ABORT; 124 } 125 126 if (status & (PCI_STATUS_PARITY | PCI_STATUS_DETECTED_PARITY)) { 127 printk(KERN_DEBUG "PCI: parity error detected: "); 128 pcibios_report_status(PCI_STATUS_PARITY | 129 PCI_STATUS_DETECTED_PARITY, 1); 130 printk("\n"); 131 132 cmd |= PCI_STATUS_PARITY | PCI_STATUS_DETECTED_PARITY; 133 134 /* Now back off of the IRQ for awhile */ 135 if (hose->err_irq) { 136 disable_irq(hose->err_irq); 137 hose->err_timer.expires = jiffies + HZ; 138 add_timer(&hose->err_timer); 139 } 140 } 141 142 return cmd; 143 } 144