diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2009-05-21 16:28:13 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2009-05-21 16:28:13 +0000 |
commit | 26f06ec2ea9d59e29d23df2ca8925f799a0c9e69 (patch) | |
tree | db6694dcb9586b701803dc2090598868e67598d1 /sys | |
parent | 79cec36cbc9159617783240e420be0c83d4f8dd7 (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.h | 4 | ||||
-rw-r--r-- | sys/arch/sgi/sgi/autoconf.c | 426 | ||||
-rw-r--r-- | sys/arch/sgi/sgi/ip32_machdep.c | 11 | ||||
-rw-r--r-- | sys/arch/sgi/sgi/machdep.c | 36 |
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 |