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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * Sun4v Platform specific functions.
28 *
29 * called when :
30 * machine_type == huron
31 *
32 */
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <unistd.h>
37 #include <kstat.h>
38 #include <fcntl.h>
39 #include <string.h>
40 #include <assert.h>
41 #include <libintl.h>
42 #include <note.h>
43 #include <sys/systeminfo.h>
44 #include <sys/openpromio.h>
45 #include <sys/sysmacros.h>
46 #include <picl.h>
47 #include "picldefs.h"
48 #include <pdevinfo.h>
49 #include <display.h>
50 #include <display_sun4v.h>
51 #include <libprtdiag.h>
52 #include "huron.h"
53
54 #if !defined(TEXT_DOMAIN)
55 #define TEXT_DOMAIN "SYS_TEST"
56 #endif
57
58 static void
huron_get_bus_type(char * path,struct io_card * card)59 huron_get_bus_type(char *path, struct io_card *card)
60 {
61 if (strcmp(path, HURON_NIU) == 0) {
62 (void) strcpy(card->bus_type, "NIU");
63 } else {
64 (void) strcpy(card->bus_type, "PCIE");
65 }
66 }
67
68 void
huron_get_slot_number(char * path,struct io_card * card)69 huron_get_slot_number(char *path, struct io_card *card)
70 {
71 if (strcmp(path, HURON_N2_XAUI0) == 0) {
72 (void) strcpy(card->slot_str, "0");
73 card->slot = 0;
74 } else if (strcmp(path, HURON_N2_XAUI1) == 0) {
75 (void) strcpy(card->slot_str, "1");
76 card->slot = 1;
77 } else if (strncmp(path, HURON_PCIE_SLOT0,
78 strlen(HURON_PCIE_SLOT0)) == 0) {
79 (void) strcpy(card->slot_str, "0");
80 card->slot = 0;
81 } else if (strncmp(path, HURON_PCIE_SLOT1,
82 strlen(HURON_PCIE_SLOT1)) == 0) {
83 (void) strcpy(card->slot_str, "1");
84 card->slot = 1;
85 } else if (strncmp(path, HURON_PCIE_SLOT2,
86 strlen(HURON_PCIE_SLOT2)) == 0) {
87 (void) strcpy(card->slot_str, "2");
88 card->slot = 2;
89 } else if (strncmp(path, HURON_PCIE_SLOT3,
90 strlen(HURON_PCIE_SLOT3)) == 0) {
91 (void) strcpy(card->slot_str, "3");
92 card->slot = 3;
93 } else if (strncmp(path, HURON_PCIE_SLOT4,
94 strlen(HURON_PCIE_SLOT4)) == 0) {
95 (void) strcpy(card->slot_str, "4");
96 card->slot = 4;
97 } else if (strncmp(path, HURON_PCIE_SLOT5,
98 strlen(HURON_PCIE_SLOT5)) == 0) {
99 (void) strcpy(card->slot_str, "5");
100 card->slot = 5;
101 } else {
102 (void) strcpy(card->slot_str, MOTHERBOARD);
103 card->slot = NO_SLOT;
104 }
105 }
106
107 int
huron_get_network_instance(char * path)108 huron_get_network_instance(char *path)
109 {
110 if (strcmp(path, HURON_NETWORK_0) == 0) {
111 return (0);
112 } else if (strcmp(path, HURON_NETWORK_1) == 0) {
113 return (1);
114 } else if (strcmp(path, HURON_NETWORK_2) == 0) {
115 return (2);
116 } else if (strcmp(path, HURON_NETWORK_3) == 0) {
117 return (3);
118 } else if (strcmp(path, HURON_N2_XAUI0) == 0) {
119 return (0);
120 } else if (strcmp(path, HURON_N2_XAUI1) == 0) {
121 return (1);
122 } else {
123 return (-1);
124 }
125 }
126 /*
127 * add all io devices under pci in io list
128 */
129 /* ARGSUSED */
130 int
huron_pci_callback(picl_nodehdl_t pcih,void * args)131 huron_pci_callback(picl_nodehdl_t pcih, void *args)
132 {
133 int err = PICL_SUCCESS;
134 picl_nodehdl_t nodeh;
135 char path[MAXSTRLEN];
136 char parent_path[MAXSTRLEN];
137 char piclclass[PICL_CLASSNAMELEN_MAX];
138 char name[MAXSTRLEN];
139 char model[MAXSTRLEN];
140 char *compatible;
141 char binding_name[MAXSTRLEN];
142 struct io_card pci_card;
143 int32_t instance;
144
145 err = picl_get_propval_by_name(pcih, PICL_PROP_DEVFS_PATH, parent_path,
146 sizeof (parent_path));
147 if (err != PICL_SUCCESS) {
148 return (err);
149 }
150
151 /* Walk through the children */
152 err = picl_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh,
153 sizeof (picl_nodehdl_t));
154
155 while (err == PICL_SUCCESS) {
156 err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
157 piclclass, sizeof (piclclass));
158 if (err != PICL_SUCCESS)
159 return (err);
160
161 if (strcmp(piclclass, "pciex") == 0) {
162 err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER,
163 &nodeh, sizeof (picl_nodehdl_t));
164 continue;
165 }
166
167 if (strcmp(piclclass, "sun4v") == 0) {
168 err = picl_get_propval_by_name(nodeh, PICL_PROP_CHILD,
169 &nodeh, sizeof (picl_nodehdl_t));
170 continue;
171 }
172
173 err = picl_get_propval_by_name(nodeh, PICL_PROP_DEVFS_PATH,
174 path, sizeof (path));
175 if (err != PICL_SUCCESS) {
176 return (err);
177 }
178
179 (void) strlcpy(pci_card.notes, path, sizeof (pci_card.notes));
180
181 huron_get_bus_type(parent_path, &pci_card);
182
183 err = picl_get_propval_by_name(nodeh, PICL_PROP_NAME, &name,
184 sizeof (name));
185 if (err == PICL_PROPNOTFOUND)
186 (void) strcpy(name, "");
187 else if (err != PICL_SUCCESS)
188 return (err);
189
190 if (strcmp(parent_path, HURON_NIU) == 0)
191 huron_get_slot_number(path, &pci_card);
192 else
193 huron_get_slot_number(parent_path, &pci_card);
194
195 /* Figure NAC name */
196 if ((strcmp(name, NETWORK) == 0) &&
197 (strcmp(pci_card.slot_str, MOTHERBOARD) == 0)) {
198 instance = huron_get_network_instance(path);
199 (void) snprintf(pci_card.status,
200 sizeof (pci_card.status), "%s/%s%d", MOTHERBOARD,
201 "NET", instance);
202 } else {
203 if (pci_card.slot != NO_SLOT) {
204 (void) snprintf(pci_card.status,
205 sizeof (pci_card.status), "%s/%s%d",
206 MOTHERBOARD, pci_card.bus_type,
207 pci_card.slot);
208 } else {
209 (void) snprintf(pci_card.status,
210 sizeof (pci_card.status), "%s/%s",
211 MOTHERBOARD, pci_card.bus_type);
212 }
213 }
214
215 /*
216 * Get the name of this card. Iif binding_name is found,
217 * name will be <nodename>-<binding_name>
218 */
219
220 err = picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME,
221 &binding_name, sizeof (binding_name));
222 if (err == PICL_PROPNOTFOUND) {
223 /*
224 * if compatible prop is found, name will be
225 * <nodename>-<compatible>
226 */
227 err = huron_get_first_compatible_value(nodeh,
228 &compatible);
229 if (err == PICL_SUCCESS) {
230 (void) strlcat(name, "-", MAXSTRLEN);
231 (void) strlcat(name, compatible, MAXSTRLEN);
232 free(compatible);
233 } else if (err != PICL_PROPNOTFOUND) {
234 return (err);
235 }
236 } else if (err != PICL_SUCCESS) {
237 return (err);
238 } else if (strcmp(name, binding_name) != 0) {
239 (void) strlcat(name, "-", MAXSTRLEN);
240 (void) strlcat(name, binding_name, MAXSTRLEN);
241 }
242
243 (void) strlcpy(pci_card.name, name, sizeof (pci_card.name));
244
245 /* Get the model of this card */
246
247 err = picl_get_propval_by_name(nodeh, OBP_PROP_MODEL,
248 &model, sizeof (model));
249 if (err == PICL_PROPNOTFOUND)
250 (void) strcpy(model, "");
251 else if (err != PICL_SUCCESS)
252 return (err);
253 (void) strlcpy(pci_card.model, model, sizeof (pci_card.model));
254
255 /* Print NAC name */
256 log_printf("%-11s", pci_card.status);
257 /* Print IO Type */
258 log_printf("%6s", pci_card.bus_type);
259 /* Print Slot # */
260 log_printf("%5s", pci_card.slot_str);
261 /* Print Parent Path */
262 log_printf("%46.45s", pci_card.notes);
263 /* Printf Card Name */
264 if (strlen(pci_card.name) > 24)
265 log_printf("%25.24s+", pci_card.name);
266 else
267 log_printf("%26s", pci_card.name);
268 /* Print Card Model */
269 if (strlen(pci_card.model) > 10)
270 log_printf("%10.9s+", pci_card.model);
271 else
272 log_printf("%10s", pci_card.model);
273 log_printf("\n");
274
275 err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
276 sizeof (picl_nodehdl_t));
277
278 }
279
280 return (PICL_WALK_CONTINUE);
281 }
282
283 /*
284 * local functions
285 */
286 /*
287 * add all io devices under pci in io list
288 */
289 /* ARGSUSED */
290 int
huron_hw_rev_callback(picl_nodehdl_t pcih,void * args)291 huron_hw_rev_callback(picl_nodehdl_t pcih, void *args)
292 {
293 int err = PICL_SUCCESS;
294 char path[MAXSTRLEN] = "";
295 char device_path[MAXSTRLEN];
296 char NAC[MAXSTRLEN];
297 char *compatible;
298 int32_t revision;
299 int device_found = 0;
300
301 err = picl_get_propval_by_name(pcih, PICL_PROP_DEVFS_PATH, path,
302 sizeof (path));
303 if (err != PICL_SUCCESS) {
304 return (err);
305 }
306
307 if ((strcmp(path, HURON_NETWORK_0) == 0) ||
308 (strcmp(path, HURON_NETWORK_1) == 0)) {
309 device_found = 1;
310 (void) snprintf(NAC, sizeof (NAC), "%s/%s%d",
311 MOTHERBOARD, OPHIR, 0);
312 revision = huron_get_int_propval(pcih, OBP_PROP_REVISION_ID,
313 &err);
314 }
315
316 if ((strcmp(path, HURON_NETWORK_2) == 0) ||
317 (strcmp(path, HURON_NETWORK_3) == 0)) {
318 device_found = 1;
319 (void) snprintf(NAC, sizeof (NAC), "%s/%s%d", MOTHERBOARD,
320 OPHIR, 1);
321 revision = huron_get_int_propval(pcih, OBP_PROP_REVISION_ID,
322 &err);
323 }
324
325 if (strcmp(path, HURON_SWITCH_A_PATH) == 0) {
326 device_found = 1;
327 (void) snprintf(NAC, sizeof (NAC), "%s/%s",
328 MOTHERBOARD, HURON_SWITCH_A);
329 revision = huron_get_int_propval(pcih, OBP_PROP_REVISION_ID,
330 &err);
331 }
332
333 if (strcmp(path, HURON_SWITCH_B_PATH) == 0) {
334 device_found = 1;
335 (void) snprintf(NAC, sizeof (NAC), "%s/%s", MOTHERBOARD,
336 HURON_SWITCH_B);
337 revision = huron_get_int_propval(pcih, OBP_PROP_REVISION_ID,
338 &err);
339 }
340
341 if (strcmp(path, HURON_SWITCH_C_PATH) == 0) {
342 device_found = 1;
343 (void) snprintf(NAC, sizeof (NAC), "%s/%s", MOTHERBOARD,
344 HURON_SWITCH_C);
345 revision = huron_get_int_propval(pcih, OBP_PROP_REVISION_ID,
346 &err);
347 }
348
349 if (strcmp(path, HURON_LSI_PATH) == 0) {
350 device_found = 1;
351 (void) snprintf(NAC, sizeof (NAC), "%s/%s", MOTHERBOARD,
352 SAS_SATA_HBA);
353 revision = huron_get_int_propval(pcih, OBP_PROP_REVISION_ID,
354 &err);
355 }
356 if (device_found == 1) {
357 (void) strcpy(device_path, path);
358 err = huron_get_first_compatible_value(pcih, &compatible);
359
360 /* Print NAC name */
361 log_printf("%-20s", NAC);
362 /* Print Device Path */
363 if (strlen(device_path) > 45)
364 log_printf("%45.44s+", device_path);
365 else
366 log_printf("%46s", device_path);
367 /* Print Compatible # */
368 if (err == PICL_SUCCESS) {
369 log_printf("%31s", compatible);
370 free(compatible);
371 } else
372 log_printf("%31s", " ");
373 /* Print Revision */
374 log_printf("%6d", revision);
375 log_printf("\n");
376 }
377
378 return (PICL_WALK_CONTINUE);
379 }
380
381 /*
382 * return the first compatible value
383 */
384 int
huron_get_first_compatible_value(picl_nodehdl_t nodeh,char ** outbuf)385 huron_get_first_compatible_value(picl_nodehdl_t nodeh, char **outbuf)
386 {
387 int err;
388 picl_prophdl_t proph;
389 picl_propinfo_t pinfo;
390 picl_prophdl_t tblh;
391 picl_prophdl_t rowproph;
392 char *pval;
393
394 err = picl_get_propinfo_by_name(nodeh, OBP_PROP_COMPATIBLE,
395 &pinfo, &proph);
396 if (err != PICL_SUCCESS)
397 return (err);
398
399 if (pinfo.type == PICL_PTYPE_CHARSTRING) {
400 pval = malloc(pinfo.size);
401 if (pval == NULL)
402 return (PICL_FAILURE);
403 err = picl_get_propval(proph, pval, pinfo.size);
404 if (err != PICL_SUCCESS) {
405 free(pval);
406 return (err);
407 }
408 *outbuf = pval;
409 return (PICL_SUCCESS);
410 }
411
412 if (pinfo.type != PICL_PTYPE_TABLE)
413 return (PICL_FAILURE);
414
415 /* get first string from table */
416 err = picl_get_propval(proph, &tblh, pinfo.size);
417 if (err != PICL_SUCCESS)
418 return (err);
419
420 err = picl_get_next_by_row(tblh, &rowproph);
421 if (err != PICL_SUCCESS)
422 return (err);
423
424 err = picl_get_propinfo(rowproph, &pinfo);
425 if (err != PICL_SUCCESS)
426 return (err);
427
428 pval = malloc(pinfo.size);
429 if (pval == NULL)
430 return (PICL_FAILURE);
431
432 err = picl_get_propval(rowproph, pval, pinfo.size);
433 if (err != PICL_SUCCESS) {
434 free(pval);
435 return (err);
436 }
437
438 *outbuf = pval;
439 return (PICL_SUCCESS);
440 }
441
442 int64_t
huron_get_int_propval(picl_nodehdl_t modh,char * prop_name,int * ret)443 huron_get_int_propval(picl_nodehdl_t modh, char *prop_name, int *ret)
444 {
445 int err;
446 picl_prophdl_t proph;
447 picl_propinfo_t pinfo;
448 int8_t int8v;
449 int16_t int16v;
450 int32_t int32v;
451 int64_t int64v;
452
453 err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph);
454 if (err != PICL_SUCCESS) {
455 *ret = err;
456 return (0);
457 }
458
459 /*
460 * If it is not an int, uint or byte array prop, return failure
461 */
462 if ((pinfo.type != PICL_PTYPE_INT) &&
463 (pinfo.type != PICL_PTYPE_UNSIGNED_INT) &&
464 (pinfo.type != PICL_PTYPE_BYTEARRAY)) {
465 *ret = PICL_FAILURE;
466 return (0);
467 }
468
469 switch (pinfo.size) {
470 case sizeof (int8_t):
471 err = picl_get_propval(proph, &int8v, sizeof (int8v));
472 *ret = err;
473 return (int8v);
474 case sizeof (int16_t):
475 err = picl_get_propval(proph, &int16v, sizeof (int16v));
476 *ret = err;
477 return (int16v);
478 case sizeof (int32_t):
479 err = picl_get_propval(proph, &int32v, sizeof (int32v));
480 *ret = err;
481 return (int32v);
482 case sizeof (int64_t):
483 err = picl_get_propval(proph, &int64v, sizeof (int64v));
484 *ret = err;
485 return (int64v);
486 default: /* not supported size */
487 *ret = PICL_FAILURE;
488 return (0);
489 }
490 }
491