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