1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 * 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <mcamd_api.h> 27 28 /* 29 * Indexed by syndrome, value is bit number. If value is -1, a multi-bit 30 * error has been detected. A special case is the zero'th entry - a 31 * syndrome of 0x0 indicates no bits in error. 32 */ 33 static char eccsynd[] = { 34 -1, 64, 65, -1, 66, -1, -1, -1, 67, -1, -1, 17, -1, -1, 16, -1, 35 68, -1, -1, 18, -1, 19, 20, -1, -1, 21, 22, -1, 23, -1, -1, -1, 36 69, -1, -1, 8, -1, 9, 10, -1, -1, 11, 12, -1, 13, -1, -1, -1, 37 -1, 14, -1, -1, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 38 70, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, -1, -1, -1, -1, 32, 39 -1, -1, 34, -1, 35, -1, -1, 36, 37, -1, -1, 38, -1, 39, -1, -1, 40 -1, -1, 56, -1, 57, -1, -1, 58, 59, -1, -1, 60, -1, 61, -1, -1, 41 62, -1, -1, -1, -1, 63, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 42 71, -1, -1, -1, -1, -1, -1, -1, -1, -1, 49, -1, -1, -1, -1, 48, 43 -1, -1, 50, -1, 51, -1, -1, 52, 53, -1, -1, 54, -1, 55, -1, -1, 44 -1, -1, 40, -1, 41, -1, -1, 42, 43, -1, -1, 44, -1, 45, -1, -1, 45 46, -1, -1, -1, -1, 47, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 46 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 0, -1, 47 -1, -1, -1, 2, -1, 3, 4, -1, -1, 5, 6, -1, 7, -1, -1, -1, 48 -1, -1, -1, 24, -1, 25, 26, -1, -1, 27, 28, -1, 29, -1, -1, -1, 49 -1, 30, -1, -1, 31, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 50 }; 51 52 /* 53 * The first dimension of this table is the errored bit pattern, which is the 54 * column dimension of the table in the BKDG. Conveniently, the bit pattern 55 * is also the lowest-order nibble in the syndrome, thus allowing the first 56 * dimension value to be calculated. The second dimension is the symbol 57 * number, which can be found by searching for a matching syndrome. 58 * 59 * Note that the first dimension is actually (errored_bit_pattern - 1) since 60 * 0 is not a valid errored bit pattern. 61 */ 62 #define MCAMD_CKSYND_NPATS 15 63 #define MCAMD_CKSYND_NSYMS 36 64 65 static uint16_t cksynd[MCAMD_CKSYND_NPATS][MCAMD_CKSYND_NSYMS] = { 66 /* table column 0x1 */ 67 { 0xe821, 0x5d31, 0x0001, 0x2021, 0x5041, 0xbe21, 0x4951, 0x74e1, 68 0x15c1, 0x3d01, 0x9801, 0xd131, 0xe1d1, 0x6051, 0xa4c1, 0x11c1, 69 0x45d1, 0x63e1, 0xb741, 0xdd41, 0x2bd1, 0x83c1, 0x8fd1, 0x4791, 70 0x5781, 0xbf41, 0x9391, 0xcce1, 0xa761, 0xff61, 0x5451, 0x6fc1, 71 0xbe01, 0x4101, 0xc441, 0x7621 }, 72 73 /* table column 0x2 */ 74 { 0x7c32, 0xa612, 0x0002, 0x3032, 0xa082, 0xd732, 0x8ea2, 0x9872, 75 0x2a42, 0x1602, 0xec02, 0x6212, 0x7262, 0xb0a2, 0xf842, 0x2242, 76 0x8a62, 0xb172, 0xd982, 0x6682, 0x3d62, 0xc142, 0xc562, 0x89e2, 77 0xa9c2, 0xd582, 0xe1e2, 0x4472, 0xf9b2, 0x55b2, 0xa8a2, 0xb542, 78 0xd702, 0x8202, 0x4882, 0x9b32 }, 79 80 /* table column 0x3 */ 81 { 0x9413, 0xfb23, 0x0003, 0x1013, 0xf0c3, 0x6913, 0xc7f3, 0xec93, 82 0x3f83, 0x2b03, 0x7403, 0xb323, 0x93b3, 0xd0f3, 0x5c83, 0x3383, 83 0xcfb3, 0xd293, 0x6ec3, 0xbbc3, 0x16b3, 0x4283, 0x4ab3, 0xce73, 84 0xfe43, 0x6ac3, 0x7273, 0x8893, 0x5ed3, 0xaad3, 0xfcf3, 0xda83, 85 0x6903, 0xc303, 0x8cc3, 0xed13 }, 86 87 /* table column 0x4 */ 88 { 0xbb44, 0x9584, 0x0004, 0x4044, 0x9054, 0x2144, 0x5394, 0xd6b4, 89 0xcef4, 0x8504, 0x6b04, 0x3884, 0xb834, 0x1094, 0xe6f4, 0xc8f4, 90 0x5e34, 0x14b4, 0x2254, 0x3554, 0x4f34, 0xa4f4, 0xa934, 0x5264, 91 0x92a4, 0x2954, 0x6464, 0xfdb4, 0xe214, 0x7914, 0x9694, 0x19f4, 92 0x2104, 0x5804, 0xf654, 0xda44 }, 93 94 /* table column 0x5 */ 95 { 0x5365, 0xc8b5, 0x0005, 0x6065, 0xc015, 0x9f65, 0x1ac5, 0xa255, 96 0xdb35, 0xb805, 0xf305, 0xe9b5, 0x59e5, 0x70c5, 0x4235, 0xd935, 97 0x1be5, 0x7755, 0x9515, 0xe815, 0x64e5, 0x2735, 0x26e5, 0x15f5, 98 0xc525, 0x9615, 0xf7f5, 0x3155, 0x4575, 0x8675, 0xc2c5, 0x7635, 99 0x9f05, 0x1905, 0x3215, 0xac65 }, 100 101 /* table column 0x6 */ 102 { 0xc776, 0x3396, 0x0006, 0x7076, 0x30d6, 0xf676, 0xdd36, 0x4ec6, 103 0xe4b6, 0x9306, 0x8706, 0x5a96, 0xca56, 0xa036, 0x1eb6, 0xeab6, 104 0xd456, 0xa5c6, 0xfbd6, 0x53d6, 0x7256, 0x65b6, 0x6c56, 0xdb86, 105 0x3b66, 0xfcd6, 0x8586, 0xb9c6, 0x1ba6, 0x2ca6, 0x3e36, 0xacb6, 106 0xf606, 0xda06, 0xbed6, 0x4176 }, 107 108 /* table column 0x7 */ 109 { 0x2f57, 0x6ea7, 0x0007, 0x5057, 0x6097, 0x4857, 0x9467, 0x3a27, 110 0xf177, 0xae07, 0x1f07, 0x8ba7, 0x2b87, 0xc067, 0xba77, 0xfb77, 111 0x9187, 0xc627, 0x4c97, 0x8e97, 0x5987, 0xe677, 0xe387, 0x9c17, 112 0x6ce7, 0x4397, 0x1617, 0x7527, 0xbcc7, 0xd3c7, 0x6a67, 0xc377, 113 0x4807, 0x9b07, 0x7a97, 0x3757 }, 114 115 /* table column 0x8 */ 116 { 0xdd88, 0xeac8, 0x0008, 0x8088, 0xe0a8, 0x3288, 0xa1e8, 0x6bd8, 117 0x4758, 0xca08, 0xbd08, 0x1cc8, 0xdc18, 0x20e8, 0x7b58, 0x4c58, 118 0xa718, 0x28d8, 0x33a8, 0x1aa8, 0x8518, 0xf858, 0xfe18, 0xa3b8, 119 0xe3f8, 0x3ea8, 0xb8b8, 0x56d8, 0x7328, 0x9e28, 0xebe8, 0x2e58, 120 0x3208, 0xac08, 0x5ba8, 0x6f88 }, 121 122 /* table column 0x9 */ 123 { 0x35a9, 0xb7f9, 0x0009, 0xa0a9, 0xb0e9, 0x8ca9, 0xe8b9, 0x1f39, 124 0x5299, 0xf709, 0x2509, 0xcdf9, 0x3dc9, 0x40b9, 0xdf99, 0x5d99, 125 0xe2c9, 0x4b39, 0x84e9, 0xc7e9, 0xaec9, 0x7b99, 0x71c9, 0xe429, 126 0xb479, 0x81e9, 0x2b29, 0x9a39, 0xd449, 0x6149, 0xbfb9, 0x4199, 127 0x8c09, 0xed09, 0x9fe9, 0x19a9 }, 128 129 /* table column 0xa */ 130 { 0xa1ba, 0x4cda, 0x000a, 0xb0ba, 0x402a, 0xe5ba, 0x2f4a, 0xf3aa, 131 0x6d1a, 0xdc0a, 0x510a, 0x7eda, 0xae7a, 0x904a, 0x831a, 0x6e1a, 132 0x2d7a, 0x99aa, 0xea2a, 0x7c2a, 0xb87a, 0x391a, 0x3b7a, 0x2a5a, 133 0x4a3a, 0xeb2a, 0x595a, 0x12aa, 0x8a9a, 0xcb9a, 0x434a, 0x9b1a, 134 0xe50a, 0x2e0a, 0x132a, 0xf4ba }, 135 136 /* table column 0xb */ 137 { 0x499b, 0x11eb, 0x000b, 0x909b, 0x106b, 0x5b9b, 0x661b, 0x874b, 138 0x78db, 0xe10b, 0xc90b, 0xafeb, 0x4fab, 0xf01b, 0x27db, 0x7fdb, 139 0x68ab, 0xfa4b, 0x5d6b, 0xa16b, 0x93ab, 0xbadb, 0xb4ab, 0x6dcb, 140 0x1dbb, 0x546b, 0xcacb, 0xde4b, 0x2dfb, 0x34fb, 0x171b, 0xf4db, 141 0x5b0b, 0x6f0b, 0xd76b, 0x829b }, 142 143 /* table column 0xc */ 144 { 0x66cc, 0x7f4c, 0x000c, 0xc0cc, 0x70fc, 0x13cc, 0xf27c, 0xbd6c, 145 0x89ac, 0x4f0c, 0xd60c, 0x244c, 0x642c, 0x307c, 0x9dac, 0x84ac, 146 0xf92c, 0x3c6c, 0x11fc, 0x2ffc, 0xca2c, 0x5cac, 0x572c, 0xf1dc, 147 0x715c, 0x17fc, 0xdcdc, 0xab6c, 0x913c, 0xe73c, 0x7d7c, 0x37ac, 148 0x130c, 0xf40c, 0xadfc, 0xb5cc }, 149 150 /* table column 0xd */ 151 { 0x8eed, 0x227d, 0x000d, 0xe0ed, 0x20bd, 0xaded, 0xbb2d, 0xc98d, 152 0x9c6d, 0x720d, 0x4e0d, 0xf57d, 0x85fd, 0x502d, 0x396d, 0x956d, 153 0xbcfd, 0x5f8d, 0xa6bd, 0xf2bd, 0xe1fd, 0xdf6d, 0xd8fd, 0xb64d, 154 0x26dd, 0xa8bd, 0x4f4d, 0x678d, 0x365d, 0x185d, 0x292d, 0x586d, 155 0xad0d, 0xb50d, 0x69bd, 0xc3ed }, 156 157 /* table column 0xe */ 158 { 0x1afe, 0xd95e, 0x000e, 0xf0fe, 0xd07e, 0xc4fe, 0x7cde, 0x251e, 159 0xa3ee, 0x590e, 0x3a0e, 0x465e, 0x164e, 0x80de, 0x65ee, 0xa6ee, 160 0x734e, 0x8d1e, 0xc87e, 0x497e, 0xf74e, 0x9dee, 0x924e, 0x783e, 161 0xd89e, 0xc27e, 0x3d3e, 0xef1e, 0x688e, 0xb28e, 0xd5de, 0x82ee, 162 0xc40e, 0x760e, 0xe57e, 0x2efe }, 163 164 /* table column 0xf */ 165 { 0xf2df, 0x846f, 0x000f, 0xd0df, 0x803f, 0x7adf, 0x358f, 0x51ff, 166 0xb62f, 0x640f, 0xa20f, 0x976f, 0xf79f, 0xe08f, 0xc12f, 0xb72f, 167 0x369f, 0xeeff, 0x7f3f, 0x943f, 0xdc9f, 0x1e2f, 0x1d9f, 0x3faf, 168 0x8f1f, 0x7d3f, 0xaeaf, 0x23ff, 0xcfef, 0x4def, 0x818f, 0xed2f, 169 0x7a0f, 0x370f, 0x213f, 0x58df } 170 }; 171 172 int 173 mcamd_synd_validate(struct mcamd_hdl *hdl, uint32_t synd, int syndtype) 174 { 175 int result; 176 177 switch (syndtype) { 178 case AMD_SYNDTYPE_ECC: 179 result = (synd > 0 && synd <= 0xff); 180 break; 181 case AMD_SYNDTYPE_CHIPKILL: 182 result = (synd > 0 && synd <= 0xffff); 183 break; 184 default: 185 mcamd_dprintf(hdl, MCAMD_DBG_FLOW, 186 "mcamd_synd_validate: invalid syndtype %d\n", syndtype); 187 return (0); 188 } 189 190 if (result == 0) 191 mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "mcamd_synd_validate: " 192 "invalid %s syndrome 0x%x\n", 193 syndtype == AMD_SYNDTYPE_ECC ? "64/8" : "ChipKill", 194 synd); 195 196 return (result); 197 } 198 199 int 200 mcamd_eccsynd_decode(struct mcamd_hdl *hdl, uint32_t synd, uint_t *bitp) 201 { 202 char bit; 203 204 if (synd > 0xff) { 205 mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "mcamd_eccsynd_decode: " 206 "invalid synd 0x%x\n", synd); 207 return (0); 208 } 209 if ((bit = eccsynd[synd]) == -1) { 210 mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "mcamd_eccsynd_decode: " 211 "synd 0x%x is a multi-bit syndrome\n", synd); 212 return (0); 213 } 214 215 mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "mcamd_eccsynd_decode: " 216 "synd 0x%x is single-bit and indicates %s bit %d\n", synd, 217 bit >= 64 ? "check" : "data", 218 bit >= 64 ? bit - 64 : bit); 219 220 *bitp = bit; 221 return (1); 222 } 223 224 int 225 mcamd_cksynd_decode(struct mcamd_hdl *hdl, uint32_t synd, uint_t *symp, 226 uint_t *patp) 227 { 228 int pat = synd & 0xf; 229 int i; 230 231 if (pat == 0) { 232 mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "mcamd_cksynd_decode: " 233 "synd 0x%x is not a correctable syndrome\n", synd); 234 return (0); 235 } 236 237 for (i = 0; i < MCAMD_CKSYND_NSYMS; i++) { 238 if (cksynd[pat - 1][i] == synd) { 239 *symp = i; 240 *patp = pat; 241 mcamd_dprintf(hdl, MCAMD_DBG_FLOW, 242 "mcamd_cksynd_decode: synd 0x%x is correctable " 243 "and indicates symbol %d\n", synd, i); 244 return (1); 245 } 246 } 247 248 mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "mcamd_cksynd_decode: " 249 "synd 0x%x is not a correctable syndrome\n", synd); 250 return (0); 251 } 252 253 /* 254 * symbols 0 to 0xf: data[63:0] 255 * symbols 0x10 to 0x1f: data[127:64] 256 * symbols 0x20, 0x21: checkbits for [63:0] 257 * symbols 0x22, 0x23: checkbits for [127:64] 258 */ 259 /*ARGSUSED*/ 260 int 261 mcamd_cksym_decode(struct mcamd_hdl *hdl, uint_t sym, int *lowbitp, 262 int *hibitp, int *data, int *check) 263 { 264 if (sym <= 0xf || sym >= 0x10 && sym <= 0x1f) { 265 *data = 1; 266 *check = 0; 267 *lowbitp = sym * 4; 268 *hibitp = (sym + 1) * 4 - 1; 269 } else if (sym >= 0x20 && sym <= 0x23) { 270 *data = 0; 271 *check = 1; 272 *lowbitp = (sym - 0x20) * 4; 273 *hibitp = (sym + 1 - 0x20) * 4 - 1; 274 } else { 275 return (0); 276 } 277 278 return (1); 279 } 280