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