summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2003-02-15 00:52:29 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2003-02-15 00:52:29 +0000
commit78afcaca5bd83ff4b4a7e708ca56e27928d2dc1c (patch)
tree0ac5fd000a213e6f904a30e163b768fdd3e12cc8 /sys/arch
parentd9e1f5a7828cb57f270071042410892e43afe214 (diff)
The current hppa code would always ask for the root device, when running
a kernel configured with "swap generic". This feature was relied upon by Theo de Raadt, so that he would have to go downstairs to type "sd0a\n\n" every time he would want to try a new kernel, effectively forcing his body to take exercise trim the fat. No more! This commit adds code to correctly detect the root device, currently either a network interface or an scsi block device. This is slightly tricky, as all the information the PDC gives up is the controller device and its numeric subpath, and we need to match the real device from that... Tested and found to be working on ie and sd only so far. This commit is brought to you by the so-called friends of Theo de Raadt.
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/hppa/hppa/autoconf.c110
-rw-r--r--sys/arch/hppa/include/types.h4
2 files changed, 105 insertions, 9 deletions
diff --git a/sys/arch/hppa/hppa/autoconf.c b/sys/arch/hppa/hppa/autoconf.c
index 7ebb6db97b3..e62f7df844e 100644
--- a/sys/arch/hppa/hppa/autoconf.c
+++ b/sys/arch/hppa/hppa/autoconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: autoconf.c,v 1.26 2003/01/04 10:35:32 mickey Exp $ */
+/* $OpenBSD: autoconf.c,v 1.27 2003/02/15 00:52:26 miod Exp $ */
/*
* Copyright (c) 1998-2001 Michael Shalayeff
@@ -73,6 +73,9 @@ int getstr(char *cp, int size);
void (*cold_hook)(int); /* see below */
+/* device we booted from */
+struct device *bootdv;
+
/*
* LED blinking thing
*/
@@ -84,6 +87,14 @@ void heartbeat(void *);
extern int hz;
#endif
+#include "cd.h"
+#include "sd.h"
+#include "st.h"
+#if NCD > 0 || NSD > 0 || NST > 0
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+#endif
+
/*
* cpu_configure:
* called at boot time, configure all devices on system
@@ -363,18 +374,15 @@ setroot()
char buf[128];
dev_t temp;
const char *rootdevname;
- struct device *bootdv, *rootdv, *swapdv;
+ struct device *rootdv, *swapdv;
#ifdef NFSCLIENT
extern char *nfsbootdevname;
#endif
#ifdef RAMDISK_HOOKS
bootdv = &fakerdrootdev;
- part = 0;
-#else
- bootdv = NULL; /* XXX */
- part = 0;
#endif
+ part = 0;
/*
* If 'swap generic' and we couldn't determine boot device,
@@ -468,10 +476,8 @@ gotswap:
if (majdev >= 0) {
/*
* Root and swap are on a disk.
- * val[2] of the boot device is the partition number.
* Assume swap is on partition b.
*/
- /* part = bp->val[2]; */
rootdv = swapdv = bootdv;
rootdev = MAKEDISKDEV(majdev, bootdv->dv_unit, part);
nswapdev = dumpdev =
@@ -675,3 +681,91 @@ hppa_mod_info(type, sv)
return mi->mi_name;
}
+void
+device_register(struct device *dev, void *aux)
+{
+ struct confargs *ca = aux;
+ char *basename;
+ enum devclass target;
+ static struct device *elder = NULL;
+
+ if (bootdv != NULL)
+ return; /* We already have a winner */
+
+
+ if (ca->ca_hpa == (hppa_hpa_t)PAGE0->mem_boot.pz_hpa) {
+ /*
+ * If hpa matches, the only thing we know is that the
+ * booted device is either this one or one of its children.
+ * And the children will not necessarily have the correct
+ * hpa value.
+ * Save this elder for now.
+ */
+ elder = dev;
+ } else if (elder == NULL) {
+ return; /* not the device we booted from */
+ }
+
+ /* What are we looking for? */
+ if (PAGE0->mem_boot.pz_class & PCL_NET_MASK) {
+ /*
+ * Netboot is the top elder
+ */
+ if (elder == dev) {
+ bootdv = dev;
+ }
+ return;
+ } else
+ switch (PAGE0->mem_boot.pz_class & PCL_CLASS_MASK) {
+ case PCL_RANDOM:
+ target = DV_DISK;
+ break;
+ case PCL_SEQU:
+ target = DV_TAPE;
+ break;
+ default:
+ /* No idea what we were booted from, but better ask the user */
+ return;
+ }
+
+ /*
+ * If control goes here, we are booted from a block device.
+ * Since multiple devices will attach with the same hpa value
+ * in their confargs, get rid of at least the controller by
+ * hunting for an appropriate device class.
+ */
+ if (dev->dv_class != target)
+ return;
+
+ basename = dev->dv_cfdata->cf_driver->cd_name;
+
+ /*
+ * We only grok SCSI boot currently. Match on proper device hierarchy,
+ * name and unit/lun values.
+ */
+#if NCD > 0 || NSD > 0 || NST > 0
+ if (strcmp(basename, "sd") == 0 || strcmp(basename, "cd") == 0 ||
+ strcmp(basename, "st") == 0) {
+ struct scsibus_attach_args *sa = aux;
+ struct scsi_link *sl = sa->sa_sc_link;
+
+ /*
+ * sd/st/cd is attached to scsibus which is attached to
+ * the controller. Hence the grandparent here should be
+ * the elder.
+ */
+ if (dev->dv_parent == NULL ||
+ dev->dv_parent->dv_parent != elder) {
+ return;
+ }
+
+ /*
+ * And now check for proper target and lun values
+ */
+ if (sl->target == PAGE0->mem_boot.pz_layers[0] &&
+ sl->lun == PAGE0->mem_boot.pz_layers[1]) {
+ bootdv = dev;
+ }
+ }
+#endif
+}
diff --git a/sys/arch/hppa/include/types.h b/sys/arch/hppa/include/types.h
index 96563543bb4..6c35e4e76a8 100644
--- a/sys/arch/hppa/include/types.h
+++ b/sys/arch/hppa/include/types.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: types.h,v 1.7 2002/08/28 23:42:16 mickey Exp $ */
+/* $OpenBSD: types.h,v 1.8 2003/02/15 00:52:28 miod Exp $ */
/*-
* Copyright (c) 1990, 1993
@@ -86,4 +86,6 @@ typedef unsigned long uint64_t;
typedef int32_t register_t;
+#define __HAVE_DEVICE_REGISTER
+
#endif /* _MACHINE_TYPES_H_ */