New style bootpath propagation to match the sparc port.
This commit is contained in:
parent
d5ca0ef2e6
commit
09a4a08b77
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user