Module Name:    src
Committed By:   snj
Date:           Sat Jan 16 10:04:05 UTC 2016

Modified Files:
        src/sys/arch/sandpoint/include [netbsd-7]: bootinfo.h
        src/sys/arch/sandpoint/stand/altboot [netbsd-7]: brdsetup.c dsk.c
            globals.h main.c siisata.c version

Log Message:
Pull up following revision(s) (requested by phx in ticket #1059):
        sys/arch/sandpoint/include/bootinfo.h: revision 1.9
        sys/arch/sandpoint/stand/altboot/brdsetup.c: revisions 1.36, 1.37
        sys/arch/sandpoint/stand/altboot/dsk.c: revision 1.18
        sys/arch/sandpoint/stand/altboot/globals.h: revisions 1.20, 1.21
        sys/arch/sandpoint/stand/altboot/main.c: revision 1.27
        sys/arch/sandpoint/stand/altboot/siisata.c: revision 1.6
        sys/arch/sandpoint/stand/altboot/version: revision 1.8
The disk's unittag is not equal to the channel, so we need an additional
unitchan entry to make lba_read() work in all cases.
The libsa-printf() does not seem to support 64-bit output, so cast the
block number to unsigned when printing an error 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.
--
fix a board type check logic error that affected Linkstation and Kurobox (HG).
They were mistakenly recognized kurot4 type and ended up with kernel boot
failure.


To generate a diff of this commit:
cvs rdiff -u -r1.8 -r1.8.34.1 src/sys/arch/sandpoint/include/bootinfo.h
cvs rdiff -u -r1.35 -r1.35.2.1 \
    src/sys/arch/sandpoint/stand/altboot/brdsetup.c
cvs rdiff -u -r1.17 -r1.17.2.1 src/sys/arch/sandpoint/stand/altboot/dsk.c
cvs rdiff -u -r1.19 -r1.19.14.1 \
    src/sys/arch/sandpoint/stand/altboot/globals.h
cvs rdiff -u -r1.26 -r1.26.2.1 src/sys/arch/sandpoint/stand/altboot/main.c
cvs rdiff -u -r1.5 -r1.5.22.1 src/sys/arch/sandpoint/stand/altboot/siisata.c
cvs rdiff -u -r1.7 -r1.7.4.1 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.8.34.1
--- src/sys/arch/sandpoint/include/bootinfo.h:1.8	Tue Jan 11 06:57:35 2011
+++ src/sys/arch/sandpoint/include/bootinfo.h	Sat Jan 16 10:04:04 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: bootinfo.h,v 1.8 2011/01/11 06:57:35 nisimura Exp $	*/
+/*	$NetBSD: bootinfo.h,v 1.8.34.1 2016/01/16 10:04:04 snj 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.35.2.1
--- 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	Sat Jan 16 10:04:04 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: brdsetup.c,v 1.35 2014/08/08 21:18:10 joerg Exp $ */
+/* $NetBSD: brdsetup.c,v 1.35.2.1 2016/01/16 10:04:04 snj 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[] = {
     {
@@ -253,10 +260,14 @@ brdsetup(void)
 	}
 	else if (PCI_CLASS(pcicfgread(dev11, PCI_CLASS_REG)) == PCI_CLASS_ETH) {
 		/* ADMtek AN985 (tlp) or RealTek 8169S (re) at dev 11 */
-		if (PCI_VENDOR(pcicfgread(dev12, PCI_ID_REG)) != 0x1095)
+		if (PCI_VENDOR(pcicfgread(dev11, PCI_ID_REG)) == 0x1317)
 			brdtype = BRD_KUROBOX;
-		else
-			brdtype = BRD_KUROBOXT4;
+		else if (PCI_VENDOR(pcicfgread(dev11, PCI_ID_REG)) == 0x10ec) {
+			if (PCI_PRODUCT(pcicfgread(dev12,PCI_ID_REG)) != 0x3512)
+				brdtype = BRD_KUROBOX;
+			else
+				brdtype = BRD_KUROBOXT4;
+		}
 	}
 	else if (PCI_VENDOR(pcicfgread(dev15, PCI_ID_REG)) == 0x11ab) {
 		/* SKnet/Marvell (sk) at dev 15 */
@@ -719,47 +730,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"
 	};
-	volatile uint8_t *cpld = (volatile uint8_t *)0xff000000;
-	uint8_t pwrstate;
+	static const char models406[3][7] = {
+		"CS406e", "CS406", "RS406"
+	};
+	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;
 
-	if (nata > 1) {
+		/*
+		 * 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;
+		}
+	}
+
+	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/dsk.c
diff -u src/sys/arch/sandpoint/stand/altboot/dsk.c:1.17 src/sys/arch/sandpoint/stand/altboot/dsk.c:1.17.2.1
--- src/sys/arch/sandpoint/stand/altboot/dsk.c:1.17	Tue Aug  5 17:55:20 2014
+++ src/sys/arch/sandpoint/stand/altboot/dsk.c	Sat Jan 16 10:04:05 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: dsk.c,v 1.17 2014/08/05 17:55:20 joerg Exp $ */
+/* $NetBSD: dsk.c,v 1.17.2.1 2016/01/16 10:04:05 snj Exp $ */
 
 /*-
  * Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -125,6 +125,7 @@ disk_scan(void *drv)
 		}
 		d = &ldisk[ndrive];
 		d->dvops = l;
+		d->unitchan = n;
 		d->unittag = ndrive;
 		snprintf(d->xname, sizeof(d->xname), "wd%d", d->unittag);
 		set_xfermode(l, n);
@@ -404,7 +405,7 @@ lba_read(struct disk *d, int64_t bno, in
 	int error;
 
 	l = d->dvops;
-	n = d->unittag;
+	n = d->unitchan;
 	p = (uint16_t *)buf;
 	chan = &l->chan[n];
 	error = 0;
@@ -414,7 +415,8 @@ lba_read(struct disk *d, int64_t bno, in
 		(*issue)(chan, bno, rdcnt);
 		for (k = 0; k < rdcnt; k++) {
 			if (spinwait_unbusy(l, n, 1000, &err) == 0) {
-				printf("%s blk %lld %s\n", d->xname, bno, err);
+				printf("%s blk %u %s\n",
+				   d->xname, (unsigned)bno, err);
 				error = EIO;
 				break;
 			}

Index: src/sys/arch/sandpoint/stand/altboot/globals.h
diff -u src/sys/arch/sandpoint/stand/altboot/globals.h:1.19 src/sys/arch/sandpoint/stand/altboot/globals.h:1.19.14.1
--- src/sys/arch/sandpoint/stand/altboot/globals.h:1.19	Thu Apr 26 19:59:37 2012
+++ src/sys/arch/sandpoint/stand/altboot/globals.h	Sat Jan 16 10:04:05 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: globals.h,v 1.19 2012/04/26 19:59:37 phx Exp $ */
+/* $NetBSD: globals.h,v 1.19.14.1 2016/01/16 10:04:05 snj Exp $ */
 
 #ifdef DEBUG
 #define	DPRINTF(x)	printf x
@@ -172,6 +172,7 @@ NIF_DECL(stg);
 struct disk {
 	char xname[8];
 	void *dvops;
+	unsigned unitchan;
 	unsigned unittag;
 	uint16_t ident[128];
 	uint64_t nsect;
@@ -196,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.26.2.1
--- 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	Sat Jan 16 10:04:05 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: main.c,v 1.26 2014/08/05 17:55:20 joerg Exp $ */
+/* $NetBSD: main.c,v 1.26.2.1 2016/01/16 10:04:05 snj 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.5.22.1
--- 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	Sat Jan 16 10:04:05 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: siisata.c,v 1.5 2012/01/22 13:08:17 phx Exp $ */
+/* $NetBSD: siisata.c,v 1.5.22.1 2016/01/16 10:04:05 snj 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.7.4.1
--- src/sys/arch/sandpoint/stand/altboot/version:1.7	Sun Sep 15 18:22:57 2013
+++ src/sys/arch/sandpoint/stand/altboot/version	Sat Jan 16 10:04:05 2016
@@ -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