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 /*
23 * Copyright 2000, 2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 *
26 * Daktari Platform specific functions.
27 */
28
29 #pragma ident "%Z%%M% %I% %E% SMI"
30
31 #include <libdevinfo.h>
32 #include <alloca.h>
33 #include <inttypes.h>
34 #include <libprtdiag.h>
35 #include <sys/mc.h>
36
37 #define EXIT_MSG(msg, err) \
38 { printf("\n%s failed with %d\n", msg, err); exit(err); }
39
40 /* we only need the 5 LSB of the portid to calculate the board number */
41 #define DAK_SAFARI_ID_MASK 0x1F /* 5 bits */
42 #define DAK_NODE_MASK 0x1F /* 5 bits */
43 #define DAK_PORTID_NODE_SHIFT 5
44 #define DAK_MIN_CPU_SAFARI_ID 0 /* 0x00 */
45 #define DAK_MAX_CPU_SAFARI_ID 23 /* 0x17 */
46 #define DAK_MIN_IO_SAFARI_ID 24 /* 0x18 */
47 #define DAK_MAX_IO_SAFARI_ID 31 /* 0x1F */
48 #define NUM_MBANKS_PER_MC 4
49
50 #define DAK_CLK_FREQ_TO_MHZ(x) (((x) + 500000) / 1000000)
51
52 /*
53 * DAK_PORTID_IS_CPU_TYPE
54 *
55 * If the portid associated with a CPU board is passed in, TRUE is returned,
56 * otherwise FALSE.
57 */
58 #define DAK_PORTID_IS_CPU_TYPE(portid) \
59 (((((portid) & DAK_SAFARI_ID_MASK) >= DAK_MIN_CPU_SAFARI_ID) && \
60 (((portid) & DAK_SAFARI_ID_MASK) <= DAK_MAX_CPU_SAFARI_ID)) ? \
61 TRUE: FALSE)
62 /*
63 * DAK_CPU_BD_PORTID_TO_BD_NUM
64 *
65 * If the portid associated with a CPU board is passed in, the board number
66 * associated with this portid is returned, otherwise -1.
67 */
68 #define DAK_CPU_BD_PORTID_TO_BD_NUM(portid) \
69 ((DAK_PORTID_IS_CPU_TYPE(portid)) ? \
70 (((portid) & DAK_SAFARI_ID_MASK) / 4) : (-1))
71
72 /*
73 * DAK_PORTID_IS_IO_TYPE
74 *
75 * If the portid associated with an IO board is passed in, TRUE is returned,
76 * otherwise FALSE.
77 */
78 #define DAK_PORTID_IS_IO_TYPE(portid) \
79 (((((portid) & DAK_SAFARI_ID_MASK) >= DAK_MIN_IO_SAFARI_ID) && \
80 (((portid) & DAK_SAFARI_ID_MASK) <= DAK_MAX_IO_SAFARI_ID)) ? \
81 TRUE: FALSE)
82
83 /*
84 * DAK_IO_BD_PORTID_TO_BD_NUM
85 *
86 * If the portid associated with an IO board is passed in, the board number
87 * associated with this portid is returned, otherwise -1.
88 */
89 #define DAK_IO_BD_PORTID_TO_BD_NUM(portid) \
90 (DAK_PORTID_IS_IO_TYPE(portid) ? \
91 (((((portid) & DAK_SAFARI_ID_MASK) - 24) / 2) + 6) : (-1))
92
93 /*
94 * DAK_PORTID_TO_BOARD_NUM
95 *
96 * If a valid portid is passed in, this macro returns the board number
97 * associated with it, otherwise it returns -1.
98 */
99
100 #define DAK_PORTID_TO_BOARD_NUM(portid) \
101 ((DAK_PORTID_IS_CPU_TYPE(portid)) ? \
102 (DAK_CPU_BD_PORTID_TO_BD_NUM(portid)) : \
103 ((DAK_PORTID_IS_IO_TYPE(portid)) ? \
104 DAK_IO_BD_PORTID_TO_BD_NUM(portid) : (-1)))
105
106
107 /* Local Functions */
108 char *get_node_name(Prom_node *pnode);
109 char *get_node_type(Prom_node *pnode);
110 void add_node(Sys_tree *root, Prom_node *pnode);
111 Prop *find_prop(Prom_node *pnode, char *name);
112 int do_prominfo(int syserrlog, char *pgname, int log_flag, int prt_flag);
113 void *get_prop_val(Prop *prop);
114 char *get_node_type(Prom_node *pnode);
115 int get_us3_mem_regs(Board_node *bnode);
116
117 void fill_pci_card_list(Prom_node *pci_instance,
118 Prom_node *pci_card_node,
119 struct io_card *pci_card,
120 struct io_card **pci_card_list,
121 char **pci_slot_name_arr);
122
123 static Prom_node *next_pci_card(Prom_node *curr_card, int *is_bridge,
124 int is_pcidev, Prom_node *curr_bridge,
125 Prom_node * parent_bridge, Prom_node *pci);
126
127 static Prom_node *dev_next_node_by_compat(Prom_node *root, char *compat);
128 static Prom_node *dev_find_node_by_compat(Prom_node *root, char *compat);
129 static Board_node *daktari_insert_board(Sys_tree *root, int board);
130 static Board_node *daktari_find_board(Sys_tree *root, int board);
131
132 static int32_t find_child_device(picl_nodehdl_t, char *, picl_nodehdl_t *);
133 static int32_t fill_device_from_id(picl_nodehdl_t, char *, picl_nodehdl_t *);
134 static int32_t fill_device_array_from_id(picl_nodehdl_t, char *, int32_t *,
135 picl_nodehdl_t **);
136
137 /* Overlaying routines */
138
139 /*
140 * This function searches through the properties of the node passed in
141 * and returns a pointer to the value of the name property.
142 */
143 char *
get_node_name(Prom_node * pnode)144 get_node_name(Prom_node *pnode)
145 {
146 Prop *prop;
147
148 if (pnode == NULL)
149 return (NULL);
150
151 prop = pnode->props;
152 while (prop != NULL) {
153 if (strcmp("name", (char *)prop->name.val_ptr) == 0)
154 return (prop->value.val_ptr);
155 prop = prop->next;
156 }
157 return (NULL);
158 }
159
160 /*
161 * This function searches through the properties of the node passed in
162 * and returns a pointer to the value of the name property.
163 */
164 char *
get_node_type(Prom_node * pnode)165 get_node_type(Prom_node *pnode)
166 {
167 Prop *prop;
168
169 if (pnode == NULL) {
170 return (NULL);
171 }
172
173 prop = pnode->props;
174 while (prop != NULL) {
175 if (strcmp("device_type", (char *)prop->name.val_ptr) == 0)
176 return (prop->value.val_ptr);
177 prop = prop->next;
178 }
179 return (NULL);
180 }
181
182 /*
183 * add_node
184 *
185 * This function adds a board node to the board structure where that
186 * that node's physical component lives.
187 */
188 void
add_node(Sys_tree * root,Prom_node * pnode)189 add_node(Sys_tree *root, Prom_node *pnode)
190 {
191 int board = -1;
192 int portid = -1;
193
194 void *value = NULL;
195 Board_node *bnode = NULL;
196 Prom_node *p = NULL;
197
198 /* Get the board number of this board from the portid prop */
199 value = get_prop_val(find_prop(pnode, "portid"));
200 if (value != NULL) {
201 portid = *(int *)value;
202 }
203 board = DAK_PORTID_TO_BOARD_NUM(portid);
204 /* board = DAK_GETSLOT(portid); */
205 /* find the board node with the same board number */
206 if ((bnode = daktari_find_board(root, board)) == NULL) {
207 bnode = daktari_insert_board(root, board);
208 }
209
210 /* now attach this prom node to the board list */
211 /* Insert this node at the end of the list */
212 pnode->sibling = NULL;
213 if (bnode->nodes == NULL)
214 bnode->nodes = pnode;
215 else {
216 p = bnode->nodes;
217 while (p->sibling != NULL)
218 p = p->sibling;
219 p->sibling = pnode;
220 }
221 }
222
223 /*
224 * Search a Prom node and retrieve the property with the correct
225 * name.
226 */
227 Prop *
find_prop(Prom_node * pnode,char * name)228 find_prop(Prom_node *pnode, char *name)
229 {
230 Prop *prop;
231
232 if (pnode == NULL)
233 return (NULL);
234
235 if (pnode->props == NULL)
236 return (NULL);
237
238 prop = pnode->props;
239
240 if (prop == NULL)
241 return (NULL);
242
243 if (prop->name.val_ptr == NULL)
244 return (NULL);
245
246 while ((prop != NULL) && (strcmp((char *)(prop->name.val_ptr), name))) {
247 prop = prop->next;
248 }
249 return (prop);
250 }
251
252 int
do_prominfo(int syserrlog,char * pgname,int log_flag,int prt_flag)253 do_prominfo(int syserrlog, char *pgname, int log_flag, int prt_flag)
254 {
255 return (do_devinfo(syserrlog, pgname, log_flag, prt_flag));
256 }
257
258
259 /*
260 * return the property value for the Prop
261 * passed in.
262 */
263 void *
get_prop_val(Prop * prop)264 get_prop_val(Prop *prop)
265 {
266 if (prop == NULL)
267 return (NULL);
268
269 return ((void *)(prop->value.val_ptr));
270 }
271
272 /* Local Routines */
273
274 /*
275 * Start from the current node and return the next node besides
276 * the current one which has the requested model property.
277 */
278 static Prom_node *
dev_next_node_by_compat(Prom_node * root,char * compat)279 dev_next_node_by_compat(Prom_node *root, char *compat)
280 {
281 Prom_node *node;
282
283 if (root == NULL)
284 return (NULL);
285
286 /* look at your children first */
287 if ((node = dev_find_node_by_compat(root->child, compat)) != NULL)
288 return (node);
289
290 /* now look at your siblings */
291 if ((node = dev_find_node_by_compat(root->sibling, compat)) != NULL)
292 return (node);
293
294 return (NULL); /* not found */
295 }
296
297 /*
298 * Do a depth-first walk of a device tree and
299 * return the first node with the matching model.
300 */
301 static Prom_node *
dev_find_node_by_compat(Prom_node * root,char * compat)302 dev_find_node_by_compat(Prom_node *root, char *compat)
303 {
304 Prom_node *node;
305 char *compatible;
306 char *name;
307
308 if (root == NULL)
309 return (NULL);
310
311 if (compat == NULL)
312 return (NULL);
313
314 name = get_node_name(root);
315 if (name == NULL)
316 name = "";
317
318 compatible = (char *)get_prop_val(find_prop(root, "compatible"));
319
320 if (compatible == NULL)
321 return (NULL);
322
323 if ((strcmp(name, "pci") == 0) && (compatible != NULL) &&
324 (strcmp(compatible, compat) == 0)) {
325 return (root); /* found a match */
326 }
327
328 /* look at your children first */
329 if ((node = dev_find_node_by_compat(root->child, compat)) != NULL)
330 return (node);
331
332 /* now look at your siblings */
333 if ((node = dev_find_node_by_compat(root->sibling, compat)) != NULL)
334 return (node);
335
336 return (NULL); /* not found */
337 }
338
339
340 /*
341 * Add a board to the system list in order (sorted by board#).
342 * Initialize all pointer fields to NULL.
343 */
344 static Board_node *
daktari_insert_board(Sys_tree * root,int board)345 daktari_insert_board(Sys_tree *root, int board)
346 {
347 Board_node *bnode;
348 Board_node *temp = root->bd_list;
349
350 if ((bnode = (Board_node *) malloc(sizeof (Board_node))) == NULL) {
351 perror("malloc");
352 exit(1);
353 }
354
355 bnode->nodes = NULL;
356 bnode->next = NULL;
357 bnode->board_num = board;
358 bnode->board_type = UNKNOWN_BOARD;
359
360 if (temp == NULL)
361 root->bd_list = bnode;
362
363 else if (temp->board_num > board) {
364 bnode->next = temp;
365 root->bd_list = bnode;
366
367 } else {
368 while ((temp->next != NULL) && (board > temp->next->board_num))
369 temp = temp->next;
370
371 bnode->next = temp->next;
372 temp->next = bnode;
373 }
374 root->board_cnt++;
375
376 return (bnode);
377 }
378
379 /*
380 * Find the requested board struct in the system device tree.
381 *
382 * This function overrides the functionality of the generic find_board()
383 * function in libprtdiag, but since we need to pass another parameter,
384 * we cannot simply overlay the symbol table.
385 */
386 static Board_node *
daktari_find_board(Sys_tree * root,int board)387 daktari_find_board(Sys_tree *root, int board)
388 {
389 Board_node *bnode = root->bd_list;
390
391 while ((bnode != NULL) && (board != bnode->board_num)) {
392 bnode = bnode->next;
393 }
394 return (bnode);
395 }
396
397
398 int32_t
find_child_device(picl_nodehdl_t parent,char * child_name,picl_nodehdl_t * child)399 find_child_device(picl_nodehdl_t parent, char *child_name,
400 picl_nodehdl_t *child)
401 {
402 int32_t err;
403 char name[PICL_PROPNAMELEN_MAX];
404
405 err = picl_get_propval_by_name(parent, PICL_PROP_CHILD, &(*child),
406 sizeof (picl_nodehdl_t));
407 switch (err) {
408 case PICL_SUCCESS:
409 break;
410 case PICL_PROPNOTFOUND:
411 err = PICL_INVALIDHANDLE;
412 return (err);
413 default:
414 #ifdef WORKFILE_DEBUG
415 log_printf(dgettext(TEXT_DOMAIN,
416 "Failed picl_get_propval_by_name with %s\n"),
417 picl_strerror(err));
418 #endif
419 return (err);
420 }
421
422 err = picl_get_propval_by_name(*child, PICL_PROP_NAME, name,
423 PICL_PROPNAMELEN_MAX);
424
425 #ifdef WORKFILE_DEBUG
426 if (err != PICL_SUCCESS) {
427 log_printf(dgettext(TEXT_DOMAIN,
428 "failed the get name for root\n"), 0);
429 log_printf(dgettext(TEXT_DOMAIN, "%s\n"),
430 picl_strerror(err), 0);
431 }
432 #endif
433
434 if (strcmp(name, child_name) == 0)
435 return (err);
436
437 while (err != PICL_PROPNOTFOUND) {
438 err = picl_get_propval_by_name(*child, PICL_PROP_PEER,
439 &(*child), sizeof (picl_nodehdl_t));
440 switch (err) {
441 case PICL_SUCCESS:
442 err = picl_get_propval_by_name(*child, PICL_PROP_NAME,
443 name, PICL_PROPNAMELEN_MAX);
444 if (strcmp(name, child_name) == 0)
445 return (err);
446 break;
447 case PICL_PROPNOTFOUND:
448 break;
449 default:
450 #ifdef WORKFILE_DEBUG
451 log_printf(dgettext(TEXT_DOMAIN,
452 "Failed picl_get_propval_by_name with %s\n"),
453 picl_strerror(err), 0);
454 #endif
455 return (err);
456 }
457 }
458 err = PICL_INVALIDHANDLE;
459 return (err);
460 }
461
462 int32_t
fill_device_from_id(picl_nodehdl_t device_id,char * assoc_id,picl_nodehdl_t * device)463 fill_device_from_id(picl_nodehdl_t device_id, char *assoc_id,
464 picl_nodehdl_t *device)
465 {
466 int32_t err;
467 picl_prophdl_t tbl_hdl;
468 picl_prophdl_t reference_property;
469
470 err = picl_get_propval_by_name(device_id, assoc_id, &tbl_hdl,
471 sizeof (picl_prophdl_t));
472 if (err != PICL_SUCCESS) {
473 #ifdef WORKFILE_DEBUG
474 if (err != PICL_INVALIDHANDLE) {
475 log_printf(dgettext(TEXT_DOMAIN,
476 "fill_device_from_id failure in "
477 "picl_get_propval_by_name err is %s\n"),
478 picl_strerror(err), 0);
479 }
480 #endif
481 return (err);
482 }
483
484 err = picl_get_next_by_row(tbl_hdl, &reference_property);
485 if (err != PICL_SUCCESS) {
486 #ifdef WORKFILE_DEBUG
487 log_printf(dgettext(TEXT_DOMAIN,
488 "fill_device_from_id failure in picl_get_next_by_row"
489 " err is %s\n"), picl_strerror(err), 0);
490 #endif
491 return (err);
492 }
493
494 /* get node associated with reference property */
495 err = picl_get_propval(reference_property, &(*device),
496 sizeof (picl_nodehdl_t));
497
498 #ifdef WORKFILE_DEBUG
499 if (err != 0) {
500 log_printf(dgettext(TEXT_DOMAIN,
501 "fill_device_from_id failure in picl_get_propval"
502 " err is %s\n"), picl_strerror(err), 0);
503 }
504 #endif
505 return (err);
506 }
507
508 int32_t
fill_device_array_from_id(picl_nodehdl_t device_id,char * assoc_id,int32_t * number_of_devices,picl_nodehdl_t * device_array[])509 fill_device_array_from_id(picl_nodehdl_t device_id, char *assoc_id,
510 int32_t *number_of_devices, picl_nodehdl_t *device_array[])
511 {
512 int32_t err;
513 int i;
514 picl_prophdl_t tbl_hdl;
515 picl_prophdl_t entry;
516 int devs = 0;
517 err = picl_get_propval_by_name(device_id, assoc_id, &tbl_hdl,
518 sizeof (picl_prophdl_t));
519 if ((err != PICL_SUCCESS) && (err != PICL_INVALIDHANDLE)) {
520 #ifdef WORKFILE_DEBUG
521 log_printf(dgettext(TEXT_DOMAIN,
522 "fill_device_array_from_id failure in "
523 "picl_get_propval_by_name err is %s\n"),
524 picl_strerror(err), 0);
525 #endif
526 return (err);
527 }
528
529 entry = tbl_hdl;
530 while (picl_get_next_by_row(entry, &entry) == 0)
531 ++devs;
532
533 *device_array = calloc((devs), sizeof (picl_nodehdl_t));
534 if (*device_array == NULL) {
535 #ifdef WORKFILE_DEBUG
536 log_printf(dgettext(TEXT_DOMAIN,
537 "fill_device_array_from_id failure getting memory"
538 " for array\n"), 0);
539 #endif
540 return (PICL_FAILURE);
541 }
542
543 entry = tbl_hdl;
544 for (i = 0; i < (devs); i++) {
545 err = picl_get_next_by_row(entry, &entry);
546 if (err != 0) {
547 #ifdef WORKFILE_DEBUG
548 log_printf(dgettext(TEXT_DOMAIN,
549 "fill_device_array_from_id failure in "
550 "picl_get_next_by_row err is %s\n"),
551 picl_strerror(err), 0);
552 #endif
553 return (err);
554 }
555
556 /* get node associated with reference property */
557 err = picl_get_propval(entry, &((*device_array)[i]),
558 sizeof (picl_nodehdl_t));
559 if (err != 0) {
560 #ifdef WORKFILE_DEBUG
561 log_printf(dgettext(TEXT_DOMAIN,
562 "fill_device_array_from_id failure in "
563 "picl_get_propval err is %s\n"),
564 picl_strerror(err), 0);
565 #endif
566 return (err);
567 }
568 }
569 *number_of_devices = devs;
570 return (err);
571 }
572
573 /*
574 * This function provides formatting of the memory config
575 * information that get_us3_mem_regs() and display_us3_banks() code has
576 * gathered. It overrides the generic print_us3_memory_line() code
577 * which prints an error message.
578 */
579 void
print_us3_memory_line(int portid,int bank_id,uint64_t bank_size,char * bank_status,uint64_t dimm_size,uint32_t intlv,int seg_id)580 print_us3_memory_line(int portid, int bank_id, uint64_t bank_size,
581 char *bank_status, uint64_t dimm_size, uint32_t intlv, int seg_id)
582 {
583 int mcid;
584 mcid = portid;
585
586 log_printf(dgettext(TEXT_DOMAIN,
587 "\n %-1c %2d %2d %4lldMB %11-s %4lldMB "
588 " %2d-way %d"),
589 'A' + DAK_GETSLOT(portid), mcid, (bank_id % 4),
590 bank_size, bank_status, dimm_size, intlv, seg_id, 0);
591 }
592
593
594 /*
595 * Fills in the i/o card list to be displayed later in display_pci();
596 */
597 void
fill_pci_card_list(Prom_node * pci_instance,Prom_node * pci_card_node,struct io_card * pci_card,struct io_card ** pci_card_list,char ** slot_name_arr)598 fill_pci_card_list(Prom_node * pci_instance, Prom_node * pci_card_node,
599 struct io_card *pci_card,
600 struct io_card **pci_card_list, char **slot_name_arr)
601 {
602 Prom_node *pci_bridge_node;
603 Prom_node *pci_parent_bridge;
604 int *int_val;
605 int pci_bridge = FALSE;
606 int pci_bridge_dev_no = -1;
607 int portid;
608 int pci_bus;
609 char buf[MAXSTRLEN];
610 char *slot_name = NULL; /* info in "slot-names" prop */
611 char *child_name;
612 char *name;
613 char *type;
614 void *value;
615
616 while (pci_card_node != NULL) {
617 int is_pci = FALSE;
618 type = NULL;
619 name = NULL;
620 /* If it doesn't have a name, skip it */
621 name = (char *)get_prop_val(
622 find_prop(pci_card_node, "name"));
623 if (name == NULL) {
624 pci_card_node = pci_card_node->sibling;
625 continue;
626 }
627
628 /*
629 * Get the portid of the schizo that this card
630 * lives under.
631 */
632 portid = -1;
633 value = get_prop_val(find_prop(pci_instance, "portid"));
634 if (value != NULL) {
635 portid = *(int *)value;
636 }
637 pci_card->schizo_portid = portid;
638 /*
639 * Find out whether this is PCI bus A or B
640 * using the 'reg' property.
641 */
642 int_val = (int *)get_prop_val(find_prop(pci_instance, "reg"));
643
644 if (int_val != NULL) {
645 int_val++; /* skip over first integer */
646 pci_bus = ((*int_val) & 0x7f0000);
647 if (pci_bus == 0x600000)
648 pci_card->pci_bus = 'A';
649 else if (pci_bus == 0x700000)
650 pci_card->pci_bus = 'B';
651 else
652 pci_card->pci_bus = '-';
653 } else {
654 pci_card->pci_bus = '-';
655 }
656
657 if ((pci_card->schizo_portid == 8) &&
658 (pci_card->pci_bus == 'A')) {
659 pci_card_node = pci_card_node->sibling;
660 continue;
661 }
662
663 /*
664 * get dev# and func# for this card from the
665 * 'reg' property.
666 */
667 int_val = (int *)get_prop_val(
668 find_prop(pci_card_node, "reg"));
669 if (int_val != NULL) {
670 pci_card->dev_no = (((*int_val) & 0xF800) >> 11);
671 pci_card->func_no = (((*int_val) & 0x700) >> 8);
672 } else {
673 pci_card->dev_no = -1;
674 pci_card->func_no = -1;
675 }
676
677 type = (char *)get_prop_val(
678 find_prop(pci_card_node, "device_type"));
679 /*
680 * If this is a pci-bridge, then store its dev#
681 * as its children nodes need this to get their slot#.
682 * We set the pci_bridge flag so that we know we are
683 * looking at a pci-bridge node. This flag gets reset
684 * every time we enter this while loop.
685 */
686
687 /*
688 * Check for a PCI-PCI Bridge for PCI and cPCI
689 * IO Boards using the name and type properties.
690 */
691 if ((type != NULL) && (strncmp(name, "pci", 3) == 0) &&
692 (strcmp(type, "pci") == 0)) {
693 pci_bridge_node = pci_card_node;
694 is_pci = TRUE;
695 if (!pci_bridge) {
696 pci_bridge_dev_no = pci_card->dev_no;
697 pci_parent_bridge = pci_bridge_node;
698 pci_bridge = TRUE;
699 }
700 }
701 if ((pci_card->pci_bus == 'B') && (pci_card->dev_no == 1) &&
702 (!pci_bridge)) {
703 pci_card_node = pci_card_node->sibling;
704 continue;
705 }
706
707 /*
708 * Get slot-names property from slot_names_arr.
709 * If we are the child of a pci_bridge we use the
710 * dev# of the pci_bridge as an index to get
711 * the slot number. We know that we are a child of
712 * a pci-bridge if our parent is the same as the last
713 * pci_bridge node found above.
714 */
715 if (pci_card->dev_no != -1) {
716 /*
717 * We compare this cards parent node with the
718 * pci_bridge_node to see if it's a child.
719 */
720 if (pci_card_node->parent != pci_instance &&
721 pci_bridge) {
722 /* use dev_no of pci_bridge */
723 if (pci_card->pci_bus == 'B') {
724 slot_name =
725 slot_name_arr[pci_bridge_dev_no -2];
726 } else {
727 slot_name =
728 slot_name_arr[pci_bridge_dev_no -1];
729 }
730 } else {
731 if (pci_card->pci_bus == 'B') {
732 slot_name =
733 slot_name_arr[pci_card->dev_no-2];
734 } else {
735 slot_name =
736 slot_name_arr[pci_card->dev_no-1];
737 }
738 }
739
740 if (slot_name != NULL &&
741 strlen(slot_name) != 0) {
742 /* Slot num is last char in string */
743 (void) snprintf(pci_card->slot_str, MAXSTRLEN,
744 "%c", slot_name[strlen(slot_name) - 1]);
745 } else {
746 (void) snprintf(pci_card->slot_str, MAXSTRLEN,
747 "-");
748 }
749
750 } else {
751 (void) snprintf(pci_card->slot_str, MAXSTRLEN,
752 "%c", '-');
753 }
754
755 /*
756 * Check for failed status.
757 */
758 if (node_failed(pci_card_node))
759 strcpy(pci_card->status, "fail");
760 else
761 strcpy(pci_card->status, "ok");
762
763 /* Get the model of this pci_card */
764 value = get_prop_val(find_prop(pci_card_node, "model"));
765 if (value == NULL)
766 pci_card->model[0] = '\0';
767 else {
768 (void) snprintf(pci_card->model, MAXSTRLEN, "%s",
769 (char *)value);
770 }
771 /*
772 * The card may have a "clock-frequency" but we
773 * are not interested in that. Instead we get the
774 * "clock-frequency" of the PCI Bus that the card
775 * resides on. PCI-A can operate at 33Mhz or 66Mhz
776 * depending on what card is plugged into the Bus.
777 * PCI-B always operates at 33Mhz.
778 */
779 int_val = get_prop_val(find_prop(pci_instance,
780 "clock-frequency"));
781 if (int_val != NULL) {
782 pci_card->freq = DAK_CLK_FREQ_TO_MHZ(*int_val);
783 } else {
784 pci_card->freq = -1;
785 }
786
787 /*
788 * Figure out how we want to display the name
789 */
790 value = get_prop_val(find_prop(pci_card_node,
791 "compatible"));
792 if (value != NULL) {
793 /* use 'name'-'compatible' */
794 (void) snprintf(buf, MAXSTRLEN, "%s-%s", name,
795 (char *)value);
796 } else {
797 /* just use 'name' */
798 (void) snprintf(buf, MAXSTRLEN, "%s", name);
799 }
800 name = buf;
801
802 /*
803 * If this node has children, add the device_type
804 * of the child to the name value of this pci_card->
805 */
806 child_name = (char *)get_node_name(pci_card_node->child);
807 if ((pci_card_node->child != NULL) &&
808 (child_name != NULL)) {
809 value = get_prop_val(find_prop(pci_card_node->child,
810 "device_type"));
811 if (value != NULL) {
812 /* add device_type of child to name */
813 (void) snprintf(pci_card->name, MAXSTRLEN,
814 "%s/%s (%s)", name, child_name,
815 (char *)value);
816 } else {
817 /* just add childs name */
818 (void) snprintf(pci_card->name, MAXSTRLEN,
819 "%s/%s", name, child_name);
820 }
821 } else {
822 (void) snprintf(pci_card->name, MAXSTRLEN, "%s",
823 (char *)name);
824 }
825
826 /*
827 * If this is a pci-bridge, then add the word
828 * 'pci-bridge' to its model. If we can't find
829 * a model, then we just describe what the device
830 * is based on some properties.
831 */
832 if (pci_bridge) {
833 if (strlen(pci_card->model) == 0) {
834 if (pci_card_node->parent == pci_bridge_node)
835 (void) snprintf(pci_card->model, MAXSTRLEN,
836 "%s", "device on pci-bridge");
837 else if (pci_card_node->parent
838 == pci_parent_bridge)
839 (void) snprintf(pci_card->model, MAXSTRLEN,
840 "%s", "pci-bridge/pci-bridge");
841 else
842 (void) snprintf(pci_card->model, MAXSTRLEN,
843 "%s", "PCI-BRIDGE");
844 }
845 else
846 (void) snprintf(pci_card->model, MAXSTRLEN,
847 "%s/pci-bridge", pci_card->model);
848 }
849 /* insert this pci_card in the list to be displayed later */
850
851 *pci_card_list = insert_io_card(*pci_card_list, pci_card);
852
853 /*
854 * If we are dealing with a pci-bridge, we need to move
855 * down to the children of this bridge if there are any.
856 *
857 * If we are not, we are either dealing with a regular
858 * card (in which case we move onto the sibling of this
859 * card) or we are dealing with a child of a pci-bridge
860 * (in which case we move onto the child's siblings or
861 * if there are no more siblings for this child, we
862 * move onto the parents siblings).
863 */
864 pci_card_node = next_pci_card(pci_card_node, &pci_bridge,
865 is_pci, pci_bridge_node,
866 pci_parent_bridge, pci_instance);
867 } /* end-while */
868 }
869
870
871 /*
872 * Helper function for fill_pci_card_list(). Indicates which
873 * card node to go to next.
874 * Parameters:
875 * -----------
876 * Prom_node * curr_card: pointer to the current card node
877 *
878 * int * is_bridge: indicates whether or not the card (is | is on)
879 * a pci bridge
880 *
881 * int is_pcidev: indicates whether or not the current card
882 * is a pci bridge
883 *
884 * Prom_node * curr_bridge: pointer to the current pci bridge. Eg:
885 * curr_card->parent.
886 *
887 * Prom_node * parent_bridge: pointer to the first pci bridge encountered.
888 * we could have nested pci bridges, this would
889 * be the first one.
890 *
891 * Prom_node * pci: pointer to the pci instance that we are attached to.
892 * This would be parent_bridge->parent, or
893 * curr_node->parent, if curr_node is not on a pci bridge.
894 */
895 static Prom_node *
next_pci_card(Prom_node * curr_card,int * is_bridge,int is_pcidev,Prom_node * curr_bridge,Prom_node * parent_bridge,Prom_node * pci)896 next_pci_card(Prom_node *curr_card, int *is_bridge, int is_pcidev,
897 Prom_node *curr_bridge, Prom_node *parent_bridge,
898 Prom_node *pci)
899 {
900 Prom_node * curr_node = curr_card;
901 if (*is_bridge) {
902 /*
903 * is_pcidev is used to prevent us from following the
904 * children of something like a scsi device.
905 */
906 if (curr_node->child != NULL && is_pcidev) {
907 curr_node = curr_node->child;
908 } else {
909 curr_node = curr_node->sibling;
910 if (curr_node == NULL) {
911 curr_node = curr_bridge->sibling;
912
913 while (curr_node == NULL &&
914 curr_bridge != parent_bridge &&
915 curr_bridge != NULL) {
916 curr_node =
917 curr_bridge->parent->sibling;
918 curr_bridge = curr_bridge->parent;
919 if (curr_node != NULL &&
920 curr_node->parent == pci) {
921 break;
922 }
923 }
924
925 if (curr_bridge == NULL ||
926 curr_node == NULL ||
927 curr_node->parent == pci ||
928 curr_bridge == parent_bridge ||
929 curr_node == parent_bridge) {
930 *is_bridge = FALSE;
931 }
932 }
933 }
934
935 } else {
936 curr_node = curr_node->sibling;
937 }
938 return (curr_node);
939 }
940