1 /* $NetBSD: pci.c,v 1.27 1997/04/10 23:12:22 cgd Exp $ */ 2 3 /* 4 * Copyright (c) 1995, 1996, 1997 5 * Christopher G. Demetriou. All rights reserved. 6 * Copyright (c) 1994 Charles Hannum. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by Charles Hannum. 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* 35 * PCI bus autoconfiguration. 36 */ 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/device.h> 41 42 #include <dev/pci/pcireg.h> 43 #include <dev/pci/pcivar.h> 44 45 #ifdef __BROKEN_INDIRECT_CONFIG 46 int pcimatch __P((struct device *, void *, void *)); 47 #else 48 int pcimatch __P((struct device *, struct cfdata *, void *)); 49 #endif 50 void pciattach __P((struct device *, struct device *, void *)); 51 52 struct cfattach pci_ca = { 53 sizeof(struct device), pcimatch, pciattach 54 }; 55 56 struct cfdriver pci_cd = { 57 NULL, "pci", DV_DULL 58 }; 59 60 int pciprint __P((void *, const char *)); 61 #ifdef __BROKEN_INDIRECT_CONFIG 62 int pcisubmatch __P((struct device *, void *, void *)); 63 #else 64 int pcisubmatch __P((struct device *, struct cfdata *, void *)); 65 #endif 66 67 /* 68 * Callback so that ISA/EISA bridges can attach their child busses 69 * after PCI configuration is done. 70 * 71 * This works because: 72 * (1) there can be at most one ISA/EISA bridge per PCI bus, and 73 * (2) any ISA/EISA bridges must be attached to primary PCI 74 * busses (i.e. bus zero). 75 * 76 * That boils down to: there can only be one of these outstanding 77 * at a time, it is cleared when configuring PCI bus 0 before any 78 * subdevices have been found, and it is run after all subdevices 79 * of PCI bus 0 have been found. 80 * 81 * This is needed because there are some (legacy) PCI devices which 82 * can show up as ISA/EISA devices as well (the prime example of which 83 * are VGA controllers). If you attach ISA from a PCI-ISA/EISA bridge, 84 * and the bridge is seen before the video board is, the board can show 85 * up as an ISA device, and that can (bogusly) complicate the PCI device's 86 * attach code, or make the PCI device not be properly attached at all. 87 */ 88 static void (*pci_isa_bridge_callback) __P((void *)); 89 static void *pci_isa_bridge_callback_arg; 90 91 int 92 #ifdef __BROKEN_INDIRECT_CONFIG 93 pcimatch(parent, match, aux) 94 #else 95 pcimatch(parent, cf, aux) 96 #endif 97 struct device *parent; 98 #ifdef __BROKEN_INDIRECT_CONFIG 99 void *match; 100 #else 101 struct cfdata *cf; 102 #endif 103 void *aux; 104 { 105 #ifdef __BROKEN_INDIRECT_CONFIG 106 struct cfdata *cf = match; 107 #endif 108 struct pcibus_attach_args *pba = aux; 109 110 if (strcmp(pba->pba_busname, cf->cf_driver->cd_name)) 111 return (0); 112 113 /* Check the locators */ 114 if (cf->pcibuscf_bus != PCIBUS_UNK_BUS && 115 cf->pcibuscf_bus != pba->pba_bus) 116 return (0); 117 118 /* sanity */ 119 if (pba->pba_bus < 0 || pba->pba_bus > 255) 120 return (0); 121 122 /* 123 * XXX check other (hardware?) indicators 124 */ 125 126 return 1; 127 } 128 129 void 130 pciattach(parent, self, aux) 131 struct device *parent, *self; 132 void *aux; 133 { 134 struct pcibus_attach_args *pba = aux; 135 bus_space_tag_t iot, memt; 136 pci_chipset_tag_t pc; 137 int bus, device, maxndevs, function, nfunctions; 138 139 pci_attach_hook(parent, self, pba); 140 printf("\n"); 141 142 iot = pba->pba_iot; 143 memt = pba->pba_memt; 144 pc = pba->pba_pc; 145 bus = pba->pba_bus; 146 maxndevs = pci_bus_maxdevs(pc, bus); 147 148 if (bus == 0) 149 pci_isa_bridge_callback = NULL; 150 151 for (device = 0; device < maxndevs; device++) { 152 pcitag_t tag; 153 pcireg_t id, class, intr, bhlcr, csr; 154 struct pci_attach_args pa; 155 int pin; 156 157 tag = pci_make_tag(pc, bus, device, 0); 158 id = pci_conf_read(pc, tag, PCI_ID_REG); 159 if (id == 0 || id == 0xffffffff) 160 continue; 161 162 bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG); 163 nfunctions = PCI_HDRTYPE_MULTIFN(bhlcr) ? 8 : 1; 164 165 for (function = 0; function < nfunctions; function++) { 166 tag = pci_make_tag(pc, bus, device, function); 167 id = pci_conf_read(pc, tag, PCI_ID_REG); 168 if (id == 0 || id == 0xffffffff) 169 continue; 170 csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); 171 class = pci_conf_read(pc, tag, PCI_CLASS_REG); 172 intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG); 173 174 pa.pa_iot = iot; 175 pa.pa_memt = memt; 176 pa.pa_pc = pc; 177 pa.pa_device = device; 178 pa.pa_function = function; 179 pa.pa_tag = tag; 180 pa.pa_id = id; 181 pa.pa_class = class; 182 183 /* set up memory and I/O enable flags as appropriate */ 184 pa.pa_flags = 0; 185 if ((pba->pba_flags & PCI_FLAGS_IO_ENABLED) && 186 (csr & PCI_COMMAND_IO_ENABLE)) 187 pa.pa_flags |= PCI_FLAGS_IO_ENABLED; 188 if ((pba->pba_flags & PCI_FLAGS_MEM_ENABLED) && 189 (csr & PCI_COMMAND_MEM_ENABLE)) 190 pa.pa_flags |= PCI_FLAGS_MEM_ENABLED; 191 192 if (bus == 0) { 193 pa.pa_intrswiz = 0; 194 pa.pa_intrtag = tag; 195 } else { 196 pa.pa_intrswiz = pba->pba_intrswiz + device; 197 pa.pa_intrtag = pba->pba_intrtag; 198 } 199 pin = PCI_INTERRUPT_PIN(intr); 200 if (pin == PCI_INTERRUPT_PIN_NONE) { 201 /* no interrupt */ 202 pa.pa_intrpin = 0; 203 } else { 204 /* 205 * swizzle it based on the number of 206 * busses we're behind and our device 207 * number. 208 */ 209 pa.pa_intrpin = /* XXX */ 210 ((pin + pa.pa_intrswiz - 1) % 4) + 1; 211 } 212 pa.pa_intrline = PCI_INTERRUPT_LINE(intr); 213 214 config_found_sm(self, &pa, pciprint, pcisubmatch); 215 } 216 } 217 218 if (bus == 0 && pci_isa_bridge_callback != NULL) 219 (*pci_isa_bridge_callback)(pci_isa_bridge_callback_arg); 220 } 221 222 int 223 pciprint(aux, pnp) 224 void *aux; 225 const char *pnp; 226 { 227 register struct pci_attach_args *pa = aux; 228 char devinfo[256]; 229 230 if (pnp) { 231 pci_devinfo(pa->pa_id, pa->pa_class, 1, devinfo); 232 printf("%s at %s", devinfo, pnp); 233 } 234 printf(" dev %d function %d", pa->pa_device, pa->pa_function); 235 #if 0 236 printf(" (%si/o, %smem)", 237 pa->pa_flags & PCI_FLAGS_IO_ENABLED ? "" : "no ", 238 pa->pa_flags & PCI_FLAGS_MEM_ENABLED ? "" : "no "); 239 #endif 240 return (UNCONF); 241 } 242 243 int 244 #ifdef __BROKEN_INDIRECT_CONFIG 245 pcisubmatch(parent, match, aux) 246 #else 247 pcisubmatch(parent, cf, aux) 248 #endif 249 struct device *parent; 250 #ifdef __BROKEN_INDIRECT_CONFIG 251 void *match; 252 #else 253 struct cfdata *cf; 254 #endif 255 void *aux; 256 { 257 #ifdef __BROKEN_INDIRECT_CONFIG 258 struct cfdata *cf = match; 259 #endif 260 struct pci_attach_args *pa = aux; 261 262 if (cf->pcicf_dev != PCI_UNK_DEV && 263 cf->pcicf_dev != pa->pa_device) 264 return 0; 265 if (cf->pcicf_function != PCI_UNK_FUNCTION && 266 cf->pcicf_function != pa->pa_function) 267 return 0; 268 return ((*cf->cf_attach->ca_match)(parent, cf, aux)); 269 } 270 271 int 272 pci_io_find(pc, pcitag, reg, iobasep, iosizep) 273 pci_chipset_tag_t pc; 274 pcitag_t pcitag; 275 int reg; 276 bus_addr_t *iobasep; 277 bus_size_t *iosizep; 278 { 279 pcireg_t addrdata, sizedata; 280 int s; 281 282 if (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3)) 283 panic("pci_io_find: bad request"); 284 285 /* XXX? 286 * Section 6.2.5.1, `Address Maps', tells us that: 287 * 288 * 1) The builtin software should have already mapped the device in a 289 * reasonable way. 290 * 291 * 2) A device which wants 2^n bytes of memory will hardwire the bottom 292 * n bits of the address to 0. As recommended, we write all 1s and see 293 * what we get back. 294 */ 295 addrdata = pci_conf_read(pc, pcitag, reg); 296 297 s = splhigh(); 298 pci_conf_write(pc, pcitag, reg, 0xffffffff); 299 sizedata = pci_conf_read(pc, pcitag, reg); 300 pci_conf_write(pc, pcitag, reg, addrdata); 301 splx(s); 302 303 if (PCI_MAPREG_TYPE(addrdata) != PCI_MAPREG_TYPE_IO) 304 panic("pci_io_find: not an I/O region"); 305 306 if (iobasep != NULL) 307 *iobasep = PCI_MAPREG_IO_ADDR(addrdata); 308 if (iosizep != NULL) 309 *iosizep = PCI_MAPREG_IO_SIZE(sizedata); 310 311 return (0); 312 } 313 314 int 315 pci_mem_find(pc, pcitag, reg, membasep, memsizep, cacheablep) 316 pci_chipset_tag_t pc; 317 pcitag_t pcitag; 318 int reg; 319 bus_addr_t *membasep; 320 bus_size_t *memsizep; 321 int *cacheablep; 322 { 323 pcireg_t addrdata, sizedata; 324 int s; 325 326 if (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3)) 327 panic("pci_find_mem: bad request"); 328 329 /* 330 * Section 6.2.5.1, `Address Maps', tells us that: 331 * 332 * 1) The builtin software should have already mapped the device in a 333 * reasonable way. 334 * 335 * 2) A device which wants 2^n bytes of memory will hardwire the bottom 336 * n bits of the address to 0. As recommended, we write all 1s and see 337 * what we get back. 338 */ 339 addrdata = pci_conf_read(pc, pcitag, reg); 340 341 s = splhigh(); 342 pci_conf_write(pc, pcitag, reg, 0xffffffff); 343 sizedata = pci_conf_read(pc, pcitag, reg); 344 pci_conf_write(pc, pcitag, reg, addrdata); 345 splx(s); 346 347 if (PCI_MAPREG_TYPE(addrdata) == PCI_MAPREG_TYPE_IO) 348 panic("pci_find_mem: I/O region"); 349 350 switch (PCI_MAPREG_MEM_TYPE(addrdata)) { 351 case PCI_MAPREG_MEM_TYPE_32BIT: 352 case PCI_MAPREG_MEM_TYPE_32BIT_1M: 353 break; 354 case PCI_MAPREG_MEM_TYPE_64BIT: 355 /* XXX */ printf("pci_find_mem: 64-bit region\n"); 356 /* XXX */ return (1); 357 default: 358 printf("pci_find_mem: reserved region type\n"); 359 return (1); 360 } 361 362 if (membasep != NULL) 363 *membasep = PCI_MAPREG_MEM_ADDR(addrdata); /* PCI addr */ 364 if (memsizep != NULL) 365 *memsizep = PCI_MAPREG_MEM_SIZE(sizedata); 366 if (cacheablep != NULL) 367 *cacheablep = PCI_MAPREG_MEM_CACHEABLE(addrdata); 368 369 return 0; 370 } 371 372 void 373 set_pci_isa_bridge_callback(fn, arg) 374 void (*fn) __P((void *)); 375 void *arg; 376 { 377 378 if (pci_isa_bridge_callback != NULL) 379 panic("set_pci_isa_bridge_callback"); 380 pci_isa_bridge_callback = fn; 381 pci_isa_bridge_callback_arg = arg; 382 } 383