1 /* $OpenBSD: pci.c,v 1.58 2008/06/13 08:45:50 deraadt 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 #include <sys/malloc.h> 42 43 #include <dev/pci/pcireg.h> 44 #include <dev/pci/pcivar.h> 45 #include <dev/pci/pcidevs.h> 46 47 int pcimatch(struct device *, void *, void *); 48 void pciattach(struct device *, struct device *, void *); 49 int pcidetach(struct device *, int); 50 void pcipower(int, void *); 51 52 #define NMAPREG ((PCI_MAPREG_END - PCI_MAPREG_START) / \ 53 sizeof(pcireg_t)) 54 struct pci_dev { 55 LIST_ENTRY(pci_dev) pd_next; 56 struct device *pd_dev; 57 pcitag_t pd_tag; /* pci register tag */ 58 pcireg_t pd_csr; 59 pcireg_t pd_bhlc; 60 pcireg_t pd_int; 61 pcireg_t pd_map[NMAPREG]; 62 }; 63 64 #ifdef APERTURE 65 extern int allowaperture; 66 #endif 67 68 struct cfattach pci_ca = { 69 sizeof(struct pci_softc), pcimatch, pciattach, pcidetach 70 }; 71 72 struct cfdriver pci_cd = { 73 NULL, "pci", DV_DULL 74 }; 75 76 int pci_ndomains; 77 78 int pciprint(void *, const char *); 79 int pcisubmatch(struct device *, void *, void *); 80 81 #ifdef PCI_MACHDEP_ENUMERATE_BUS 82 #define pci_enumerate_bus PCI_MACHDEP_ENUMERATE_BUS 83 #else 84 int pci_enumerate_bus(struct pci_softc *, 85 int (*)(struct pci_attach_args *), struct pci_attach_args *); 86 #endif 87 88 /* 89 * Important note about PCI-ISA bridges: 90 * 91 * Callbacks are used to configure these devices so that ISA/EISA bridges 92 * can attach their child busses after PCI configuration is done. 93 * 94 * This works because: 95 * (1) there can be at most one ISA/EISA bridge per PCI bus, and 96 * (2) any ISA/EISA bridges must be attached to primary PCI 97 * busses (i.e. bus zero). 98 * 99 * That boils down to: there can only be one of these outstanding 100 * at a time, it is cleared when configuring PCI bus 0 before any 101 * subdevices have been found, and it is run after all subdevices 102 * of PCI bus 0 have been found. 103 * 104 * This is needed because there are some (legacy) PCI devices which 105 * can show up as ISA/EISA devices as well (the prime example of which 106 * are VGA controllers). If you attach ISA from a PCI-ISA/EISA bridge, 107 * and the bridge is seen before the video board is, the board can show 108 * up as an ISA device, and that can (bogusly) complicate the PCI device's 109 * attach code, or make the PCI device not be properly attached at all. 110 * 111 * We use the generic config_defer() facility to achieve this. 112 */ 113 114 int 115 pcimatch(struct device *parent, void *match, void *aux) 116 { 117 struct cfdata *cf = match; 118 struct pcibus_attach_args *pba = aux; 119 120 if (strcmp(pba->pba_busname, cf->cf_driver->cd_name)) 121 return (0); 122 123 /* Check the locators */ 124 if (cf->pcibuscf_bus != PCIBUS_UNK_BUS && 125 cf->pcibuscf_bus != pba->pba_bus) 126 return (0); 127 128 /* sanity */ 129 if (pba->pba_bus < 0 || pba->pba_bus > 255) 130 return (0); 131 132 /* 133 * XXX check other (hardware?) indicators 134 */ 135 136 return (1); 137 } 138 139 void 140 pciattach(struct device *parent, struct device *self, void *aux) 141 { 142 struct pcibus_attach_args *pba = aux; 143 struct pci_softc *sc = (struct pci_softc *)self; 144 145 pci_attach_hook(parent, self, pba); 146 147 printf("\n"); 148 149 LIST_INIT(&sc->sc_devs); 150 sc->sc_powerhook = powerhook_establish(pcipower, sc); 151 152 sc->sc_iot = pba->pba_iot; 153 sc->sc_memt = pba->pba_memt; 154 sc->sc_dmat = pba->pba_dmat; 155 sc->sc_pc = pba->pba_pc; 156 sc->sc_domain = pba->pba_domain; 157 sc->sc_bus = pba->pba_bus; 158 sc->sc_bridgetag = pba->pba_bridgetag; 159 sc->sc_bridgeih = pba->pba_bridgeih; 160 sc->sc_maxndevs = pci_bus_maxdevs(pba->pba_pc, pba->pba_bus); 161 sc->sc_intrswiz = pba->pba_intrswiz; 162 sc->sc_intrtag = pba->pba_intrtag; 163 pci_enumerate_bus(sc, NULL, NULL); 164 } 165 166 int 167 pcidetach(struct device *self, int flags) 168 { 169 return pci_detach_devices((struct pci_softc *)self, flags); 170 } 171 172 /* save and restore the pci config space */ 173 void 174 pcipower(int why, void *arg) 175 { 176 struct pci_softc *sc = (struct pci_softc *)arg; 177 struct pci_dev *pd; 178 pcireg_t reg; 179 int i; 180 181 LIST_FOREACH(pd, &sc->sc_devs, pd_next) { 182 if (why != PWR_RESUME) { 183 for (i = 0; i < NMAPREG; i++) 184 pd->pd_map[i] = pci_conf_read(sc->sc_pc, 185 pd->pd_tag, PCI_MAPREG_START + (i * 4)); 186 pd->pd_csr = pci_conf_read(sc->sc_pc, pd->pd_tag, 187 PCI_COMMAND_STATUS_REG); 188 pd->pd_bhlc = pci_conf_read(sc->sc_pc, pd->pd_tag, 189 PCI_BHLC_REG); 190 pd->pd_int = pci_conf_read(sc->sc_pc, pd->pd_tag, 191 PCI_INTERRUPT_REG); 192 } else { 193 for (i = 0; i < NMAPREG; i++) 194 pci_conf_write(sc->sc_pc, pd->pd_tag, 195 PCI_MAPREG_START + (i * 4), 196 pd->pd_map[i]); 197 reg = pci_conf_read(sc->sc_pc, pd->pd_tag, 198 PCI_COMMAND_STATUS_REG); 199 pci_conf_write(sc->sc_pc, pd->pd_tag, 200 PCI_COMMAND_STATUS_REG, 201 (reg & 0xffff0000) | (pd->pd_csr & 0x0000ffff)); 202 pci_conf_write(sc->sc_pc, pd->pd_tag, PCI_BHLC_REG, 203 pd->pd_bhlc); 204 pci_conf_write(sc->sc_pc, pd->pd_tag, PCI_INTERRUPT_REG, 205 pd->pd_int); 206 } 207 } 208 } 209 210 int 211 pciprint(void *aux, const char *pnp) 212 { 213 struct pci_attach_args *pa = aux; 214 char devinfo[256]; 215 216 if (pnp) { 217 pci_devinfo(pa->pa_id, pa->pa_class, 1, devinfo, 218 sizeof devinfo); 219 printf("%s at %s", devinfo, pnp); 220 } 221 printf(" dev %d function %d", pa->pa_device, pa->pa_function); 222 if (!pnp) { 223 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, 224 sizeof devinfo); 225 printf(" %s", devinfo); 226 } 227 228 return (UNCONF); 229 } 230 231 int 232 pcisubmatch(struct device *parent, void *match, void *aux) 233 { 234 struct cfdata *cf = match; 235 struct pci_attach_args *pa = aux; 236 237 if (cf->pcicf_dev != PCI_UNK_DEV && 238 cf->pcicf_dev != pa->pa_device) 239 return (0); 240 if (cf->pcicf_function != PCI_UNK_FUNCTION && 241 cf->pcicf_function != pa->pa_function) 242 return (0); 243 244 return ((*cf->cf_attach->ca_match)(parent, match, aux)); 245 } 246 247 int 248 pci_probe_device(struct pci_softc *sc, pcitag_t tag, 249 int (*match)(struct pci_attach_args *), struct pci_attach_args *pap) 250 { 251 pci_chipset_tag_t pc = sc->sc_pc; 252 struct pci_attach_args pa; 253 struct pci_dev *pd; 254 struct device *dev; 255 pcireg_t id, csr, class, intr, bhlcr; 256 int ret = 0, pin, bus, device, function; 257 258 pci_decompose_tag(pc, tag, &bus, &device, &function); 259 260 bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG); 261 if (PCI_HDRTYPE_TYPE(bhlcr) > 2) 262 return (0); 263 264 id = pci_conf_read(pc, tag, PCI_ID_REG); 265 csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); 266 class = pci_conf_read(pc, tag, PCI_CLASS_REG); 267 268 /* Invalid vendor ID value? */ 269 if (PCI_VENDOR(id) == PCI_VENDOR_INVALID) 270 return (0); 271 /* XXX Not invalid, but we've done this ~forever. */ 272 if (PCI_VENDOR(id) == 0) 273 return (0); 274 275 pa.pa_iot = sc->sc_iot; 276 pa.pa_memt = sc->sc_memt; 277 pa.pa_dmat = sc->sc_dmat; 278 pa.pa_pc = pc; 279 pa.pa_domain = sc->sc_domain; 280 pa.pa_bus = bus; 281 pa.pa_device = device; 282 pa.pa_function = function; 283 pa.pa_tag = tag; 284 pa.pa_id = id; 285 pa.pa_class = class; 286 pa.pa_bridgetag = sc->sc_bridgetag; 287 pa.pa_bridgeih = sc->sc_bridgeih; 288 289 /* This is a simplification of the NetBSD code. 290 We don't support turning off I/O or memory 291 on broken hardware. <csapuntz@stanford.edu> */ 292 pa.pa_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED; 293 294 #ifdef __i386__ 295 /* 296 * on i386 we really need to know the device tag 297 * and not the pci bridge tag, in intr_map 298 * to be able to program the device and the 299 * pci interrupt router. 300 */ 301 pa.pa_intrtag = tag; 302 pa.pa_intrswiz = 0; 303 #else 304 if (sc->sc_bridgetag == NULL) { 305 pa.pa_intrswiz = 0; 306 pa.pa_intrtag = tag; 307 } else { 308 pa.pa_intrswiz = sc->sc_intrswiz + device; 309 pa.pa_intrtag = sc->sc_intrtag; 310 } 311 #endif 312 313 intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG); 314 315 pin = PCI_INTERRUPT_PIN(intr); 316 pa.pa_rawintrpin = pin; 317 if (pin == PCI_INTERRUPT_PIN_NONE) { 318 /* no interrupt */ 319 pa.pa_intrpin = 0; 320 } else { 321 /* 322 * swizzle it based on the number of busses we're 323 * behind and our device number. 324 */ 325 pa.pa_intrpin = /* XXX */ 326 ((pin + pa.pa_intrswiz - 1) % 4) + 1; 327 } 328 pa.pa_intrline = PCI_INTERRUPT_LINE(intr); 329 330 if (match != NULL) { 331 ret = (*match)(&pa); 332 if (ret != 0 && pap != NULL) 333 *pap = pa; 334 } else { 335 if ((dev = config_found_sm(&sc->sc_dev, &pa, pciprint, 336 pcisubmatch))) { 337 pcireg_t reg; 338 339 /* skip header type != 0 */ 340 reg = pci_conf_read(pc, tag, PCI_BHLC_REG); 341 if (PCI_HDRTYPE_TYPE(reg) != 0) 342 return(0); 343 if (pci_get_capability(pc, tag, 344 PCI_CAP_PWRMGMT, NULL, NULL) == 0) 345 return(0); 346 if (!(pd = malloc(sizeof *pd, M_DEVBUF, 347 M_NOWAIT))) 348 return(0); 349 pd->pd_tag = tag; 350 pd->pd_dev = dev; 351 LIST_INSERT_HEAD(&sc->sc_devs, pd, pd_next); 352 } 353 } 354 355 return (ret); 356 } 357 358 int 359 pci_detach_devices(struct pci_softc *sc, int flags) 360 { 361 struct pci_dev *pd, *next; 362 int ret; 363 364 ret = config_detach_children(&sc->sc_dev, flags); 365 if (ret != 0) 366 return (ret); 367 368 for (pd = LIST_FIRST(&sc->sc_devs); 369 pd != LIST_END(&sc->sc_devs); pd = next) { 370 next = LIST_NEXT(pd, pd_next); 371 free(pd, M_DEVBUF); 372 } 373 LIST_INIT(&sc->sc_devs); 374 375 return (0); 376 } 377 378 int 379 pci_get_capability(pci_chipset_tag_t pc, pcitag_t tag, int capid, 380 int *offset, pcireg_t *value) 381 { 382 pcireg_t reg; 383 unsigned int ofs; 384 385 reg = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); 386 if (!(reg & PCI_STATUS_CAPLIST_SUPPORT)) 387 return (0); 388 389 /* Determine the Capability List Pointer register to start with. */ 390 reg = pci_conf_read(pc, tag, PCI_BHLC_REG); 391 switch (PCI_HDRTYPE_TYPE(reg)) { 392 case 0: /* standard device header */ 393 case 1: /* PCI-PCI bridge header */ 394 ofs = PCI_CAPLISTPTR_REG; 395 break; 396 case 2: /* PCI-CardBus bridge header */ 397 ofs = PCI_CARDBUS_CAPLISTPTR_REG; 398 break; 399 default: 400 return (0); 401 } 402 403 ofs = PCI_CAPLIST_PTR(pci_conf_read(pc, tag, ofs)); 404 while (ofs != 0) { 405 #ifdef DIAGNOSTIC 406 if ((ofs & 3) || (ofs < 0x40)) 407 panic("pci_get_capability"); 408 #endif 409 reg = pci_conf_read(pc, tag, ofs); 410 if (PCI_CAPLIST_CAP(reg) == capid) { 411 if (offset) 412 *offset = ofs; 413 if (value) 414 *value = reg; 415 return (1); 416 } 417 ofs = PCI_CAPLIST_NEXT(reg); 418 } 419 420 return (0); 421 } 422 423 int 424 pci_find_device(struct pci_attach_args *pa, 425 int (*match)(struct pci_attach_args *)) 426 { 427 extern struct cfdriver pci_cd; 428 struct device *pcidev; 429 int i; 430 431 for (i = 0; i < pci_cd.cd_ndevs; i++) { 432 pcidev = pci_cd.cd_devs[i]; 433 if (pcidev != NULL && 434 pci_enumerate_bus((struct pci_softc *)pcidev, 435 match, pa) != 0) 436 return (1); 437 } 438 return (0); 439 } 440 441 int 442 pci_set_powerstate(pci_chipset_tag_t pc, pcitag_t tag, int state) 443 { 444 pcireg_t reg; 445 int offset; 446 447 if (pci_get_capability(pc, tag, PCI_CAP_PWRMGMT, &offset, 0)) { 448 reg = pci_conf_read(pc, tag, offset + PCI_PMCSR); 449 if ((reg & PCI_PMCSR_STATE_MASK) != state) { 450 pci_conf_write(pc, tag, offset + PCI_PMCSR, 451 (reg & ~PCI_PMCSR_STATE_MASK) | state); 452 return (reg & PCI_PMCSR_STATE_MASK); 453 } 454 } 455 return (state); 456 } 457 458 #ifndef PCI_MACHDEP_ENUMERATE_BUS 459 /* 460 * Generic PCI bus enumeration routine. Used unless machine-dependent 461 * code needs to provide something else. 462 */ 463 int 464 pci_enumerate_bus(struct pci_softc *sc, 465 int (*match)(struct pci_attach_args *), struct pci_attach_args *pap) 466 { 467 pci_chipset_tag_t pc = sc->sc_pc; 468 int device, function, nfunctions, ret; 469 const struct pci_quirkdata *qd; 470 pcireg_t id, bhlcr; 471 pcitag_t tag; 472 473 for (device = 0; device < sc->sc_maxndevs; device++) { 474 tag = pci_make_tag(pc, sc->sc_bus, device, 0); 475 476 bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG); 477 if (PCI_HDRTYPE_TYPE(bhlcr) > 2) 478 continue; 479 480 id = pci_conf_read(pc, tag, PCI_ID_REG); 481 482 /* Invalid vendor ID value? */ 483 if (PCI_VENDOR(id) == PCI_VENDOR_INVALID) 484 continue; 485 /* XXX Not invalid, but we've done this ~forever. */ 486 if (PCI_VENDOR(id) == 0) 487 continue; 488 489 qd = pci_lookup_quirkdata(PCI_VENDOR(id), PCI_PRODUCT(id)); 490 491 if (qd != NULL && 492 (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0) 493 nfunctions = 8; 494 else if (qd != NULL && 495 (qd->quirks & PCI_QUIRK_MONOFUNCTION) != 0) 496 nfunctions = 1; 497 else 498 nfunctions = PCI_HDRTYPE_MULTIFN(bhlcr) ? 8 : 1; 499 500 for (function = 0; function < nfunctions; function++) { 501 tag = pci_make_tag(pc, sc->sc_bus, device, function); 502 ret = pci_probe_device(sc, tag, match, pap); 503 if (match != NULL && ret != 0) 504 return (ret); 505 } 506 } 507 508 return (0); 509 } 510 #endif /* PCI_MACHDEP_ENUMERATE_BUS */ 511 512 /* 513 * Vital Product Data (PCI 2.2) 514 */ 515 516 int 517 pci_vpd_read(pci_chipset_tag_t pc, pcitag_t tag, int offset, int count, 518 pcireg_t *data) 519 { 520 uint32_t reg; 521 int ofs, i, j; 522 523 KASSERT(data != NULL); 524 KASSERT((offset + count) < 0x7fff); 525 526 if (pci_get_capability(pc, tag, PCI_CAP_VPD, &ofs, ®) == 0) 527 return (1); 528 529 for (i = 0; i < count; offset += sizeof(*data), i++) { 530 reg &= 0x0000ffff; 531 reg &= ~PCI_VPD_OPFLAG; 532 reg |= PCI_VPD_ADDRESS(offset); 533 pci_conf_write(pc, tag, ofs, reg); 534 535 /* 536 * PCI 2.2 does not specify how long we should poll 537 * for completion nor whether the operation can fail. 538 */ 539 j = 0; 540 do { 541 if (j++ == 20) 542 return (1); 543 delay(4); 544 reg = pci_conf_read(pc, tag, ofs); 545 } while ((reg & PCI_VPD_OPFLAG) == 0); 546 data[i] = pci_conf_read(pc, tag, PCI_VPD_DATAREG(ofs)); 547 } 548 549 return (0); 550 } 551 552 int 553 pci_vpd_write(pci_chipset_tag_t pc, pcitag_t tag, int offset, int count, 554 pcireg_t *data) 555 { 556 pcireg_t reg; 557 int ofs, i, j; 558 559 KASSERT(data != NULL); 560 KASSERT((offset + count) < 0x7fff); 561 562 if (pci_get_capability(pc, tag, PCI_CAP_VPD, &ofs, ®) == 0) 563 return (1); 564 565 for (i = 0; i < count; offset += sizeof(*data), i++) { 566 pci_conf_write(pc, tag, PCI_VPD_DATAREG(ofs), data[i]); 567 568 reg &= 0x0000ffff; 569 reg |= PCI_VPD_OPFLAG; 570 reg |= PCI_VPD_ADDRESS(offset); 571 pci_conf_write(pc, tag, ofs, reg); 572 573 /* 574 * PCI 2.2 does not specify how long we should poll 575 * for completion nor whether the operation can fail. 576 */ 577 j = 0; 578 do { 579 if (j++ == 20) 580 return (1); 581 delay(1); 582 reg = pci_conf_read(pc, tag, ofs); 583 } while (reg & PCI_VPD_OPFLAG); 584 } 585 586 return (0); 587 } 588 589 int 590 pci_matchbyid(struct pci_attach_args *pa, const struct pci_matchid *ids, 591 int nent) 592 { 593 const struct pci_matchid *pm; 594 int i; 595 596 for (i = 0, pm = ids; i < nent; i++, pm++) 597 if (PCI_VENDOR(pa->pa_id) == pm->pm_vid && 598 PCI_PRODUCT(pa->pa_id) == pm->pm_pid) 599 return (1); 600 return (0); 601 } 602 603 #ifdef USER_PCICONF 604 /* 605 * This is the user interface to PCI configuration space. 606 */ 607 608 #include <sys/pciio.h> 609 #include <sys/fcntl.h> 610 611 #ifdef DEBUG 612 #define PCIDEBUG(x) printf x 613 #else 614 #define PCIDEBUG(x) 615 #endif 616 617 618 int pciopen(dev_t dev, int oflags, int devtype, struct proc *p); 619 int pciclose(dev_t dev, int flag, int devtype, struct proc *p); 620 int pciioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p); 621 622 int 623 pciopen(dev_t dev, int oflags, int devtype, struct proc *p) 624 { 625 PCIDEBUG(("pciopen ndevs: %d\n" , pci_cd.cd_ndevs)); 626 627 if (minor(dev) >= pci_ndomains) { 628 return ENXIO; 629 } 630 631 #ifndef APERTURE 632 if ((oflags & FWRITE) && securelevel > 0) { 633 return EPERM; 634 } 635 #else 636 if ((oflags & FWRITE) && securelevel > 0 && allowaperture == 0) { 637 return EPERM; 638 } 639 #endif 640 return (0); 641 } 642 643 int 644 pciclose(dev_t dev, int flag, int devtype, struct proc *p) 645 { 646 PCIDEBUG(("pciclose\n")); 647 return (0); 648 } 649 650 int 651 pciioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 652 { 653 struct pci_io *io; 654 int i, error; 655 pcitag_t tag; 656 struct pci_softc *pci = NULL; 657 pci_chipset_tag_t pc; 658 659 io = (struct pci_io *)data; 660 661 PCIDEBUG(("pciioctl cmd %s", cmd == PCIOCREAD ? "pciocread" 662 : cmd == PCIOCWRITE ? "pciocwrite" : "unknown")); 663 PCIDEBUG((" bus %d dev %d func %d reg %x\n", io->pi_sel.pc_bus, 664 io->pi_sel.pc_dev, io->pi_sel.pc_func, io->pi_reg)); 665 666 for (i = 0; i < pci_cd.cd_ndevs; i++) { 667 pci = pci_cd.cd_devs[i]; 668 if (pci != NULL && pci->sc_domain == minor(dev) && 669 pci->sc_bus == io->pi_sel.pc_bus) 670 break; 671 } 672 if (i >= pci_cd.cd_ndevs) 673 return ENXIO; 674 675 /* Check bounds */ 676 if (pci->sc_bus >= 256 || 677 io->pi_sel.pc_dev >= pci_bus_maxdevs(pci->sc_pc, pci->sc_bus) || 678 io->pi_sel.pc_func >= 8) 679 return EINVAL; 680 681 pc = pci->sc_pc; 682 tag = pci_make_tag(pc, io->pi_sel.pc_bus, io->pi_sel.pc_dev, 683 io->pi_sel.pc_func); 684 685 switch(cmd) { 686 case PCIOCGETCONF: 687 error = ENODEV; 688 break; 689 690 case PCIOCREAD: 691 switch(io->pi_width) { 692 case 4: 693 /* Make sure the register is properly aligned */ 694 if (io->pi_reg & 0x3) 695 return EINVAL; 696 io->pi_data = pci_conf_read(pc, tag, io->pi_reg); 697 error = 0; 698 break; 699 default: 700 error = ENODEV; 701 break; 702 } 703 break; 704 705 case PCIOCWRITE: 706 if (!(flag & FWRITE)) 707 return EPERM; 708 709 switch(io->pi_width) { 710 case 4: 711 /* Make sure the register is properly aligned */ 712 if (io->pi_reg & 0x3) 713 return EINVAL; 714 pci_conf_write(pc, tag, io->pi_reg, io->pi_data); 715 error = 0; 716 break; 717 default: 718 error = ENODEV; 719 break; 720 } 721 break; 722 723 default: 724 error = ENOTTY; 725 break; 726 } 727 728 return (error); 729 } 730 731 #endif 732