Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 | /* * $Id: pci.c,v 1.27 1998/04/24 02:46:47 cort Exp $ * Common pmac/prep/chrp pci routines. -- Cort */ #include <linux/kernel.h> #include <linux/pci.h> #include <linux/delay.h> #include <linux/string.h> #include <linux/init.h> #include <linux/config.h> #include <linux/pci.h> #include <linux/openpic.h> #include <asm/processor.h> #include <asm/io.h> #include <asm/prom.h> #include <asm/pci-bridge.h> #include <asm/irq.h> #if !defined(CONFIG_MACH_SPECIFIC) || defined(CONFIG_PMAC) unsigned long isa_io_base; #endif /* CONFIG_MACH_SPECIFIC || CONFIG_PMAC */ #if !defined(CONFIG_MACH_SPECIFIC) unsigned long isa_mem_base; unsigned long pci_dram_offset; #endif /* CONFIG_MACH_SPECIFIC */ /* * It would be nice if we could create a include/asm/pci.h and have just * function ptrs for all these in there, but that isn't the case. * We have a function, pcibios_*() which calls the function ptr ptr_pcibios_*() * which has been setup by pcibios_init(). This is all to avoid a check * for pmac/prep every time we call one of these. It should also make the move * to a include/asm/pcibios.h easier, we can drop the ptr_ on these functions * and create pci.h * -- Cort */ int (*ptr_pcibios_read_config_byte)(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned char *val); int (*ptr_pcibios_read_config_word)(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned short *val); int (*ptr_pcibios_read_config_dword)(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned int *val); int (*ptr_pcibios_write_config_byte)(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned char val); int (*ptr_pcibios_write_config_word)(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned short val); int (*ptr_pcibios_write_config_dword)(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned int val); extern int pmac_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned char *val); extern int pmac_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned short *val); extern int pmac_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned int *val); extern int pmac_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned char val); extern int pmac_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned short val); extern int pmac_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned int val); extern int chrp_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned char *val); extern int chrp_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned short *val); extern int chrp_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned int *val); extern int chrp_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned char val); extern int chrp_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned short val); extern int chrp_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned int val); extern int prep_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned char *val); extern int prep_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned short *val); extern int prep_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned int *val); extern int prep_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned char val); extern int prep_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned short val); extern int prep_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned int val); extern int mbx_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned char *val); extern int mbx_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned short *val); extern int mbx_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned int *val); extern int mbx_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned char val); extern int mbx_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned short val); extern int mbx_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned int val); int pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned char *val) { return ptr_pcibios_read_config_byte(bus,dev_fn,offset,val); } int pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned short *val) { return ptr_pcibios_read_config_word(bus,dev_fn,offset,val); } int pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned int *val) { return ptr_pcibios_read_config_dword(bus,dev_fn,offset,val); } int pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned char val) { return ptr_pcibios_write_config_byte(bus,dev_fn,offset,val); } int pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned short val) { return ptr_pcibios_write_config_word(bus,dev_fn,offset,val); } int pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned int val) { return ptr_pcibios_write_config_dword(bus,dev_fn,offset,val); } int pcibios_present(void) { return 1; } __initfunc(void pcibios_init(void)) { } __initfunc(void setup_pci_ptrs(void)) { #ifndef CONFIG_MBX switch (_machine) { case _MACH_prep: ptr_pcibios_read_config_byte = prep_pcibios_read_config_byte; ptr_pcibios_read_config_word = prep_pcibios_read_config_word; ptr_pcibios_read_config_dword = prep_pcibios_read_config_dword; ptr_pcibios_write_config_byte = prep_pcibios_write_config_byte; ptr_pcibios_write_config_word = prep_pcibios_write_config_word; ptr_pcibios_write_config_dword = prep_pcibios_write_config_dword; break; case _MACH_Pmac: ptr_pcibios_read_config_byte = pmac_pcibios_read_config_byte; ptr_pcibios_read_config_word = pmac_pcibios_read_config_word; ptr_pcibios_read_config_dword = pmac_pcibios_read_config_dword; ptr_pcibios_write_config_byte = pmac_pcibios_write_config_byte; ptr_pcibios_write_config_word = pmac_pcibios_write_config_word; ptr_pcibios_write_config_dword = pmac_pcibios_write_config_dword; break; case _MACH_chrp: ptr_pcibios_read_config_byte = chrp_pcibios_read_config_byte; ptr_pcibios_read_config_word = chrp_pcibios_read_config_word; ptr_pcibios_read_config_dword = chrp_pcibios_read_config_dword; ptr_pcibios_write_config_byte = chrp_pcibios_write_config_byte; ptr_pcibios_write_config_word = chrp_pcibios_write_config_word; ptr_pcibios_write_config_dword = chrp_pcibios_write_config_dword; break; default: printk("setup_pci_ptrs(): unknown machine type!\n"); } #else /* CONFIG_MBX */ ptr_pcibios_read_config_byte = mbx_pcibios_read_config_byte; ptr_pcibios_read_config_word = mbx_pcibios_read_config_word; ptr_pcibios_read_config_dword = mbx_pcibios_read_config_dword; ptr_pcibios_write_config_byte = mbx_pcibios_write_config_byte; ptr_pcibios_write_config_word = mbx_pcibios_write_config_word; ptr_pcibios_write_config_dword = mbx_pcibios_write_config_dword; #endif /* CONFIG_MBX */ } __initfunc(void pcibios_fixup(void)) { extern route_pci_interrupts(void); struct pci_dev *dev; extern struct bridge_data **bridges; extern unsigned char *Motherboard_map; extern unsigned char *Motherboard_routes; /* * FIXME: This is broken: We should not assign IRQ's to IRQless * devices (look at PCI_INTERRUPT_PIN) and we also should * honor the existence of multi-function devices where * different functions have different interrupt pins. [mj] */ switch (_machine ) { case _MACH_prep: route_pci_interrupts(); for(dev=pci_devices; dev; dev=dev->next) { unsigned char d = PCI_SLOT(dev->devfn); dev->irq = Motherboard_routes[Motherboard_map[d]]; } break; case _MACH_chrp: /* PCI interrupts are controlled by the OpenPIC */ for(dev=pci_devices; dev; dev=dev->next) if (dev->irq) dev->irq = openpic_to_irq(dev->irq); break; case _MACH_Pmac: for(dev=pci_devices; dev; dev=dev->next) { /* * Open Firmware often doesn't initialize the, * PCI_INTERRUPT_LINE config register properly, so we * should find the device node and se if it has an * AAPL,interrupts property. */ struct bridge_data *bp = bridges[dev->bus->number]; struct device_node *node; unsigned int *reg; unsigned char pin; if (pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin) || !pin) continue; /* No interrupt generated -> no fixup */ for (node = bp->node->child; node != 0; node = node->sibling) { reg = (unsigned int *) get_property(node, "reg", 0); if (reg == 0 || ((reg[0] >> 8) & 0xff) != dev->devfn) continue; /* this is the node, see if it has interrupts */ if (node->n_intrs > 0) dev->irq = node->intrs[0].line; break; } } break; } } __initfunc(void pcibios_fixup_bus(struct pci_bus *bus)) { } __initfunc(char *pcibios_setup(char *str)) { return str; } |