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
mcamd_synd_validate(struct mcamd_hdl * hdl,uint32_t synd,int syndtype)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
mcamd_eccsynd_decode(struct mcamd_hdl * hdl,uint32_t synd,uint_t * bitp)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
mcamd_cksynd_decode(struct mcamd_hdl * hdl,uint32_t synd,uint_t * symp,uint_t * patp)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
mcamd_cksym_decode(struct mcamd_hdl * hdl,uint_t sym,int * lowbitp,int * hibitp,int * data,int * check)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