1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2006 Marcel Moolenaar 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 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 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/kernel.h> 35 #include <sys/bus.h> 36 #include <sys/conf.h> 37 #include <sys/malloc.h> 38 #include <sys/mutex.h> 39 #include <sys/sysctl.h> 40 41 #include <machine/bus.h> 42 #include <machine/resource.h> 43 #include <sys/rman.h> 44 45 #include <dev/pci/pcireg.h> 46 #include <dev/pci/pcivar.h> 47 48 #include <dev/puc/puc_bus.h> 49 #include <dev/puc/puc_cfg.h> 50 #include <dev/puc/puc_bfe.h> 51 52 #define PUC_ISRCCNT 5 53 54 struct puc_port { 55 struct puc_bar *p_bar; 56 struct resource *p_rres; 57 struct resource *p_ires; 58 device_t p_dev; 59 int p_nr; 60 int p_type; 61 int p_rclk; 62 63 int p_hasintr:1; 64 65 serdev_intr_t *p_ihsrc[PUC_ISRCCNT]; 66 void *p_iharg; 67 68 int p_ipend; 69 }; 70 71 devclass_t puc_devclass; 72 const char puc_driver_name[] = "puc"; 73 74 static MALLOC_DEFINE(M_PUC, "PUC", "PUC driver"); 75 76 SYSCTL_NODE(_hw, OID_AUTO, puc, CTLFLAG_RD, 0, "puc(9) driver configuration"); 77 78 struct puc_bar * 79 puc_get_bar(struct puc_softc *sc, int rid) 80 { 81 struct puc_bar *bar; 82 struct rman *rm; 83 rman_res_t end, start; 84 int error, i; 85 86 /* Find the BAR entry with the given RID. */ 87 i = 0; 88 while (i < PUC_PCI_BARS && sc->sc_bar[i].b_rid != rid) 89 i++; 90 if (i < PUC_PCI_BARS) 91 return (&sc->sc_bar[i]); 92 93 /* Not found. If we're looking for an unused entry, return NULL. */ 94 if (rid == -1) 95 return (NULL); 96 97 /* Get an unused entry for us to fill. */ 98 bar = puc_get_bar(sc, -1); 99 if (bar == NULL) 100 return (NULL); 101 bar->b_rid = rid; 102 bar->b_type = SYS_RES_IOPORT; 103 bar->b_res = bus_alloc_resource_any(sc->sc_dev, bar->b_type, 104 &bar->b_rid, RF_ACTIVE); 105 if (bar->b_res == NULL) { 106 bar->b_rid = rid; 107 bar->b_type = SYS_RES_MEMORY; 108 bar->b_res = bus_alloc_resource_any(sc->sc_dev, bar->b_type, 109 &bar->b_rid, RF_ACTIVE); 110 if (bar->b_res == NULL) { 111 bar->b_rid = -1; 112 return (NULL); 113 } 114 } 115 116 /* Update our managed space. */ 117 rm = (bar->b_type == SYS_RES_IOPORT) ? &sc->sc_ioport : &sc->sc_iomem; 118 start = rman_get_start(bar->b_res); 119 end = rman_get_end(bar->b_res); 120 error = rman_manage_region(rm, start, end); 121 if (error) { 122 bus_release_resource(sc->sc_dev, bar->b_type, bar->b_rid, 123 bar->b_res); 124 bar->b_res = NULL; 125 bar->b_rid = -1; 126 bar = NULL; 127 } 128 129 return (bar); 130 } 131 132 static int 133 puc_intr(void *arg) 134 { 135 struct puc_port *port; 136 struct puc_softc *sc = arg; 137 u_long ds, dev, devs; 138 int i, idx, ipend, isrc, nints; 139 uint8_t ilr; 140 141 nints = 0; 142 while (1) { 143 /* 144 * Obtain the set of devices with pending interrupts. 145 */ 146 devs = sc->sc_serdevs; 147 if (sc->sc_ilr == PUC_ILR_DIGI) { 148 idx = 0; 149 while (devs & (0xfful << idx)) { 150 ilr = ~bus_read_1(sc->sc_port[idx].p_rres, 7); 151 devs &= ~0ul ^ ((u_long)ilr << idx); 152 idx += 8; 153 } 154 } else if (sc->sc_ilr == PUC_ILR_QUATECH) { 155 /* 156 * Don't trust the value if it's the same as the option 157 * register. It may mean that the ILR is not active and 158 * we're reading the option register instead. This may 159 * lead to false positives on 8-port boards. 160 */ 161 ilr = bus_read_1(sc->sc_port[0].p_rres, 7); 162 if (ilr != (sc->sc_cfg_data & 0xff)) 163 devs &= (u_long)ilr; 164 } 165 if (devs == 0UL) 166 break; 167 168 /* 169 * Obtain the set of interrupt sources from those devices 170 * that have pending interrupts. 171 */ 172 ipend = 0; 173 idx = 0, dev = 1UL; 174 ds = devs; 175 while (ds != 0UL) { 176 while ((ds & dev) == 0UL) 177 idx++, dev <<= 1; 178 ds &= ~dev; 179 port = &sc->sc_port[idx]; 180 port->p_ipend = SERDEV_IPEND(port->p_dev); 181 ipend |= port->p_ipend; 182 } 183 if (ipend == 0) 184 break; 185 186 i = 0, isrc = SER_INT_OVERRUN; 187 while (ipend) { 188 while (i < PUC_ISRCCNT && !(ipend & isrc)) 189 i++, isrc <<= 1; 190 KASSERT(i < PUC_ISRCCNT, ("%s", __func__)); 191 ipend &= ~isrc; 192 idx = 0, dev = 1UL; 193 ds = devs; 194 while (ds != 0UL) { 195 while ((ds & dev) == 0UL) 196 idx++, dev <<= 1; 197 ds &= ~dev; 198 port = &sc->sc_port[idx]; 199 if (!(port->p_ipend & isrc)) 200 continue; 201 if (port->p_ihsrc[i] != NULL) 202 (*port->p_ihsrc[i])(port->p_iharg); 203 nints++; 204 } 205 } 206 } 207 208 return ((nints > 0) ? FILTER_HANDLED : FILTER_STRAY); 209 } 210 211 int 212 puc_bfe_attach(device_t dev) 213 { 214 char buffer[64]; 215 struct puc_bar *bar; 216 struct puc_port *port; 217 struct puc_softc *sc; 218 struct rman *rm; 219 intptr_t res; 220 bus_addr_t ofs, start; 221 bus_size_t size; 222 bus_space_handle_t bsh; 223 bus_space_tag_t bst; 224 int error, idx; 225 226 sc = device_get_softc(dev); 227 228 for (idx = 0; idx < PUC_PCI_BARS; idx++) 229 sc->sc_bar[idx].b_rid = -1; 230 231 do { 232 sc->sc_ioport.rm_type = RMAN_ARRAY; 233 error = rman_init(&sc->sc_ioport); 234 if (!error) { 235 sc->sc_iomem.rm_type = RMAN_ARRAY; 236 error = rman_init(&sc->sc_iomem); 237 if (!error) { 238 sc->sc_irq.rm_type = RMAN_ARRAY; 239 error = rman_init(&sc->sc_irq); 240 if (!error) 241 break; 242 rman_fini(&sc->sc_iomem); 243 } 244 rman_fini(&sc->sc_ioport); 245 } 246 return (error); 247 } while (0); 248 249 snprintf(buffer, sizeof(buffer), "%s I/O port mapping", 250 device_get_nameunit(dev)); 251 sc->sc_ioport.rm_descr = strdup(buffer, M_PUC); 252 snprintf(buffer, sizeof(buffer), "%s I/O memory mapping", 253 device_get_nameunit(dev)); 254 sc->sc_iomem.rm_descr = strdup(buffer, M_PUC); 255 snprintf(buffer, sizeof(buffer), "%s port numbers", 256 device_get_nameunit(dev)); 257 sc->sc_irq.rm_descr = strdup(buffer, M_PUC); 258 259 error = puc_config(sc, PUC_CFG_GET_NPORTS, 0, &res); 260 KASSERT(error == 0, ("%s %d", __func__, __LINE__)); 261 sc->sc_nports = (int)res; 262 sc->sc_port = malloc(sc->sc_nports * sizeof(struct puc_port), 263 M_PUC, M_WAITOK|M_ZERO); 264 265 error = rman_manage_region(&sc->sc_irq, 1, sc->sc_nports); 266 if (error) 267 goto fail; 268 269 error = puc_config(sc, PUC_CFG_SETUP, 0, &res); 270 if (error) 271 goto fail; 272 273 for (idx = 0; idx < sc->sc_nports; idx++) { 274 port = &sc->sc_port[idx]; 275 port->p_nr = idx + 1; 276 error = puc_config(sc, PUC_CFG_GET_TYPE, idx, &res); 277 if (error) 278 goto fail; 279 port->p_type = res; 280 error = puc_config(sc, PUC_CFG_GET_RID, idx, &res); 281 if (error) 282 goto fail; 283 bar = puc_get_bar(sc, res); 284 if (bar == NULL) { 285 error = ENXIO; 286 goto fail; 287 } 288 port->p_bar = bar; 289 start = rman_get_start(bar->b_res); 290 error = puc_config(sc, PUC_CFG_GET_OFS, idx, &res); 291 if (error) 292 goto fail; 293 ofs = res; 294 error = puc_config(sc, PUC_CFG_GET_LEN, idx, &res); 295 if (error) 296 goto fail; 297 size = res; 298 rm = (bar->b_type == SYS_RES_IOPORT) 299 ? &sc->sc_ioport: &sc->sc_iomem; 300 port->p_rres = rman_reserve_resource(rm, start + ofs, 301 start + ofs + size - 1, size, 0, NULL); 302 if (port->p_rres != NULL) { 303 bsh = rman_get_bushandle(bar->b_res); 304 bst = rman_get_bustag(bar->b_res); 305 bus_space_subregion(bst, bsh, ofs, size, &bsh); 306 rman_set_bushandle(port->p_rres, bsh); 307 rman_set_bustag(port->p_rres, bst); 308 } 309 port->p_ires = rman_reserve_resource(&sc->sc_irq, port->p_nr, 310 port->p_nr, 1, 0, NULL); 311 if (port->p_ires == NULL) { 312 error = ENXIO; 313 goto fail; 314 } 315 error = puc_config(sc, PUC_CFG_GET_CLOCK, idx, &res); 316 if (error) 317 goto fail; 318 port->p_rclk = res; 319 320 port->p_dev = device_add_child(dev, NULL, -1); 321 if (port->p_dev != NULL) 322 device_set_ivars(port->p_dev, (void *)port); 323 } 324 325 error = puc_config(sc, PUC_CFG_GET_ILR, 0, &res); 326 if (error) 327 goto fail; 328 sc->sc_ilr = res; 329 if (bootverbose && sc->sc_ilr != 0) 330 device_printf(dev, "using interrupt latch register\n"); 331 332 sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irid, 333 RF_ACTIVE|RF_SHAREABLE); 334 if (sc->sc_ires != NULL) { 335 error = bus_setup_intr(dev, sc->sc_ires, 336 INTR_TYPE_TTY, puc_intr, NULL, sc, &sc->sc_icookie); 337 if (error) 338 error = bus_setup_intr(dev, sc->sc_ires, 339 INTR_TYPE_TTY | INTR_MPSAFE, NULL, 340 (driver_intr_t *)puc_intr, sc, &sc->sc_icookie); 341 else 342 sc->sc_fastintr = 1; 343 344 if (error) { 345 device_printf(dev, "could not activate interrupt\n"); 346 bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid, 347 sc->sc_ires); 348 sc->sc_ires = NULL; 349 } 350 } 351 if (sc->sc_ires == NULL) { 352 /* XXX no interrupt resource. Force polled mode. */ 353 sc->sc_polled = 1; 354 } 355 356 /* Probe and attach our children. */ 357 for (idx = 0; idx < sc->sc_nports; idx++) { 358 port = &sc->sc_port[idx]; 359 if (port->p_dev == NULL) 360 continue; 361 error = device_probe_and_attach(port->p_dev); 362 if (error) { 363 device_delete_child(dev, port->p_dev); 364 port->p_dev = NULL; 365 } 366 } 367 368 /* 369 * If there are no serdev devices, then our interrupt handler 370 * will do nothing. Tear it down. 371 */ 372 if (sc->sc_serdevs == 0UL) 373 bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie); 374 375 return (0); 376 377 fail: 378 for (idx = 0; idx < sc->sc_nports; idx++) { 379 port = &sc->sc_port[idx]; 380 if (port->p_dev != NULL) 381 device_delete_child(dev, port->p_dev); 382 if (port->p_rres != NULL) 383 rman_release_resource(port->p_rres); 384 if (port->p_ires != NULL) 385 rman_release_resource(port->p_ires); 386 } 387 for (idx = 0; idx < PUC_PCI_BARS; idx++) { 388 bar = &sc->sc_bar[idx]; 389 if (bar->b_res != NULL) 390 bus_release_resource(sc->sc_dev, bar->b_type, 391 bar->b_rid, bar->b_res); 392 } 393 rman_fini(&sc->sc_irq); 394 free(__DECONST(void *, sc->sc_irq.rm_descr), M_PUC); 395 rman_fini(&sc->sc_iomem); 396 free(__DECONST(void *, sc->sc_iomem.rm_descr), M_PUC); 397 rman_fini(&sc->sc_ioport); 398 free(__DECONST(void *, sc->sc_ioport.rm_descr), M_PUC); 399 free(sc->sc_port, M_PUC); 400 return (error); 401 } 402 403 int 404 puc_bfe_detach(device_t dev) 405 { 406 struct puc_bar *bar; 407 struct puc_port *port; 408 struct puc_softc *sc; 409 int error, idx; 410 411 sc = device_get_softc(dev); 412 413 /* Detach our children. */ 414 error = 0; 415 for (idx = 0; idx < sc->sc_nports; idx++) { 416 port = &sc->sc_port[idx]; 417 if (port->p_dev == NULL) 418 continue; 419 if (device_delete_child(dev, port->p_dev) == 0) { 420 if (port->p_rres != NULL) 421 rman_release_resource(port->p_rres); 422 if (port->p_ires != NULL) 423 rman_release_resource(port->p_ires); 424 } else 425 error = ENXIO; 426 } 427 if (error) 428 return (error); 429 430 if (sc->sc_serdevs != 0UL) 431 bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie); 432 bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid, sc->sc_ires); 433 434 for (idx = 0; idx < PUC_PCI_BARS; idx++) { 435 bar = &sc->sc_bar[idx]; 436 if (bar->b_res != NULL) 437 bus_release_resource(sc->sc_dev, bar->b_type, 438 bar->b_rid, bar->b_res); 439 } 440 441 rman_fini(&sc->sc_irq); 442 free(__DECONST(void *, sc->sc_irq.rm_descr), M_PUC); 443 rman_fini(&sc->sc_iomem); 444 free(__DECONST(void *, sc->sc_iomem.rm_descr), M_PUC); 445 rman_fini(&sc->sc_ioport); 446 free(__DECONST(void *, sc->sc_ioport.rm_descr), M_PUC); 447 free(sc->sc_port, M_PUC); 448 return (0); 449 } 450 451 int 452 puc_bfe_probe(device_t dev, const struct puc_cfg *cfg) 453 { 454 struct puc_softc *sc; 455 intptr_t res; 456 int error; 457 458 sc = device_get_softc(dev); 459 sc->sc_dev = dev; 460 sc->sc_cfg = cfg; 461 462 /* We don't attach to single-port serial cards. */ 463 if (cfg->ports == PUC_PORT_1S || cfg->ports == PUC_PORT_1P) 464 return (EDOOFUS); 465 error = puc_config(sc, PUC_CFG_GET_NPORTS, 0, &res); 466 if (error) 467 return (error); 468 error = puc_config(sc, PUC_CFG_GET_DESC, 0, &res); 469 if (error) 470 return (error); 471 if (res != 0) 472 device_set_desc(dev, (const char *)res); 473 return (BUS_PROBE_DEFAULT); 474 } 475 476 struct resource * 477 puc_bus_alloc_resource(device_t dev, device_t child, int type, int *rid, 478 rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) 479 { 480 struct puc_port *port; 481 struct resource *res; 482 device_t assigned, originator; 483 int error; 484 485 /* Get our immediate child. */ 486 originator = child; 487 while (child != NULL && device_get_parent(child) != dev) 488 child = device_get_parent(child); 489 if (child == NULL) 490 return (NULL); 491 492 port = device_get_ivars(child); 493 KASSERT(port != NULL, ("%s %d", __func__, __LINE__)); 494 495 if (rid == NULL || *rid != 0) 496 return (NULL); 497 498 /* We only support default allocations. */ 499 if (!RMAN_IS_DEFAULT_RANGE(start, end)) 500 return (NULL); 501 502 if (type == port->p_bar->b_type) 503 res = port->p_rres; 504 else if (type == SYS_RES_IRQ) 505 res = port->p_ires; 506 else 507 return (NULL); 508 509 if (res == NULL) 510 return (NULL); 511 512 assigned = rman_get_device(res); 513 if (assigned == NULL) /* Not allocated */ 514 rman_set_device(res, originator); 515 else if (assigned != originator) 516 return (NULL); 517 518 if (flags & RF_ACTIVE) { 519 error = rman_activate_resource(res); 520 if (error) { 521 if (assigned == NULL) 522 rman_set_device(res, NULL); 523 return (NULL); 524 } 525 } 526 527 return (res); 528 } 529 530 int 531 puc_bus_release_resource(device_t dev, device_t child, int type, int rid, 532 struct resource *res) 533 { 534 struct puc_port *port; 535 device_t originator; 536 537 /* Get our immediate child. */ 538 originator = child; 539 while (child != NULL && device_get_parent(child) != dev) 540 child = device_get_parent(child); 541 if (child == NULL) 542 return (EINVAL); 543 544 port = device_get_ivars(child); 545 KASSERT(port != NULL, ("%s %d", __func__, __LINE__)); 546 547 if (rid != 0 || res == NULL) 548 return (EINVAL); 549 550 if (type == port->p_bar->b_type) { 551 if (res != port->p_rres) 552 return (EINVAL); 553 } else if (type == SYS_RES_IRQ) { 554 if (res != port->p_ires) 555 return (EINVAL); 556 if (port->p_hasintr) 557 return (EBUSY); 558 } else 559 return (EINVAL); 560 561 if (rman_get_device(res) != originator) 562 return (ENXIO); 563 if (rman_get_flags(res) & RF_ACTIVE) 564 rman_deactivate_resource(res); 565 rman_set_device(res, NULL); 566 return (0); 567 } 568 569 int 570 puc_bus_get_resource(device_t dev, device_t child, int type, int rid, 571 rman_res_t *startp, rman_res_t *countp) 572 { 573 struct puc_port *port; 574 struct resource *res; 575 rman_res_t start; 576 577 /* Get our immediate child. */ 578 while (child != NULL && device_get_parent(child) != dev) 579 child = device_get_parent(child); 580 if (child == NULL) 581 return (EINVAL); 582 583 port = device_get_ivars(child); 584 KASSERT(port != NULL, ("%s %d", __func__, __LINE__)); 585 586 if (type == port->p_bar->b_type) 587 res = port->p_rres; 588 else if (type == SYS_RES_IRQ) 589 res = port->p_ires; 590 else 591 return (ENXIO); 592 593 if (rid != 0 || res == NULL) 594 return (ENXIO); 595 596 start = rman_get_start(res); 597 if (startp != NULL) 598 *startp = start; 599 if (countp != NULL) 600 *countp = rman_get_end(res) - start + 1; 601 return (0); 602 } 603 604 int 605 puc_bus_setup_intr(device_t dev, device_t child, struct resource *res, 606 int flags, driver_filter_t *filt, void (*ihand)(void *), void *arg, void **cookiep) 607 { 608 struct puc_port *port; 609 struct puc_softc *sc; 610 device_t originator; 611 int i, isrc, serdev; 612 613 sc = device_get_softc(dev); 614 615 /* Get our immediate child. */ 616 originator = child; 617 while (child != NULL && device_get_parent(child) != dev) 618 child = device_get_parent(child); 619 if (child == NULL) 620 return (EINVAL); 621 622 port = device_get_ivars(child); 623 KASSERT(port != NULL, ("%s %d", __func__, __LINE__)); 624 625 if (cookiep == NULL || res != port->p_ires) 626 return (EINVAL); 627 /* We demand that serdev devices use filter_only interrupts. */ 628 if (port->p_type == PUC_TYPE_SERIAL && ihand != NULL) 629 return (ENXIO); 630 if (rman_get_device(port->p_ires) != originator) 631 return (ENXIO); 632 633 /* 634 * Have non-serdev ports handled by the bus implementation. It 635 * supports multiple handlers for a single interrupt as it is, 636 * so we wouldn't add value if we did it ourselves. 637 */ 638 serdev = 0; 639 if (port->p_type == PUC_TYPE_SERIAL) { 640 i = 0, isrc = SER_INT_OVERRUN; 641 while (i < PUC_ISRCCNT) { 642 port->p_ihsrc[i] = SERDEV_IHAND(originator, isrc); 643 if (port->p_ihsrc[i] != NULL) 644 serdev = 1; 645 i++, isrc <<= 1; 646 } 647 } 648 if (!serdev) 649 return (BUS_SETUP_INTR(device_get_parent(dev), originator, 650 sc->sc_ires, flags, filt, ihand, arg, cookiep)); 651 652 sc->sc_serdevs |= 1UL << (port->p_nr - 1); 653 654 port->p_hasintr = 1; 655 port->p_iharg = arg; 656 657 *cookiep = port; 658 return (0); 659 } 660 661 int 662 puc_bus_teardown_intr(device_t dev, device_t child, struct resource *res, 663 void *cookie) 664 { 665 struct puc_port *port; 666 struct puc_softc *sc; 667 device_t originator; 668 int i; 669 670 sc = device_get_softc(dev); 671 672 /* Get our immediate child. */ 673 originator = child; 674 while (child != NULL && device_get_parent(child) != dev) 675 child = device_get_parent(child); 676 if (child == NULL) 677 return (EINVAL); 678 679 port = device_get_ivars(child); 680 KASSERT(port != NULL, ("%s %d", __func__, __LINE__)); 681 682 if (res != port->p_ires) 683 return (EINVAL); 684 if (rman_get_device(port->p_ires) != originator) 685 return (ENXIO); 686 687 if (!port->p_hasintr) 688 return (BUS_TEARDOWN_INTR(device_get_parent(dev), originator, 689 sc->sc_ires, cookie)); 690 691 if (cookie != port) 692 return (EINVAL); 693 694 port->p_hasintr = 0; 695 port->p_iharg = NULL; 696 697 for (i = 0; i < PUC_ISRCCNT; i++) 698 port->p_ihsrc[i] = NULL; 699 700 return (0); 701 } 702 703 int 704 puc_bus_read_ivar(device_t dev, device_t child, int index, uintptr_t *result) 705 { 706 struct puc_port *port; 707 708 /* Get our immediate child. */ 709 while (child != NULL && device_get_parent(child) != dev) 710 child = device_get_parent(child); 711 if (child == NULL) 712 return (EINVAL); 713 714 port = device_get_ivars(child); 715 KASSERT(port != NULL, ("%s %d", __func__, __LINE__)); 716 717 if (result == NULL) 718 return (EINVAL); 719 720 switch(index) { 721 case PUC_IVAR_CLOCK: 722 *result = port->p_rclk; 723 break; 724 case PUC_IVAR_TYPE: 725 *result = port->p_type; 726 break; 727 default: 728 return (ENOENT); 729 } 730 return (0); 731 } 732 733 int 734 puc_bus_print_child(device_t dev, device_t child) 735 { 736 struct puc_port *port; 737 int retval; 738 739 port = device_get_ivars(child); 740 retval = 0; 741 742 retval += bus_print_child_header(dev, child); 743 retval += printf(" at port %d", port->p_nr); 744 retval += bus_print_child_footer(dev, child); 745 746 return (retval); 747 } 748 749 int 750 puc_bus_child_location_str(device_t dev, device_t child, char *buf, 751 size_t buflen) 752 { 753 struct puc_port *port; 754 755 port = device_get_ivars(child); 756 snprintf(buf, buflen, "port=%d", port->p_nr); 757 return (0); 758 } 759 760 int 761 puc_bus_child_pnpinfo_str(device_t dev, device_t child, char *buf, 762 size_t buflen) 763 { 764 struct puc_port *port; 765 766 port = device_get_ivars(child); 767 snprintf(buf, buflen, "type=%d", port->p_type); 768 return (0); 769 } 770