Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/sandpoint Pass a name and flags precisely describin...



details:   https://anonhg.NetBSD.org/src/rev/627daebd45a4
branches:  trunk
changeset: 340777:627daebd45a4
user:      phx <phx%NetBSD.org@localhost>
date:      Wed Sep 30 14:14:32 2015 +0000

description:
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.

diffstat:

 sys/arch/sandpoint/include/bootinfo.h       |   17 ++-
 sys/arch/sandpoint/stand/altboot/brdsetup.c |  179 +++++++++++++++++++++++++--
 sys/arch/sandpoint/stand/altboot/globals.h  |    4 +-
 sys/arch/sandpoint/stand/altboot/main.c     |    4 +-
 sys/arch/sandpoint/stand/altboot/siisata.c  |   26 +++-
 sys/arch/sandpoint/stand/altboot/version    |    2 +
 6 files changed, 205 insertions(+), 27 deletions(-)

diffs (truncated from 375 to 300 lines):

diff -r fbb2d6ff1951 -r 627daebd45a4 sys/arch/sandpoint/include/bootinfo.h
--- a/sys/arch/sandpoint/include/bootinfo.h     Wed Sep 30 08:42:04 2015 +0000
+++ b/sys/arch/sandpoint/include/bootinfo.h     Wed Sep 30 14:14:32 2015 +0000
@@ -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 @@
 #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 @@
        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;
diff -r fbb2d6ff1951 -r 627daebd45a4 sys/arch/sandpoint/stand/altboot/brdsetup.c
--- a/sys/arch/sandpoint/stand/altboot/brdsetup.c       Wed Sep 30 08:42:04 2015 +0000
+++ b/sys/arch/sandpoint/stand/altboot/brdsetup.c       Wed Sep 30 14:14:32 2015 +0000
@@ -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 @@
 #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 @@
        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"
+       };
+       static const char models407[4][7] = {
+               "???", "CS407e", "CS407", "RS407"
        };
-       volatile uint8_t *cpld = (volatile uint8_t *)0xff000000;
-       uint8_t pwrstate;
+       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 */
 
-       if (nata > 1) {
+               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;
 
-       if (nata > 1) {
-               /* enable drive LEDs for active disk drives on CS/RS models */
+       cpld = bi_model.flags & BI_MODEL_CPLD_MASK;
+
+       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));
        }
 }
 
diff -r fbb2d6ff1951 -r 627daebd45a4 sys/arch/sandpoint/stand/altboot/globals.h
--- a/sys/arch/sandpoint/stand/altboot/globals.h        Wed Sep 30 08:42:04 2015 +0000
+++ b/sys/arch/sandpoint/stand/altboot/globals.h        Wed Sep 30 14:14:32 2015 +0000
@@ -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 @@
 DSK_DECL(pciide);
 DSK_DECL(siisata);
 
+extern int sata_delay[4];
+
 /* status */
 #define ATA_STS_BUSY           0x80
 #define ATA_STS_DRDY           0x40
diff -r fbb2d6ff1951 -r 627daebd45a4 sys/arch/sandpoint/stand/altboot/main.c
--- a/sys/arch/sandpoint/stand/altboot/main.c   Wed Sep 30 08:42:04 2015 +0000
+++ b/sys/arch/sandpoint/stand/altboot/main.c   Wed Sep 30 14:14:32 2015 +0000
@@ -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_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 @@
                        /* need to pass this MAC address to kernel */



Home | Main Index | Thread Index | Old Index