Module Name: src Committed By: phx Date: Sat Nov 12 23:57:55 UTC 2011
Modified Files: src/sys/arch/sandpoint/sandpoint: satmgr.c Log Message: Add Iomega support (init, reboot, poweroff). Make new sysctl-nodes for Iomega fan control in machdep.satmgr. To generate a diff of this commit: cvs rdiff -u -r1.12 -r1.13 src/sys/arch/sandpoint/sandpoint/satmgr.c 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/sandpoint/satmgr.c diff -u src/sys/arch/sandpoint/sandpoint/satmgr.c:1.12 src/sys/arch/sandpoint/sandpoint/satmgr.c:1.13 --- src/sys/arch/sandpoint/sandpoint/satmgr.c:1.12 Fri Jul 1 19:16:06 2011 +++ src/sys/arch/sandpoint/sandpoint/satmgr.c Sat Nov 12 23:57:55 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: satmgr.c,v 1.12 2011/07/01 19:16:06 dyoung Exp $ */ +/* $NetBSD: satmgr.c,v 1.13 2011/11/12 23:57:55 phx Exp $ */ /*- * Copyright (c) 2010 The NetBSD Foundation, Inc. @@ -65,6 +65,7 @@ struct satmgr_softc { struct selinfo sc_rsel; callout_t sc_ch_wdog; callout_t sc_ch_pbutton; + callout_t sc_ch_sync; struct sysmon_pswitch sc_sm_pbutton; int sc_open; void *sc_si; @@ -79,6 +80,10 @@ struct satmgr_softc { struct satops *sc_ops; char sc_btn_buf[8]; int sc_btn_cnt; + char sc_cmd_buf[8]; + int sc_sysctl_wdog; + int sc_sysctl_fanlow; + int sc_sysctl_fanhigh; }; static int satmgr_match(device_t, cfdata_t, void *); @@ -105,8 +110,11 @@ const struct cdevsw satmgr_cdevsw = { static void satmgr_reboot(int); static int satmgr_sysctl_wdogenable(SYSCTLFN_PROTO); +static int satmgr_sysctl_fanlow(SYSCTLFN_PROTO); +static int satmgr_sysctl_fanhigh(SYSCTLFN_PROTO); static void wdog_tickle(void *); static void send_sat(struct satmgr_softc *, const char *); +static void send_sat_len(struct satmgr_softc *, const char *, int); static int hwintr(void *); static void rxintr(struct satmgr_softc *); static void txintr(struct satmgr_softc *); @@ -114,17 +122,23 @@ static void startoutput(struct satmgr_so static void swintr(void *); static void sinit(struct satmgr_softc *); static void qinit(struct satmgr_softc *); +static void iinit(struct satmgr_softc *); static void kreboot(struct satmgr_softc *); static void sreboot(struct satmgr_softc *); static void qreboot(struct satmgr_softc *); +static void ireboot(struct satmgr_softc *); static void kpwroff(struct satmgr_softc *); static void spwroff(struct satmgr_softc *); static void qpwroff(struct satmgr_softc *); static void dpwroff(struct satmgr_softc *); +static void ipwroff(struct satmgr_softc *); static void kbutton(struct satmgr_softc *, int); static void sbutton(struct satmgr_softc *, int); static void qbutton(struct satmgr_softc *, int); static void dbutton(struct satmgr_softc *, int); +static void ibutton(struct satmgr_softc *, int); +static void idosync(void *); +static void iprepcmd(struct satmgr_softc *, int, int, int, int, int, int); static void guarded_pbutton(void *); static void sched_sysmon_pbutton(void *); @@ -137,8 +151,9 @@ struct satops { }; static struct satops satmodel[] = { - { "dlink", NULL, NULL, dpwroff, dbutton }, - { "kurobox", NULL, kreboot, kpwroff, kbutton }, + { "dlink", NULL, NULL, dpwroff, dbutton }, + { "iomega", iinit, ireboot, ipwroff, ibutton }, + { "kurobox", NULL, kreboot, kpwroff, kbutton }, { "qnap", qinit, qreboot, qpwroff, qbutton }, { "synology", sinit, sreboot, spwroff, sbutton } }; @@ -155,8 +170,6 @@ static struct satops satmodel[] = { #define CSR_READ(t,r) bus_space_read_1((t)->sc_iot, (t)->sc_ioh, (r)) #define CSR_WRITE(t,r,v) bus_space_write_1((t)->sc_iot, (t)->sc_ioh, (r), (v)) -static int satmgr_wdog; - static int satmgr_match(device_t parent, cfdata_t match, void *aux) { @@ -210,6 +223,7 @@ satmgr_attach(device_t parent, device_t selinit(&sc->sc_rsel); callout_init(&sc->sc_ch_wdog, 0); callout_init(&sc->sc_ch_pbutton, 0); + callout_init(&sc->sc_ch_sync, 0); mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_HIGH); cv_init(&sc->sc_rdcv, "satrd"); cv_init(&sc->sc_wrcv, "satwr"); @@ -233,11 +247,11 @@ satmgr_attach(device_t parent, device_t aprint_error_dev(sc->sc_dev, "unable to register power button with sysmon\n"); + /* create machdep.satmgr subtree for those models which support it */ if (strcmp(ops->family, "kurobox") == 0) { const struct sysctlnode *rnode; struct sysctllog *clog; - /* create machdep.satmgr.* subtree */ clog = NULL; sysctl_createv(&clog, 0, NULL, &rnode, CTLFLAG_PERMANENT, @@ -256,6 +270,34 @@ satmgr_attach(device_t parent, device_t satmgr_sysctl_wdogenable, 0, NULL, 0, CTL_CREATE, CTL_EOL); } + else if (strcmp(ops->family, "iomega") == 0) { + const struct sysctlnode *rnode; + struct sysctllog *clog; + + clog = NULL; + sysctl_createv(&clog, 0, NULL, &rnode, + CTLFLAG_PERMANENT, + CTLTYPE_NODE, "machdep", NULL, + NULL, 0, NULL, 0, + CTL_MACHDEP, CTL_EOL); + sysctl_createv(&clog, 0, &rnode, &rnode, + CTLFLAG_PERMANENT, + CTLTYPE_NODE, "satmgr", NULL, + NULL, 0, NULL, 0, + CTL_CREATE, CTL_EOL); + sysctl_createv(&clog, 0, &rnode, NULL, + CTLFLAG_PERMANENT|CTLFLAG_READWRITE, + CTLTYPE_INT, "fan_low_temp", + SYSCTL_DESCR("Turn off fan below this temperature"), + satmgr_sysctl_fanlow, 0, NULL, 0, + CTL_CREATE, CTL_EOL); + sysctl_createv(&clog, 0, &rnode, NULL, + CTLFLAG_PERMANENT|CTLFLAG_READWRITE, + CTLTYPE_INT, "fan_high_temp", + SYSCTL_DESCR("Turn on fan above this temperature"), + satmgr_sysctl_fanhigh, 0, NULL, 0, + CTL_CREATE, CTL_EOL); + } md_reboot = satmgr_reboot; /* cpu_reboot() hook */ if (ops->init != NULL) @@ -287,21 +329,21 @@ satmgr_reboot(int howto) static int satmgr_sysctl_wdogenable(SYSCTLFN_ARGS) { - int error, t; struct sysctlnode node; struct satmgr_softc *sc; + int error, t; + sc = device_lookup_private(&satmgr_cd, 0); node = *rnode; - t = satmgr_wdog; + t = sc->sc_sysctl_wdog; node.sysctl_data = &t; error = sysctl_lookup(SYSCTLFN_CALL(&node)); if (error || newp == NULL) return error; - if (t < 0 || t > 1) return EINVAL; - sc = device_lookup_private(&satmgr_cd, 0); + sc->sc_sysctl_wdog = t; if (t == 1) { callout_setfunc(&sc->sc_ch_wdog, wdog_tickle, sc); callout_schedule(&sc->sc_ch_wdog, 90 * hz); @@ -323,20 +365,72 @@ wdog_tickle(void *arg) callout_schedule(&sc->sc_ch_wdog, 90 * hz); } +static int +satmgr_sysctl_fanlow(SYSCTLFN_ARGS) +{ + struct sysctlnode node; + struct satmgr_softc *sc; + int error, t; + + sc = device_lookup_private(&satmgr_cd, 0); + node = *rnode; + t = sc->sc_sysctl_fanlow; + node.sysctl_data = &t; + error = sysctl_lookup(SYSCTLFN_CALL(&node)); + if (error || newp == NULL) + return error; + if (t < 0 || t > 99) + return EINVAL; + sc->sc_sysctl_fanlow = t; + iprepcmd(sc, 'b', 'b', 10, 'a', + sc->sc_sysctl_fanhigh, sc->sc_sysctl_fanlow); + return 0; +} + +static int +satmgr_sysctl_fanhigh(SYSCTLFN_ARGS) +{ + struct sysctlnode node; + struct satmgr_softc *sc; + int error, t; + + sc = device_lookup_private(&satmgr_cd, 0); + node = *rnode; + t = sc->sc_sysctl_fanhigh; + node.sysctl_data = &t; + error = sysctl_lookup(SYSCTLFN_CALL(&node)); + if (error || newp == NULL) + return error; + if (t < 0 || t > 99) + return EINVAL; + sc->sc_sysctl_fanhigh = t; + iprepcmd(sc, 'b', 'b', 10, 'a', + sc->sc_sysctl_fanhigh, sc->sc_sysctl_fanlow); + return 0; +} + static void send_sat(struct satmgr_softc *sc, const char *msg) { - unsigned lsr, ch, n; + + send_sat_len(sc, msg, strlen(msg)); +} + + +static void +send_sat_len(struct satmgr_softc *sc, const char *msg, int len) +{ + unsigned lsr; + int n; again: do { lsr = CSR_READ(sc, LSR); } while ((lsr & LSR_TXRDY) == 0); n = 16; /* FIFO depth */ - while ((ch = *msg++) != '\0' && n-- > 0) { - CSR_WRITE(sc, THR, ch); - } - if (ch != '\0') + while (len-- > 0 && n-- > 0) + CSR_WRITE(sc, THR, *msg++); + if (len > 0) goto again; } @@ -762,6 +856,98 @@ dbutton(struct satmgr_softc *sc, int ch) } static void +iinit(struct satmgr_softc *sc) +{ + + /* LED blue, auto-fan, turn on at 50C, turn off at 45C */ + sc->sc_sysctl_fanhigh = 50; + sc->sc_sysctl_fanlow = 45; + iprepcmd(sc, 'b', 'b', 10, 'a', + sc->sc_sysctl_fanhigh, sc->sc_sysctl_fanlow); +} + +static void +ireboot(struct satmgr_softc *sc) +{ + + iprepcmd(sc, 'g', 0, 0, 0, 0, 0); +} + +static void +ipwroff(struct satmgr_softc *sc) +{ + + iprepcmd(sc, 'c', 0, 0, 0, 0, 0); +} + +static void +ibutton(struct satmgr_softc *sc, int ch) +{ + int i; + char cksum; + + sc->sc_btn_buf[sc->sc_btn_cnt++] = ch; + + if (sc->sc_btn_cnt >= 8) { + sc->sc_btn_cnt = 0; + + if (callout_active(&sc->sc_ch_sync) == true) { + /* now we can send a pending command packet */ + callout_stop(&sc->sc_ch_sync); + for (i = 0, cksum = 0; i < 7; i++) + cksum += sc->sc_cmd_buf[i]; + sc->sc_cmd_buf[7] = cksum & 0x7f; + send_sat_len(sc, sc->sc_cmd_buf, 8); + } + } +} + +static void +idosync(void *arg) +{ + /* + * Send 0-bytes until the 68HC908 sends a reply packet. + * This means we are synchronized again, and the pending command, + * constructed by iprepcmd(), is transmitted automatically. + */ + struct satmgr_softc *sc = arg; + unsigned lsr; + + /* we're now in callout(9) context */ + do { + lsr = CSR_READ(sc, LSR); + } while ((lsr & LSR_TXRDY) == 0); + callout_schedule(&sc->sc_ch_sync, hz / 5); + CSR_WRITE(sc, THR, 0); +} + +static void +iprepcmd(struct satmgr_softc *sc, int pow, int led, int rat, int fan, + int fhi, int flo) +{ + char *p = sc->sc_cmd_buf; + + /* + * Construct the command packet. Values of -1 (0xff) will be + * replaced later by the current values from the last status. + */ + *p++ = pow; + *p++ = led; + *p++ = rat; + *p++ = fan; + *p++ = fhi; + *p++ = flo; + *p = 7; /* host id */ + + /* synchronize transmitter, before packet can be sent */ + callout_reset(&sc->sc_ch_sync, hz / 5, idosync, sc); + /* + * XXX We should protect ourselves against other writers, while + * XXX synchronization is active! + */ +} + +static void guarded_pbutton(void *arg) { struct satmgr_softc *sc = arg;