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