summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2009-05-21 16:28:13 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2009-05-21 16:28:13 +0000
commit26f06ec2ea9d59e29d23df2ca8925f799a0c9e69 (patch)
treedb6694dcb9586b701803dc2090598868e67598d1 /sys
parent79cec36cbc9159617783240e420be0c83d4f8dd7 (diff)
Overhaul root device detection; the code will now follow the ARCS bootpath
component by component, from device_register(). IP27 and IP35 systems using the dksc() syntax get their dksc() syntax converted to an ARCS bootpath, so the same logic will apply.
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/sgi/include/autoconf.h4
-rw-r--r--sys/arch/sgi/sgi/autoconf.c426
-rw-r--r--sys/arch/sgi/sgi/ip32_machdep.c11
-rw-r--r--sys/arch/sgi/sgi/machdep.c36
4 files changed, 289 insertions, 188 deletions
diff --git a/sys/arch/sgi/include/autoconf.h b/sys/arch/sgi/include/autoconf.h
index 8307579195d..d91fc883b1d 100644
--- a/sys/arch/sgi/include/autoconf.h
+++ b/sys/arch/sgi/include/autoconf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: autoconf.h,v 1.16 2008/09/17 01:30:58 jsing Exp $ */
+/* $OpenBSD: autoconf.h,v 1.17 2009/05/21 16:28:11 miod Exp $ */
/*
* Copyright (c) 2001-2003 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -89,4 +89,6 @@ void ip27_setup(void);
void ip30_setup(void);
void ip32_setup(void);
+extern char osloadpartition[256];
+
#endif /* _MACHINE_AUTOCONF_H_ */
diff --git a/sys/arch/sgi/sgi/autoconf.c b/sys/arch/sgi/sgi/autoconf.c
index 48129f0284a..82e8be89684 100644
--- a/sys/arch/sgi/sgi/autoconf.c
+++ b/sys/arch/sgi/sgi/autoconf.c
@@ -1,4 +1,19 @@
-/* $OpenBSD: autoconf.c,v 1.19 2009/03/20 18:41:07 miod Exp $ */
+/* $OpenBSD: autoconf.c,v 1.20 2009/05/21 16:28:12 miod Exp $ */
+/*
+ * Copyright (c) 2009 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
/*
* Copyright (c) 1996 Per Fogelstrom
* Copyright (c) 1995 Theo de Raadt
@@ -50,33 +65,24 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/buf.h>
-#include <sys/disklabel.h>
#include <sys/conf.h>
#include <sys/reboot.h>
#include <sys/device.h>
-#include <uvm/uvm_extern.h>
-
-#include <dev/cons.h>
#include <machine/autoconf.h>
#include <mips64/archtype.h>
+#include <sgi/xbow/xbow.h>
+#include <dev/pci/pcivar.h>
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+
extern void dumpconf(void);
-struct device *getdevunit(char *, int);
-const struct devmap *boot_findtype(char *);
-int makebootdev(const char *, int);
-const char *boot_get_path_component(const char *, char *, int *);
-const char *boot_getnr(const char *, int *);
-
-/* Struct translating from ARCS to bsd. */
-struct devmap {
- const char *att;
- const char *dev;
- int what;
-};
-#define DEVMAP_TYPE 0x01
-#define DEVMAP_UNIT 0x02
-#define DEVMAP_PART 0x04
+
+void bootpath_convert(void);
+const char *bootpath_get(int *);
+void bootpath_init(void);
+void bootpath_next(void);
/*
* The following several variables are related to
@@ -84,9 +90,10 @@ struct devmap {
* the machine.
*/
int cold = 1; /* if 1, still working on cold-start */
-char bootdev[16] = "unknown"; /* to hold boot dev name */
struct device *bootdv = NULL;
+char osloadpartition[256];
+
/*
* Configure all devices found that we know about.
* This is done at boot time.
@@ -107,20 +114,10 @@ cpu_configure(void)
}
void
-device_register(struct device *dev, void *aux)
-{
-}
-
-void
diskconf(void)
{
- dev_t tmpdev;
-
- /* Lookup boot device from boot if not set by configuration */
- if (bootdv == NULL)
- bootdv = parsedisk(bootdev, strlen(bootdev), 0, &tmpdev);
if (bootdv == NULL)
- printf("boot device: lookup '%s' failed.\n", bootdev);
+ printf("boot device: '%s' unrecognized.\n", osloadpartition);
else
printf("boot device: %s\n", bootdv->dv_xname);
@@ -128,150 +125,273 @@ diskconf(void)
dumpconf();
}
+static char bootpath_store[sizeof osloadpartition];
+static char *bootpath_curpos;
+static char *bootpath_lastpos;
+static int bootpath_lastunit;
+#if defined(TGT_ORIGIN200) || defined(TGT_ORIGIN2000)
+static int dksc_ctrl, dksc_mode;
+#endif
+
/*
- * find a device matching "name" and unit number
+ * Initialize bootpath analysis.
*/
-struct device *
-getdevunit(name, unit)
- char *name;
- int unit;
+void
+bootpath_init()
{
- struct device *dev = TAILQ_FIRST(&alldevs);
- char num[10], fullname[16];
- int lunit;
-
- /* compute length of name and decimal expansion of unit number */
- snprintf(num, sizeof(num), "%d", unit);
- lunit = strlen(num);
- if (strlen(name) + lunit >= sizeof(fullname) - 1)
- panic("config_attach: device name too long");
-
- strlcpy(fullname, name, sizeof(fullname));
- strlcat(fullname, num, sizeof(fullname));
-
- while (strcmp(dev->dv_xname, fullname) != 0) {
- if ((dev = TAILQ_NEXT(dev, dv_list)) == NULL)
- return NULL;
- }
- return dev;
+ strlcpy(bootpath_store, osloadpartition, sizeof bootpath_store);
+ bootpath_curpos = bootpath_store;
+
+#if defined(TGT_ORIGIN200) || defined(TGT_ORIGIN2000)
+ /*
+ * If this is the first time we're ever invoked,
+ * check for a dksc() syntax and rewrite it as
+ * something more friendly to us.
+ */
+ if (strncmp(bootpath_store, "dksc(", 5) == 0)
+ bootpath_convert();
+#endif
}
-const struct devmap *
-boot_findtype(char *s)
+#if defined(TGT_ORIGIN200) || defined(TGT_ORIGIN2000)
+/*
+ * Convert a `dksc()' bootpath into an ARC-friendly bootpath.
+ */
+void
+bootpath_convert()
{
- const struct devmap devmap[] = {
- { "scsi", "sd", DEVMAP_TYPE },
- { "disk", "", DEVMAP_UNIT },
- { "part", "", DEVMAP_PART },
- { "partition", "", DEVMAP_PART },
- { NULL, NULL }
- };
- const struct devmap *dp = &devmap[0];
-
- while (dp->att) {
- if (strcmp (s, dp->att) == 0) {
+ int val[3], idx;
+ char *c;
+
+ val[0] = val[1] = val[2] = 0;
+ idx = 0;
+
+ for (c = bootpath_store + 5; *c != '\0'; c++) {
+ if (*c == ')')
break;
- }
- dp++;
+ else if (*c == ',') {
+ if (++idx == 3)
+ break;
+ } else if (*c >= '0' && *c <= '9')
+ val[idx] = 10 * val[idx] + (*c - '0');
}
- if (dp->att)
- return dp;
- else
- return NULL;
+
+ /*
+ * We can not convert the dksc() bootpath to an exact ARCS bootpath
+ * without knowing our device tree already. This is because
+ * the controller number is not an absolute locator, but rather an
+ * occurence number.
+ *
+ * So we convert to an incomplete ARCS bootpath and have explicit
+ * dksc handling in device_register(). This relies on our device
+ * probe order matching ARCS.
+ */
+
+ dksc_ctrl = val[0];
+ dksc_mode = 1;
+ snprintf(bootpath_store, sizeof bootpath_store,
+ "scsi(%d)disk(%d)rdisk(0)partition(%d)",
+ val[0], val[1], val[2]);
+#ifdef DEBUG
+ printf("%s: converting %s to %s\n",
+ __func__, osloadpartition, bootpath_store);
+#endif
}
+#endif
/*
- * Look at the string 'bp' and decode the boot device.
- * Boot devices look like: 'scsi()disk(n)rdisk()partition(0)'
- * or
- * 'dksc(0,1,0)'
+ * Extract a component of the boot path, and return its name and unit
+ * value.
*/
-int
-makebootdev(const char *bp, int offs)
+const char *
+bootpath_get(int *u)
{
- char namebuf[256];
- const char *cp, *ncp, *ecp, *devname;
- int i, unit, partition;
- const struct devmap *dp;
-
- if (bp == NULL)
- return -1;
-
- ecp = cp = bp;
- unit = partition = 0;
- devname = NULL;
-
- if (strncmp(cp, "dksc(", 5) == 0) {
- devname = "sd";
- cp += 5;
- cp = boot_getnr(cp, &i);
- if (*cp++ == ',') {
- cp = boot_getnr(cp, &i);
- unit = i - 1;
- if (*cp++ == ',') {
- cp = boot_getnr(cp, &i);
- partition = i;
- }
- }
- } else {
- ncp = boot_get_path_component(cp, namebuf, &i);
- while (ncp != NULL) {
- if ((dp = boot_findtype(namebuf)) != NULL) {
- switch(dp->what) {
- case DEVMAP_TYPE:
- devname = dp->dev;
- break;
- case DEVMAP_UNIT:
- unit = i - 1 + offs;
- break;
- case DEVMAP_PART:
- partition = i;
- break;
- }
- }
- cp = ncp;
- ncp = boot_get_path_component(cp, namebuf, &i);
+ char *c;
+ int unit;
+
+ /*
+ * If we don't have a value in cache, compute it.
+ */
+ if (bootpath_lastpos == NULL) {
+ if (bootpath_curpos == NULL)
+ bootpath_init();
+
+ unit = 0;
+ c = strchr(bootpath_curpos, '(');
+ if (c != NULL) {
+ for (*c++ = '\0'; *c >= '0' && *c <= '9'; c++)
+ unit = 10 * unit + (*c - '0');
+ while (*c != ')' && *c != '\0')
+ c++;
+ if (*c == ')')
+ c++;
+ } else {
+ c = bootpath_curpos + strlen(bootpath_curpos);
}
- }
- if (devname == NULL) {
- return -1;
+ bootpath_lastpos = bootpath_curpos;
+ bootpath_lastunit = unit;
+ bootpath_curpos = c;
+#ifdef DEBUG
+ printf("%s: new component %s unit %d remainder %s\n", __func__,
+ bootpath_lastpos, bootpath_lastunit, bootpath_curpos);
+#endif
}
- snprintf(bootdev, sizeof(bootdev), "%s%d%c", devname, unit,
- 'a' + partition);
- return 0;
+ *u = bootpath_lastunit;
+ return bootpath_lastpos;
}
-const char *
-boot_get_path_component(const char *p, char *comp, int *no)
+/*
+ * Consume the current component of the bootpath, and switch to the next.
+ */
+void
+bootpath_next()
{
- while (*p && *p != '(') {
- *comp++ = *p++;
- }
- *comp = '\0';
-
- if (*p == NULL)
- return NULL;
-
- *no = 0;
- p++;
- while (*p && *p != ')') {
- if (*p >= '0' && *p <= '9')
- *no = *no * 10 + *p++ - '0';
- else
- return NULL;
- }
- return ++p;
+ /* force bootpath_get to go forward */
+ bootpath_lastpos = NULL;
+#ifdef DEBUG
+ printf("%s\n", __func__);
+#endif
}
-const char *
-boot_getnr(const char *p, int *no)
+void
+device_register(struct device *dev, void *aux)
{
- *no = 0;
- while (*p >= '0' && *p <= '9')
- *no = *no * 10 + *p++ - '0';
- return p;
+ static struct device *lastparent = NULL;
+ static struct device *pciparent = NULL;
+
+ struct device *parent = dev->dv_parent;
+ struct cfdata *cf = dev->dv_cfdata;
+ struct cfdriver *cd = cf->cf_driver;
+
+ const char *component;
+ int unit;
+
+ if (bootdv != NULL)
+ return;
+
+ component = bootpath_get(&unit);
+ if (*component == '\0')
+ return; /* exhausted path */
+
+ /*
+ * The matching rules are as follows:
+ * xio() matches xbow (we ignore nasid so far).
+ * pci() matches any pci controller (macepcibr, xbridge), with the
+ * unit number being ignored on O2 and the widget number of the
+ * controller elsewhere.
+ * scsi() matches any pci scsi controller, with the unit number
+ * being the pci device number (minus one on the O2, grr),
+ * or the scsibus number in dksc mode.
+ * disk() and cdrom() match sd and cd, respectively, with the
+ * unit number being the target number.
+ *
+ * When a disk is found, we stop the parsing; rdisk() and
+ * partition() components are ignored.
+ */
+
+ if (strcmp(component, "xio") == 0) {
+ if (strcmp(cd->cd_name, "xbow") == 0)
+ goto found_advance;
+ }
+
+ if (strcmp(component, "pci") == 0) {
+ /*
+ * We'll work in two steps. The controller itself will be
+ * recognized with its parent device and attachment
+ * arguments (if necessary).
+ *
+ * Then we'll only advance the bootpath when matching the
+ * pci device.
+ */
+ if (strcmp(cd->cd_name, "pci") == 0 &&
+ parent == lastparent) {
+ pciparent = dev;
+ goto found_advance;
+ }
+
+ if (strcmp(cd->cd_name, "macepcibr") == 0)
+ goto found;
+ if (strcmp(cd->cd_name, "xbridge") == 0 &&
+ parent == lastparent) {
+ struct xbow_attach_args *xaa = aux;
+
+ if (unit == xaa->xaa_widget)
+ goto found;
+ }
+ }
+
+ if (strcmp(component, "scsi") == 0) {
+ /*
+ * We'll work in two steps. The controller itself will be
+ * recognized with its parent device and pci_attach_args
+ * need to match the scsi() unit number.
+ *
+ * Then we'll only advance the bootpath when matching the
+ * scsibus device.
+ *
+ * With a dksc bootpath, things are a little different:
+ * we need to count scsi controllers, until we find ours.
+ */
+
+#if defined(TGT_ORIGIN200) || defined(TGT_ORIGIN2000)
+ if (dksc_mode) {
+ if (strcmp(cd->cd_name, "scsibus") == 0 &&
+ dev->dv_unit == dksc_ctrl)
+ goto found_advance;
+
+ return;
+ }
+#endif
+
+ if (strcmp(cd->cd_name, "scsibus") == 0 &&
+ parent == lastparent)
+ goto found_advance;
+
+ if (parent == lastparent) {
+ if (parent == pciparent) {
+ struct pci_attach_args *paa = aux;
+
+ if (unit == paa->pa_device -
+ (sys_config.system_type == SGI_O2 ? 1 : 0))
+ goto found;
+ }
+ /*
+ * in case scsi() can follow something else then
+ * pci(), write code to handle this here...
+ */
+ }
+ }
+
+ if ((strcmp(component, "disk") == 0 &&
+ strcmp(cd->cd_name, "sd") == 0) ||
+ (strcmp(component, "cdrom") == 0 &&
+ strcmp(cd->cd_name, "cd") == 0)) {
+ if (parent == lastparent) {
+ struct scsi_attach_args *saa = aux;
+
+ if (unit == saa->sa_sc_link->target) {
+ /*
+ * We found our boot device.
+ * Now get the partition number.
+ */
+ bootdv = dev;
+#ifdef DEBUG
+ printf("%s: boot device is %s\n",
+ __func__, dev->dv_xname);
+#endif
+ return;
+ }
+ }
+ }
+
+ return;
+
+found_advance:
+ bootpath_next();
+found:
+ lastparent = dev;
}
struct nam2blk nam2blk[] = {
diff --git a/sys/arch/sgi/sgi/ip32_machdep.c b/sys/arch/sgi/sgi/ip32_machdep.c
index f2b6f31a114..72fc6542985 100644
--- a/sys/arch/sgi/sgi/ip32_machdep.c
+++ b/sys/arch/sgi/sgi/ip32_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip32_machdep.c,v 1.5 2009/05/08 18:42:07 miod Exp $ */
+/* $OpenBSD: ip32_machdep.c,v 1.6 2009/05/21 16:28:12 miod Exp $ */
/*
* Copyright (c) 2003-2004 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -50,8 +50,6 @@
void crime_configure_memory(void);
-extern int bootdriveoffs;
-
void
crime_configure_memory(void)
{
@@ -137,13 +135,6 @@ ip32_setup()
crime_configure_memory();
- /* R1xK O2s are one disk slot machines. Offset slotno. */
- switch ((cp0_get_prid() >> 8) & 0xff) {
- case MIPS_R10000:
- case MIPS_R12000:
- bootdriveoffs = -1;
- break;
- }
/* R12K O2s must run with DSD on. */
switch ((cp0_get_prid() >> 8) & 0xff) {
case MIPS_R12000:
diff --git a/sys/arch/sgi/sgi/machdep.c b/sys/arch/sgi/sgi/machdep.c
index 48fdb2f6e67..bbf7a8ead15 100644
--- a/sys/arch/sgi/sgi/machdep.c
+++ b/sys/arch/sgi/sgi/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.65 2009/05/08 18:42:07 miod Exp $ */
+/* $OpenBSD: machdep.c,v 1.66 2009/05/21 16:28:12 miod Exp $ */
/*
* Copyright (c) 2003-2004 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -80,8 +80,6 @@
#include <machine/bus.h>
extern char kernel_text[];
-extern int makebootdev(const char *, int);
-extern void stacktrace(void);
extern bus_addr_t comconsaddr;
#ifdef DEBUG
@@ -119,7 +117,6 @@ int ncpu = 1; /* At least one CPU in the system. */
struct user *proc0paddr;
struct user *curprocpaddr;
int console_ok; /* Set when console initialized. */
-int bootdriveoffs = 0;
int kbd_reset;
int32_t *environment;
@@ -132,15 +129,11 @@ caddr_t ekern;
struct phys_mem_desc mem_layout[MAXMEMSEGS];
-void crime_configure_memory(void);
-
-caddr_t mips_init(int, void *, caddr_t);
-void initcpu(void);
-void dumpsys(void);
-void dumpconf(void);
-caddr_t allocsys(caddr_t);
-
-void db_command_loop(void);
+caddr_t mips_init(int, void *, caddr_t);
+void initcpu(void);
+void dumpsys(void);
+void dumpconf(void);
+caddr_t allocsys(caddr_t);
static void dobootopts(int, void *);
static int atoi(const char *, int, const char **);
@@ -302,13 +295,15 @@ mips_init(int argc, void *argv, caddr_t boot_esym)
dobootopts(argc, argv);
/*
- * Figure out where we booted from.
+ * Figure out where we supposedly booted from.
*/
cp = Bios_GetEnvironmentVariable("OSLoadPartition");
if (cp == NULL)
cp = "unknown";
- if (makebootdev(cp, bootdriveoffs))
- bios_printf("Boot device unrecognized: '%s'\n", cp);
+ if (strlcpy(osloadpartition, cp, sizeof osloadpartition) >=
+ sizeof osloadpartition)
+ bios_printf("Value of `OSLoadPartition' is too large.\n"
+ "The kernel might not be able to find out its root device.\n");
/*
* Read platform-specific environment variables.
@@ -478,8 +473,7 @@ mips_init(int argc, void *argv, caddr_t boot_esym)
/*
* Last chance to call the BIOS. Wiping the TLB means the BIOS' data
- * areas are demapped on most systems. O2s are okay as they do not have
- * mapped BIOS text or data.
+ * areas are demapped on most systems.
*/
delay(20*1000); /* Let any UART FIFO drain... */
@@ -586,7 +580,6 @@ allocsys(caddr_t v)
return(v);
}
-
/*
* Decode boot options.
*/
@@ -831,11 +824,6 @@ boot(int howto)
if (curproc)
savectx(curproc->p_addr, 0);
-#ifdef DEBUG
- if (panicstr)
- stacktrace();
-#endif
-
if (cold) {
/*
* If the system is cold, just halt, unless the user