1 /*- 2 * Copyright (c) 2015-2016 Landon Fuller <landonf@FreeBSD.org> 3 * Copyright (c) 2017 The FreeBSD Foundation 4 * All rights reserved. 5 * 6 * Portions of this software were developed by Landon Fuller 7 * under sponsorship from the FreeBSD Foundation. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer, 14 * without modification. 15 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 16 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 17 * redistribution must be conditioned upon including a substantially 18 * similar Disclaimer requirement for further binary redistribution. 19 * 20 * NO WARRANTY 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 24 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 25 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 26 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 29 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31 * THE POSSIBILITY OF SUCH DAMAGES. 32 */ 33 34 #include <sys/param.h> 35 #include <sys/bus.h> 36 #include <sys/kernel.h> 37 #include <sys/malloc.h> 38 #include <sys/module.h> 39 40 #include <machine/bus.h> 41 42 #include <dev/bhnd/bhnd_eromvar.h> 43 44 #include <dev/bhnd/cores/chipc/chipcreg.h> 45 46 #include "sibareg.h" 47 #include "sibavar.h" 48 49 #include "siba_eromvar.h" 50 51 struct siba_erom; 52 struct siba_erom_io; 53 54 static int siba_eio_init(struct siba_erom_io *io, 55 struct bhnd_erom_io *eio, u_int ncores); 56 57 static uint32_t siba_eio_read_4(struct siba_erom_io *io, 58 u_int core_idx, bus_size_t offset); 59 60 static int siba_eio_read_core_id(struct siba_erom_io *io, 61 u_int core_idx, int unit, 62 struct siba_core_id *sid); 63 64 static int siba_eio_read_chipid(struct siba_erom_io *io, 65 bus_addr_t enum_addr, 66 struct bhnd_chipid *cid); 67 68 /** 69 * SIBA EROM generic I/O context 70 */ 71 struct siba_erom_io { 72 struct bhnd_erom_io *eio; /**< erom I/O callbacks */ 73 bhnd_addr_t base_addr; /**< address of first core */ 74 u_int ncores; /**< core count */ 75 }; 76 77 /** 78 * SIBA EROM per-instance state. 79 */ 80 struct siba_erom { 81 struct bhnd_erom obj; 82 struct siba_erom_io io; /**< i/o context */ 83 }; 84 85 #define EROM_LOG(io, fmt, ...) do { \ 86 printf("%s: " fmt, __FUNCTION__, ##__VA_ARGS__); \ 87 } while(0) 88 89 /* SIBA implementation of BHND_EROM_PROBE() */ 90 static int 91 siba_erom_probe(bhnd_erom_class_t *cls, struct bhnd_erom_io *eio, 92 const struct bhnd_chipid *hint, struct bhnd_chipid *cid) 93 { 94 struct siba_erom_io io; 95 uint32_t idreg; 96 int error; 97 98 /* Initialize I/O context, assuming at least the first core is mapped */ 99 if ((error = siba_eio_init(&io, eio, 1))) 100 return (error); 101 102 /* Try using the provided hint. */ 103 if (hint != NULL) { 104 struct siba_core_id sid; 105 106 /* Validate bus type */ 107 if (hint->chip_type != BHND_CHIPTYPE_SIBA) 108 return (ENXIO); 109 110 /* 111 * Verify the first core's IDHIGH/IDLOW identification. 112 * 113 * The core must be a Broadcom core, but must *not* be 114 * a chipcommon core; those shouldn't be hinted. 115 * 116 * The first core on EXTIF-equipped devices varies, but on the 117 * BCM4710, it's a SDRAM core (0x803). 118 */ 119 120 if ((error = siba_eio_read_core_id(&io, 0, 0, &sid))) 121 return (error); 122 123 if (sid.core_info.vendor != BHND_MFGID_BCM) 124 return (ENXIO); 125 126 if (sid.core_info.device == BHND_COREID_CC) 127 return (EINVAL); 128 129 *cid = *hint; 130 } else { 131 /* Validate bus type */ 132 idreg = siba_eio_read_4(&io, 0, CHIPC_ID); 133 if (CHIPC_GET_BITS(idreg, CHIPC_ID_BUS) != BHND_CHIPTYPE_SIBA) 134 return (ENXIO); 135 136 /* Identify the chipset */ 137 if ((error = siba_eio_read_chipid(&io, SIBA_ENUM_ADDR, cid))) 138 return (error); 139 140 /* Verify the chip type */ 141 if (cid->chip_type != BHND_CHIPTYPE_SIBA) 142 return (ENXIO); 143 } 144 145 /* 146 * gcc hack: ensure bhnd_chipid.ncores cannot exceed SIBA_MAX_CORES 147 * without triggering build failure due to -Wtype-limits 148 * 149 * if (cid.ncores > SIBA_MAX_CORES) 150 * return (EINVAL) 151 */ 152 _Static_assert((2^sizeof(cid->ncores)) <= SIBA_MAX_CORES, 153 "ncores could result in over-read of backing resource"); 154 155 return (0); 156 } 157 158 /* SIBA implementation of BHND_EROM_INIT() */ 159 static int 160 siba_erom_init(bhnd_erom_t *erom, const struct bhnd_chipid *cid, 161 struct bhnd_erom_io *eio) 162 { 163 struct siba_erom *sc; 164 int error; 165 166 sc = (struct siba_erom *)erom; 167 168 /* Attempt to map the full core enumeration space */ 169 error = bhnd_erom_io_map(eio, cid->enum_addr, 170 cid->ncores * SIBA_CORE_SIZE); 171 if (error) { 172 printf("%s: failed to map %u cores: %d\n", __FUNCTION__, 173 cid->ncores, error); 174 return (error); 175 } 176 177 /* Initialize I/O context */ 178 return (siba_eio_init(&sc->io, eio, cid->ncores)); 179 } 180 181 /* SIBA implementation of BHND_EROM_FINI() */ 182 static void 183 siba_erom_fini(bhnd_erom_t *erom) 184 { 185 struct siba_erom *sc = (struct siba_erom *)erom; 186 187 bhnd_erom_io_fini(sc->io.eio); 188 } 189 190 /* Initialize siba_erom resource I/O context */ 191 static int 192 siba_eio_init(struct siba_erom_io *io, struct bhnd_erom_io *eio, u_int ncores) 193 { 194 io->eio = eio; 195 io->ncores = ncores; 196 return (0); 197 } 198 199 /** 200 * Read a 32-bit value from @p offset relative to the base address of 201 * the given @p core_idx. 202 * 203 * @param io EROM I/O context. 204 * @param core_idx Core index. 205 * @param offset Core register offset. 206 */ 207 static uint32_t 208 siba_eio_read_4(struct siba_erom_io *io, u_int core_idx, bus_size_t offset) 209 { 210 /* Sanity check core index and offset */ 211 if (core_idx >= io->ncores) 212 panic("core index %u out of range (ncores=%u)", core_idx, 213 io->ncores); 214 215 if (offset > SIBA_CORE_SIZE - sizeof(uint32_t)) 216 panic("invalid core offset %#jx", (uintmax_t)offset); 217 218 /* Perform read */ 219 return (bhnd_erom_io_read(io->eio, SIBA_CORE_OFFSET(core_idx) + offset, 220 4)); 221 } 222 223 /** 224 * Read and parse identification registers for the given @p core_index. 225 * 226 * @param io EROM I/O context. 227 * @param core_idx The core index. 228 * @param unit The caller-specified unit number to be included in the return 229 * value. 230 * @param[out] sid On success, the parsed siba core id. 231 * 232 * @retval 0 success 233 * @retval non-zero if reading or parsing the identification registers 234 * otherwise fails, a regular unix error code will be 235 * returned. 236 */ 237 static int 238 siba_eio_read_core_id(struct siba_erom_io *io, u_int core_idx, int unit, 239 struct siba_core_id *sid) 240 { 241 struct siba_admatch admatch[SIBA_MAX_ADDRSPACE]; 242 uint32_t idhigh, idlow; 243 uint32_t tpsflag; 244 uint16_t ocp_vendor; 245 uint8_t sonics_rev; 246 uint8_t num_admatch; 247 uint8_t num_admatch_en; 248 uint8_t num_cfg; 249 bool intr_en; 250 u_int intr_flag; 251 int error; 252 253 idhigh = siba_eio_read_4(io, core_idx, SB0_REG_ABS(SIBA_CFG0_IDHIGH)); 254 idlow = siba_eio_read_4(io, core_idx, SB0_REG_ABS(SIBA_CFG0_IDLOW)); 255 tpsflag = siba_eio_read_4(io, core_idx, SB0_REG_ABS(SIBA_CFG0_TPSFLAG)); 256 257 ocp_vendor = SIBA_REG_GET(idhigh, IDH_VENDOR); 258 sonics_rev = SIBA_REG_GET(idlow, IDL_SBREV); 259 num_admatch = SIBA_REG_GET(idlow, IDL_NRADDR) + 1 /* + enum block */; 260 if (num_admatch > nitems(admatch)) { 261 printf("core%u: invalid admatch count %hhu\n", core_idx, 262 num_admatch); 263 return (EINVAL); 264 } 265 266 /* Determine backplane interrupt distribution configuration */ 267 intr_en = ((tpsflag & SIBA_TPS_F0EN0) != 0); 268 intr_flag = SIBA_REG_GET(tpsflag, TPS_NUM0); 269 270 /* Determine the number of sonics config register blocks */ 271 num_cfg = SIBA_CFG_NUM_2_2; 272 if (sonics_rev >= SIBA_IDL_SBREV_2_3) 273 num_cfg = SIBA_CFG_NUM_2_3; 274 275 /* Parse all admatch descriptors */ 276 num_admatch_en = 0; 277 for (uint8_t i = 0; i < num_admatch; i++) { 278 uint32_t am_value; 279 u_int am_offset; 280 281 KASSERT(i < nitems(admatch), ("invalid admatch index")); 282 283 /* Determine the register offset */ 284 am_offset = siba_admatch_offset(i); 285 if (am_offset == 0) { 286 printf("core%u: addrspace %hhu is unsupported", 287 core_idx, i); 288 return (ENODEV); 289 } 290 291 /* Read and parse the address match register */ 292 am_value = siba_eio_read_4(io, core_idx, am_offset); 293 error = siba_parse_admatch(am_value, &admatch[num_admatch_en]); 294 if (error) { 295 printf("core%u: failed to decode admatch[%hhu] " 296 "register value 0x%x\n", core_idx, i, am_value); 297 return (error); 298 } 299 300 /* Skip disabled entries */ 301 if (!admatch[num_admatch_en].am_enabled) 302 continue; 303 304 /* Reject unsupported negative matches. These are not used on 305 * any known devices */ 306 if (admatch[num_admatch_en].am_negative) { 307 printf("core%u: unsupported negative admatch[%hhu] " 308 "value 0x%x\n", core_idx, i, am_value); 309 return (ENXIO); 310 } 311 312 num_admatch_en++; 313 } 314 315 /* Populate the result */ 316 *sid = (struct siba_core_id) { 317 .core_info = { 318 .vendor = siba_get_bhnd_mfgid(ocp_vendor), 319 .device = SIBA_REG_GET(idhigh, IDH_DEVICE), 320 .hwrev = SIBA_IDH_CORE_REV(idhigh), 321 .core_idx = core_idx, 322 .unit = unit 323 }, 324 .sonics_vendor = ocp_vendor, 325 .sonics_rev = sonics_rev, 326 .intr_en = intr_en, 327 .intr_flag = intr_flag, 328 .num_admatch = num_admatch_en, 329 .num_cfg_blocks = num_cfg 330 }; 331 memcpy(sid->admatch, admatch, num_admatch_en * sizeof(admatch[0])); 332 333 return (0); 334 } 335 336 /** 337 * Read and parse the SSB identification registers for the given @p core_index, 338 * returning the siba(4) core identification in @p sid. 339 * 340 * @param sc A siba EROM instance. 341 * @param core_idx The index of the core to be identified. 342 * @param[out] result On success, the parsed siba core id. 343 * 344 * @retval 0 success 345 * @retval non-zero if reading or parsing the identification registers 346 * otherwise fails, a regular unix error code will be 347 * returned. 348 */ 349 int 350 siba_erom_get_core_id(struct siba_erom *sc, u_int core_idx, 351 struct siba_core_id *result) 352 { 353 struct siba_core_id sid; 354 int error; 355 356 /* Fetch the core info, assuming a unit number of 0 */ 357 if ((error = siba_eio_read_core_id(&sc->io, core_idx, 0, &sid))) 358 return (error); 359 360 /* Scan preceding cores to determine the real unit number. */ 361 for (u_int i = 0; i < core_idx; i++) { 362 struct siba_core_id prev; 363 364 if ((error = siba_eio_read_core_id(&sc->io, i, 0, &prev))) 365 return (error); 366 367 /* Bump the unit number? */ 368 if (sid.core_info.vendor == prev.core_info.vendor && 369 sid.core_info.device == prev.core_info.device) 370 sid.core_info.unit++; 371 } 372 373 *result = sid; 374 return (0); 375 } 376 377 /** 378 * Read and parse the chip identification register from the ChipCommon core. 379 * 380 * @param io EROM I/O context. 381 * @param enum_addr The physical address mapped by @p io. 382 * @param cid On success, the parsed chip identifier. 383 */ 384 static int 385 siba_eio_read_chipid(struct siba_erom_io *io, bus_addr_t enum_addr, 386 struct bhnd_chipid *cid) 387 { 388 struct siba_core_id ccid; 389 int error; 390 391 /* Identify the chipcommon core */ 392 if ((error = siba_eio_read_core_id(io, 0, 0, &ccid))) 393 return (error); 394 395 if (ccid.core_info.vendor != BHND_MFGID_BCM || 396 ccid.core_info.device != BHND_COREID_CC) 397 { 398 if (bootverbose) { 399 EROM_LOG(io, "first core not chipcommon " 400 "(vendor=%#hx, core=%#hx)\n", ccid.core_info.vendor, 401 ccid.core_info.device); 402 } 403 return (ENXIO); 404 } 405 406 /* Identify the chipset */ 407 if ((error = bhnd_erom_read_chipid(io->eio, cid))) 408 return (error); 409 410 /* Do we need to fix up the core count? */ 411 if (CHIPC_NCORES_MIN_HWREV(ccid.core_info.hwrev)) 412 return (0); 413 414 switch (cid->chip_id) { 415 case BHND_CHIPID_BCM4306: 416 cid->ncores = 6; 417 break; 418 case BHND_CHIPID_BCM4704: 419 cid->ncores = 9; 420 break; 421 case BHND_CHIPID_BCM5365: 422 /* 423 * BCM5365 does support ID_NUMCORE in at least 424 * some of its revisions, but for unknown 425 * reasons, Broadcom's drivers always exclude 426 * the ChipCommon revision (0x5) used by BCM5365 427 * from the set of revisions supporting 428 * ID_NUMCORE, and instead supply a fixed value. 429 * 430 * Presumably, at least some of these devices 431 * shipped with a broken ID_NUMCORE value. 432 */ 433 cid->ncores = 7; 434 break; 435 default: 436 return (EINVAL); 437 } 438 439 return (0); 440 } 441 442 static int 443 siba_erom_lookup_core(bhnd_erom_t *erom, const struct bhnd_core_match *desc, 444 struct bhnd_core_info *core) 445 { 446 struct siba_erom *sc; 447 struct bhnd_core_match imatch; 448 int error; 449 450 sc = (struct siba_erom *)erom; 451 452 /* We can't determine a core's unit number during the initial scan. */ 453 imatch = *desc; 454 imatch.m.match.core_unit = 0; 455 456 /* Locate the first matching core */ 457 for (u_int i = 0; i < sc->io.ncores; i++) { 458 struct siba_core_id sid; 459 struct bhnd_core_info ci; 460 461 /* Read the core info */ 462 if ((error = siba_eio_read_core_id(&sc->io, i, 0, &sid))) 463 return (error); 464 465 ci = sid.core_info; 466 467 /* Check for initial match */ 468 if (!bhnd_core_matches(&ci, &imatch)) 469 continue; 470 471 /* Re-scan preceding cores to determine the unit number. */ 472 for (u_int j = 0; j < i; j++) { 473 error = siba_eio_read_core_id(&sc->io, j, 0, &sid); 474 if (error) 475 return (error); 476 477 /* Bump the unit number? */ 478 if (sid.core_info.vendor == ci.vendor && 479 sid.core_info.device == ci.device) 480 ci.unit++; 481 } 482 483 /* Check for full match against now-valid unit number */ 484 if (!bhnd_core_matches(&ci, desc)) 485 continue; 486 487 /* Matching core found */ 488 *core = ci; 489 return (0); 490 } 491 492 /* Not found */ 493 return (ENOENT); 494 } 495 496 static int 497 siba_erom_lookup_core_addr(bhnd_erom_t *erom, const struct bhnd_core_match *desc, 498 bhnd_port_type type, u_int port, u_int region, struct bhnd_core_info *info, 499 bhnd_addr_t *addr, bhnd_size_t *size) 500 { 501 struct siba_erom *sc; 502 struct bhnd_core_info core; 503 struct siba_core_id sid; 504 struct siba_admatch admatch; 505 uint32_t am; 506 u_int am_offset; 507 u_int addrspace, cfg; 508 509 int error; 510 511 sc = (struct siba_erom *)erom; 512 513 /* Locate the requested core */ 514 if ((error = siba_erom_lookup_core(erom, desc, &core))) 515 return (error); 516 517 /* Fetch full siba core ident */ 518 error = siba_eio_read_core_id(&sc->io, core.core_idx, core.unit, &sid); 519 if (error) 520 return (error); 521 522 /* Is port valid? */ 523 if (!siba_is_port_valid(&sid, type, port)) 524 return (ENOENT); 525 526 /* Is region valid? */ 527 if (region >= siba_port_region_count(&sid, type, port)) 528 return (ENOENT); 529 530 /* Is this a siba configuration region? If so, this is mapped to an 531 * offset within the device0.0 port */ 532 error = siba_cfg_index(&sid, type, port, region, &cfg); 533 if (!error) { 534 bhnd_addr_t region_addr; 535 bhnd_addr_t region_size; 536 bhnd_size_t cfg_offset, cfg_size; 537 538 cfg_offset = SIBA_CFG_OFFSET(cfg); 539 cfg_size = SIBA_CFG_SIZE; 540 541 /* Fetch the device0.0 addr/size */ 542 error = siba_erom_lookup_core_addr(erom, desc, BHND_PORT_DEVICE, 543 0, 0, NULL, ®ion_addr, ®ion_size); 544 if (error) 545 return (error); 546 547 /* Verify that our offset fits within the region */ 548 if (region_size < cfg_size) { 549 printf("%s%u.%u offset %ju exceeds %s0.0 size %ju\n", 550 bhnd_port_type_name(type), port, region, cfg_offset, 551 bhnd_port_type_name(BHND_PORT_DEVICE), region_size); 552 553 return (ENXIO); 554 } 555 556 if (BHND_ADDR_MAX - region_addr < cfg_offset) { 557 printf("%s%u.%u offset %ju would overflow %s0.0 addr " 558 "%ju\n", bhnd_port_type_name(type), port, region, 559 cfg_offset, bhnd_port_type_name(BHND_PORT_DEVICE), 560 region_addr); 561 562 return (ENXIO); 563 } 564 565 if (info != NULL) 566 *info = core; 567 568 *addr = region_addr + cfg_offset; 569 *size = cfg_size; 570 return (0); 571 } 572 573 /* 574 * Otherwise, must be a device port. 575 * 576 * Map the bhnd device port to a siba addrspace index. Unlike siba(4) 577 * bus drivers, we do not exclude the siba(4) configuration blocks from 578 * the first device port. 579 */ 580 error = siba_addrspace_index(&sid, type, port, region, &addrspace); 581 if (error) 582 return (error); 583 584 /* Determine the register offset */ 585 am_offset = siba_admatch_offset(addrspace); 586 if (am_offset == 0) { 587 printf("addrspace %u is unsupported", addrspace); 588 return (ENODEV); 589 } 590 591 /* Read and parse the address match register */ 592 am = siba_eio_read_4(&sc->io, core.core_idx, am_offset); 593 594 if ((error = siba_parse_admatch(am, &admatch))) { 595 printf("failed to decode address match register value 0x%x\n", 596 am); 597 return (error); 598 } 599 600 if (info != NULL) 601 *info = core; 602 603 *addr = admatch.am_base; 604 *size = admatch.am_size; 605 606 return (0); 607 } 608 609 /* BHND_EROM_GET_CORE_TABLE() */ 610 static int 611 siba_erom_get_core_table(bhnd_erom_t *erom, struct bhnd_core_info **cores, 612 u_int *num_cores) 613 { 614 struct siba_erom *sc; 615 struct bhnd_core_info *out; 616 int error; 617 618 sc = (struct siba_erom *)erom; 619 620 /* Allocate our core array */ 621 out = mallocarray(sc->io.ncores, sizeof(*out), M_BHND, M_NOWAIT); 622 if (out == NULL) 623 return (ENOMEM); 624 625 *cores = out; 626 *num_cores = sc->io.ncores; 627 628 /* Enumerate all cores. */ 629 for (u_int i = 0; i < sc->io.ncores; i++) { 630 struct siba_core_id sid; 631 632 /* Read the core info */ 633 if ((error = siba_eio_read_core_id(&sc->io, i, 0, &sid))) 634 return (error); 635 636 out[i] = sid.core_info; 637 638 /* Determine unit number */ 639 for (u_int j = 0; j < i; j++) { 640 if (out[j].vendor == out[i].vendor && 641 out[j].device == out[i].device) 642 out[i].unit++; 643 } 644 } 645 646 return (0); 647 } 648 649 /* BHND_EROM_FREE_CORE_TABLE() */ 650 static void 651 siba_erom_free_core_table(bhnd_erom_t *erom, struct bhnd_core_info *cores) 652 { 653 free(cores, M_BHND); 654 } 655 656 /* BHND_EROM_DUMP() */ 657 static int 658 siba_erom_dump(bhnd_erom_t *erom) 659 { 660 struct siba_erom *sc; 661 int error; 662 663 sc = (struct siba_erom *)erom; 664 665 /* Enumerate all cores. */ 666 for (u_int i = 0; i < sc->io.ncores; i++) { 667 uint32_t idhigh, idlow; 668 uint32_t nraddr; 669 670 idhigh = siba_eio_read_4(&sc->io, i, 671 SB0_REG_ABS(SIBA_CFG0_IDHIGH)); 672 idlow = siba_eio_read_4(&sc->io, i, 673 SB0_REG_ABS(SIBA_CFG0_IDLOW)); 674 675 printf("siba core %u:\n", i); 676 printf("\tvendor:\t0x%04x\n", SIBA_REG_GET(idhigh, IDH_VENDOR)); 677 printf("\tdevice:\t0x%04x\n", SIBA_REG_GET(idhigh, IDH_DEVICE)); 678 printf("\trev:\t0x%04x\n", SIBA_IDH_CORE_REV(idhigh)); 679 printf("\tsbrev:\t0x%02x\n", SIBA_REG_GET(idlow, IDL_SBREV)); 680 681 /* Enumerate the address match registers */ 682 nraddr = SIBA_REG_GET(idlow, IDL_NRADDR); 683 printf("\tnraddr\t0x%04x\n", nraddr); 684 685 for (size_t addrspace = 0; addrspace < nraddr; addrspace++) { 686 struct siba_admatch admatch; 687 uint32_t am; 688 u_int am_offset; 689 690 /* Determine the register offset */ 691 am_offset = siba_admatch_offset(addrspace); 692 if (am_offset == 0) { 693 printf("addrspace %zu unsupported", 694 addrspace); 695 break; 696 } 697 698 /* Read and parse the address match register */ 699 am = siba_eio_read_4(&sc->io, i, am_offset); 700 if ((error = siba_parse_admatch(am, &admatch))) { 701 printf("failed to decode address match " 702 "register value 0x%x\n", am); 703 continue; 704 } 705 706 printf("\taddrspace %zu\n", addrspace); 707 printf("\t\taddr: 0x%08x\n", admatch.am_base); 708 printf("\t\tsize: 0x%08x\n", admatch.am_size); 709 } 710 } 711 712 return (0); 713 } 714 715 static kobj_method_t siba_erom_methods[] = { 716 KOBJMETHOD(bhnd_erom_probe, siba_erom_probe), 717 KOBJMETHOD(bhnd_erom_init, siba_erom_init), 718 KOBJMETHOD(bhnd_erom_fini, siba_erom_fini), 719 KOBJMETHOD(bhnd_erom_get_core_table, siba_erom_get_core_table), 720 KOBJMETHOD(bhnd_erom_free_core_table, siba_erom_free_core_table), 721 KOBJMETHOD(bhnd_erom_lookup_core, siba_erom_lookup_core), 722 KOBJMETHOD(bhnd_erom_lookup_core_addr, siba_erom_lookup_core_addr), 723 KOBJMETHOD(bhnd_erom_dump, siba_erom_dump), 724 725 KOBJMETHOD_END 726 }; 727 728 BHND_EROM_DEFINE_CLASS(siba_erom, siba_erom_parser, siba_erom_methods, sizeof(struct siba_erom)); 729