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