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