New style bootpath propagation to match the sparc port.

This commit is contained in:
eeh 1999-01-09 23:23:47 +00:00
parent d5ca0ef2e6
commit 09a4a08b77
1 changed files with 251 additions and 9 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: autoconf.c,v 1.10 1998/12/04 20:22:37 thorpej Exp $ */
/* $NetBSD: autoconf.c,v 1.11 1999/01/09 23:23:47 eeh Exp $ */
/*
* Copyright (c) 1996
@ -386,6 +386,23 @@ bootpath_store(storep, bp)
return (retval);
}
/* TEMP: */
struct bootpath *altbootpath_store(int, struct bootpath *);
struct bootpath *
altbootpath_store(storep, bp)
int storep;
struct bootpath *bp;
{
static struct bootpath *save;
struct bootpath *retval;
retval = save;
if (storep)
save = bp;
return (retval);
}
/* END TEMP */
/*
* Set up the sd target mappings for non SUN4 PROMs.
@ -482,6 +499,8 @@ configure()
cold = 0;
}
struct device *altbootdev;
void
cpu_rootconf()
{
@ -1179,8 +1198,6 @@ nextsibling(node)
return OF_peer(node);
}
u_int hexatoi __P((const char *));
/* The following recursively searches a PROM tree for a given node */
int
search_prom(rootnode, name)
@ -1324,12 +1341,237 @@ getdevunit(name, unit)
return dev;
}
u_int
hexatoi(nptr) /* atoi assuming hex, no 0x */
const char *nptr;
/*
* Device registration used to determine the boot device.
*
* Copied from the sparc port.
*/
#include <dev/scsipi/scsi_all.h>
#include <dev/scsipi/scsipi_all.h>
#include <dev/scsipi/scsiconf.h>
#define BUSCLASS_GENERIC 0
#define BUSCLASS_MAINBUS 1
#define BUSCLASS_IOMMU 2
#define BUSCLASS_OBIO 3
#define BUSCLASS_SBUS 4
#define BUSCLASS_VME 5
static int bus_class __P((struct device *));
static int instance_match __P((struct device *, void *, struct bootpath *));
static void nail_bootdev __P((struct device *, struct bootpath *));
static struct {
char *name;
int class;
} bus_class_tab[] = {
{ "mainbus", BUSCLASS_MAINBUS },
{ "obio", BUSCLASS_OBIO },
{ "iommu", BUSCLASS_IOMMU },
{ "sbus", BUSCLASS_SBUS },
{ "xbox", BUSCLASS_SBUS },
{ "esp", BUSCLASS_SBUS },
{ "dma", BUSCLASS_SBUS },
{ "espdma", BUSCLASS_SBUS },
{ "ledma", BUSCLASS_SBUS },
{ "vme", BUSCLASS_VME }
};
static int
bus_class(dev)
struct device *dev;
{
u_int retval;
str2hex((char *)nptr, &retval);
return retval;
struct device *parent = dev->dv_parent;
char *name = parent->dv_cfdata->cf_driver->cd_name;
int i, class;
class = BUSCLASS_GENERIC;
for (i = sizeof(bus_class_tab)/sizeof(bus_class_tab[0]); i-- > 0;) {
if (strcmp(name, bus_class_tab[i].name) == 0) {
class = bus_class_tab[i].class;
break;
}
}
/* sun4m obio special case */
if (CPU_ISSUN4M && class == BUSCLASS_OBIO)
class = BUSCLASS_SBUS;
return (class);
}
int
instance_match(dev, aux, bp)
struct device *dev;
void *aux;
struct bootpath *bp;
{
struct mainbus_attach_args *ma;
struct sbus_attach_args *sa;
struct iommu_attach_args *iom;
/*
* Several Sbus devices are represented on bootpaths in one of
* two formats:
* (1) ../sbus@.../esp@<offset>,<slot>/sd@.. (PROM v3 style)
* (2) /sbus0/esp0/sd@.. (PROM v2 style)
*
* hence we fall back on a `unit number' check if the Sbus-specific
* instance parameter check does not produce a match.
*/
switch (bus_class(dev)) {
case BUSCLASS_MAINBUS:
ma = aux;
if (bp->val[0] == ma->ma_address)
return (1);
break;
case BUSCLASS_SBUS:
sa = aux;
if (bp->val[0] == sa->sa_slot && bp->val[1] == sa->sa_offset)
return (1);
break;
default:
break;
}
if (bp->val[0] == -1 && bp->val[1] == dev->dv_unit)
return (1);
return (0);
}
void
nail_bootdev(dev, bp)
struct device *dev;
struct bootpath *bp;
{
/*bp->dev = dev; -* got it! */
if (altbootdev != NULL)
panic("device_register: already got a boot device: %s",
altbootdev->dv_xname);
altbootdev = dev;
/*
* Clear current bootpath component, so we don't spuriously
* match similar instances on other busses, e.g. a disk on
* another SCSI bus with the same target.
*/
altbootpath_store(1, NULL);
}
void
device_register(dev, aux)
struct device *dev;
void *aux;
{
struct bootpath *bp = altbootpath_store(0, NULL);
char *dvname = dev->dv_cfdata->cf_driver->cd_name;
/*
* If device name does not match current bootpath component
* then there's nothing interesting to consider.
*/
if (bp == NULL)
return;
if (strcmp(bp->name, "espdma") == 0) {
/* espdma special case */
if (strcmp(dvname, "dma") != 0)
return;
} else if (strcmp(dvname, bp->name) != 0)
return;
if (strcmp(dvname, "obio") == 0 ||
strcmp(dvname, "vme") == 0 ||
strcmp(dvname, "iommu") == 0 ||
strcmp(dvname, "sbus") == 0 ||
strcmp(dvname, "xbox") == 0 ||
strcmp(dvname, "dma") == 0 ||
strcmp(dvname, "ledma") == 0 ||
strcmp(dvname, "espdma") == 0 ||
strcmp(dvname, "esp") == 0 ||
strcmp(dvname, "xdc") == 0 ||
strcmp(dvname, "xyc") == 0 ) {
/*
* A bus or controller device of sorts. Check instance
* parameters and advance boot path on match.
*/
if (instance_match(dev, aux, bp) != 0) {
altbootpath_store(1, bp + 1);
return;
}
} else if (strcmp(dvname, "le") == 0) {
/*
* LANCE ethernet device
*/
if (instance_match(dev, aux, bp) != 0) {
nail_bootdev(dev, bp);
return;
}
} else if (strcmp(dvname, "sd") == 0 || strcmp(dvname, "cd") == 0) {
/*
* A SCSI disk or cd; retrieve target/lun information
* from parent and match with current bootpath component.
*/
struct scsipibus_attach_args *sa = aux;
struct scsipi_link *sc_link = sa->sa_sc_link;
struct scsibus_softc *sbsc =
(struct scsibus_softc *)dev->dv_parent;
u_int target = bp->val[0];
u_int lun = bp->val[1];
/*
* Bounds check; XXX - guess a reasonable target/lun bound.
*/
if (target >= 16 || lun >= 16) {
printf("SCSI disk bootpath component not accepted: "
"target %u; lun %u\n", target, lun);
return;
}
if (CPU_ISSUN4 && dvname[0] == 's' &&
target == 0 && sbsc->sc_link[0][0] == NULL) {
/*
* disk unit 0 is magic: if there is actually no
* target 0 scsi device, the PROM will call
* target 3 `sd0'.
* XXX - what if someone puts a tape at target 0?
*/
target = 3; /* remap to 3 */
lun = 0;
}
if (CPU_ISSUN4C && dvname[0] == 's')
target = sd_crazymap(target);
if (sc_link->scsipi_scsi.target == target &&
sc_link->scsipi_scsi.lun == lun) {
nail_bootdev(dev, bp);
return;
}
} else if (strcmp("xd", dvname) == 0 || strcmp("xy", dvname) == 0) {
/*
* XXX - x[dy]c attach args are not exported right now..
* XXX we happen to know they look like this:
*/
struct xxxx_attach_args { int driveno; } *aap = aux;
if (aap->driveno == bp->val[0]) {
/* We've found the boot device */
nail_bootdev(dev, bp);
return;
}
} else {
/*
* Generic match procedure.
*/
if (instance_match(dev, aux, bp) != 0) {
nail_bootdev(dev, bp);
return;
}
}
}