Module Name:    src
Committed By:   phx
Date:           Wed Sep 30 14:14:32 UTC 2015

Modified Files:
        src/sys/arch/sandpoint/include: bootinfo.h
        src/sys/arch/sandpoint/stand/altboot: brdsetup.c globals.h main.c
            siisata.c version

Log Message:
Pass a name and flags precisely describing the current model and its
features via a new bootinfo node (currently Synology only). This allows
for example the configuration of model-specific temperature I2C sensors
and fan control.
Support for the Synology DS207 and DS209 drive LEDs and wait until the
2nd drive is completely powered up.


To generate a diff of this commit:
cvs rdiff -u -r1.8 -r1.9 src/sys/arch/sandpoint/include/bootinfo.h
cvs rdiff -u -r1.35 -r1.36 src/sys/arch/sandpoint/stand/altboot/brdsetup.c
cvs rdiff -u -r1.20 -r1.21 src/sys/arch/sandpoint/stand/altboot/globals.h
cvs rdiff -u -r1.26 -r1.27 src/sys/arch/sandpoint/stand/altboot/main.c
cvs rdiff -u -r1.5 -r1.6 src/sys/arch/sandpoint/stand/altboot/siisata.c
cvs rdiff -u -r1.7 -r1.8 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/include/bootinfo.h
diff -u src/sys/arch/sandpoint/include/bootinfo.h:1.8 src/sys/arch/sandpoint/include/bootinfo.h:1.9
--- src/sys/arch/sandpoint/include/bootinfo.h:1.8	Tue Jan 11 06:57:35 2011
+++ src/sys/arch/sandpoint/include/bootinfo.h	Wed Sep 30 14:14:32 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: bootinfo.h,v 1.8 2011/01/11 06:57:35 nisimura Exp $	*/
+/*	$NetBSD: bootinfo.h,v 1.9 2015/09/30 14:14:32 phx Exp $	*/
 
 /*
  * Copyright (c) 1997
@@ -45,6 +45,7 @@ struct btinfo_common {
 #define BTINFO_NET		7
 #define BTINFO_PRODFAMILY	8
 #define BTINFO_MODULELIST	9
+#define BTINFO_MODEL		10
 
 struct btinfo_magic {
 	struct btinfo_common common;
@@ -91,6 +92,20 @@ struct btinfo_prodfamily {
 	char name[24];
 };
 
+struct btinfo_model {
+	struct btinfo_common common;
+	char name[28];
+	unsigned flags;			/* model specific flags */
+/* Synology flags: */
+#define BI_MODEL_CPLDVER_MASK	0x07
+#define BI_MODEL_CPLD207	0x08
+#define BI_MODEL_CPLD209	0x10
+#define BI_MODEL_CPLD406	0x18
+#define BI_MODEL_CPLD407	0x20
+#define BI_MODEL_CPLD_MASK	0x38
+#define BI_MODEL_THERMAL	0x40
+};
+
 struct btinfo_modulelist {
 	struct btinfo_common common;
 	int num;

Index: src/sys/arch/sandpoint/stand/altboot/brdsetup.c
diff -u src/sys/arch/sandpoint/stand/altboot/brdsetup.c:1.35 src/sys/arch/sandpoint/stand/altboot/brdsetup.c:1.36
--- src/sys/arch/sandpoint/stand/altboot/brdsetup.c:1.35	Fri Aug  8 21:18:10 2014
+++ src/sys/arch/sandpoint/stand/altboot/brdsetup.c	Wed Sep 30 14:14:32 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: brdsetup.c,v 1.35 2014/08/08 21:18:10 joerg Exp $ */
+/* $NetBSD: brdsetup.c,v 1.36 2015/09/30 14:14:32 phx Exp $ */
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -111,7 +111,14 @@ static unsigned mpc107memsize(void);
 #define IOMEGA_PACKETSIZE	8
 
 /* NH230/231 GPIO */
-#define NHGPIO_WRITE(x)		*((uint8_t *)0x70000000) = x
+#define NHGPIO_WRITE(x)		*((volatile uint8_t *)0x70000000) = (x)
+
+/* Synology CPLD (2007 and newer models) */
+#define SYNOCPLD_READ(r)	*((volatile uint8_t *)0xff000000 + (r))
+#define SYNOCPLD_WRITE(r,x)	do { \
+    *((volatile uint8_t *)0xff000000 + (r)) = (x); \
+    delay(10); \
+    } while(0)
 
 static struct brdprop brdlist[] = {
     {
@@ -719,47 +726,183 @@ synobrdfix(struct brdprop *brd)
 	send_sat("247");
 }
 
+#define SYNO_FAN_TIMEOUT	500	/* 500ms to turn the fan off */
+#define SYNO_DISK_DELAY		30	/* 30 seconds to power up 2nd disk */
+
 void
 synopcifix(struct brdprop *brd)
 {
-	static const char csmodel[4][7] = {
-		"CS406e", "CS406", "RS406", "CS407e"
+	static const char models207[4][7] = {
+		"???", "DS107e", "DS107", "DS207"
+	};
+	static const char models209[2][7] = {
+		"DS109j", "DS209j"
+	};
+	static const char models406[3][7] = {
+		"CS406e", "CS406", "RS406"
 	};
-	volatile uint8_t *cpld = (volatile uint8_t *)0xff000000;
-	uint8_t pwrstate;
+	static const char models407[4][7] = {
+		"???", "CS407e", "CS407", "RS407"
+	};
+	extern struct btinfo_model bi_model;
+	const char *model_name;
+	unsigned cpld, version, flags;
+	uint8_t v, status;
+	int i;
+
+	/*
+	 * Determine if a CPLD is present and whether is has 4-bit
+	 * (models 107, 207, 209)  or 8-bit (models 406, 407) registers.
+	 * The register set repeats every 16 bytes.
+	 */
+	cpld = 0;
+	flags = 0;
+	version = 0;
+	model_name = NULL;
+
+	SYNOCPLD_WRITE(0, 0x00);	/* LEDs blinking yellow (default) */
+	v = SYNOCPLD_READ(0);
+
+	if (v != 0x00) {
+		v &= 0xf0;
+		if (v != 0x00 || (SYNOCPLD_READ(16 + 0) & 0xf0) != v)
+			goto cpld_done;
+
+  cpld4bits:
+		/* 4-bit registers assumed, make LEDs solid yellow */
+		SYNOCPLD_WRITE(0, 0x50);
+		v = SYNOCPLD_READ(0) & 0xf0;
+		if (v != 0x50 || (SYNOCPLD_READ(32 + 0) & 0xf0) != v)
+			goto cpld_done;
+
+		v = SYNOCPLD_READ(2) & 0xf0;
+		if ((SYNOCPLD_READ(48 + 2) & 0xf0) != v)
+			goto cpld_done;
+		version = (v >> 4) & 7;
+
+		/*
+		 * Try to determine whether it is a 207-style or 209-style
+		 * CPLD register set, by turning the fan off and check if
+		 * either bit 5 or bit 4 changes from 0 to 1 to indicate
+		 * the fan is stopped.
+		 */
+		status = SYNOCPLD_READ(3) & 0xf0;
+		SYNOCPLD_WRITE(3, 0x00);	/* fan off */
+
+		for (i = 0; i < SYNO_FAN_TIMEOUT * 100; i++) {
+			delay(10);
+			v = SYNOCPLD_READ(3) & 0xf0;
+			if ((status & 0x20) == 0 && (v & 0x20) != 0) {
+				/* set x07 model */
+				v = SYNOCPLD_READ(1) >> 6;
+				model_name = models207[v];
+				cpld = BI_MODEL_CPLD207;
+				/* XXXX DS107v2/v3 have no thermal sensor */
+				flags |= BI_MODEL_THERMAL;
+				break;
+			}
+			if ((status & 0x10) == 0 && (v & 0x10) != 0) {
+				/* set x09 model */
+				v = SYNOCPLD_READ(1) >> 7;
+				model_name = models209[v];
+				cpld = BI_MODEL_CPLD209;
+				if (v == 1)	/* DS209j */
+					flags |= BI_MODEL_THERMAL;
+				break;
+			}
+			/* XXX What about DS108j? Does it have a CPLD? */
+		}
+
+		/* turn the fan on again */
+		SYNOCPLD_WRITE(3, status);
+
+		if (i >= SYNO_FAN_TIMEOUT * 100)
+			goto cpld_done;		/* timeout: no valid CPLD */
+	} else {
+		if (SYNOCPLD_READ(16 + 0) != v)
+			goto cpld4bits;
+
+		/* 8-bit registers assumed, make LEDs solid yellow */
+		SYNOCPLD_WRITE(0, 0x55);
+		v = SYNOCPLD_READ(0);
+		if (v != 0x55)
+			goto cpld4bits;		/* try 4 bits instead */
+		if (SYNOCPLD_READ(32 + 0) != v)
+			goto cpld_done;
+
+		v = SYNOCPLD_READ(2);
+		if (SYNOCPLD_READ(48 + 2) != v)
+			goto cpld_done;
+		version = v & 3;
+
+		if ((v & 0x0c) != 0x0c) {
+			/* set 406 model */
+			model_name = models406[(v >> 2) & 3];
+			cpld = BI_MODEL_CPLD406;
+		} else {
+			/* set 407 model */
+			model_name = models407[v >> 6];
+			cpld = BI_MODEL_CPLD407;
+			flags |= BI_MODEL_THERMAL;
+		}
+	}
 
-	if (nata > 1) {
+	printf("CPLD V%s%u detected for model %s\n",
+	    cpld < BI_MODEL_CPLD406 ? "" : "1.",
+	    version, model_name);
+
+	if (cpld ==  BI_MODEL_CPLD406 || cpld ==  BI_MODEL_CPLD407) {
 		/*
 		 * CS/RS stations power-up their disks one after another.
 		 * We have to watch over the current power state in a CPLD
 		 * register, until all disks become available.
 		 */
-		printf("CPLD V1.%d for model %s\n", cpld[2] & 3,
-		    csmodel[(cpld[2] & 0x0c) >> 2]);
-		cpld[0] = 0x00; /* all drive LEDs blinking yellow */
 		do {
 			delay(1000 * 1000);
-			pwrstate = cpld[1];
-			printf("Power state: %02x\r", pwrstate);
-		} while (pwrstate != 0xff);
+			v = SYNOCPLD_READ(1);
+			printf("Power state: %02x\r", v);
+		} while (v != 0xff);
 		putchar('\n');
+	} else if (model_name != NULL && model_name[2] == '2') {
+		/*
+		 * DS207 and DS209 have a second SATA disk, which is started
+		 * with several seconds delay, but no CPLD register to
+		 * monitor the power state. So all we can do is to
+		 * wait some more seconds during SATA-init.
+		 */
+		sata_delay[1] = SYNO_DISK_DELAY;
 	}
+
+  cpld_done:
+	if (model_name != NULL) {
+		snprintf(bi_model.name, sizeof(bi_model.name), "%s", model_name);
+		bi_model.flags = cpld | version | flags;
+	} else
+		printf("No CPLD found. DS101/DS106.\n");
 }
 
 void
 synolaunch(struct brdprop *brd)
 {
-	volatile uint8_t *cpld = (volatile uint8_t *)0xff000000;
+	extern struct btinfo_model bi_model;
 	struct dkdev_ata *sata1, *sata2;
+	unsigned cpld;
+
+	cpld = bi_model.flags & BI_MODEL_CPLD_MASK;
 
-	if (nata > 1) {
-		/* enable drive LEDs for active disk drives on CS/RS models */
+	if (cpld ==  BI_MODEL_CPLD406 || cpld ==  BI_MODEL_CPLD407) {
+		/* set drive LEDs for active disk drives on CS/RS models */
 		sata1 = lata[0].drv;
 		sata2 = lata[1].drv;
-		cpld[0] = (sata1->presense[0] ? 0x80 : 0xc0) |
+		SYNOCPLD_WRITE(0, (sata1->presense[0] ? 0x80 : 0xc0) |
 		    (sata1->presense[1] ? 0x20 : 0x30) |
 		    (sata2->presense[0] ? 0x08 : 0x0c) |
-		    (sata2->presense[1] ? 0x02 : 0x03);
+		    (sata2->presense[1] ? 0x02 : 0x03));
+	} else if (cpld ==  BI_MODEL_CPLD207 || cpld ==  BI_MODEL_CPLD209) {
+		/* set drive LEDs for DS207 and DS209 models */
+		sata1 = lata[0].drv;
+		SYNOCPLD_WRITE(0, (sata1->presense[0] ? 0x80 : 0xc0) |
+		    (sata1->presense[1] ? 0x20 : 0x30));
 	}
 }
 

Index: src/sys/arch/sandpoint/stand/altboot/globals.h
diff -u src/sys/arch/sandpoint/stand/altboot/globals.h:1.20 src/sys/arch/sandpoint/stand/altboot/globals.h:1.21
--- src/sys/arch/sandpoint/stand/altboot/globals.h:1.20	Tue Sep 29 15:12:52 2015
+++ src/sys/arch/sandpoint/stand/altboot/globals.h	Wed Sep 30 14:14:32 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: globals.h,v 1.20 2015/09/29 15:12:52 phx Exp $ */
+/* $NetBSD: globals.h,v 1.21 2015/09/30 14:14:32 phx Exp $ */
 
 #ifdef DEBUG
 #define	DPRINTF(x)	printf x
@@ -197,6 +197,8 @@ struct fs_ops *dsk_fsops(struct open_fil
 DSK_DECL(pciide);
 DSK_DECL(siisata);
 
+extern int sata_delay[4];
+
 /* status */
 #define ATA_STS_BUSY		0x80
 #define ATA_STS_DRDY		0x40

Index: src/sys/arch/sandpoint/stand/altboot/main.c
diff -u src/sys/arch/sandpoint/stand/altboot/main.c:1.26 src/sys/arch/sandpoint/stand/altboot/main.c:1.27
--- src/sys/arch/sandpoint/stand/altboot/main.c:1.26	Tue Aug  5 17:55:20 2014
+++ src/sys/arch/sandpoint/stand/altboot/main.c	Wed Sep 30 14:14:32 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: main.c,v 1.26 2014/08/05 17:55:20 joerg Exp $ */
+/* $NetBSD: main.c,v 1.27 2015/09/30 14:14:32 phx Exp $ */
 
 /*-
  * Copyright (c) 2007 The NetBSD Foundation, Inc.
@@ -72,6 +72,7 @@ struct btinfo_memory bi_mem;
 struct btinfo_console bi_cons;
 struct btinfo_clock bi_clk;
 struct btinfo_prodfamily bi_fam;
+struct btinfo_model bi_model;
 struct btinfo_bootpath bi_path;
 struct btinfo_rootdevice bi_rdev;
 struct btinfo_net bi_net;
@@ -362,6 +363,7 @@ main(int argc, char *argv[], char *boota
 			/* need to pass this MAC address to kernel */
 			bi_add(&bi_net, BTINFO_NET, sizeof(bi_net));
 		}
+		bi_add(&bi_model, BTINFO_MODEL, sizeof(bi_model));
 
 		if (modules_enabled) {
 			if (fsmod != NULL)

Index: src/sys/arch/sandpoint/stand/altboot/siisata.c
diff -u src/sys/arch/sandpoint/stand/altboot/siisata.c:1.5 src/sys/arch/sandpoint/stand/altboot/siisata.c:1.6
--- src/sys/arch/sandpoint/stand/altboot/siisata.c:1.5	Sun Jan 22 13:08:17 2012
+++ src/sys/arch/sandpoint/stand/altboot/siisata.c	Wed Sep 30 14:14:32 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: siisata.c,v 1.5 2012/01/22 13:08:17 phx Exp $ */
+/* $NetBSD: siisata.c,v 1.6 2015/09/30 14:14:32 phx Exp $ */
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -45,6 +45,8 @@ static int satapresense(struct dkdev_ata
 
 static uint32_t pciiobase = PCI_XIOBASE;
 
+int sata_delay[4] = { 3, 3, 3, 3 };	/* drive power-up delay per channel */
+
 int
 siisata_match(unsigned tag, void *data)
 {
@@ -110,13 +112,24 @@ siisata_init(unsigned tag, void *data)
 	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;
+			/* wait some seconds to power-up the drive */
+			for (retries = 0; retries < sata_delay[n]; retries++) {
+				wakeup_drive(l, n);
+				printf("Waiting %2d seconds for powering up "
+				    "port %d.\r", sata_delay[n] - retries, n);
+				delay(1000 * 1000);
+				if ((l->presense[n] = satapresense(l, n)) != 0)
+					break;
+			}
+			putchar('\n');
+			if (l->presense[n] == 0) {
+				DPRINTF(("port %d not present\n", n));
+				continue;
+			}
 		}
 		if (atachkpwr(l, n) != ATA_PWR_ACTIVE) {
 			/* drive is probably sleeping, wake it up */
-			for (retries = 0; retries < 10; retries++) {
+			for (retries = 0; retries < 20; retries++) {
 				wakeup_drive(l, n);
 				DPRINTF(("port %d spinning up...\n", n));
 				delay(1000 * 1000);
@@ -127,10 +140,11 @@ siisata_init(unsigned tag, void *data)
 		} else {
 			/* check to see whether soft reset works */
 			DPRINTF(("port %d active\n", n));
-			for (retries = 0; retries < 10; retries++) {
+			for (retries = 0; retries < 20; retries++) {
 				l->presense[n] = perform_atareset(l, n);
 				if (l->presense[n] != 0)
 					break;
+				wakeup_drive(l, n);
 				DPRINTF(("port %d cold-starting...\n", n));
 				delay(1000 * 1000);
 			}

Index: src/sys/arch/sandpoint/stand/altboot/version
diff -u src/sys/arch/sandpoint/stand/altboot/version:1.7 src/sys/arch/sandpoint/stand/altboot/version:1.8
--- src/sys/arch/sandpoint/stand/altboot/version:1.7	Sun Sep 15 18:22:57 2013
+++ src/sys/arch/sandpoint/stand/altboot/version	Wed Sep 30 14:14:32 2015
@@ -16,3 +16,5 @@
         A default command line can be saved to flash as initrd image.
 1.10:	Read correct MAC address from flash on QNAP-TS systems with re(4)
 	NIC.
+1.11:	Pass precise model information and flags with bootinfo.
+	Synology DS207/209 LED and 2nd disk power-up support.

Reply via email to