Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | /* |
2 | * ========== Copyright Header Begin ========================================== | |
3 | * | |
4 | * Hypervisor Software File: mem-seeprom.c | |
5 | * | |
6 | * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. | |
7 | * | |
8 | * - Do no alter or remove copyright notices | |
9 | * | |
10 | * - Redistribution and use of this software in source and binary forms, with | |
11 | * or without modification, are permitted provided that the following | |
12 | * conditions are met: | |
13 | * | |
14 | * - Redistribution of source code must retain the above copyright notice, | |
15 | * this list of conditions and the following disclaimer. | |
16 | * | |
17 | * - Redistribution in binary form must reproduce the above copyright notice, | |
18 | * this list of conditions and the following disclaimer in the | |
19 | * documentation and/or other materials provided with the distribution. | |
20 | * | |
21 | * Neither the name of Sun Microsystems, Inc. or the names of contributors | |
22 | * may be used to endorse or promote products derived from this software | |
23 | * without specific prior written permission. | |
24 | * | |
25 | * This software is provided "AS IS," without a warranty of any kind. | |
26 | * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, | |
27 | * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A | |
28 | * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN | |
29 | * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR | |
30 | * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR | |
31 | * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN | |
32 | * OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR | |
33 | * FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE | |
34 | * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, | |
35 | * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF | |
36 | * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. | |
37 | * | |
38 | * You acknowledge that this software is not designed, licensed or | |
39 | * intended for use in the design, construction, operation or maintenance of | |
40 | * any nuclear facility. | |
41 | * | |
42 | * ========== Copyright Header End ============================================ | |
43 | */ | |
44 | /* | |
45 | * id: @(#)mem-seeprom.c 1.4 05/11/15 | |
46 | * purpose: | |
47 | * copyright: Copyright 2005 Sun Microsystems, Inc. All Rights Reserved | |
48 | * copyright: Use is subject to license terms. | |
49 | */ | |
50 | ||
51 | #include <stdio.h> | |
52 | #include <stdlib.h> | |
53 | #include <strings.h> | |
54 | #include <sys/param.h> | |
55 | #include "gen-seeprom.h" | |
56 | #include "mem-seeprom.h" | |
57 | #include "prototypes.h" | |
58 | ||
59 | struct fixed_seeprom mem_seeprom_data[] = { | |
60 | /* name size type value */ | |
61 | { NULL, 0, 0, 0, NULL}, | |
62 | }; | |
63 | ||
64 | static struct dimm_list_entry *dimm_list = NULL; | |
65 | static struct dimm_list_entry *cur_dimm; | |
66 | ||
67 | /* mem_layout is array of pointers to data for each memc */ | |
68 | static struct mem_data_entry *mem_layout = NULL; | |
69 | ||
70 | static int max_bits = 0; | |
71 | static int max_banks = 0; | |
72 | static int num_dimms_per_bank = 0; | |
73 | static int num_memc = 1; | |
74 | ||
75 | static int cur_memc = 0; /* bit_mask to indicate which memc data applies */ | |
76 | static int force_default_mc = 0; /* support for older cfgs w/out memc_id */ | |
77 | ||
78 | static int max_encode_dimm_bits = 0; | |
79 | static int max_dimms = 0; | |
80 | static int num_dimms_in_list = 0; | |
81 | static int num_bits_in_list = 0; | |
82 | static int *bit_to_dimm_map = NULL; | |
83 | static int *bit_to_pin_map = NULL; | |
84 | ||
85 | static int processing_dimm_list = 0; | |
86 | static int processing_bit_map = 0; | |
87 | static int table_width = 0; | |
88 | static int memc_id_init = 0; | |
89 | ||
90 | static int | |
91 | parse_memc_id(char *line) | |
92 | { | |
93 | unsigned int input_val; | |
94 | ||
95 | if (scan_line(line, &input_val) == ERROR) | |
96 | return (ERROR); | |
97 | ||
98 | /* For each memc_id, set the mask bit */ | |
99 | if ((input_val >= 0) && (input_val < num_memc)) { | |
100 | cur_memc |= (1 << input_val); | |
101 | memc_id_init = 1; | |
102 | } else { | |
103 | print_error("Invalid memc_id\n"); | |
104 | return (ERROR); | |
105 | } | |
106 | ||
107 | return (NO_ERROR); | |
108 | } | |
109 | ||
110 | static int | |
111 | update_dimm_list(char *parameter, char *line) | |
112 | { | |
113 | ||
114 | char temp[MAXNAMESIZE], input_str[DIMM_NAME_SIZE+1]; | |
115 | ||
116 | if (strcmp("memc_id", parameter) == 0) { | |
117 | return (parse_memc_id(line)); | |
118 | } else if (strcmp("DIMM", parameter) != 0) { | |
119 | fprintf(stderr, "%s is not a valid DIMM list parameter\n", | |
120 | parameter); | |
121 | return (ERROR); | |
122 | } | |
123 | if (sscanf(line, "%32s %s", temp, input_str) != 2) { | |
124 | fprintf(stderr, "DIMM list entries need 2 strings\n"); | |
125 | return (ERROR); | |
126 | } | |
127 | if (strlen(input_str) > (DIMM_NAME_SIZE - 1)) { | |
128 | fprintf(stderr, "DIMM name cannot be greater than %d letters\n", | |
129 | DIMM_NAME_SIZE-1); | |
130 | return (ERROR); | |
131 | } | |
132 | ||
133 | if (dimm_list == NULL) { | |
134 | dimm_list = malloc(sizeof (struct dimm_list_entry)); | |
135 | dimm_list->next = NULL; | |
136 | cur_dimm = dimm_list; | |
137 | } else { | |
138 | cur_dimm->next = malloc(sizeof (struct dimm_list_entry)); | |
139 | cur_dimm = cur_dimm->next; | |
140 | cur_dimm->next = NULL; | |
141 | } | |
142 | num_dimms_in_list += 1; | |
143 | (void) strcpy(cur_dimm->name, input_str); | |
144 | return (NO_ERROR); | |
145 | } | |
146 | ||
147 | int prev_bit_num = 0; | |
148 | ||
149 | ||
150 | static int | |
151 | update_bit_map(char *parameter, char *line) | |
152 | { | |
153 | int bit_num, dimm, pin_num; | |
154 | ||
155 | if (strcmp("memc_id", parameter) == 0) { | |
156 | return (parse_memc_id(line)); | |
157 | } | |
158 | ||
159 | if (sscanf(line, "%d %d %d", &bit_num, &dimm, &pin_num) != 3) { | |
160 | fprintf(stderr, "bit map entries need 3 numeric values\n"); | |
161 | return (ERROR); | |
162 | } | |
163 | ||
164 | if ((bit_num >= 0 && (bit_num < (max_bits))) && | |
165 | (dimm >= 0 && (dimm < (num_dimms_per_bank))) && | |
166 | (pin_num >= 0)) { | |
167 | bit_to_dimm_map[bit_num] = dimm; | |
168 | bit_to_pin_map[bit_num] = pin_num; | |
169 | } else { | |
170 | fprintf(stderr, "Invalid bit map entry for bit# %d\n", bit_num); | |
171 | fprintf(stderr, "bit#, dimm# and pin# must be >= 0, "); | |
172 | fprintf(stderr, " bit# must be < %d and dimm# < %d\n", max_bits, | |
173 | num_dimms_per_bank); | |
174 | return (ERROR); | |
175 | } | |
176 | ||
177 | num_bits_in_list++; | |
178 | ||
179 | return (NO_ERROR); | |
180 | ||
181 | } | |
182 | ||
183 | static int | |
184 | mem_params(char *line, int *mem_data) | |
185 | { | |
186 | char temp2[MAXNAMESIZE]; | |
187 | int data = 0; | |
188 | ||
189 | if ((sscanf(line, "%32s %d", temp2, &data) != 2) || (data <= 0)) { | |
190 | return (ERROR); | |
191 | } else { | |
192 | *mem_data = data; | |
193 | } | |
194 | return (NO_ERROR); | |
195 | } | |
196 | ||
197 | static int | |
198 | init_mem_params() | |
199 | { | |
200 | int retval = NO_ERROR; | |
201 | ||
202 | if (table_width == 0) { | |
203 | print_error("table_width must be initialized!\n"); | |
204 | retval = ERROR; | |
205 | } | |
206 | if (max_banks == 0) { | |
207 | print_error("max_banks must be initialized!\n"); | |
208 | retval = ERROR; | |
209 | } | |
210 | if (max_bits == 0) { | |
211 | print_error("max_bits must be initialized!\n"); | |
212 | retval = ERROR; | |
213 | } | |
214 | if (num_dimms_per_bank == 0) { | |
215 | print_error("num_dimms_per_bank must be initialized!\n"); | |
216 | retval = ERROR; | |
217 | } | |
218 | if (mem_layout == NULL) { | |
219 | print_error("num_memc not initialized. Assuming 1\n"); | |
220 | mem_layout = malloc(sizeof (struct mem_data_entry)); | |
221 | force_default_mc = 1; | |
222 | } | |
223 | return (retval); | |
224 | } | |
225 | ||
226 | int | |
227 | mem_dynamic(char *parameter, char *line) | |
228 | { | |
229 | ||
230 | int retval = NO_ERROR; | |
231 | unsigned long long temp; | |
232 | char temp2[MAXNAMESIZE]; | |
233 | int count, i; | |
234 | ||
235 | if (strcmp(parameter, "table_width") == 0) { | |
236 | retval = mem_params(line, &table_width); | |
237 | } else if (strcmp(parameter, "max_bits") == 0) { | |
238 | retval = mem_params(line, &max_bits); | |
239 | } else if (strcmp(parameter, "max_banks") == 0) { | |
240 | retval = mem_params(line, &max_banks); | |
241 | } else if (strcmp(parameter, "num_memc") == 0) { | |
242 | retval = mem_params(line, &num_memc); | |
243 | if (mem_layout == NULL) { | |
244 | mem_layout = | |
245 | malloc(sizeof (struct mem_data_entry)*num_memc); | |
246 | } else { | |
247 | printf("ERROR: Already initialized num_memc\n"); | |
248 | retval = ERROR; | |
249 | } | |
250 | } else if (strcmp(parameter, "num_dimms_per_bank") == 0) { | |
251 | retval = mem_params(line, &num_dimms_per_bank); | |
252 | if (retval != ERROR) { | |
253 | max_dimms = num_dimms_per_bank * max_banks; | |
254 | max_encode_dimm_bits = 0; | |
255 | count = num_dimms_per_bank; | |
256 | while (count != 1) { | |
257 | count >>= 1; | |
258 | max_encode_dimm_bits++; | |
259 | } | |
260 | } | |
261 | } else if (processing_dimm_list) { | |
262 | if (strcmp(parameter, "dimm_list_end") == 0) { | |
263 | processing_dimm_list = 0; | |
264 | if (num_dimms_in_list != | |
265 | (num_dimms_per_bank * max_banks)) { | |
266 | sprintf(err_string, | |
267 | "DIMM list must have %d names!\n", | |
268 | num_dimms_per_bank * max_banks); | |
269 | print_error(err_string); | |
270 | retval = ERROR; | |
271 | } | |
272 | if (force_default_mc) { | |
273 | cur_memc = 1; | |
274 | } else if (memc_id_init == 0) { | |
275 | print_error("Must init memc_id in dimm_list\n"); | |
276 | retval = ERROR; | |
277 | } | |
278 | for (i = 0; i < num_memc; i++) { | |
279 | if (cur_memc & (1 << i)) { | |
280 | mem_layout[i].dimm_list = dimm_list; | |
281 | } | |
282 | } | |
283 | dimm_list = NULL; | |
284 | } else { | |
285 | retval = update_dimm_list(parameter, line); | |
286 | } | |
287 | } else if (processing_bit_map) { | |
288 | if (strcmp(parameter, "bit_map_end") == 0) { | |
289 | processing_bit_map = 0; | |
290 | if (num_bits_in_list != max_bits) { | |
291 | sprintf(err_string, | |
292 | "Bit map has %d entries, should have %d!\n", | |
293 | num_bits_in_list, max_bits); | |
294 | print_error(err_string); | |
295 | retval = ERROR; | |
296 | } | |
297 | if (force_default_mc) { | |
298 | cur_memc = 1; | |
299 | } else if (memc_id_init == 0) { | |
300 | print_error("Must init memc_id in bitmap\n"); | |
301 | retval = ERROR; | |
302 | } | |
303 | for (i = 0; i < num_memc; i++) { | |
304 | if (cur_memc & (1 << i)) { | |
305 | mem_layout[i].bit_to_dimm_map = | |
306 | bit_to_dimm_map; | |
307 | mem_layout[i].bit_to_pin_map = | |
308 | bit_to_pin_map; | |
309 | } | |
310 | } | |
311 | } else { | |
312 | retval = update_bit_map(parameter, line); | |
313 | } | |
314 | } else if (strcmp(parameter, "dimm_list_start") == 0) { | |
315 | if (init_mem_params() == NO_ERROR) { | |
316 | num_dimms_in_list = 0; | |
317 | processing_dimm_list = 1; | |
318 | cur_memc = 0; | |
319 | memc_id_init = 0; | |
320 | } else | |
321 | retval = ERROR; | |
322 | } else if (strcmp(parameter, "dimm_list_end") == 0) { | |
323 | fprintf(stderr, "Missing dimm_list_start\n"); | |
324 | retval = ERROR; | |
325 | } else if (strcmp(parameter, "bit_map_start") == 0) { | |
326 | if (init_mem_params() == NO_ERROR) { | |
327 | num_bits_in_list = 0; | |
328 | bit_to_dimm_map = malloc(max_bits * sizeof (int)); | |
329 | bit_to_pin_map = malloc(max_bits * sizeof (int)); | |
330 | processing_bit_map = 1; | |
331 | cur_memc = 0; | |
332 | memc_id_init = 0; | |
333 | } else | |
334 | retval = ERROR; | |
335 | } else { | |
336 | retval = UNKNOWN; | |
337 | } | |
338 | return (retval); | |
339 | } | |
340 | ||
341 | static void | |
342 | free_mem(void) | |
343 | { | |
344 | struct dimm_list_entry *dimm_ptr, *tmp1; | |
345 | ||
346 | free(bit_to_dimm_map); | |
347 | free(bit_to_pin_map); | |
348 | ||
349 | dimm_ptr = dimm_list; | |
350 | while (dimm_ptr->next != NULL) { | |
351 | tmp1 = dimm_ptr->next; | |
352 | free(dimm_ptr); | |
353 | dimm_ptr = tmp1; | |
354 | } | |
355 | free(dimm_ptr); | |
356 | } | |
357 | ||
358 | void | |
359 | write_mem(unsigned char **ptr) | |
360 | { | |
361 | struct dimm_list_entry *dimm_ptr; | |
362 | unsigned char *p; | |
363 | int bits; | |
364 | int i, j, new_val, size; | |
365 | ||
366 | size = (max_dimms * DIMM_NAME_SIZE) + max_bits + | |
367 | (max_bits*max_encode_dimm_bits)/8 + TABLE_WIDTH_LEN + 1; | |
368 | store_bytes(4, (unsigned long long) size, ptr); | |
369 | ||
370 | for (j = 0; j < num_memc; j++) { | |
371 | dimm_ptr = mem_layout[j].dimm_list; | |
372 | while (dimm_ptr != NULL) { | |
373 | p = (unsigned char *) dimm_ptr->name; | |
374 | store_chars(DIMM_NAME_SIZE, p, ptr); | |
375 | dimm_ptr = dimm_ptr->next; | |
376 | } | |
377 | store_bytes(1, (unsigned long long) table_width, ptr); | |
378 | ||
379 | bits = max_bits - 1; | |
380 | while (bits >= 0) { | |
381 | new_val = 0; | |
382 | for (i = 8-max_encode_dimm_bits; i >= 0; | |
383 | i -= max_encode_dimm_bits) { | |
384 | new_val |= | |
385 | mem_layout[j].bit_to_dimm_map[bits--] << i; | |
386 | } | |
387 | store_bytes(1, (unsigned long long) new_val, ptr); | |
388 | } | |
389 | for (i = 0; i < max_bits; i++) { | |
390 | store_bytes(1, | |
391 | (unsigned long long) mem_layout[j].bit_to_pin_map[i], | |
392 | ptr); | |
393 | } | |
394 | /* last byte ends in 0 */ | |
395 | store_bytes(1, 0, ptr); | |
396 | } | |
397 | } | |
398 | ||
399 | void | |
400 | dump_mem(void) | |
401 | { | |
402 | } | |
403 | ||
404 | int | |
405 | check_mem(void) | |
406 | { | |
407 | return (0); | |
408 | } | |
409 | ||
410 | int | |
411 | reg_mem(char *s1, data_reg **reg) | |
412 | { | |
413 | return (0); | |
414 | } |