03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CDDL HEADER START
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The contents of this file are subject to the terms of the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Common Development and Distribution License, Version 1.0 only
03831d35f7499c87d51205817c93e9a8d42c4baestevel * (the "License"). You may not use this file except in compliance
03831d35f7499c87d51205817c93e9a8d42c4baestevel * with the License.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
03831d35f7499c87d51205817c93e9a8d42c4baestevel * or http://www.opensolaris.org/os/licensing.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * See the License for the specific language governing permissions
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and limitations under the License.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * When distributing Covered Code, include this CDDL HEADER in each
03831d35f7499c87d51205817c93e9a8d42c4baestevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If applicable, add the following below this CDDL HEADER, with the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fields enclosed by brackets "[]" replaced with your own identifying
03831d35f7499c87d51205817c93e9a8d42c4baestevel * information: Portions Copyright [yyyy] [name of copyright owner]
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CDDL HEADER END
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Use is subject to license terms.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#pragma ident "%Z%%M% %I% %E% SMI"
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <stdio.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <stdlib.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <string.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <fcntl.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <stdarg.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <errno.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <unistd.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/utsname.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/openpromio.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <libintl.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include "pdevinfo.h"
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include "display.h"
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include "pdevinfo_sun4u.h"
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * For machines that support the openprom, fetch and print the list
03831d35f7499c87d51205817c93e9a8d42c4baestevel * of devices that the kernel has fetched from the prom or conjured up.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int prom_fd;
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern char *progname;
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern char *promdev;
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern void getppdata();
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern void printppdata();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Define DPRINT for run-time debugging printf's...
03831d35f7499c87d51205817c93e9a8d42c4baestevel * #define DPRINT 1
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DPRINT
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic char vdebug_flag = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define dprintf if (vdebug_flag) printf
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void dprint_dev_info(caddr_t, dev_info_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DPRINT */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if !defined(TEXT_DOMAIN)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define TEXT_DOMAIN "SYS_TEST"
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*VARARGS1*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevel_error(char *fmt, ...)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int saved_errno;
03831d35f7499c87d51205817c93e9a8d42c4baestevel va_list ap;
03831d35f7499c87d51205817c93e9a8d42c4baestevel extern int errno;
03831d35f7499c87d51205817c93e9a8d42c4baestevel saved_errno = errno;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (progname)
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) fprintf(stderr, "%s: ", progname);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel va_start(ap, fmt);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) vfprintf(stderr, fmt, ap);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel va_end(ap);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) fprintf(stderr, ": ");
03831d35f7499c87d51205817c93e9a8d42c4baestevel errno = saved_errno;
03831d35f7499c87d51205817c93e9a8d42c4baestevel perror("");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (2);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelis_openprom(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel Oppbuf oppbuf;
03831d35f7499c87d51205817c93e9a8d42c4baestevel register struct openpromio *opp = &(oppbuf.opp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel register unsigned int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel opp->oprom_size = MAXVALSIZE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ioctl(prom_fd, OPROMGETCONS, opp) < 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel exit(_error("OPROMGETCONS"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = (unsigned int)((unsigned char)opp->oprom_array[0]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return ((i & OPROMCONS_OPENPROM) == OPROMCONS_OPENPROM);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Read all properties and values from nodes.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Copy the properties read into the prom_node passsed in.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baesteveldump_node(Prom_node *node)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel Oppbuf oppbuf;
03831d35f7499c87d51205817c93e9a8d42c4baestevel register struct openpromio *opp = &oppbuf.opp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel Prop *prop = NULL; /* tail of properties list */
03831d35f7499c87d51205817c93e9a8d42c4baestevel StaticProp *temp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* clear out pointers in pnode */
03831d35f7499c87d51205817c93e9a8d42c4baestevel node->props = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* get first prop by asking for null string */
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) memset((void *) oppbuf.buf, 0, BUFSIZE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* allocate space for the property */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((temp = malloc(sizeof (StaticProp))) == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel perror("malloc");
03831d35f7499c87d51205817c93e9a8d42c4baestevel exit(1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel opp->oprom_size = MAXPROPSIZE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (opp->oprom_size != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel Prop *new;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *tempp, *newp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get property
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel opp->oprom_size = MAXPROPSIZE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ioctl(prom_fd, OPROMNXTPROP, opp) < 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel exit(_error("OPROMNXTPROP"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (opp->oprom_size != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel temp->name.opp.oprom_size = opp->oprom_size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) strcpy(temp->name.opp.oprom_array,
03831d35f7499c87d51205817c93e9a8d42c4baestevel opp->oprom_array);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) strcpy(temp->value.opp.oprom_array,
03831d35f7499c87d51205817c93e9a8d42c4baestevel temp->name.opp.oprom_array);
03831d35f7499c87d51205817c93e9a8d42c4baestevel getpropval(&temp->value.opp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel temp->size = temp->value.opp.oprom_size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Now copy over temp's data to new. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((new = malloc(sizeof (Prop))) == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel perror("malloc");
03831d35f7499c87d51205817c93e9a8d42c4baestevel exit(1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * First copy over temp->name's data. The
03831d35f7499c87d51205817c93e9a8d42c4baestevel * temp->name.opp.opio_u union always contains char[]
03831d35f7499c87d51205817c93e9a8d42c4baestevel * (as opposed to an int or int []).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel new->name.opp.oprom_size = temp->name.opp.oprom_size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((new->name.opp.oprom_array =
03831d35f7499c87d51205817c93e9a8d42c4baestevel malloc(new->name.opp.oprom_size)) == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel perror("malloc");
03831d35f7499c87d51205817c93e9a8d42c4baestevel exit(1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) strcpy(new->name.opp.oprom_array,
03831d35f7499c87d51205817c93e9a8d42c4baestevel temp->name.opp.oprom_array);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel new->name.opp.holds_array = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Then copy over temp->value's data.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * temp->value.opp.opio_u could contain char[], int or
03831d35f7499c87d51205817c93e9a8d42c4baestevel * int []. If *(temp->value.opp.oprom_array) is '\0',
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this indicates int or int []. int is the norm, but
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to be safe we assume int [] and copy over
03831d35f7499c87d51205817c93e9a8d42c4baestevel * OPROM_NODE_SIZE int elements.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel new->value.opp.oprom_size = temp->value.opp.oprom_size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (*(temp->value.opp.oprom_array) == '\0') {
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < OPROM_NODE_SIZE; i++)
03831d35f7499c87d51205817c93e9a8d42c4baestevel new->value.opp.oprom_node[i] =
03831d35f7499c87d51205817c93e9a8d42c4baestevel *(&temp->value.opp.oprom_node+i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel new->value.opp.holds_array = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((new->value.opp.oprom_array =
03831d35f7499c87d51205817c93e9a8d42c4baestevel malloc(new->value.opp.oprom_size))
03831d35f7499c87d51205817c93e9a8d42c4baestevel == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel perror("malloc");
03831d35f7499c87d51205817c93e9a8d42c4baestevel exit(1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * temp->value.opp.oprom_array can contain one
03831d35f7499c87d51205817c93e9a8d42c4baestevel * or more embedded NULLs. These trip-up the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * standard string copying functions, so we do
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the copy by hand. temp->value.opp.oprom_array
03831d35f7499c87d51205817c93e9a8d42c4baestevel * will be NULL-terminated. oprom_size includes
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this terminating NULL.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel newp = new->value.opp.oprom_array;
03831d35f7499c87d51205817c93e9a8d42c4baestevel tempp = temp->value.opp.oprom_array;
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = new->value.opp.oprom_size; i > 0; i--)
03831d35f7499c87d51205817c93e9a8d42c4baestevel *newp++ = *tempp++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel new->value.opp.holds_array = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel new->size = temp->size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* everything worked so link the property list */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (node->props == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel node->props = new;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else if (prop != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel prop->next = new;
03831d35f7499c87d51205817c93e9a8d42c4baestevel prop = new;
03831d35f7499c87d51205817c93e9a8d42c4baestevel prop->next = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel free(temp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelpromopen(int oflag)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*CONSTCOND*/
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((prom_fd = open(promdev, oflag)) < 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (errno == EAGAIN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) sleep(5);
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (errno == ENXIO)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel exit(_error(dgettext(TEXT_DOMAIN, "cannot open %s"),
03831d35f7499c87d51205817c93e9a8d42c4baestevel promdev));
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*NOTREACHED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelpromclose(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (close(prom_fd) < 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel exit(_error(dgettext(TEXT_DOMAIN, "close error on %s"),
03831d35f7499c87d51205817c93e9a8d42c4baestevel promdev));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Read the value of the property from the PROM device tree
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelgetpropval(struct openpromio *opp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel opp->oprom_size = MAXVALSIZE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ioctl(prom_fd, OPROMGETPROP, opp) < 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel exit(_error("OPROMGETPROP"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelnext(int id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel Oppbuf oppbuf;
03831d35f7499c87d51205817c93e9a8d42c4baestevel register struct openpromio *opp = &(oppbuf.opp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* LINTED */
03831d35f7499c87d51205817c93e9a8d42c4baestevel int *ip = (int *)(opp->oprom_array);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) memset((void *) oppbuf.buf, 0, BUFSIZE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel opp->oprom_size = MAXVALSIZE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel *ip = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ioctl(prom_fd, OPROMNEXT, opp) < 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (_error("OPROMNEXT"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* LINTED */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (*(int *)opp->oprom_array);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelchild(int id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel Oppbuf oppbuf;
03831d35f7499c87d51205817c93e9a8d42c4baestevel register struct openpromio *opp = &(oppbuf.opp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* LINTED */
03831d35f7499c87d51205817c93e9a8d42c4baestevel int *ip = (int *)(opp->oprom_array);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) memset((void *) oppbuf.buf, 0, BUFSIZE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel opp->oprom_size = MAXVALSIZE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel *ip = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ioctl(prom_fd, OPROMCHILD, opp) < 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (_error("OPROMCHILD"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* LINTED */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (*(int *)opp->oprom_array);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check if the Prom node passed in contains a property called
03831d35f7499c87d51205817c93e9a8d42c4baestevel * "board#".
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelhas_board_num(Prom_node *node)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel Prop *prop = node->props;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * walk thru all properties in this PROM node and look for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * board# prop
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (prop != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (strcmp(prop->name.opp.oprom_array, "board#") == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel prop = prop->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel} /* end of has_board_num() */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Retrieve the value of the board number property from this Prom
03831d35f7499c87d51205817c93e9a8d42c4baestevel * node. It has the type of int.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelget_board_num(Prom_node *node)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel Prop *prop = node->props;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * walk thru all properties in this PROM node and look for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * board# prop
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (prop != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (strcmp(prop->name.opp.oprom_array, "board#") == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (prop->value.opp.oprom_node[0]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel prop = prop->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel} /* end of get_board_num() */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Find the requested board struct in the system device tree.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelBoard_node *
03831d35f7499c87d51205817c93e9a8d42c4baestevelfind_board(Sys_tree *root, int board)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel Board_node *bnode = root->bd_list;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel while ((bnode != NULL) && (board != bnode->board_num))
03831d35f7499c87d51205817c93e9a8d42c4baestevel bnode = bnode->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (bnode);
03831d35f7499c87d51205817c93e9a8d42c4baestevel} /* end of find_board() */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Add a board to the system list in order. Initialize all pointer
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fields to NULL.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelBoard_node *
03831d35f7499c87d51205817c93e9a8d42c4baestevelinsert_board(Sys_tree *root, int board)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel Board_node *bnode;
03831d35f7499c87d51205817c93e9a8d42c4baestevel Board_node *temp = root->bd_list;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((bnode = (Board_node *) malloc(sizeof (Board_node))) == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel perror("malloc");
03831d35f7499c87d51205817c93e9a8d42c4baestevel exit(1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel bnode->nodes = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel bnode->next = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel bnode->board_num = board;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (temp == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel root->bd_list = bnode;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else if (temp->board_num > board) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel bnode->next = temp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel root->bd_list = bnode;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel while ((temp->next != NULL) && (board > temp->next->board_num))
03831d35f7499c87d51205817c93e9a8d42c4baestevel temp = temp->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel bnode->next = temp->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel temp->next = bnode;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel root->board_cnt++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (bnode);
03831d35f7499c87d51205817c93e9a8d42c4baestevel} /* end of insert_board() */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This function searches through the properties of the node passed in
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and returns a pointer to the value of the name property.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelchar *
03831d35f7499c87d51205817c93e9a8d42c4baestevelget_node_name(Prom_node *pnode)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel Prop *prop;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (pnode == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel prop = pnode->props;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (prop != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (strcmp("name", prop->name.opp.oprom_array) == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (prop->value.opp.oprom_array);
03831d35f7499c87d51205817c93e9a8d42c4baestevel prop = prop->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel} /* end of get_node_name() */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This function searches through the properties of the node passed in
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and returns a pointer to the value of the name property.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelchar *
03831d35f7499c87d51205817c93e9a8d42c4baestevelget_node_type(Prom_node *pnode)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel Prop *prop;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (pnode == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel prop = pnode->props;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (prop != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (strcmp("device_type", prop->name.opp.oprom_array) == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (prop->value.opp.oprom_array);
03831d35f7499c87d51205817c93e9a8d42c4baestevel prop = prop->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel} /* end of get_node_type() */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Do a depth-first walk of a device tree and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * return the first node with the name matching.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelProm_node *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldev_find_node(Prom_node *root, char *name)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel Prom_node *node;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel node = dev_find_node_by_type(root, "name", name);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelProm_node *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldev_next_node(Prom_node *root, char *name)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel Prom_node *node;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel node = dev_next_node_by_type(root, "name", name);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Search for and return a node of the required type. If no node is found,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * then return NULL.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelProm_node *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldev_find_type(Prom_node *root, char *type)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel Prom_node *node;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel node = dev_find_node_by_type(root, "device_type", type);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (node); /* not found */
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Start from the current node and return the next node besides the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * current one which has the requested type property.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelProm_node *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldev_next_type(Prom_node *root, char *type)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel Prom_node *node;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel node = dev_next_node_by_type(root, "device_type", type);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (node); /* not found */
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Search a device tree and return the first failed node that is found.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * (has a 'status' property)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelProm_node *
03831d35f7499c87d51205817c93e9a8d42c4baestevelfind_failed_node(Prom_node * root)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel Prom_node *pnode;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (root == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (node_failed(root)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (root);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* search the child */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((pnode = find_failed_node(root->child)) != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (pnode);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* search the siblings */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((pnode = find_failed_node(root->sibling)) != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (pnode);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel} /* end of find_failed_node() */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Start from the current node and return the next node besides
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the current one which is failed. (has a 'status' property)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelProm_node *
03831d35f7499c87d51205817c93e9a8d42c4baestevelnext_failed_node(Prom_node * root)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel Prom_node *pnode;
03831d35f7499c87d51205817c93e9a8d42c4baestevel Prom_node *parent;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (root == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* search the child */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((pnode = find_failed_node(root->child)) != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (pnode);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* search the siblings */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((pnode = find_failed_node(root->sibling)) != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (pnode);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* backtracking the search up through parents' siblings */
03831d35f7499c87d51205817c93e9a8d42c4baestevel parent = root->parent;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (parent != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((pnode = find_failed_node(parent->sibling)) != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (pnode);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel parent = parent->parent;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel} /* end of find_failed_node() */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * node_failed
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This function determines if the current Prom node is failed. This
03831d35f7499c87d51205817c93e9a8d42c4baestevel * is defined by having a status property containing the token 'fail'.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelnode_failed(Prom_node *node)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (node_status(node, "fail"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelnode_status(Prom_node *node, char *status)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel void *value;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* search the local node */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((value = get_prop_val(find_prop(node, "status"))) != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((value != NULL) && strstr((char *)value, status))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Get a property's value. Must be void * since the property can
03831d35f7499c87d51205817c93e9a8d42c4baestevel * be any data type. Caller must know the *PROPER* way to use this
03831d35f7499c87d51205817c93e9a8d42c4baestevel * data.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid *
03831d35f7499c87d51205817c93e9a8d42c4baestevelget_prop_val(Prop *prop)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (prop == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (prop->value.opp.holds_array)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return ((void *)(prop->value.opp.oprom_array));
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel return ((void *)(&prop->value.opp.oprom_node[0]));
03831d35f7499c87d51205817c93e9a8d42c4baestevel} /* end of get_prop_val() */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Search a Prom node and retrieve the property with the correct
03831d35f7499c87d51205817c93e9a8d42c4baestevel * name.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelProp *
03831d35f7499c87d51205817c93e9a8d42c4baestevelfind_prop(Prom_node *pnode, char *name)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel Prop *prop;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (pnode == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (pnode->props == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) printf("%s", dgettext(TEXT_DOMAIN, "Prom node has "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "no properties\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel prop = pnode->props;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while ((prop != NULL) && (strcmp(prop->name.opp.oprom_array, name)))
03831d35f7499c87d51205817c93e9a8d42c4baestevel prop = prop->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (prop);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This function adds a board node to the board structure where that
03831d35f7499c87d51205817c93e9a8d42c4baestevel * that node's physical component lives.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baesteveladd_node(Sys_tree *root, Prom_node *pnode)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int board;
03831d35f7499c87d51205817c93e9a8d42c4baestevel Board_node *bnode;
03831d35f7499c87d51205817c93e9a8d42c4baestevel Prom_node *p;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* add this node to the Board list of the appropriate board */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((board = get_board_num(pnode)) == -1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* board is 0 if not on Sunfire */
03831d35f7499c87d51205817c93e9a8d42c4baestevel board = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* find the node with the same board number */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((bnode = find_board(root, board)) == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel bnode = insert_board(root, board);
03831d35f7499c87d51205817c93e9a8d42c4baestevel bnode->board_type = UNKNOWN_BOARD;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* now attach this prom node to the board list */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Insert this node at the end of the list */
03831d35f7499c87d51205817c93e9a8d42c4baestevel pnode->sibling = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (bnode->nodes == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel bnode->nodes = pnode;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel p = bnode->nodes;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (p->sibling != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel p = p->sibling;
03831d35f7499c87d51205817c93e9a8d42c4baestevel p->sibling = pnode;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Find the device on the current board with the requested device ID
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and name. If this rountine is passed a NULL pointer, it simply returns
03831d35f7499c87d51205817c93e9a8d42c4baestevel * NULL.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelProm_node *
03831d35f7499c87d51205817c93e9a8d42c4baestevelfind_device(Board_node *board, int id, char *name)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel Prom_node *pnode;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int mask;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* find the first cpu node */
03831d35f7499c87d51205817c93e9a8d42c4baestevel pnode = dev_find_node(board->nodes, name);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mask = 0x1F;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (pnode != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((get_id(pnode) & mask) == id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (pnode);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel pnode = dev_next_node(pnode, name);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelProm_node *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldev_find_node_by_type(Prom_node *root, char *type, char *property)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel Prom_node *node;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *type_prop;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (root == NULL || property == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel type_prop = (char *)get_prop_val(find_prop(root, type));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (type_prop != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (strcmp(type_prop, property) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (root);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* look at your children first */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((node = dev_find_node_by_type(root->child, type,
03831d35f7499c87d51205817c93e9a8d42c4baestevel property)) != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* now look at your siblings */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((node = dev_find_node_by_type(root->sibling, type,
03831d35f7499c87d51205817c93e9a8d42c4baestevel property)) != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL); /* not found */
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelProm_node *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldev_next_node_by_type(Prom_node *root, char *type, char *property)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel Prom_node *node;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (root == NULL || property == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* look at your children first */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((node = dev_find_node_by_type(root->child, type,
03831d35f7499c87d51205817c93e9a8d42c4baestevel property)) != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* now look at your siblings */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((node = dev_find_node_by_type(root->sibling, type,
03831d35f7499c87d51205817c93e9a8d42c4baestevel property)) != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* now look at papa's siblings */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((node = dev_find_node_by_type(root->parent->sibling,
03831d35f7499c87d51205817c93e9a8d42c4baestevel type, property)) != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL); /* not found */
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Do a depth-first walk of a device tree and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * return the first node with the matching compatible.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelProm_node *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldev_find_node_by_compatible(Prom_node *root, char *compatible)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel Prom_node *node;
03831d35f7499c87d51205817c93e9a8d42c4baestevel Prop *prop;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *compatible_array;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int size, nbytes;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (root == NULL || compatible == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((prop = find_prop(root, "compatible")) != NULL &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel (compatible_array = (char *)get_prop_val(prop)) != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The Prop structure returned by find_prop() is supposed
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to contain an indication of how big the value of the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * compatible property is. Since it is an array of strings
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this is our only means of determining just how many
03831d35f7499c87d51205817c93e9a8d42c4baestevel * strings might be in this property. However, this size
03831d35f7499c87d51205817c93e9a8d42c4baestevel * is often left as zero even though there is at least one
03831d35f7499c87d51205817c93e9a8d42c4baestevel * string present. When this is the case, all we can do
03831d35f7499c87d51205817c93e9a8d42c4baestevel * is examine the first string in the compatible property.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (size = prop->size; size >= 0; size -= nbytes) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (strcmp(compatible_array, compatible) == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (root); /* found a match */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel nbytes = strlen(compatible_array) + 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel compatible_array += nbytes;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel node = dev_find_node_by_compatible(root->child, compatible);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (node != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Note the very deliberate use of tail recursion here. A good
03831d35f7499c87d51205817c93e9a8d42c4baestevel * compiler (such as Sun's) will recognize this and generate code
03831d35f7499c87d51205817c93e9a8d42c4baestevel * that does not allocate another stack frame. Instead, it will
03831d35f7499c87d51205817c93e9a8d42c4baestevel * overlay the existing stack frame with the new one, the only change
03831d35f7499c87d51205817c93e9a8d42c4baestevel * having been to replace the original root with its sibling.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This has the potential to create some confusion for anyone
03831d35f7499c87d51205817c93e9a8d42c4baestevel * trying to debug this code from a core dump, since the stack
03831d35f7499c87d51205817c93e9a8d42c4baestevel * trace will not reveal recursion on siblings, only on children.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (dev_find_node_by_compatible(root->sibling, compatible));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Start from the current node and return the next node besides
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the current one which has the requested compatible property.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelProm_node *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldev_next_node_by_compatible(Prom_node *root, char *compatible)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel Prom_node *node;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (root == NULL || compatible == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel node = dev_find_node_by_compatible(root->child, compatible);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (node != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * More tail recursion. Even though it is a different function,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this will overlay the current stack frame. Caveat exterminator.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel node = dev_find_node_by_compatible(root->sibling, compatible);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (node != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (dev_find_node_by_compatible(root->parent->sibling, compatible));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}