Module Name:    src
Committed By:   phx
Date:           Sun Jan 22 13:08:17 UTC 2012

Modified Files:
        src/sys/arch/sandpoint/stand/altboot: dsk.c globals.h main.c pciide.c
            siisata.c version

Log Message:
Support PATA drive configuration option (ide:N[N...]).
Wait until drives are ready after cold-start.
Wake up drives from standby mode.
A default command line can be saved to flash as initrd image.


To generate a diff of this commit:
cvs rdiff -u -r1.12 -r1.13 src/sys/arch/sandpoint/stand/altboot/dsk.c
cvs rdiff -u -r1.15 -r1.16 src/sys/arch/sandpoint/stand/altboot/globals.h
cvs rdiff -u -r1.16 -r1.17 src/sys/arch/sandpoint/stand/altboot/main.c
cvs rdiff -u -r1.11 -r1.12 src/sys/arch/sandpoint/stand/altboot/pciide.c
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/sandpoint/stand/altboot/siisata.c
cvs rdiff -u -r1.5 -r1.6 src/sys/arch/sandpoint/stand/altboot/version

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/sandpoint/stand/altboot/dsk.c
diff -u src/sys/arch/sandpoint/stand/altboot/dsk.c:1.12 src/sys/arch/sandpoint/stand/altboot/dsk.c:1.13
--- src/sys/arch/sandpoint/stand/altboot/dsk.c:1.12	Thu Jan 19 07:38:05 2012
+++ src/sys/arch/sandpoint/stand/altboot/dsk.c	Sun Jan 22 13:08:16 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: dsk.c,v 1.12 2012/01/19 07:38:05 nisimura Exp $ */
+/* $NetBSD: dsk.c,v 1.13 2012/01/22 13:08:16 phx Exp $ */
 
 /*-
  * Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -179,34 +179,46 @@ int
 perform_atareset(struct dkdev_ata *l, int n)
 {
 	struct dvata_chan *chan = &l->chan[n];
+//	int retries;
 
-	CSR_WRITE_1(chan->ctl, ATA_DREQ);
-	delay(10);
-	CSR_WRITE_1(chan->ctl, ATA_SRST|ATA_DREQ);
-	delay(10);
-	CSR_WRITE_1(chan->ctl, ATA_DREQ);
+//	for (retries = 0; retries < 10; retries++) {
+		CSR_WRITE_1(chan->ctl, ATA_DREQ);
+		delay(10);
+		CSR_WRITE_1(chan->ctl, ATA_SRST|ATA_DREQ);
+		delay(10);
+		CSR_WRITE_1(chan->ctl, ATA_DREQ);
+//		if (spinwait_unbusy(l, n, 1000/*250*/, NULL) != 0)
+//			return 1;
+//		delay(1000 * 1000);
+//	}
+	return spinwait_unbusy(l, n, 1000/*250*/, NULL);
+}
+
+/* clear idle and standby timers to spin up the drive */
+void
+wakeup_drive(struct dkdev_ata *l, int n)
+{
+	struct dvata_chan *chan = &l->chan[n];
 
-	return spinwait_unbusy(l, n, 250, NULL);
+	CSR_WRITE_1(chan->cmd + _NSECT, 0);
+	CSR_WRITE_1(chan->cmd + _CMD, ATA_CMD_IDLE);
+	(void)CSR_READ_1(chan->alt);
+	delay(10 * 1000);
+	CSR_WRITE_1(chan->cmd + _NSECT, 0);
+	CSR_WRITE_1(chan->cmd + _CMD, ATA_CMD_STANDBY);
+	(void)CSR_READ_1(chan->alt);
+	delay(10 * 1000);
 }
 
 int
-satapresense(struct dkdev_ata *l, int n)
+atachkpwr(struct dkdev_ata *l, int n)
 {
-#define VND_CH(n) (((n&02)<<8)+((n&01)<<7))
-#define VND_SC(n) (0x100+VND_CH(n))
-#define VND_SS(n) (0x104+VND_CH(n))
-
-	uint32_t sc = l->bar[5] + VND_SC(n);
-	uint32_t ss = l->bar[5] + VND_SS(n);
-	unsigned val;
-
-	val = (00 << 4) | (03 << 8);	/* any speed, no pwrmgt */
-	CSR_WRITE_4(sc, val | 01);	/* perform init */
-	delay(50 * 1000);
-	CSR_WRITE_4(sc, val);
-	delay(50 * 1000);	
-	val = CSR_READ_4(ss);		/* has completed */
-	return ((val & 03) == 03);	/* active drive found */
+	struct dvata_chan *chan = &l->chan[n];
+
+	CSR_WRITE_1(chan->cmd + _CMD, ATA_CMD_CHKPWR);
+	(void)CSR_READ_1(chan->alt);
+	delay(10 * 1000);
+	return CSR_READ_1(chan->cmd + _NSECT);
 }
 
 static int

Index: src/sys/arch/sandpoint/stand/altboot/globals.h
diff -u src/sys/arch/sandpoint/stand/altboot/globals.h:1.15 src/sys/arch/sandpoint/stand/altboot/globals.h:1.16
--- src/sys/arch/sandpoint/stand/altboot/globals.h:1.15	Sat Jan  7 19:57:49 2012
+++ src/sys/arch/sandpoint/stand/altboot/globals.h	Sun Jan 22 13:08:16 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: globals.h,v 1.15 2012/01/07 19:57:49 phx Exp $ */
+/* $NetBSD: globals.h,v 1.16 2012/01/22 13:08:16 phx Exp $ */
 
 #ifdef DEBUG
 #define	DPRINTF(x)	printf x
@@ -42,6 +42,7 @@ extern uint32_t cpuclock, busclock;
 
 /* board specific support code */
 struct brdprop *brd_lookup(int);
+int get_drive_config(int);
 int tstchar(void);
 #ifdef DEBUG
 void sat_write(char *, int);
@@ -177,16 +178,23 @@ DSK_DECL(siisata);
 #define ATA_STS_DRDY		0x40
 #define ATA_STS_ERR 		0x01
 /* command */
+#define ATA_CMD_CHKPWR		0xe5
 #define ATA_CMD_IDENT		0xec
+#define ATA_CMD_IDLE		0xe3
 #define ATA_CMD_READ		0x20
 #define ATA_CMD_READ_EXT	0x24
 #define ATA_CMD_SETF		0xef
+#define ATA_CMD_STANDBY		0xe2
 /* device */
 #define ATA_DEV_LBA		0xe0
 #define ATA_DEV_OBS		0x90
 /* control */
 #define ATA_DREQ		0x08
 #define ATA_SRST		0x04
+/* power state */
+#define ATA_PWR_ACTIVE		0xff
+#define ATA_PWR_IDLE		0x80
+#define ATA_PWR_STANDBY		0x00
 
 #define ATA_XFER		0x03
 #define XFER_PIO4		0x0c
@@ -229,4 +237,5 @@ struct disk {
 
 int spinwait_unbusy(struct dkdev_ata *, int, int, const char **);
 int perform_atareset(struct dkdev_ata *, int);
-int satapresense(struct dkdev_ata *, int);
+void wakeup_drive(struct dkdev_ata *, int);
+int atachkpwr(struct dkdev_ata *, int);

Index: src/sys/arch/sandpoint/stand/altboot/main.c
diff -u src/sys/arch/sandpoint/stand/altboot/main.c:1.16 src/sys/arch/sandpoint/stand/altboot/main.c:1.17
--- src/sys/arch/sandpoint/stand/altboot/main.c:1.16	Sun Jan  1 18:25:03 2012
+++ src/sys/arch/sandpoint/stand/altboot/main.c	Sun Jan 22 13:08:16 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: main.c,v 1.16 2012/01/01 18:25:03 phx Exp $ */
+/* $NetBSD: main.c,v 1.17 2012/01/22 13:08:16 phx Exp $ */
 
 /*-
  * Copyright (c) 2007 The NetBSD Foundation, Inc.
@@ -58,6 +58,9 @@ static const struct bootarg {
 	{ "altboot",	-1 }
 };
 
+/* default PATA drive configuration is "10": single master on first channel */
+static char *drive_config = "10";
+
 void *bootinfo; /* low memory reserved to pass bootinfo structures */
 int bi_size;	/* BOOTINFO_MAXSIZE */
 char *bi_next;
@@ -176,20 +179,6 @@ main(int argc, char *argv[], char *boota
 	pcisetup();
 	pcifixup();
 
-	/* intialize a disk driver */
-	for (n = 0; n < nata; n++)
-		if (dskdv_init(&lata[n]) != 0)
-			break;
-	if (n >= nata)
-		printf("IDE/SATA device driver was not found\n");
-
-	/* initialize a network interface */
-	for (n = 0; n < nnif; n++)
-		if (netif_init(&lnif[n]) != 0)
-			break;
-	if (n >= nnif)
-		printf("no NET device driver was found\n");
-
 	/*
 	 * When argc is too big then it is probably a pointer, which could
 	 * indicate that we were launched as a Linux kernel module using
@@ -198,10 +187,19 @@ main(int argc, char *argv[], char *boota
 	if (argc > MAX_ARGS) {
 		if (argv != NULL) {
 			/*
-			 * initrd image was loaded: assume extremely
-			 * restricted firmware and boot default
+			 * initrd image was loaded:
+			 * check if it contains a valid altboot command line
 			 */
-			argc = 0;
+			char *p = (char *)argv;
+
+			if (strncmp(p, "altboot:", 8) == 0) {
+				*p = 0;
+				for (p = p + 8; *p >= ' '; p++);
+				argc = parse_cmdline(new_argv, MAX_ARGS,
+				    ((char *)argv) + 8, p);
+				argv = new_argv;
+			} else
+				argc = 0;	/* boot default */
 		} else {
 			/* parse standard Linux bootargs */
 			argc = parse_cmdline(new_argv, MAX_ARGS,
@@ -210,6 +208,29 @@ main(int argc, char *argv[], char *boota
 		}
 	}
 
+	/* look for a PATA drive configuration string under the arguments */
+	for (n = 1; n < argc; n++) {
+		if (strncmp(argv[n], "ide:", 4) == 0 &&
+		    argv[n][4] >= '0' && argv[n][4] <= '2') {
+			drive_config = &argv[n][4];
+			break;
+		}
+	}
+
+	/* intialize a disk driver */
+	for (n = 0; n < nata; n++)
+		if (dskdv_init(&lata[n]) != 0)
+			break;
+	if (n >= nata)
+		printf("IDE/SATA device driver was not found\n");
+
+	/* initialize a network interface */
+	for (n = 0; n < nnif; n++)
+		if (netif_init(&lnif[n]) != 0)
+			break;
+	if (n >= nnif)
+		printf("no NET device driver was found\n");
+
 	/* wait 2s for user to enter interactive mode */
 	for (n = 200; n >= 0; n--) {
 		if (n % 100 == 0)
@@ -239,6 +260,9 @@ main(int argc, char *argv[], char *boota
 
 	/* get boot options and determine bootname */
 	for (n = 1; n < argc; n++) {
+		if (strncmp(argv[n], "ide:", 4) == 0)
+			continue; /* ignore drive configuration argument */
+
 		for (i = 0; i < sizeof(bootargs) / sizeof(bootargs[0]); i++) {
 			if (strncasecmp(argv[n], bootargs[i].name,
 			    strlen(bootargs[i].name)) == 0) {
@@ -491,52 +515,24 @@ module_open(struct boot_module *bm)
 	return fd;
 }
 
-#if 0
-static const char *cmdln[] = {
-	"console=ttyS0,115200 root=/dev/sda1 rw initrd=0x200000,2M",
-	"console=ttyS0,115200 root=/dev/nfs ip=dhcp"
-};
-
-void
-mkatagparams(unsigned addr, char *kcmd)
+/*
+ * Return the drive configuration for the requested channel 'ch'.
+ * Channel 2 is the first channel of the next IDE controller.
+ * 0: for no drive present on channel
+ * 1: for master drive present on channel, no slave
+ * 2: for master and slave drive present
+ */
+int
+get_drive_config(int ch)
 {
-	struct tag {
-		unsigned siz;
-		unsigned tag;
-		unsigned val[1];
-	};
-	struct tag *p;
-#define ATAG_CORE 	0x54410001
-#define ATAG_MEM	0x54410002
-#define ATAG_INITRD	0x54410005
-#define ATAG_CMDLINE	0x54410009
-#define ATAG_NONE	0x00000000
-#define tagnext(p) (struct tag *)((unsigned *)(p) + (p)->siz)
-#define tagsize(n) (2 + (n))
-
-	p = (struct tag *)addr;
-	p->tag = ATAG_CORE;
-	p->siz = tagsize(3);
-	p->val[0] = 0;		/* flags */
-	p->val[1] = 0;		/* pagesize */
-	p->val[2] = 0;		/* rootdev */
-	p = tagnext(p);
-	p->tag = ATAG_MEM;
-	p->siz = tagsize(2);
-	p->val[0] = 64 * 1024 * 1024;
-	p->val[1] = 0;		/* start */
-	p = tagnext(p);
-	if (kcmd != NULL) {
-		p = tagnext(p);
-		p->tag = ATAG_CMDLINE;
-		p->siz = tagsize((strlen(kcmd) + 1 + 3) >> 2);
-		strcpy((void *)p->val, kcmd);
-	}
-	p = tagnext(p);
-	p->tag = ATAG_NONE;
-	p->siz = 0;
+	if (drive_config != NULL) {
+		if (strlen(drive_config) <= ch)
+			return 0;	/* an unspecified channel is unused */
+		if (drive_config[ch] >= '0' && drive_config[ch] <= '2')
+			return drive_config[ch] - '0';
+	}
+	return -1;
 }
-#endif
 
 void *
 allocaligned(size_t size, size_t align)

Index: src/sys/arch/sandpoint/stand/altboot/pciide.c
diff -u src/sys/arch/sandpoint/stand/altboot/pciide.c:1.11 src/sys/arch/sandpoint/stand/altboot/pciide.c:1.12
--- src/sys/arch/sandpoint/stand/altboot/pciide.c:1.11	Sun Nov 13 00:06:54 2011
+++ src/sys/arch/sandpoint/stand/altboot/pciide.c	Sun Jan 22 13:08:16 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: pciide.c,v 1.11 2011/11/13 00:06:54 phx Exp $ */
+/* $NetBSD: pciide.c,v 1.12 2012/01/22 13:08:16 phx Exp $ */
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -82,7 +82,8 @@ pciide_match(unsigned tag, void *data)
 void *
 pciide_init(unsigned tag, void *data)
 {
-	int native, n;
+	static int cntrl = 0;
+	int native, n, retries;
 	unsigned val;
 	struct dkdev_ata *l;
 
@@ -128,16 +129,37 @@ pciide_init(unsigned tag, void *data)
 	}
 
 	for (n = 0; n < 2; n++) {
-		if (myops->presense && (*myops->presense)(l, n) == 0)
-			l->presense[n] = 0; /* found not exist */
-		else
+		if (myops->presense != NULL && (*myops->presense)(l, n) == 0) {
+			DPRINTF(("channel %d not present\n", n));
+			l->presense[n] = 0;
+			continue;
+		} else if (get_drive_config(cntrl * 2 + n) == 0) {
+			DPRINTF(("channel %d disabled by config\n", n));
+			l->presense[n] = 0;
+			continue;
+		}
+
+		if (atachkpwr(l, n) != ATA_PWR_ACTIVE) {
+			/* drive is probably sleeping, wake it up */
+			for (retries = 0; retries < 10; retries++) {
+				wakeup_drive(l, n);
+				DPRINTF(("channel %d spinning up...\n", n));
+				delay(1000 * 1000);
+				l->presense[n] = perform_atareset(l, n);
+				if (atachkpwr(l, n) == ATA_PWR_ACTIVE)
+					break;
+			}
+		} else {
 			/* check to see whether soft reset works */
+			DPRINTF(("channel %d active\n", n));
 			l->presense[n] = perform_atareset(l, n);
+		}
 
 		if (l->presense[n])
 			printf("channel %d present\n", n);
 	}
 
+	cntrl++;	/* increment controller number for next call */
 	return l;
 }
 

Index: src/sys/arch/sandpoint/stand/altboot/siisata.c
diff -u src/sys/arch/sandpoint/stand/altboot/siisata.c:1.4 src/sys/arch/sandpoint/stand/altboot/siisata.c:1.5
--- src/sys/arch/sandpoint/stand/altboot/siisata.c:1.4	Mon May 30 19:48:12 2011
+++ src/sys/arch/sandpoint/stand/altboot/siisata.c	Sun Jan 22 13:08:17 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: siisata.c,v 1.4 2011/05/30 19:48:12 phx Exp $ */
+/* $NetBSD: siisata.c,v 1.5 2012/01/22 13:08:17 phx Exp $ */
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -35,6 +35,14 @@
 
 #include "globals.h"
 
+/*
+ * - no vtophys() translation, vaddr_t == paddr_t.
+ */
+#define CSR_READ_4(r)		in32rb(r)
+#define CSR_WRITE_4(r,v)	out32rb(r,v)
+
+static int satapresense(struct dkdev_ata *, int);
+
 static uint32_t pciiobase = PCI_XIOBASE;
 
 int
@@ -56,7 +64,7 @@ void *
 siisata_init(unsigned tag, void *data)
 {
 	unsigned idreg;
-	int n, nchan, retries;
+	int n, nchan, retries/*waitforspinup*/;
 	struct dkdev_ata *l;
 
 	l = alloc(sizeof(struct dkdev_ata));
@@ -99,22 +107,57 @@ siisata_init(unsigned tag, void *data)
 	pcicfgwrite(tag, 0x80, 0x00);
 	pcicfgwrite(tag, 0x84, 0x00);
 
-	for (n = 0, retries = 0; n < nchan; n++) {
-		l->presense[n] = 0;
-
-		if (satapresense(l, n)) {
-			/* drive present, now check whether soft reset works */
-			while (retries++ < 10) {
-				if (perform_atareset(l, n)) {
-					DPRINTF(("port %d device present\n", n));
-					l->presense[n] = 1;
+	for (n = 0; n < nchan; n++) {
+		l->presense[n] = satapresense(l, n);
+		if (l->presense[n] == 0) {
+			DPRINTF(("port %d not present\n", n));
+			l->presense[n] = 0;
+			continue;
+		}
+		if (atachkpwr(l, n) != ATA_PWR_ACTIVE) {
+			/* drive is probably sleeping, wake it up */
+			for (retries = 0; retries < 10; retries++) {
+				wakeup_drive(l, n);
+				DPRINTF(("port %d spinning up...\n", n));
+				delay(1000 * 1000);
+				l->presense[n] = perform_atareset(l, n);
+				if (atachkpwr(l, n) == ATA_PWR_ACTIVE)
 					break;
-				}
-				/* give the drive another second to spin up */
-				if (retries < 10)
-					delay(1000 * 1000);
+			}
+		} else {
+			/* check to see whether soft reset works */
+			DPRINTF(("port %d active\n", n));
+			for (retries = 0; retries < 10; retries++) {
+				l->presense[n] = perform_atareset(l, n);
+				if (l->presense[n] != 0)
+					break;
+				DPRINTF(("port %d cold-starting...\n", n));
+				delay(1000 * 1000);
 			}
 		}
+
+		if (l->presense[n])
+			printf("port %d present\n", n);
 	}
 	return l;
 }
+
+static int
+satapresense(struct dkdev_ata *l, int n)
+{
+#define VND_CH(n) (((n&02)<<8)+((n&01)<<7))
+#define VND_SC(n) (0x100+VND_CH(n))
+#define VND_SS(n) (0x104+VND_CH(n))
+
+	uint32_t sc = l->bar[5] + VND_SC(n);
+	uint32_t ss = l->bar[5] + VND_SS(n);
+	unsigned val;
+
+	val = (00 << 4) | (03 << 8);	/* any speed, no pwrmgt */
+	CSR_WRITE_4(sc, val | 01);	/* perform init */
+	delay(50 * 1000);
+	CSR_WRITE_4(sc, val);
+	delay(50 * 1000);	
+	val = CSR_READ_4(ss);		/* has completed */
+	return ((val & 03) == 03);	/* active drive found */
+}

Index: src/sys/arch/sandpoint/stand/altboot/version
diff -u src/sys/arch/sandpoint/stand/altboot/version:1.5 src/sys/arch/sandpoint/stand/altboot/version:1.6
--- src/sys/arch/sandpoint/stand/altboot/version:1.5	Sat Nov 12 23:52:54 2011
+++ src/sys/arch/sandpoint/stand/altboot/version	Sun Jan 22 13:08:17 2012
@@ -11,3 +11,6 @@
 	mode, default boot path is now wd0:netbsd in multiuser mode
 1.8:	Iomega support, IT821x & VT6410 IDE support, fixed interrupt
 	issue, exception handler and sat-controller test mode (DEBUG)
+1.9:	Support PATA drive configuration option. Wait until drives are
+        ready after cold-start. Wake up drives from standby mode.
+        A default command line can be saved to flash as initrd image.

Reply via email to