2021-10-11 18:37:13 -03:00

162 lines
3.7 KiB
C

#if !defined(lint) && !defined(BOOTBLOCK)
static char sccsid[] = "@(#)init_devsw.c 1.1 94/10/31 SMI";
#endif
/*
* Copyright (c) 1988 Sun Microsystems, Inc.
*
* Devswitch support routines for the Open Boot Proms.
*
*/
#include <sys/param.h>
#include <sun/autoconf.h>
#include <sun/openprom.h>
#include <mon/sunromvec.h>
#include <string.h>
#include "boot/conf.h"
#define NEXT prom_nextnode
#define CHILD prom_childnode
extern char *getlongprop();
char bdevnames[8][3]; /* 3 chars each (2 letters and Null) */
extern struct boottab *(devsw[]);
extern struct bdevlist bdevlist[];
extern struct boottab blkdriver, tapedriver, ifdriver;
extern struct ndevlist ndevlist[];
/*
* Initial indices for the devsw[] and bdevlist[]. Note that the bdevlist[]
* has to start at entry [1]! Device [0] is defined to be NODEV and
* the open routine fails.
*/
static int dev = 0;
static int bdev = 1;
#ifndef sun4m
static void walk(), check_this_node(), add_to_devsw();
#else
static void add_to_devsw();
#endif !sun4m
/*
* At run time, walk the dev_info structure in the monitor and find all
* "block", "byte", and "network" devices. Fill in the devsw and bdevlist
* tables with their names and driver entry points.
*/
init_devsw()
{
if (prom_getversion() > 0)
return (init_devlist());
#ifndef sun4m
walk(NEXT(0)); /* Get the root node */
#endif !sun4m
}
#ifndef sun4m
/*
* CS201: Data Structures. MWF 11:00-11:50 Wilmot 214. 4 credits. Grade: B-
*/
static void
walk(id)
int id;
{
register int curnode;
register char *c;
register char *s;
if (id)
check_this_node(id);
if (curnode = CHILD(id))
walk(curnode);
if (curnode = NEXT(id))
walk(curnode);
}
static void
check_this_node(id)
int id;
{
register char *name, *type;
register char *s1, *s2;
char *dupstring();
type = name = (char *)0;
name = getlongprop(id, "name");
if (((int)name == 0) || ((int)name == -1))
return;
type = getlongprop(id, "device_type");
if ((int)type == -1)
type = (char *)0;
if (strncmp(type, "block", 5) == 0) {
add_to_devsw(name, &blkdriver, dev);
(void)strncpy(bdevnames[bdev], name, 3);
bdevlist[bdev].bl_name = bdevnames[bdev];
bdevlist[bdev].bl_root = makedev(bdev, 0);
bdevlist[bdev++].bl_driver = devsw[dev++];
} else if (strncmp(type, "byte", 4) == 0) {
add_to_devsw(name, &tapedriver, dev);
(void)strncpy(bdevnames[bdev], name, 3);
bdevlist[bdev].bl_name = bdevnames[bdev];
bdevlist[bdev].bl_root = makedev(bdev, 0);
bdevlist[bdev++].bl_driver = devsw[dev++];
} else if (strncmp(type, "network", 7) == 0) {
add_to_devsw(name, &ifdriver, dev++);
}
}
#endif !sun4m
static void
add_to_devsw(name, driver, i)
char *name;
struct boottab *driver;
int i;
{
register struct boottab *bp;
bp = (struct boottab *)kmem_alloc(sizeof (struct boottab));
if (bp == 0)
_stop("kmem_alloc: couldn't get space");
*bp = *driver;
/*
* b_dev has only 2 characters for the device name whinch is
* not enough space for the OBP full path. For OBP interface,
* tempararily use b_desc field to keep the full path name
*/
if (prom_getversion() > 0) {
bp->b_dev[0] = '\0';
bp->b_desc = name;
} else
(void)strncpy(bp->b_dev, name, 2);
devsw[i] = bp;
}
init_devlist()
{
register char *name;
name = (char *)kmem_alloc(128);
if (name == 0)
_stop("kmem_alloc: couldn't get space");
bzero((caddr_t)name, 128);
add_to_devsw(name, &blkdriver, dev);
bdevlist[1].bl_name = name;
bdevlist[1].bl_root = makedev(1, 0);
bdevlist[1].bl_driver = devsw[dev++];
name = (char *)kmem_alloc(128);
if (name == 0)
_stop("kmem_alloc: couldn't get space");
bzero((caddr_t)name, 128);
add_to_devsw(name, &ifdriver, dev);
ndevlist[0].nl_name = name;
ndevlist[0].nl_root = 0;
ndevlist[0].nl_driver = devsw[dev++];
}