1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2022 Oxide Computer Company 14 */ 15 16 #ifndef _ZEN_UMC_H 17 #define _ZEN_UMC_H 18 19 /* 20 * This file contains definitions that are used to manage and decode the Zen UMC 21 * state. 22 */ 23 24 #ifdef __cplusplus 25 extern "C" { 26 #endif 27 28 #include <sys/stdint.h> 29 #include <sys/sunddi.h> 30 #include <sys/nvpair.h> 31 #include <amdzen_client.h> 32 33 /* 34 * This is the maximum number of DRAM rules that we expect any supported device 35 * to have here. The actual number may be less. These are rules that come from a 36 * DF CCM. 37 */ 38 #define ZEN_UMC_MAX_DRAM_RULES 20 39 40 /* 41 * This is the maximum number of rules that we expect any system to actually 42 * have for each UMC. 43 */ 44 #define ZEN_UMC_MAX_CS_RULES 4 45 46 /* 47 * This is the maximum number of DFs that we expect to encounter in a given 48 * platform. This number comes from the Naples generation, where there were up 49 * to 4 per socket, 2 sockets per machine, so 8 total. In subsequent generations 50 * there is only a single 1 per socket. 51 */ 52 #define ZEN_UMC_MAX_DFS 8 53 54 /* 55 * This indicates the maximum number of UMC DF nodes that we expect to 56 * encounter. 57 */ 58 #define ZEN_UMC_MAX_UMCS 12 59 60 /* 61 * This indicates the maximum number of DRAM offset rules that can exist in a 62 * platform. Note, this is directly tied to the maximum number of CS rules. 63 */ 64 #define ZEN_UMC_MAX_DRAM_OFFSET (ZEN_UMC_MAX_CS_RULES - 1) 65 66 /* 67 * This indicates the maximum number of remap rule sets and corresponding 68 * entries that can exist. Milan's max is smaller than the current overall DFv4 69 * maximum. 70 */ 71 #define ZEN_UMC_MAX_CS_REMAPS 4 72 #define ZEN_UMC_MAX_REMAP_ENTS 16 73 #define ZEN_UMC_MILAN_CS_NREMAPS 2 74 #define ZEN_UMC_MILAN_REMAP_ENTS 12 75 #define ZEN_UMC_REMAP_PER_REG 8 76 77 /* 78 * DRAM Channel related maximums. 79 */ 80 #define ZEN_UMC_MAX_DIMMS 2 81 #define ZEN_UMC_MAX_CS_PER_DIMM 2 82 #define ZEN_UMC_MAX_CS_BITS 2 83 #define ZEN_UMC_MAX_CHAN_BASE 2 84 #define ZEN_UMC_MAX_CHAN_MASK 2 85 #define ZEN_UMC_MAX_BANK_BITS 5 86 #define ZEN_UMC_MAX_COL_BITS 16 87 #define ZEN_UMC_MAX_RM_BITS 4 88 #define ZEN_UMC_MAX_COLSEL_PER_REG 8 89 90 #define ZEN_UMC_DDR4_CHAN_NMASKS 1 91 92 /* 93 * DRAM Channel hash maximums. Surprisingly enough, the DDR4 and DDR5 maximums 94 * are the same; however, in exchange what hashes are actually implemented 95 * varies. 96 */ 97 #define ZEN_UMC_MAX_CHAN_BANK_HASH 5 98 #define ZEN_UMC_MAX_CHAN_RM_HASH 3 99 #define ZEN_UMC_MAX_CHAN_CS_HASH 2 100 101 /* 102 * This is the logical set of different channel interleaving rules that we 103 * support today in the driver. The actual values of the enumeration do not 104 * overlap at all with hardware. Do not use these to try and marry up against 105 * values from the DF itself. 106 * 107 * Note, these values are also encoded in the private mc decoder dumps that we 108 * can produce. If these values change, please take care of ensuring 109 * compatibility for others who may be consuming this. Appending to this list 110 * should be OK. 111 */ 112 typedef enum df_chan_ileave { 113 DF_CHAN_ILEAVE_1CH = 0, 114 DF_CHAN_ILEAVE_2CH, 115 DF_CHAN_ILEAVE_4CH, 116 DF_CHAN_ILEAVE_6CH, 117 DF_CHAN_ILEAVE_8CH, 118 DF_CHAN_ILEAVE_16CH, 119 DF_CHAN_ILEAVE_32CH, 120 DF_CHAN_ILEAVE_COD4_2CH, 121 DF_CHAN_ILEAVE_COD2_4CH, 122 DF_CHAN_ILEAVE_COD1_8CH, 123 DF_CHAN_ILEAVE_NPS4_2CH, 124 DF_CHAN_ILEAVE_NPS2_4CH, 125 DF_CHAN_ILEAVE_NPS1_8CH, 126 DF_CHAN_ILEAVE_NPS4_3CH, 127 DF_CHAN_ILEAVE_NPS2_6CH, 128 DF_CHAN_ILEAVE_NPS1_12CH, 129 DF_CHAN_ILEAVE_NPS2_5CH, 130 DF_CHAN_ILEAVE_NPS1_10CH 131 } df_chan_ileave_t; 132 133 /* 134 * This is a collection of logical flags that we use to cover attributes of a 135 * DRAM rule. 136 */ 137 typedef enum df_dram_flags { 138 /* 139 * Used to indicate that the contents of the rule are actually valid and 140 * should be considered. Many rules can be unused in hardware. 141 */ 142 DF_DRAM_F_VALID = 1 << 0, 143 /* 144 * Indicates that the DRAM hole is active for this particular rule. If 145 * this flag is set and the hole is valid in the DF, then we need to 146 * take the actual DRAM hole into account. 147 */ 148 DF_DRAM_F_HOLE = 1 << 1, 149 /* 150 * These next three are used to indicate when hashing is going on, which 151 * bits to use. These are for 64K, 2M, and 1G parts of addresses 152 * respectively. 153 */ 154 DF_DRAM_F_HASH_16_18 = 1 << 2, 155 DF_DRAM_F_HASH_21_23 = 1 << 3, 156 DF_DRAM_F_HASH_30_32 = 1 << 4, 157 /* 158 * Indicates that this rule should have remap processing and the remap 159 * target is valid. If the DF_DRAM_F_REMAP_SOCK flag is set, this 160 * indicates that the processing is based on socket versus a particular 161 * entry. 162 */ 163 DF_DRAM_F_REMAP_EN = 1 << 5, 164 DF_DRAM_F_REMAP_SOCK = 1 << 6 165 } df_dram_flags_t; 166 167 /* 168 * This represents a single offset value for a channel. This is used when 169 * applying normalization. 170 */ 171 typedef struct chan_offset { 172 uint32_t cho_raw; 173 boolean_t cho_valid; 174 uint64_t cho_offset; 175 } chan_offset_t; 176 177 /* 178 * This structure represents a single DRAM rule, no matter where it shows up. 179 * This smooths over the differences between generations. 180 */ 181 typedef struct df_dram_rule { 182 uint32_t ddr_raw_base; 183 uint32_t ddr_raw_limit; 184 uint32_t ddr_raw_ctrl; 185 uint32_t ddr_raw_ileave; 186 df_dram_flags_t ddr_flags; 187 uint64_t ddr_base; 188 uint64_t ddr_limit; 189 uint16_t ddr_dest_fabid; 190 uint8_t ddr_sock_ileave_bits; 191 uint8_t ddr_die_ileave_bits; 192 uint8_t ddr_addr_start; 193 uint8_t ddr_remap_ent; 194 df_chan_ileave_t ddr_chan_ileave; 195 } df_dram_rule_t; 196 197 typedef struct umc_dimm_base { 198 uint64_t udb_base; 199 boolean_t udb_valid; 200 } umc_dimm_base_t; 201 202 typedef enum umc_dimm_type { 203 UMC_DIMM_T_UNKNOWN, 204 UMC_DIMM_T_DDR4, 205 UMC_DIMM_T_LPDDR4, 206 UMC_DIMM_T_DDR5, 207 UMC_DIMM_T_LPDDR5 208 } umc_dimm_type_t; 209 210 typedef enum umc_dimm_width { 211 UMC_DIMM_W_X4, 212 UMC_DIMM_W_X8, 213 UMC_DIMM_W_X16, 214 } umc_dimm_width_t; 215 216 typedef enum umc_dimm_kind { 217 UMC_DIMM_K_UDIMM, 218 UMC_DIMM_K_RDIMM, 219 UMC_DIMM_K_LRDIMM, 220 UMC_DIMM_K_3DS_RDIMM 221 } umc_dimm_kind_t; 222 223 typedef enum umc_dimm_flags { 224 /* 225 * This flag indicates that this DIMM should be used for decoding 226 * purposes. It basically means that there is at least one chip-select 227 * decoding register that has been enabled. Unfortunately, we don't have 228 * a good way right now of distinguishing between a DIMM being present 229 * and being usable. This likely needs to be re-evaluated when we 230 * consider how we present things to topo. We may be able to pull this 231 * out of the clock disable logic. 232 */ 233 UMC_DIMM_F_VALID = 1 << 0, 234 } umc_dimm_flags_t; 235 236 /* 237 * A DIMM may have one or more ranks, which is an independent logical item that 238 * is activated by a 'chip-select' signal on a DIMM (e.g. CS_L[1:0]). In a given 239 * channel, AMD always has two instances of a 'chip-select' data structure. 240 * While these have a 1:1 correspondence in the case of single and dual rank 241 * DIMMs, in the case where there are more, then rank multiplication rules are 242 * used to determine which of the additional chip and chip-select signals to 243 * actually drive on the bus. But still, there are only up to two of these 244 * structures. To match AMD terminology we call these a 'chip-select' or 245 * 'umc_cs_t'. 246 * 247 * The amount of information that exists on a per-chip-select and per-DIMM basis 248 * varies between the different memory controller generations. As such, we 249 * normalize things such that a given chip-select always has all of the 250 * information related to it, duplicating it in the DDR4 case. 251 * 252 * While DDR5 adds the notion of sub-channels, a single chip-select is used to 253 * cover both sub-channels and instead a bit in the normalized address (and 254 * hashing) is used to determine which sub-channel to active. So while hardware 255 * actually has different chip-select lines for each sub-channel they are not 256 * represented that way in the UMC. 257 */ 258 typedef struct umc_cs { 259 umc_dimm_base_t ucs_base; 260 umc_dimm_base_t ucs_sec; 261 uint64_t ucs_base_mask; 262 uint64_t ucs_sec_mask; 263 uint8_t ucs_nbanks; 264 uint8_t ucs_ncol; 265 uint8_t ucs_nrow_lo; 266 uint8_t ucs_nrow_hi; 267 uint8_t ucs_nrm; 268 uint8_t ucs_nbank_groups; 269 uint8_t ucs_cs_xor; 270 uint8_t ucs_row_hi_bit; 271 uint8_t ucs_row_low_bit; 272 uint8_t ucs_bank_bits[ZEN_UMC_MAX_BANK_BITS]; 273 uint8_t ucs_col_bits[ZEN_UMC_MAX_COL_BITS]; 274 uint8_t ucs_inv_msbs; 275 uint8_t ucs_rm_bits[ZEN_UMC_MAX_RM_BITS]; 276 uint8_t ucs_inv_msbs_sec; 277 uint8_t ucs_rm_bits_sec[ZEN_UMC_MAX_RM_BITS]; 278 uint8_t ucs_subchan; 279 } umc_cs_t; 280 281 /* 282 * This structure represents information about a DIMM. Most of the interesting 283 * stuff is on the umc_cs_t up above, which is the logical 'chip-select' that 284 * AMD implements in the UMC. 285 * 286 * When we come back and add topo glue for the driver, we should consider adding 287 * the following information here and in the channel: 288 * 289 * o Configured DIMM speed 290 * o Channel capable speed 291 * o Calculated size 292 * o A way to map this DIMM to an SMBIOS / SPD style entry 293 */ 294 typedef struct umc_dimm { 295 umc_dimm_flags_t ud_flags; 296 umc_dimm_width_t ud_width; 297 umc_dimm_type_t ud_type; 298 umc_dimm_kind_t ud_kind; 299 uint32_t ud_dimmno; 300 uint32_t ud_dimmcfg_raw; 301 umc_cs_t ud_cs[ZEN_UMC_MAX_CS_PER_DIMM]; 302 } umc_dimm_t; 303 304 typedef enum umc_chan_flags { 305 /* 306 * Indicates that the channel has enabled ECC logic. 307 */ 308 UMC_CHAN_F_ECC_EN = 1 << 0, 309 /* 310 * We believe that this indicates some amount of the AMD SEV encryption 311 * is ongoing, leveraging some of the page-table control. 312 */ 313 UMC_CHAN_F_ENCR_EN = 1 << 1, 314 /* 315 * Indicates that the channel is employing data scrambling. This is 316 * basically what folks have called Transparent Shared Memory 317 * Encryption. 318 */ 319 UMC_CHAN_F_SCRAMBLE_EN = 1 << 2 320 } umc_chan_flags_t; 321 322 typedef struct umc_bank_hash { 323 uint32_t ubh_row_xor; 324 uint32_t ubh_col_xor; 325 boolean_t ubh_en; 326 } umc_bank_hash_t; 327 328 typedef struct umc_addr_hash { 329 uint64_t uah_addr_xor; 330 boolean_t uah_en; 331 } umc_addr_hash_t; 332 333 typedef struct umc_pc_hash { 334 uint32_t uph_row_xor; 335 uint32_t uph_col_xor; 336 uint8_t uph_bank_xor; 337 boolean_t uph_en; 338 } umc_pc_hash_t; 339 340 typedef enum umc_chan_hash_flags { 341 UMC_CHAN_HASH_F_BANK = 1 << 0, 342 UMC_CHAN_HASH_F_RM = 1 << 1, 343 UMC_CHAN_HASH_F_PC = 1 << 2, 344 UMC_CHAN_HASH_F_CS = 1 << 3, 345 } umc_chan_hash_flags_t; 346 347 typedef struct umc_chan_hash { 348 umc_chan_hash_flags_t uch_flags; 349 umc_bank_hash_t uch_bank_hashes[ZEN_UMC_MAX_CHAN_BANK_HASH]; 350 umc_addr_hash_t uch_rm_hashes[ZEN_UMC_MAX_CHAN_RM_HASH]; 351 umc_addr_hash_t uch_cs_hashes[ZEN_UMC_MAX_CHAN_CS_HASH]; 352 umc_pc_hash_t uch_pc_hash; 353 } umc_chan_hash_t; 354 355 /* 356 * This structure represents the overall memory channel. There is a 1:1 357 * relationship between these structures and discover UMC hardware entities on 358 * the data fabric. Note, these always exist regardless of whether the channels 359 * are actually implemented on a PCB or not. 360 */ 361 typedef struct zen_umc_chan { 362 umc_chan_flags_t chan_flags; 363 uint32_t chan_fabid; 364 uint32_t chan_instid; 365 uint32_t chan_logid; 366 uint32_t chan_nrules; 367 uint32_t chan_umccfg_raw; 368 uint32_t chan_datactl_raw; 369 uint32_t chan_eccctl_raw; 370 uint32_t chan_umccap_raw; 371 uint32_t chan_umccap_hi_raw; 372 uint32_t chan_np2_raw; 373 uint32_t chan_np2_space0; 374 df_dram_rule_t chan_rules[ZEN_UMC_MAX_CS_RULES]; 375 chan_offset_t chan_offsets[ZEN_UMC_MAX_DRAM_OFFSET]; 376 umc_dimm_t chan_dimms[ZEN_UMC_MAX_DIMMS]; 377 umc_chan_hash_t chan_hash; 378 } zen_umc_chan_t; 379 380 typedef struct zen_umc_cs_remap { 381 uint_t csr_nremaps; 382 uint16_t csr_remaps[ZEN_UMC_MAX_REMAP_ENTS]; 383 } zen_umc_cs_remap_t; 384 385 typedef enum zen_umc_df_flags { 386 /* 387 * Indicates that the DRAM Hole is valid and in use. 388 */ 389 ZEN_UMC_DF_F_HOLE_VALID = 1 << 0, 390 /* 391 * These next three are used to indicate when hashing is going on, which 392 * bits to use. These are for 64K, 2M, and 1G parts of addresses 393 * respectively. 394 */ 395 ZEN_UMC_DF_F_HASH_16_18 = 1 << 1, 396 ZEN_UMC_DF_F_HASH_21_23 = 1 << 2, 397 ZEN_UMC_DF_F_HASH_30_32 = 1 << 3 398 } zen_umc_df_flags_t; 399 400 typedef struct zen_umc_df { 401 zen_umc_df_flags_t zud_flags; 402 uint_t zud_dfno; 403 uint_t zud_ccm_inst; 404 uint_t zud_dram_nrules; 405 uint_t zud_nchan; 406 uint_t zud_cs_nremap; 407 uint32_t zud_hole_raw; 408 uint32_t zud_glob_ctl_raw; 409 uint64_t zud_hole_base; 410 df_dram_rule_t zud_rules[ZEN_UMC_MAX_DRAM_RULES]; 411 zen_umc_cs_remap_t zud_remap[ZEN_UMC_MAX_CS_REMAPS]; 412 zen_umc_chan_t zud_chan[ZEN_UMC_MAX_UMCS]; 413 } zen_umc_df_t; 414 415 typedef enum zen_umc_umc_style { 416 ZEN_UMC_UMC_S_DDR4, 417 ZEN_UMC_UMC_S_DDR4_APU, 418 ZEN_UMC_UMC_S_DDR5, 419 ZEN_UMC_UMC_S_DDR5_APU 420 } zen_umc_umc_style_t; 421 422 typedef enum zen_umc_fam_flags { 423 /* 424 * Indicates that there's an indirection table for the destinations of 425 * target rules. 426 */ 427 ZEN_UMC_FAM_F_TARG_REMAP = 1 << 0, 428 /* 429 * Indicates that non-power of two interleave rules are supported and 430 * that we need additional register configuration. 431 */ 432 ZEN_UMC_FAM_F_NP2 = 1 << 1, 433 /* 434 * Indicates that the DF hashing rules to configure COD hashes need to 435 * be checked. 436 */ 437 ZEN_UMC_FAM_F_NORM_HASH = 1 << 2, 438 /* 439 * In DDR4 this indicates presence of the HashRM and in DDR5 the 440 * AddrHash. 441 */ 442 ZEN_UMC_FAM_F_UMC_HASH = 1 << 3, 443 /* 444 * Indicates support for extended UMC registers for larger addresses. 445 * Generally on Server parts. 446 */ 447 ZEN_UMC_FAM_F_UMC_EADDR = 1 << 4, 448 /* 449 * Indicates that CS decoder supports an XOR function. 450 */ 451 ZEN_UMC_FAM_F_CS_XOR = 1 << 5 452 } zen_umc_fam_flags_t; 453 454 /* 455 * This structure is meant to contain per SoC family (not CPUID family) 456 * information. This is stuff that we basically need to encode about the 457 * processor itself and relates to its limits, the style it operates in, the 458 * way it works, etc. 459 */ 460 typedef struct zen_umc_fam_data { 461 zen_family_t zufd_family; 462 zen_umc_fam_flags_t zufd_flags; 463 uint8_t zufd_dram_nrules; 464 uint8_t zufd_cs_nrules; 465 zen_umc_umc_style_t zufd_umc_style; 466 umc_chan_hash_flags_t zufd_chan_hash; 467 } zen_umc_fam_data_t; 468 469 /* 470 * The top-level data structure for the system. This is a single structure that 471 * represents everything that could possibly exist and is filled in with what we 472 * actually discover. 473 */ 474 typedef struct zen_umc { 475 uint64_t umc_tom; 476 uint64_t umc_tom2; 477 dev_info_t *umc_dip; 478 zen_family_t umc_family; 479 df_rev_t umc_df_rev; 480 const zen_umc_fam_data_t *umc_fdata; 481 df_fabric_decomp_t umc_decomp; 482 uint_t umc_ndfs; 483 zen_umc_df_t umc_dfs[ZEN_UMC_MAX_DFS]; 484 /* 485 * This lock protects the data underneath here. 486 */ 487 kmutex_t umc_nvl_lock; 488 nvlist_t *umc_decoder_nvl; 489 char *umc_decoder_buf; 490 size_t umc_decoder_len; 491 } zen_umc_t; 492 493 typedef enum zen_umc_decode_failure { 494 ZEN_UMC_DECODE_F_NONE = 0, 495 /* 496 * Indicates that the address was not contained within the TOM and TOM2 497 * regions that indicate DRAM (or was in a reserved hole). 498 */ 499 ZEN_UMC_DECODE_F_OUTSIDE_DRAM, 500 /* 501 * Indicates that we could not find a DF rule in the CCM rule that 502 * claims to honor this address. 503 */ 504 ZEN_UMC_DECODE_F_NO_DF_RULE, 505 /* 506 * Indicates that trying to construct the interleave address to use 507 * would have led to an underflow somehow. 508 */ 509 ZEN_UMC_DECODE_F_ILEAVE_UNDERFLOW, 510 /* 511 * Indicates that we do not currently support decoding the indicated 512 * channel interleave type. 513 */ 514 ZEN_UMC_DECODE_F_CHAN_ILEAVE_NOTSUP, 515 /* 516 * Indicates that we found a COD hash rule that had a non-zero socket or 517 * die interleave, which isn't supported and we don't know how to 518 * decode. 519 */ 520 ZEN_UMC_DECODE_F_COD_BAD_ILEAVE, 521 /* 522 * This is similar to the above, but indicates that we hit a bad NPS 523 * interleave rule instead of a COD. 524 */ 525 ZEN_UMC_DECODE_F_NPS_BAD_ILEAVE, 526 /* 527 * Indicates that somehow we thought we should use a remap rule set that 528 * was beyond our capabilities. 529 */ 530 ZEN_UMC_DECODE_F_BAD_REMAP_SET, 531 /* 532 * Indicates that we tried to find an index for the remap rules; 533 * however, the logical component ID was outside the range of the number 534 * of entries that we have. 535 */ 536 ZEN_UMC_DECODE_F_BAD_REMAP_ENTRY, 537 /* 538 * Indicates that the remap rule had an invalid component bit set in its 539 * mask. 540 */ 541 ZEN_UMC_DECODE_F_REMAP_HAS_BAD_COMP, 542 /* 543 * Indicates that we could not find a UMC with the fabric ID we thought 544 * we should have. 545 */ 546 ZEN_UMC_DECODE_F_CANNOT_MAP_FABID, 547 /* 548 * Indicates that somehow the UMC we found did not actually contain a 549 * DRAM rule that covered our original PA. 550 */ 551 ZEN_UMC_DECODE_F_UMC_DOESNT_HAVE_PA, 552 /* 553 * Indicates that we would have somehow underflowed the address 554 * calculations normalizing the system address. 555 */ 556 ZEN_UMC_DECODE_F_CALC_NORM_UNDERFLOW, 557 /* 558 * Indicates that none of the UMC's chip-selects actually matched a base 559 * or secondary. 560 */ 561 ZEN_UMC_DECODE_F_NO_CS_BASE_MATCH 562 } zen_umc_decode_failure_t; 563 564 /* 565 * This struct accumulates all of our decoding logic and states and we use it so 566 * it's easier for us to look at what's going on and the decisions that we made 567 * along the way. 568 */ 569 typedef struct zen_umc_decoder { 570 zen_umc_decode_failure_t dec_fail; 571 uint64_t dec_fail_data; 572 uint64_t dec_pa; 573 const zen_umc_df_t *dec_df_rulesrc; 574 uint32_t dec_df_ruleno; 575 const df_dram_rule_t *dec_df_rule; 576 uint64_t dec_ilv_pa; 577 /* 578 * These three values represent the IDs that we extract from the 579 * interleave address. 580 */ 581 uint32_t dec_ilv_sock; 582 uint32_t dec_ilv_die; 583 uint32_t dec_ilv_chan; 584 uint32_t dec_ilv_fabid; 585 uint32_t dec_log_fabid; 586 uint32_t dec_remap_comp; 587 uint32_t dec_targ_fabid; 588 const zen_umc_chan_t *dec_umc_chan; 589 uint32_t dec_umc_ruleno; 590 uint64_t dec_norm_addr; 591 const umc_dimm_t *dec_dimm; 592 const umc_cs_t *dec_cs; 593 boolean_t dec_cs_sec; 594 uint32_t dec_dimm_col; 595 uint32_t dec_dimm_row; 596 uint8_t dec_log_csno; 597 uint8_t dec_dimm_bank; 598 uint8_t dec_dimm_bank_group; 599 uint8_t dec_dimm_subchan; 600 uint8_t dec_dimm_rm; 601 uint8_t dec_chan_csno; 602 uint8_t dec_dimm_no; 603 uint8_t dec_dimm_csno; 604 } zen_umc_decoder_t; 605 606 /* 607 * Decoding and normalization routines. 608 */ 609 extern boolean_t zen_umc_decode_pa(const zen_umc_t *, const uint64_t, 610 zen_umc_decoder_t *); 611 612 /* 613 * Fabric ID utilities 614 */ 615 extern boolean_t zen_fabric_id_valid_fabid(const df_fabric_decomp_t *, 616 const uint32_t); 617 extern boolean_t zen_fabric_id_valid_parts(const df_fabric_decomp_t *, 618 const uint32_t, const uint32_t, const uint32_t); 619 extern void zen_fabric_id_decompose(const df_fabric_decomp_t *, const uint32_t, 620 uint32_t *, uint32_t *, uint32_t *); 621 extern void zen_fabric_id_compose(const df_fabric_decomp_t *, const uint32_t, 622 const uint32_t, const uint32_t, uint32_t *); 623 624 /* 625 * Encoding and decoding 626 */ 627 extern nvlist_t *zen_umc_dump_decoder(zen_umc_t *); 628 extern boolean_t zen_umc_restore_decoder(nvlist_t *, zen_umc_t *); 629 630 #ifdef __cplusplus 631 } 632 #endif 633 634 #endif /* _ZEN_UMC_H */ 635