Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/dev/bhnd/siba/siba_erom.c
39566 views
1
/*-
2
* Copyright (c) 2015-2016 Landon Fuller <[email protected]>
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, &region_addr, &region_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
730