Transform `mainbus' attach code to use its own attach arguments.

Add a couple rom-property helper functions; some overlapping functionality
with existing function, but hold on to the latter for just a while.
This commit is contained in:
pk 1998-03-21 12:18:25 +00:00
parent 8d63cb6db8
commit d19772ea9e
1 changed files with 295 additions and 144 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: autoconf.c,v 1.84 1998/01/28 00:15:09 pk Exp $ */ /* $NetBSD: autoconf.c,v 1.85 1998/03/21 12:18:25 pk Exp $ */
/* /*
* Copyright (c) 1996 * Copyright (c) 1996
@ -69,8 +69,10 @@
#include <vm/vm.h> #include <vm/vm.h>
#include <machine/bus.h>
#include <machine/autoconf.h> #include <machine/autoconf.h>
#include <machine/bsd_openprom.h> #include <machine/bsd_openprom.h>
#ifdef SUN4 #ifdef SUN4
#include <machine/oldmon.h> #include <machine/oldmon.h>
#include <machine/idprom.h> #include <machine/idprom.h>
@ -130,15 +132,9 @@ matchbyname(parent, cf, aux)
struct cfdata *cf; struct cfdata *cf;
void *aux; void *aux;
{ {
struct confargs *ca = aux; printf("%s: WARNING: matchbyname\n", cf->cf_driver->cd_name);
if (CPU_ISSUN4) {
printf("WARNING: matchbyname not valid on sun4!");
printf("%s\n", cf->cf_driver->cd_name);
return (0); return (0);
} }
return (strcmp(cf->cf_driver->cd_name, ca->ca_ra.ra_name) == 0);
}
/* /*
* Convert hex ASCII string to a value. Returns updated pointer. * Convert hex ASCII string to a value. Returns updated pointer.
@ -251,7 +247,7 @@ bootstrap()
/* First we'll do the interrupt registers */ /* First we'll do the interrupt registers */
if (CPU_ISSUN4M) { if (CPU_ISSUN4M) {
register int node; register int node;
struct romaux ra; int nvaddrs, *vaddrs, vstore[10];
register u_int pte; register u_int pte;
register int i; register int i;
extern void setpte4m __P((u_int, u_int)); extern void setpte4m __P((u_int, u_int));
@ -261,19 +257,30 @@ bootstrap()
panic("bootstrap: could not get interrupt " panic("bootstrap: could not get interrupt "
"node from prom"); "node from prom");
vaddrs = vstore;
if (getpropA(node, "address", sizeof(int),
&nvaddrs, (void **)&vaddrs) != 0) {
printf("bootstrap: could not get interrupt properties");
romhalt();
}
#if 0
if (!romprop(&ra, "interrupt", node)) if (!romprop(&ra, "interrupt", node))
panic("bootstrap: could not get interrupt properties"); panic("bootstrap: could not get interrupt properties");
if (ra.ra_nvaddrs < 2) #endif
panic("bootstrap: less than 2 interrupt regs. available"); if (nvaddrs < 2 || nvaddrs > 4) {
if (ra.ra_nvaddrs > 5) printf("bootstrap: cannot handle %d interrupt regs\n",
panic("bootstrap: cannot support capability of > 4 CPUs"); nvaddrs);
romhalt();
}
for (i = 0; i < ra.ra_nvaddrs - 1; i++) { for (i = 0; i < nvaddrs - 1; i++) {
pte = getpte4m((u_int)ra.ra_vaddrs[i]); pte = getpte4m((u_int)vaddrs[i]);
if ((pte & SRMMU_TETYPE) != SRMMU_TEPTE) if ((pte & SRMMU_TETYPE) != SRMMU_TEPTE) {
panic("bootstrap: PROM has invalid mapping for " panic("bootstrap: PROM has invalid mapping for "
"processor interrupt register %d",i); "processor interrupt register %d",i);
romhalt();
}
pte |= PPROT_S; pte |= PPROT_S;
/* Duplicate existing mapping */ /* Duplicate existing mapping */
@ -285,7 +292,7 @@ bootstrap()
* That was the processor register...now get system register; * That was the processor register...now get system register;
* it is the last returned by the PROM * it is the last returned by the PROM
*/ */
pte = getpte4m((u_int)ra.ra_vaddrs[i]); pte = getpte4m((u_int)vaddrs[i]);
if ((pte & SRMMU_TETYPE) != SRMMU_TEPTE) if ((pte & SRMMU_TETYPE) != SRMMU_TEPTE)
panic("bootstrap: PROM has invalid mapping for system " panic("bootstrap: PROM has invalid mapping for system "
"interrupt register"); "interrupt register");
@ -671,6 +678,7 @@ crazymap(prop, map)
{ {
int i; int i;
char *propval; char *propval;
char buf[32];
if (!CPU_ISSUN4 && promvec->pv_romvec_vers < 2) { if (!CPU_ISSUN4 && promvec->pv_romvec_vers < 2) {
/* /*
@ -678,7 +686,7 @@ crazymap(prop, map)
* which contains the mapping for us to use. v2 proms donot * which contains the mapping for us to use. v2 proms donot
* require remapping. * require remapping.
*/ */
propval = getpropstring(optionsnode, prop); propval = getpropstringA(optionsnode, prop, buf);
if (propval == NULL || strlen(propval) != 8) { if (propval == NULL || strlen(propval) != 8) {
build_default_map: build_default_map:
printf("WARNING: %s map is bogus, using default\n", printf("WARNING: %s map is bogus, using default\n",
@ -754,9 +762,6 @@ struct devnametobdevmaj sparc_nam2blk[] = {
void void
configure() configure()
{ {
struct confargs oca;
register int node = 0;
register char *cp;
/* build the bootpath */ /* build the bootpath */
bootpath_build(); bootpath_build();
@ -767,8 +772,8 @@ configure()
extern struct cfdriver obio_cd; extern struct cfdriver obio_cd;
extern struct cfdata cfdata[]; extern struct cfdata cfdata[];
struct cfdata *cf, *memregcf = NULL; struct cfdata *cf, *memregcf = NULL;
bus_space_handle_t bh;
register short *p; register short *p;
struct rom_reg rr;
for (cf = cfdata; memregcf == NULL && cf->cf_driver; cf++) { for (cf = cfdata; memregcf == NULL && cf->cf_driver; cf++) {
if (cf->cf_driver != &memreg_cd || if (cf->cf_driver != &memreg_cd ||
@ -795,32 +800,25 @@ configure()
if (memregcf == NULL) if (memregcf == NULL)
panic("configure: no memreg found!"); panic("configure: no memreg found!");
rr.rr_iospace = PMAP_OBIO; if (obio_bus_map(0, /* XXX - obio tag; we haven't got one */
rr.rr_paddr = (void *)memregcf->cf_loc[0]; (void *)memregcf->cf_loc[0], 0, NBPG,
rr.rr_len = NBPG; 0, 0, &bh) != 0)
par_err_reg = (u_int *)obio_bus_map(&rr, NBPG);
if (par_err_reg == NULL)
panic("configure: ROM hasn't mapped memreg!"); panic("configure: ROM hasn't mapped memreg!");
} }
#endif #endif
#if defined(SUN4C) #if defined(SUN4C)
if (CPU_ISSUN4C) { if (CPU_ISSUN4C) {
node = findroot(); char *cp, buf[32];
cp = getpropstring(node, "device_type"); int node = findroot();
cp = getpropstringA(node, "device_type", buf);
if (strcmp(cp, "cpu") != 0) if (strcmp(cp, "cpu") != 0)
panic("PROM root device type = %s (need CPU)\n", cp); panic("PROM root device type = %s (need CPU)\n", cp);
} }
#endif #endif
#if defined(SUN4M)
if (CPU_ISSUN4M)
node = findroot();
#endif
*promvec->pv_synchook = sync_crash; *promvec->pv_synchook = sync_crash;
oca.ca_ra.ra_node = node; if (config_rootfound("mainbus", NULL) == NULL)
oca.ca_ra.ra_name = cp = "mainbus";
if (config_rootfound(cp, (void *)&oca) == NULL)
panic("mainbus not configured"); panic("mainbus not configured");
/* Enable device interrupts */ /* Enable device interrupts */
@ -887,13 +885,14 @@ mbprint(aux, name)
void *aux; void *aux;
const char *name; const char *name;
{ {
register struct confargs *ca = aux; struct mainbus_attach_args *ma = aux;
if (name) if (name)
printf("%s at %s", ca->ca_ra.ra_name, name); printf("%s at %s", ma->ma_name, name);
if (ca->ca_ra.ra_paddr) if (ma->ma_paddr)
printf(" %saddr 0x%x", ca->ca_ra.ra_iospace ? "io" : "", printf(" %saddr %p", ma->ma_iospace ? "io" : "", ma->ma_paddr);
(int)ca->ca_ra.ra_paddr); if (ma->ma_pri)
printf(" ipl %d", ma->ma_pri);
return (UNCONF); return (UNCONF);
} }
@ -917,14 +916,16 @@ findnode(first, name)
int first; int first;
register const char *name; register const char *name;
{ {
register int node; int node;
char buf[32];
for (node = first; node; node = nextsibling(node)) for (node = first; node; node = nextsibling(node))
if (strcmp(getpropstring(node, "name"), name) == 0) if (strcmp(getpropstringA(node, "name", buf), name) == 0)
return (node); return (node);
return (0); return (0);
} }
#if 0
/* /*
* Fill in a romaux. Returns 1 on success, 0 if the register property * Fill in a romaux. Returns 1 on success, 0 if the register property
* was not the right size. * was not the right size.
@ -998,6 +999,7 @@ romprop(rp, cp, node)
} }
return (1); return (1);
} }
#endif
int int
mainbus_match(parent, cf, aux) mainbus_match(parent, cf, aux)
@ -1005,10 +1007,8 @@ mainbus_match(parent, cf, aux)
struct cfdata *cf; struct cfdata *cf;
void *aux; void *aux;
{ {
register struct confargs *ca = aux;
register struct romaux *ra = &ca->ca_ra;
return (strcmp(cf->cf_driver->cd_name, ra->ra_name) == 0); return (1);
} }
int autoconf_nzs = 0; /* must be global so obio.c can see it */ int autoconf_nzs = 0; /* must be global so obio.c can see it */
@ -1025,23 +1025,16 @@ mainbus_attach(parent, dev, aux)
struct device *parent, *dev; struct device *parent, *dev;
void *aux; void *aux;
{ {
struct confargs oca; extern struct sparc_bus_dma_tag mainbus_dma_tag;
register const char *const *ssp, *sp = NULL; extern struct sparc_bus_space_tag mainbus_space_tag;
struct confargs *ca = aux;
struct mainbus_attach_args ma;
char namebuf[32];
#if defined(SUN4C) || defined(SUN4M) #if defined(SUN4C) || defined(SUN4M)
register int node0, node; const char *const *ssp, *sp = NULL;
int node0, node;
const char *const *openboot_special; const char *const *openboot_special;
#define L1A_HACK /* XXX hack to allow L1-A during autoconf */
#ifdef L1A_HACK
int audio = 0;
#endif #endif
#endif
#if defined(SUN4)
static const char *const oldmon_special[] = {
"vme",
NULL
};
#endif /* SUN4 */
#if defined(SUN4C) #if defined(SUN4C)
static const char *const openboot_special4c[] = { static const char *const openboot_special4c[] = {
@ -1094,7 +1087,7 @@ mainbus_attach(parent, dev, aux)
if (CPU_ISSUN4) if (CPU_ISSUN4)
printf(": SUN-4/%d series\n", cpuinfo.classlvl); printf(": SUN-4/%d series\n", cpuinfo.classlvl);
else else
printf(": %s\n", getpropstring(ca->ca_ra.ra_node, "name")); printf(": %s\n", getpropstringA(findroot(), "name", namebuf));
/* /*
@ -1106,26 +1099,27 @@ mainbus_attach(parent, dev, aux)
#if defined(SUN4) #if defined(SUN4)
if (CPU_ISSUN4) { if (CPU_ISSUN4) {
bzero(&ma, sizeof(ma));
/* Configure the CPU. */ /* Configure the CPU. */
bzero(&oca, sizeof(oca)); ma.ma_bustag = &mainbus_space_tag;
oca.ca_ra.ra_name = "cpu"; ma.ma_dmatag = &mainbus_dma_tag;
(void)config_found(dev, (void *)&oca, mbprint); ma.ma_name = "cpu";
if (config_found(dev, (void *)&ma, mbprint) == NULL)
panic("cpu missing");
/* Start at the beginning of the bootpath */ ma.ma_bustag = &mainbus_space_tag;
bzero(&oca, sizeof(oca)); ma.ma_dmatag = &mainbus_dma_tag;
oca.ca_ra.ra_bp = bootpath; ma.ma_name = "obio";
ma.ma_bp = bootpath;
oca.ca_bustype = BUS_MAIN; if (config_found(dev, (void *)&ma, mbprint) == NULL)
oca.ca_ra.ra_name = "obio";
if (config_found(dev, (void *)&oca, mbprint) == NULL)
panic("obio missing"); panic("obio missing");
for (ssp = oldmon_special; (sp = *ssp) != NULL; ssp++) { ma.ma_bustag = &mainbus_space_tag;
oca.ca_bustype = BUS_MAIN; ma.ma_dmatag = &mainbus_dma_tag;
oca.ca_ra.ra_name = sp; ma.ma_name = "vme";
(void)config_found(dev, (void *)&oca, mbprint); ma.ma_bp = bootpath;
} (void)config_found(dev, (void *)&ma, mbprint);
return;
} }
#endif #endif
@ -1138,7 +1132,7 @@ mainbus_attach(parent, dev, aux)
? openboot_special4m ? openboot_special4m
: openboot_special4c; : openboot_special4c;
node = ca->ca_ra.ra_node; /* i.e., the root node */ node = findroot();
/* the first early device to be configured is the cpu */ /* the first early device to be configured is the cpu */
if (CPU_ISSUN4M) { if (CPU_ISSUN4M) {
@ -1146,30 +1140,30 @@ mainbus_attach(parent, dev, aux)
register const char *cp; register const char *cp;
for (node = firstchild(node); node; node = nextsibling(node)) { for (node = firstchild(node); node; node = nextsibling(node)) {
cp = getpropstring(node, "device_type"); cp = getpropstringA(node, "device_type", namebuf);
if (strcmp(cp, "cpu") == 0) { if (strcmp(cp, "cpu") == 0) {
bzero(&oca, sizeof(oca)); bzero(&ma, sizeof(ma));
oca.ca_ra.ra_node = node; ma.ma_bustag = &mainbus_space_tag;
oca.ca_ra.ra_name = "cpu"; ma.ma_dmatag = &mainbus_dma_tag;
oca.ca_ra.ra_paddr = 0; ma.ma_node = node;
oca.ca_ra.ra_nreg = 0; ma.ma_name = "cpu";
config_found(dev, (void *)&oca, mbprint); config_found(dev, (void *)&ma, mbprint);
} }
} }
} else if (CPU_ISSUN4C) { } else if (CPU_ISSUN4C) {
bzero(&oca, sizeof(oca)); bzero(&ma, sizeof(ma));
oca.ca_ra.ra_node = node; ma.ma_bustag = &mainbus_space_tag;
oca.ca_ra.ra_name = "cpu"; ma.ma_dmatag = &mainbus_dma_tag;
oca.ca_ra.ra_paddr = 0; ma.ma_node = node;
oca.ca_ra.ra_nreg = 0; ma.ma_name = "cpu";
config_found(dev, (void *)&oca, mbprint); config_found(dev, (void *)&ma, mbprint);
} }
node = ca->ca_ra.ra_node; /* re-init root node */ node = findroot(); /* re-init root node */
if (promvec->pv_romvec_vers <= 2) if (promvec->pv_romvec_vers <= 2)
/* remember which frame buffer, if any, is to be /dev/fb */ /* remember which frame buffer, if any, is to be `/dev/fb' */
fbnode = getpropint(node, "fb", 0); fbnode = getpropint(node, "fb", 0);
/* Find the "options" node */ /* Find the "options" node */
@ -1178,17 +1172,34 @@ mainbus_attach(parent, dev, aux)
if (optionsnode == 0) if (optionsnode == 0)
panic("no options in OPENPROM"); panic("no options in OPENPROM");
/* Start at the beginning of the bootpath */
oca.ca_ra.ra_bp = bootpath;
for (ssp = openboot_special; *(sp = *ssp) != 0; ssp++) { for (ssp = openboot_special; *(sp = *ssp) != 0; ssp++) {
struct rom_reg romreg;
if ((node = findnode(node0, sp)) == 0) { if ((node = findnode(node0, sp)) == 0) {
printf("could not find %s in OPENPROM\n", sp); printf("could not find %s in OPENPROM\n", sp);
panic(sp); panic(sp);
} }
oca.ca_bustype = BUS_MAIN;
if (!romprop(&oca.ca_ra, sp, node) || bzero(&ma, sizeof ma);
(config_found(dev, (void *)&oca, mbprint) == NULL)) ma.ma_bustag = &mainbus_space_tag;
ma.ma_dmatag = &mainbus_dma_tag;
ma.ma_name = getpropstringA(node, "name", namebuf);
ma.ma_node = node;
if (getprop_reg1(node, &romreg) != 0)
continue;
ma.ma_paddr = (void *)romreg.rr_paddr;
ma.ma_iospace = romreg.rr_iospace;
ma.ma_size = romreg.rr_len;
if (getprop_intr1(node, &ma.ma_pri) != 0)
continue;
if (getprop_address1(node, &ma.ma_promvaddr) != 0)
continue;
/* Start at the beginning of the bootpath */
ma.ma_bp = bootpath;
if (config_found(dev, (void *)&ma, mbprint) == NULL)
panic(sp); panic(sp);
} }
@ -1198,30 +1209,45 @@ mainbus_attach(parent, dev, aux)
* done before we get here. * done before we get here.
*/ */
for (node = node0; node; node = nextsibling(node)) { for (node = node0; node; node = nextsibling(node)) {
register const char *cp; const char *cp;
struct rom_reg romreg;
#if defined(SUN4M) #if defined(SUN4M)
if (CPU_ISSUN4M) /* skip the CPUs */ if (CPU_ISSUN4M) /* skip the CPUs */
if (node_has_property(node, "device_type") && if (node_has_property(node, "device_type") &&
!strcmp(getpropstring(node, "device_type"), "cpu")) strcmp(getpropstringA(node, "device_type", namebuf),
"cpu") == 0)
continue; continue;
#endif #endif
cp = getpropstring(node, "name"); cp = getpropstringA(node, "name", namebuf);
for (ssp = openboot_special; (sp = *ssp) != NULL; ssp++) for (ssp = openboot_special; (sp = *ssp) != NULL; ssp++)
if (strcmp(cp, sp) == 0) if (strcmp(cp, sp) == 0)
break; break;
if (sp == NULL && romprop(&oca.ca_ra, cp, node)) { if (sp != NULL)
#ifdef L1A_HACK continue; /* an "early" device already configured */
if (strcmp(cp, "audio") == 0)
audio = 1; bzero(&ma, sizeof ma);
if (strcmp(cp, "zs") == 0) ma.ma_bustag = &mainbus_space_tag;
autoconf_nzs++; ma.ma_dmatag = &mainbus_dma_tag;
if (/*audio &&*/ autoconf_nzs >= 2) /*XXX*/ ma.ma_name = getpropstringA(node, "name", namebuf);
(void) splx(11 << 8); /*XXX*/ ma.ma_node = node;
#endif if (getprop_reg1(node, &romreg) != 0)
oca.ca_bustype = BUS_MAIN; continue;
(void) config_found(dev, (void *)&oca, mbprint);
} ma.ma_paddr = (void *)romreg.rr_paddr;
ma.ma_iospace = romreg.rr_iospace;
ma.ma_size = romreg.rr_len;
if (getprop_intr1(node, &ma.ma_pri) != 0)
continue;
if (getprop_address1(node, &ma.ma_promvaddr) != 0)
continue;
/* Start at the beginning of the bootpath */
ma.ma_bp = bootpath;
(void) config_found(dev, (void *)&ma, mbprint);
} }
#endif /* SUN4C || SUN4M */ #endif /* SUN4C || SUN4M */
} }
@ -1248,28 +1274,29 @@ findzs(zs)
#define ZS2_PHYS 0xe0000000 #define ZS2_PHYS 0xe0000000
if (CPU_ISSUN4) { if (CPU_ISSUN4) {
struct rom_reg rr; bus_space_handle_t bh;
register void *vaddr; void * paddr;
switch (zs) { switch (zs) {
case 0: case 0:
rr.rr_paddr = (void *)ZS0_PHYS; paddr = (void *)ZS0_PHYS;
break; break;
case 1: case 1:
rr.rr_paddr = (void *)ZS1_PHYS; paddr = (void *)ZS1_PHYS;
break; break;
case 2: case 2:
rr.rr_paddr = (void *)ZS2_PHYS; paddr = (void *)ZS2_PHYS;
break; break;
default: default:
panic("findzs: unknown zs device %d", zs); panic("findzs: unknown zs device %d", zs);
} }
rr.rr_iospace = PMAP_OBIO; if (obio_bus_map(0, /* XXX - obio tag; we haven't got one */
rr.rr_len = NBPG; paddr, 0, NBPG,
vaddr = obio_bus_map(&rr, NBPG); 0, 0, &bh) != 0)
if (vaddr) panic("findzs: can't map zs%d registers", zs);
return (vaddr);
return ((void *)bh);
} }
#endif #endif
@ -1460,6 +1487,112 @@ getprop(node, name, buf, bufsiz)
#endif #endif
} }
int
getpropA(node, name, size, nitem, bufp)
int node;
char *name;
int size;
int *nitem;
void **bufp;
{
struct nodeops *no;
void *buf;
int len;
no = promvec->pv_nodeops;
len = no->no_proplen(node, name);
if (len <= 0)
return (ENOENT);
if ((len % size) != 0)
return (EINVAL);
buf = *bufp;
if (buf == NULL) {
/* No storage provided, so we allocate some */
buf = malloc(len, M_DEVBUF, M_NOWAIT);
if (buf == NULL)
return (ENOMEM);
}
no->no_getprop(node, name, buf);
*bufp = buf;
*nitem = len / size;
return (0);
}
int
getprop_reg1(node, rrp)
int node;
struct rom_reg *rrp;
{
int error, n;
struct rom_reg *rrp0 = NULL;
char buf[32];
error = getpropA(node, "reg", sizeof(struct rom_reg),
&n, (void **)&rrp0);
if (error != 0) {
if (error == ENOENT &&
node_has_property(node, "device_type") &&
strcmp(getpropstringA(node, "device_type", buf),
"hierarchical") == 0) {
bzero(rrp, sizeof(struct rom_reg));
error = 0;
}
return (error);
}
*rrp = rrp0[0];
free(rrp0, M_DEVBUF);
return (0);
}
int
getprop_intr1(node, ip)
int node;
int *ip;
{
int error, n;
struct rom_intr *rip = NULL;
error = getpropA(node, "intr", sizeof(struct rom_intr),
&n, (void **)&rip);
if (error != 0) {
if (error == ENOENT) {
*ip = 0;
error = 0;
}
return (error);
}
*ip = rip[0].int_pri & 0xf;
free(rip, M_DEVBUF);
return (0);
}
int
getprop_address1(node, vpp)
int node;
void **vpp;
{
int error, n;
void **vp = NULL;
error = getpropA(node, "address", sizeof(u_int32_t), &n, (void **)&vp);
if (error != 0) {
if (error == ENOENT) {
*vpp = 0;
error = 0;
}
return (error);
}
*vpp = vp[0];
free(vp, M_DEVBUF);
return (0);
}
/* /*
* Internal form of proplen(). Returns the property length. * Internal form of proplen(). Returns the property length.
*/ */
@ -1493,6 +1626,22 @@ getpropstring(node, name)
return (stringbuf); return (stringbuf);
} }
/* Alternative getpropstring(), where caller provides the buffer */
char *
getpropstringA(node, name, buffer)
int node;
char *name;
char *buffer;
{
int blen;
if (getpropA(node, name, 1, &blen, (void **)&buffer) != 0)
blen = 0;
buffer[blen] = '\0'; /* usually unnecessary */
return (buffer);
}
/* /*
* Fetch an integer (or pointer) property. * Fetch an integer (or pointer) property.
* The return value is the property, or the default if there was none. * The return value is the property, or the default if there was none.
@ -1540,29 +1689,31 @@ search_prom(rootnode, name)
register int rootnode; register int rootnode;
register char *name; register char *name;
{ {
register int rtnnode; int rtnnode;
register int node = rootnode; int node = rootnode;
char buf[32];
if (node == findroot() || !strcmp("hierarchical", if (node == findroot() ||
getpropstring(node, "device_type"))) !strcmp("hierarchical", getpropstringA(node, "device_type", buf)))
node = firstchild(node); node = firstchild(node);
if (!node) if (node == 0)
panic("search_prom: null node"); panic("search_prom: null node");
do { do {
if (strcmp(getpropstring(node, "name"),name) == 0) if (strcmp(getpropstringA(node, "name", buf), name) == 0)
return node; return (node);
if (node_has_property(node,"device_type") && if (node_has_property(node,"device_type") &&
(!strcmp(getpropstring(node, "device_type"),"hierarchical") (strcmp(getpropstringA(node, "device_type", buf),
|| !strcmp(getpropstring(node, "name"),"iommu")) "hierarchical") == 0
|| strcmp(getpropstringA(node, "name", buf), "iommu") == 0)
&& (rtnnode = search_prom(node, name)) != 0) && (rtnnode = search_prom(node, name)) != 0)
return rtnnode; return (rtnnode);
} while ((node = nextsibling(node))); } while ((node = nextsibling(node)));
return 0; return (0);
} }
/* The following are used primarily in consinit() */ /* The following are used primarily in consinit() */