Use device_register to find the boot device more reliably. Should now work

on anything it's possible to boot from that we have a driver for.
This commit is contained in:
danw 2000-02-01 04:04:17 +00:00
parent aedaba9bc9
commit 33051e5117
4 changed files with 144 additions and 130 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: pci_machdep.h,v 1.8 1999/05/06 19:16:44 thorpej Exp $ */
/* $NetBSD: pci_machdep.h,v 1.9 2000/02/01 04:04:17 danw Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
@ -58,6 +58,7 @@ struct pci_bridge {
bus_space_tag_t iot;
bus_space_tag_t memt;
pci_chipset_tag_t pc;
u_int reg[2];
int present;
};
struct pci_bridge pci_bridges[2];

View File

@ -1,3 +1,5 @@
/* $NetBSD: types.h,v 1.2 1998/05/29 10:32:55 tsubai Exp $ */
/* $NetBSD: types.h,v 1.3 2000/02/01 04:04:17 danw Exp $ */
#include <powerpc/types.h>
#define __HAVE_DEVICE_REGISTER

View File

@ -1,4 +1,4 @@
/* $NetBSD: autoconf.c,v 1.15 1999/09/17 20:04:37 thorpej Exp $ */
/* $NetBSD: autoconf.c,v 1.16 2000/02/01 04:04:19 danw Exp $ */
/*
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
@ -53,6 +53,8 @@
void findroot __P((void));
int OF_interpret __P((char *cmd, int nreturns, ...));
extern char bootpath[256];
char cbootpath[256];
struct device *booted_device; /* boot device */
int booted_partition; /* ...and partition on that device */
@ -71,6 +73,8 @@ cpu_configure()
{
int node, reg[5];
int msr;
int phandle;
char *p;
node = OF_finddevice("mac-io");
if (node == -1)
@ -87,6 +91,15 @@ cpu_configure()
calc_delayconst();
/* Canonicalize bootpath. */
strcpy(cbootpath, bootpath);
p = strchr(cbootpath, ':');
if (p)
*p = '\0';
phandle = OF_finddevice(cbootpath);
if (phandle != -1)
OF_package_to_path(phandle, cbootpath, sizeof(cbootpath) - 1);
if (config_rootfound("mainbus", NULL) == NULL)
panic("configure: mainbus not configured");
@ -99,6 +112,123 @@ cpu_configure()
: "=r"(msr) : "K"((u_short)(PSL_EE|PSL_RI)));
}
#define DEVICE_IS(dev, name) \
(!strncmp(dev->dv_xname, name, sizeof(name) - 1) && \
dev->dv_xname[sizeof(name) - 1] >= '0' && \
dev->dv_xname[sizeof(name) - 1] <= '9')
/*
* device_register is called from config_attach as each device is
* attached. We use it to find the NetBSD device corresponding to the
* known OF boot device.
*/
void
device_register(dev, aux)
struct device *dev;
void *aux;
{
static struct device *parent = NULL;
static char *bp = bootpath + 1, *cp = cbootpath;
unsigned long addr;
char *p;
if (booted_device || dev->dv_parent != parent)
return;
/* Skip over devices not represented in the OF tree. */
if (DEVICE_IS(dev, "mainbus") || DEVICE_IS(dev, "scsibus") ||
DEVICE_IS(dev, "atapibus") || DEVICE_IS(parent, "ppb")) {
parent = dev;
return;
}
/* Get the address part of the current path component. The
* last component of the canonical bootpath may have no
* address (eg, "disk"), in which case we need to get the
* address from the original bootpath instead.
*/
p = strchr(cp, '@');
if (!p) {
if (bp)
p = strchr(bp, '@');
if (!p)
addr = 0;
else {
addr = strtoul(p + 1, NULL, 16);
p = NULL;
}
} else
addr = strtoul(p + 1, &p, 16);
if (DEVICE_IS(parent, "mainbus") && DEVICE_IS(dev, "pci")) {
struct pcibus_attach_args *pba = aux;
int n;
for (n = 0; n < 2; n++) {
if (pci_bridges[n].present &&
pci_bridges[n].bus == pba->pba_bus)
break;
}
if (n == 2 || addr != pci_bridges[n].reg[0])
return;
} else if (DEVICE_IS(parent, "pci")) {
struct pci_attach_args *pa = aux;
if (addr != pa->pa_device)
return;
} else if (DEVICE_IS(parent, "obio")) {
struct confargs *ca = aux;
if (addr != ca->ca_reg[0])
return;
} else if (DEVICE_IS(parent, "scsibus") ||
DEVICE_IS(parent, "atapibus")) {
struct scsipibus_attach_args *sa = aux;
if (parent->dv_xname[0] == 's') {
if (addr != sa->sa_sc_link->scsipi_scsi.target)
return;
} else {
if (addr != sa->sa_sc_link->scsipi_atapi.drive)
return;
}
} else if (DEVICE_IS(parent, "pciide")) {
struct ata_atapi_attach *aa = aux;
if (addr != aa->aa_channel)
return;
/*
* OF splits channel and drive into separate path
* components, so check the addr part of the next
* component. (Ignore bp, because the canonical path
* will be complete in the pciide case.)
*/
p = strchr(p, '@');
if (!p++)
return;
if (strtoul(p, &p, 16) != aa->aa_drv_data->drive)
return;
} else
return;
/* If we reach this point, then dev is a match for the current
* path component.
*/
if (p && *p) {
parent = dev;
cp = p;
bp = strchr(bp, '/');
if (bp)
bp++;
return;
} else {
booted_device = dev;
return;
}
}
/*
* Setup root device.
* Configure swap area.
@ -106,133 +236,12 @@ cpu_configure()
void
cpu_rootconf()
{
findroot();
printf("boot device: %s\n",
booted_device ? booted_device->dv_xname : "<unknown>");
setroot(booted_device, booted_partition);
}
/*
* Try to find the device we were booted from to set rootdev.
*/
void
findroot()
{
int chosen, node, pnode;
u_int targ, lun = 0; /* XXX lun */
struct device *dv;
char *p, *controller = "nodev";
char path[64], type[16], name[16], compat[16];
booted_device = NULL;
/* Cut off filename from "boot/devi/ce/file". */
path[0] = 0;
p = bootpath;
while ((p = strchr(p + 1, '/')) != NULL) {
char new[64];
strcpy(new, bootpath);
new[p - bootpath] = 0;
if (OF_finddevice(new) == -1)
break;
strcpy(path, new);
}
if ((node = OF_finddevice(path)) == -1)
goto out;
bzero(type, sizeof(type));
bzero(name, sizeof(name));
bzero(compat, sizeof(compat));
if (OF_getprop(node, "device_type", type, 16) == -1)
goto out;
if (OF_getprop(node, "name", name, 16) == -1)
goto out;
OF_getprop(node, "compatible", compat, 16); /* ignore error */
if (strcmp(type, "block") == 0) {
char *addr;
if ((addr = strrchr(path, '@')) == NULL) /* XXX fd:0 */
goto out;
targ = addr[1] - '0'; /* XXX > '9' */
booted_partition = 0; /* = addr[3] - '0'; */
if ((pnode = OF_parent(node)) == -1)
goto out;
bzero(name, sizeof(name));
if (OF_getprop(pnode, "name", name, sizeof(name)) == -1)
goto out;
bzero(compat, sizeof(compat));
OF_getprop(pnode, "compatible", compat, 16);
}
if (strcmp(compat, "heathrow-ata") == 0) controller = "wdc";
if (strcmp(name, "mace") == 0) controller = "mc";
if (strcmp(name, "bmac") == 0) controller = "bm";
if (strcmp(name, "ethernet") == 0) controller = "bm";
if (strcmp(name, "53c94") == 0) controller = "esp";
if (strcmp(name, "mesh") == 0) controller = "mesh";
if (strcmp(name, "ide") == 0) controller = "wdc";
if (strcmp(name, "ata") == 0) controller = "wdc";
if (strcmp(name, "ata0") == 0) controller = "wdc";
if (strcmp(name, "ATA") == 0) controller = "wdc";
for (dv = alldevs.tqh_first; dv; dv=dv->dv_list.tqe_next) {
if (dv->dv_class != DV_DISK && dv->dv_class != DV_IFNET)
continue;
/* XXX ATAPI */
if (strncmp(dv->dv_xname, "sd", 2) == 0) {
struct scsibus_softc *sdv = (void *)dv->dv_parent;
/* sd? at scsibus at esp/mesh */
if (strncmp(dv->dv_parent->dv_parent->dv_xname,
controller, strlen(controller)) != 0)
continue;
if (targ > 7 || lun > 7)
goto out;
if (sdv->sc_link[targ][lun]->device_softc != dv)
continue;
booted_device = dv;
break;
}
if (strncmp(dv->dv_xname, "wd", 2) == 0) {
struct wdc_softc *wdv = (void *)dv->dv_parent;
if (strncmp(dv->dv_parent->dv_xname,
controller, strlen(controller)) != 0)
continue;
if (targ >= 2
|| wdv->channels == NULL
|| wdv->channels[0]->ch_drive[targ].drv_softc != dv)
continue;
booted_device = dv;
break;
}
if (strncmp(dv->dv_xname, "mc", 2) == 0)
if (strcmp(controller, "mc") == 0) {
booted_device = dv;
break;
}
if (strncmp(dv->dv_xname, "bm", 2) == 0)
if (strcmp(controller, "bm") == 0) {
booted_device = dv;
break;
}
}
out:
dk_cleanup();
}
int
#ifdef __STDC__
OF_interpret(char *cmd, int nreturns, ...)

View File

@ -1,4 +1,4 @@
/* $NetBSD: bandit.c,v 1.11 1999/05/06 19:16:45 thorpej Exp $ */
/* $NetBSD: bandit.c,v 1.12 2000/02/01 04:04:18 danw Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@ -231,17 +231,19 @@ scan_pci_devs(canmap)
* Map the PCI configuration space access registers,
* and perform any PCI-Host bridge initialization.
*/
if (OF_getprop(node, "reg", pci_bridges[n].reg,
sizeof(pci_bridges[n].reg)) != 8)
continue;
if (is_bandit) {
/* XXX magic numbers */
pci_bridges[n].pc = n;
if (canmap) {
if (OF_getprop(node, "reg", reg,
sizeof(reg)) != 8)
continue;
pci_bridges[n].addr =
mapiodev(reg[0] + 0x800000, 4);
mapiodev(pci_bridges[n].reg[0] + 0x800000,
4);
pci_bridges[n].data =
mapiodev(reg[0] + 0xc00000, 4);
mapiodev(pci_bridges[n].reg[0] + 0xc00000,
4);
bandit_init(n);
}
} else if (is_mpc106) {