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