1 /* $OpenBSD: pci.c,v 1.33 2003/04/27 11:22:53 ho Exp $ */ 2 /* $NetBSD: pci.c,v 1.31 1997/06/06 23:48:04 thorpej Exp $ */ 3 4 /* 5 * Copyright (c) 1995, 1996 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 #include <dev/pci/pcidevs.h> 45 46 int pcimatch(struct device *, void *, void *); 47 void pciattach(struct device *, struct device *, void *); 48 49 #ifdef USER_PCICONF 50 struct pci_softc { 51 struct device sc_dev; 52 pci_chipset_tag_t sc_pc; 53 int sc_bus; /* PCI configuration space bus # */ 54 }; 55 #endif 56 57 #ifdef APERTURE 58 extern int allowaperture; 59 #endif 60 61 struct cfattach pci_ca = { 62 #ifndef USER_PCICONF 63 sizeof(struct device), pcimatch, pciattach 64 #else 65 sizeof(struct pci_softc), pcimatch, pciattach 66 #endif 67 }; 68 69 struct cfdriver pci_cd = { 70 NULL, "pci", DV_DULL 71 }; 72 73 int pciprint(void *, const char *); 74 int pcisubmatch(struct device *, void *, void *); 75 76 /* 77 * Callback so that ISA/EISA bridges can attach their child busses 78 * after PCI configuration is done. 79 * 80 * This works because: 81 * (1) there can be at most one ISA/EISA bridge per PCI bus, and 82 * (2) any ISA/EISA bridges must be attached to primary PCI 83 * busses (i.e. bus zero). 84 * 85 * That boils down to: there can only be one of these outstanding 86 * at a time, it is cleared when configuring PCI bus 0 before any 87 * subdevices have been found, and it is run after all subdevices 88 * of PCI bus 0 have been found. 89 * 90 * This is needed because there are some (legacy) PCI devices which 91 * can show up as ISA/EISA devices as well (the prime example of which 92 * are VGA controllers). If you attach ISA from a PCI-ISA/EISA bridge, 93 * and the bridge is seen before the video board is, the board can show 94 * up as an ISA device, and that can (bogusly) complicate the PCI device's 95 * attach code, or make the PCI device not be properly attached at all. 96 */ 97 static void (*pci_isa_bridge_callback)(void *); 98 static void *pci_isa_bridge_callback_arg; 99 100 int 101 pcimatch(parent, match, aux) 102 struct device *parent; 103 void *match, *aux; 104 { 105 struct cfdata *cf = match; 106 struct pcibus_attach_args *pba = aux; 107 108 if (strcmp(pba->pba_busname, cf->cf_driver->cd_name)) 109 return (0); 110 111 /* Check the locators */ 112 if (cf->pcibuscf_bus != PCIBUS_UNK_BUS && 113 cf->pcibuscf_bus != pba->pba_bus) 114 return (0); 115 116 /* sanity */ 117 if (pba->pba_bus < 0 || pba->pba_bus > 255) 118 return (0); 119 120 /* 121 * XXX check other (hardware?) indicators 122 */ 123 124 return 1; 125 } 126 127 void 128 pciattach(parent, self, aux) 129 struct device *parent, *self; 130 void *aux; 131 { 132 struct pcibus_attach_args *pba = aux; 133 bus_space_tag_t iot, memt; 134 pci_chipset_tag_t pc; 135 int bus, device, maxndevs, function, nfunctions; 136 #ifdef USER_PCICONF 137 struct pci_softc *sc = (struct pci_softc *)self; 138 #endif 139 #ifdef __PCI_BUS_DEVORDER 140 char devs[32]; 141 int i; 142 #endif 143 #ifdef __PCI_DEV_FUNCORDER 144 char funcs[8]; 145 int j; 146 #endif 147 148 pci_attach_hook(parent, self, pba); 149 printf("\n"); 150 151 iot = pba->pba_iot; 152 memt = pba->pba_memt; 153 pc = pba->pba_pc; 154 bus = pba->pba_bus; 155 maxndevs = pci_bus_maxdevs(pc, bus); 156 157 #ifdef USER_PCICONF 158 sc->sc_pc = pba->pba_pc; 159 sc->sc_bus = bus; 160 #endif 161 162 if (bus == 0) 163 pci_isa_bridge_callback = NULL; 164 165 #ifdef __PCI_BUS_DEVORDER 166 pci_bus_devorder(pc, bus, devs); 167 for (i = 0; (device = devs[i]) < 32 && device >= 0; i++) { 168 #else 169 for (device = 0; device < maxndevs; device++) { 170 #endif 171 pcitag_t tag; 172 pcireg_t id, class, intr; 173 #ifndef __sparc64__ 174 pcireg_t bhlcr; 175 #endif 176 struct pci_attach_args pa; 177 int pin; 178 179 tag = pci_make_tag(pc, bus, device, 0); 180 id = pci_conf_read(pc, tag, PCI_ID_REG); 181 182 #ifdef __sparc64__ 183 pci_dev_funcorder(pc, bus, device, funcs); 184 nfunctions = 8; 185 186 /* Invalid vendor ID value or 0 (see below for zero) 187 * ... of course, if the pci_dev_funcorder found 188 * functions other than zero, we probably want 189 * to attach them. 190 */ 191 if (PCI_VENDOR(id) == PCI_VENDOR_INVALID || PCI_VENDOR(id) == 0) 192 if (funcs[0] < 0) 193 continue; 194 195 for (j = 0; (function = funcs[j]) < nfunctions && 196 function >= 0; j++) { 197 #else 198 199 /* Invalid vendor ID value? */ 200 if (PCI_VENDOR(id) == PCI_VENDOR_INVALID) 201 continue; 202 /* XXX Not invalid, but we've done this ~forever. */ 203 if (PCI_VENDOR(id) == 0) 204 continue; 205 206 bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG); 207 nfunctions = PCI_HDRTYPE_MULTIFN(bhlcr) ? 8 : 1; 208 209 #ifdef __PCI_DEV_FUNCORDER 210 pci_dev_funcorder(pc, bus, device, funcs); 211 for (j = 0; (function = funcs[j]) < nfunctions && 212 function >= 0; j++) { 213 #else 214 for (function = 0; function < nfunctions; function++) { 215 #endif 216 #endif 217 tag = pci_make_tag(pc, bus, device, function); 218 id = pci_conf_read(pc, tag, PCI_ID_REG); 219 220 /* Invalid vendor ID value? */ 221 if (PCI_VENDOR(id) == PCI_VENDOR_INVALID) 222 continue; 223 /* XXX Not invalid, but we've done this ~forever. */ 224 if (PCI_VENDOR(id) == 0) 225 continue; 226 227 class = pci_conf_read(pc, tag, PCI_CLASS_REG); 228 intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG); 229 230 pa.pa_iot = iot; 231 pa.pa_memt = memt; 232 pa.pa_dmat = pba->pba_dmat; 233 pa.pa_pc = pc; 234 pa.pa_device = device; 235 pa.pa_function = function; 236 pa.pa_bus = bus; 237 pa.pa_tag = tag; 238 pa.pa_id = id; 239 pa.pa_class = class; 240 241 /* This is a simplification of the NetBSD code. 242 We don't support turning off I/O or memory 243 on broken hardware. <csapuntz@stanford.edu> */ 244 pa.pa_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED; 245 #ifdef __i386__ 246 /* 247 * on i386 we really need to know the device tag 248 * and not the pci bridge tag, in intr_map 249 * to be able to program the device and the 250 * pci interrupt router. 251 */ 252 pa.pa_intrtag = tag; 253 pa.pa_intrswiz = 0; 254 #else 255 if (bus == 0) { 256 pa.pa_intrswiz = 0; 257 pa.pa_intrtag = tag; 258 } else { 259 pa.pa_intrswiz = pba->pba_intrswiz + device; 260 pa.pa_intrtag = pba->pba_intrtag; 261 } 262 #endif 263 pin = PCI_INTERRUPT_PIN(intr); 264 if (pin == PCI_INTERRUPT_PIN_NONE) { 265 /* no interrupt */ 266 pa.pa_intrpin = 0; 267 } else { 268 /* 269 * swizzle it based on the number of 270 * busses we're behind and our device 271 * number. 272 */ 273 pa.pa_intrpin = /* XXX */ 274 ((pin + pa.pa_intrswiz - 1) % 4) + 1; 275 } 276 pa.pa_intrline = PCI_INTERRUPT_LINE(intr); 277 278 config_found_sm(self, &pa, pciprint, pcisubmatch); 279 } 280 } 281 282 if (bus == 0 && pci_isa_bridge_callback != NULL) 283 (*pci_isa_bridge_callback)(pci_isa_bridge_callback_arg); 284 } 285 286 int 287 pciprint(aux, pnp) 288 void *aux; 289 const char *pnp; 290 { 291 register struct pci_attach_args *pa = aux; 292 char devinfo[256]; 293 294 if (pnp) { 295 pci_devinfo(pa->pa_id, pa->pa_class, 1, devinfo, 296 sizeof devinfo); 297 printf("%s at %s", devinfo, pnp); 298 } 299 printf(" dev %d function %d", pa->pa_device, pa->pa_function); 300 if (!pnp) { 301 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, 302 sizeof devinfo); 303 printf(" %s", devinfo); 304 } 305 306 return (UNCONF); 307 } 308 309 int 310 pcisubmatch(parent, match, aux) 311 struct device *parent; 312 void *match, *aux; 313 { 314 struct cfdata *cf = match; 315 struct pci_attach_args *pa = aux; 316 int success; 317 318 if (cf->pcicf_dev != PCI_UNK_DEV && 319 cf->pcicf_dev != pa->pa_device) 320 return 0; 321 if (cf->pcicf_function != PCI_UNK_FUNCTION && 322 cf->pcicf_function != pa->pa_function) 323 return 0; 324 325 success = (*cf->cf_attach->ca_match)(parent, match, aux); 326 327 /* My Dell BIOS does not enable certain non-critical PCI devices 328 for IO and memory cycles (e.g. network card). This is 329 the generic approach to fixing this problem. Basically, if 330 we support the card, then we enable its IO cycles. 331 */ 332 if (success) { 333 u_int32_t csr = pci_conf_read(pa->pa_pc, pa->pa_tag, 334 PCI_COMMAND_STATUS_REG); 335 336 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, 337 csr | PCI_COMMAND_MASTER_ENABLE | 338 PCI_COMMAND_IO_ENABLE | 339 PCI_COMMAND_MEM_ENABLE); 340 } 341 342 return (success); 343 } 344 345 void 346 set_pci_isa_bridge_callback(fn, arg) 347 void (*fn)(void *); 348 void *arg; 349 { 350 351 if (pci_isa_bridge_callback != NULL) 352 panic("set_pci_isa_bridge_callback"); 353 pci_isa_bridge_callback = fn; 354 pci_isa_bridge_callback_arg = arg; 355 } 356 357 int 358 pci_get_capability(pc, tag, capid, offset, value) 359 pci_chipset_tag_t pc; 360 pcitag_t tag; 361 int capid; 362 int *offset; 363 pcireg_t *value; 364 { 365 pcireg_t reg; 366 unsigned int ofs; 367 368 reg = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); 369 if (!(reg & PCI_STATUS_CAPLIST_SUPPORT)) 370 return (0); 371 372 ofs = PCI_CAPLIST_PTR(pci_conf_read(pc, tag, PCI_CAPLISTPTR_REG)); 373 while (ofs != 0) { 374 #ifdef DIAGNOSTIC 375 if ((ofs & 3) || (ofs < 0x40)) 376 panic("pci_get_capability"); 377 #endif 378 reg = pci_conf_read(pc, tag, ofs); 379 if (PCI_CAPLIST_CAP(reg) == capid) { 380 if (offset) 381 *offset = ofs; 382 if (value) 383 *value = reg; 384 return (1); 385 } 386 ofs = PCI_CAPLIST_NEXT(reg); 387 } 388 389 return (0); 390 } 391 392 int 393 pci_matchbyid(struct pci_attach_args *pa, const struct pci_matchid *ids, 394 int nent) 395 { 396 const struct pci_matchid *pm; 397 int i; 398 399 for (i = 0, pm = ids; i < nent; i++, pm++) 400 if (PCI_VENDOR(pa->pa_id) == pm->pm_vid && 401 PCI_PRODUCT(pa->pa_id) == pm->pm_pid) 402 return (1); 403 return (0); 404 } 405 406 #ifdef USER_PCICONF 407 /* 408 * This is the user interface to PCI configuration space. 409 */ 410 411 #include <sys/pciio.h> 412 #include <sys/fcntl.h> 413 414 #ifdef DEBUG 415 #define PCIDEBUG(x) printf x 416 #else 417 #define PCIDEBUG(x) 418 #endif 419 420 421 int pciopen(dev_t dev, int oflags, int devtype, struct proc *p); 422 int pciclose(dev_t dev, int flag, int devtype, struct proc *p); 423 int pciioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p); 424 425 int 426 pciopen(dev_t dev, int oflags, int devtype, struct proc *p) 427 { 428 PCIDEBUG(("pciopen ndevs: %d\n" , pci_cd.cd_ndevs)); 429 430 #ifndef APERTURE 431 if ((oflags & FWRITE) && securelevel > 0) { 432 return EPERM; 433 } 434 #else 435 if ((oflags & FWRITE) && securelevel > 0 && allowaperture == 0) { 436 return EPERM; 437 } 438 #endif 439 return 0; 440 } 441 442 int 443 pciclose(dev_t dev, int flag, int devtype, struct proc *p) 444 { 445 PCIDEBUG(("pciclose\n")); 446 return 0; 447 } 448 449 int 450 pciioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 451 { 452 struct pci_io *io; 453 int error; 454 pcitag_t tag; 455 struct pci_softc *pci; 456 pci_chipset_tag_t pc; 457 458 io = (struct pci_io *)data; 459 460 PCIDEBUG(("pciioctl cmd %s", cmd == PCIOCREAD ? "pciocread" 461 : cmd == PCIOCWRITE ? "pciocwrite" : "unknown")); 462 PCIDEBUG((" bus %d dev %d func %d reg %x\n", io->pi_sel.pc_bus, 463 io->pi_sel.pc_dev, io->pi_sel.pc_func, io->pi_reg)); 464 465 if (io->pi_sel.pc_bus >= pci_cd.cd_ndevs) { 466 error = ENXIO; 467 goto done; 468 } 469 pci = pci_cd.cd_devs[io->pi_sel.pc_bus]; 470 if (pci != NULL) { 471 pc = pci->sc_pc; 472 } else { 473 error = ENXIO; 474 goto done; 475 } 476 /* Check bounds */ 477 if (pci->sc_bus >= 256 || 478 io->pi_sel.pc_dev >= pci_bus_maxdevs(pc, pci->sc_bus) || 479 io->pi_sel.pc_func >= 8) { 480 error = EINVAL; 481 goto done; 482 } 483 484 tag = pci_make_tag(pc, pci->sc_bus, io->pi_sel.pc_dev, 485 io->pi_sel.pc_func); 486 487 switch(cmd) { 488 case PCIOCGETCONF: 489 error = ENODEV; 490 break; 491 492 case PCIOCREAD: 493 switch(io->pi_width) { 494 case 4: 495 /* Make sure the register is properly aligned */ 496 if (io->pi_reg & 0x3) 497 return EINVAL; 498 io->pi_data = pci_conf_read(pc, tag, io->pi_reg); 499 error = 0; 500 break; 501 default: 502 error = ENODEV; 503 break; 504 } 505 break; 506 507 case PCIOCWRITE: 508 if (!(flag & FWRITE)) 509 return EPERM; 510 511 switch(io->pi_width) { 512 case 4: 513 /* Make sure the register is properly aligned */ 514 if (io->pi_reg & 0x3) 515 return EINVAL; 516 pci_conf_write(pc, tag, io->pi_reg, io->pi_data); 517 error = 0; 518 break; 519 default: 520 error = ENODEV; 521 break; 522 } 523 break; 524 525 default: 526 error = ENOTTY; 527 break; 528 } 529 done: 530 return (error); 531 } 532 533 #endif 534