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