From 95b9ab0ebcfc7893c7456240145521f6168b53d2 Mon Sep 17 00:00:00 2001 From: thorpej Date: Sat, 4 Nov 2000 18:47:20 +0000 Subject: [PATCH] Add a device driver for the Middle Digital, Inc. PC-Weasel serial console board. This glues into the `pcdisplay' driver and provides support for the watchdog timer function on the PC-Weasel. --- sys/dev/isa/files.isa | 10 +- sys/dev/isa/pcdisplay.c | 24 +++- sys/dev/isa/weasel.c | 303 ++++++++++++++++++++++++++++++++++++++++ sys/dev/isa/weaselvar.h | 55 ++++++++ 4 files changed, 390 insertions(+), 2 deletions(-) create mode 100644 sys/dev/isa/weasel.c create mode 100644 sys/dev/isa/weaselvar.h diff --git a/sys/dev/isa/files.isa b/sys/dev/isa/files.isa index 5131cf12eda6..9680a58e846d 100644 --- a/sys/dev/isa/files.isa +++ b/sys/dev/isa/files.isa @@ -1,4 +1,4 @@ -# $NetBSD: files.isa,v 1.103 2000/08/11 02:27:11 thorpej Exp $ +# $NetBSD: files.isa,v 1.104 2000/11/04 18:47:20 thorpej Exp $ # # Config file and device description for machine-independent ISA code. # Included by ports that need it. Requires that the SCSI files be @@ -402,6 +402,14 @@ device pcdisplay: wsemuldisplaydev, pcdisplayops attach pcdisplay at isa file dev/isa/pcdisplay.c pcdisplay needs-flag +# Middle Digital, Inc. PC-Weasel serial console board. +# XXX This is a little gross... this is to conditionally compile +# support for the PC-Weasel into the `pcdisplay' driver, +# but we can't use an `option', because options can't have +# attributes. +defpseudo pcweasel: sysmon +file dev/isa/weasel.c pcweasel needs-flag + # PC PPI + TIMER 1 (speaker interface) device pcppi {} attach pcppi at isa diff --git a/sys/dev/isa/pcdisplay.c b/sys/dev/isa/pcdisplay.c index 1430762b7e28..742431c41943 100644 --- a/sys/dev/isa/pcdisplay.c +++ b/sys/dev/isa/pcdisplay.c @@ -1,4 +1,4 @@ -/* $NetBSD: pcdisplay.c,v 1.10 2000/06/26 04:56:21 simonb Exp $ */ +/* $NetBSD: pcdisplay.c,v 1.11 2000/11/04 18:47:20 thorpej Exp $ */ /* * Copyright (c) 1998 @@ -50,6 +50,12 @@ #include #include +#include "pcweasel.h" +#if NPCWEASEL > 0 +#include +#include +#endif + struct pcdisplay_config { struct pcdisplayscreen pcs; struct pcdisplay_handle dc_ph; @@ -60,6 +66,9 @@ struct pcdisplay_softc { struct device sc_dev; struct pcdisplay_config *sc_dc; int nscreens; +#if NPCWEASEL > 0 + struct weasel_handle sc_weasel; +#endif }; static int pcdisplayconsole, pcdisplay_console_attached; @@ -286,6 +295,19 @@ pcdisplay_attach(parent, self, aux) } sc->sc_dc = dc; +#if NPCWEASEL > 0 + /* + * If the display is monochrome, check to see if we have + * a PC-Weasel, and initialize its special features. + */ + if (dc->mono) { + sc->sc_weasel.wh_st = dc->dc_ph.ph_memt; + sc->sc_weasel.wh_sh = dc->dc_ph.ph_memh; + sc->sc_weasel.wh_parent = &sc->sc_dev; + weasel_init(&sc->sc_weasel); + } +#endif /* NPCWEASEL > 0 */ + aa.console = console; aa.scrdata = &pcdisplay_screenlist; aa.accessops = &pcdisplay_accessops; diff --git a/sys/dev/isa/weasel.c b/sys/dev/isa/weasel.c new file mode 100644 index 000000000000..3e53f3e033f6 --- /dev/null +++ b/sys/dev/isa/weasel.c @@ -0,0 +1,303 @@ +/* $NetBSD: weasel.c,v 1.1 2000/11/04 18:47:20 thorpej Exp $ */ + +/*- + * Copyright (c) 2000 Zembu Labs, Inc. + * All rights reserved. + * + * Author: Jason R. Thorpe + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Zembu Labs, Inc. + * 4. Neither the name of Zembu Labs nor the names of its employees may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ZEMBU LABS, INC. ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WAR- + * RANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DIS- + * CLAIMED. IN NO EVENT SHALL ZEMBU LABS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Device driver for the Middle Digital, Inc. PC-Weasel serial + * console board. + * + * We're glued into the MDA display driver (`pcdisplay'), and + * handle things like the watchdog timer. + */ + +#include +#include +#include +#include + +#include + +#include +#include + +#include + +int weasel_wdog_setmode(struct sysmon_wdog *); +int weasel_wdog_tickle(struct sysmon_wdog *); + +int weasel_wdog_toggle(struct weasel_handle *); + +void pcweaselattach(int); + +/* ARGSUSED */ +void +pcweaselattach(int count) +{ + + /* Nothing to do; pseudo-device glue. */ +} + +void +weasel_init(struct weasel_handle *wh) +{ + struct weasel_config_block cfg; + int i, j; + u_int8_t *cp, sum; + const char *vers, *mode; + + /* + * Write a NOP to the command register and see if it + * reverts back to READY within 1.5 seconds. + */ + bus_space_write_1(wh->wh_st, wh->wh_sh, WEASEL_MISC_COMMAND, OS_NOP); + for (i = 0; i < 1500; i++) { + delay(1000); + sum = bus_space_read_1(wh->wh_st, wh->wh_sh, + WEASEL_MISC_COMMAND); + if (sum == OS_READY) + break; + } + if (sum != OS_READY) { + /* This is not a Weasel. */ + return; + } + + /* + * It can take a while for the config block to be copied + * into the offscreen area, as the Weasel may be busy + * sending data to the terminal. Wait up to 3 seconds, + * reading the block each time, and breaking out of the + * loop once the checksum passes. + */ + + bus_space_write_1(wh->wh_st, wh->wh_sh, WEASEL_MISC_COMMAND, + OS_CONFIG_COPY); + + /* ...one second to get it started... */ + delay(1000 * 1000); + + /* ...two seconds to let it finish... */ + for (i = 0; i < 2000; i++) { + delay(1000); + bus_space_read_region_1(wh->wh_st, wh->wh_sh, + WEASEL_CONFIG_BLOCK, &cfg, sizeof(cfg)); + /* + * Compute the checksum of the config block. + */ + for (cp = (u_int8_t *)&cfg, j = 0, sum = 1; + j < (sizeof(cfg) - 1); j++) + sum += cp[j]; + if (sum == cfg.cksum) + break; + } + + if (sum != cfg.cksum) { + /* + * Checksum doesn't match; either it's not a Weasel, + * or something is wrong with it. + */ + printf("%s: PC-Weasel config block checksum mismatch " + "0x%02x != 0x%02x\n", wh->wh_parent->dv_xname, + sum, cfg.cksum); + return; + } + + switch (cfg.cfg_version) { + case CFG_VERSION_1_0: + vers = "1.0"; + switch (cfg.enable_duart_switching) { + case 0: + mode = "emulation"; + break; + + case 1: + mode = "autoswitch"; + break; + + default: + mode = "unknown"; + } + break; + + case CFG_VERSION_1_1: + vers = "1.1"; + switch (cfg.enable_duart_switching) { + case 0: + mode = "emulation"; + break; + + case 1: + mode = "serial"; + break; + + case 2: + mode = "autoswitch"; + break; + + default: + mode = "unknown"; + } + break; + + default: + vers = mode = NULL; + } + + printf("%s: PC-Weasel, ", wh->wh_parent->dv_xname); + if (vers != NULL) + printf("version %s, %s mode", vers, mode); + else + printf("unknown version 0x%x", cfg.cfg_version); + printf("\n"); + + printf("%s: break passthrough %s", wh->wh_parent->dv_xname, + cfg.break_passthru ? "enabled" : "disabled"); + if (cfg.wdt_allow) { + if (cfg.wdt_msec == 0) { + /* + * Old firmware -- these Weasels have + * a 3000ms watchdog period. + */ + cfg.wdt_msec = 3000; + } + + /* + * There's no way to determine what mode the watchdog + * is in, but we can safely assume that it starts off + * disarmed. + */ + wh->wh_wdog_armed = 0; + wh->wh_wdog_period = cfg.wdt_msec / 1000; + + printf(", watchdog interval %d sec.", wh->wh_wdog_period); + } + printf("\n"); + + if (cfg.wdt_allow) { + wh->wh_smw.smw_name = "weasel"; + wh->wh_smw.smw_cookie = wh; + wh->wh_smw.smw_setmode = weasel_wdog_setmode; + wh->wh_smw.smw_tickle = weasel_wdog_tickle; + wh->wh_smw.smw_period = wh->wh_wdog_period; + + if (sysmon_wdog_register(&wh->wh_smw) != 0) + printf("%s: unable to register PC-Weasel watchdog " + "with sysmon\n", wh->wh_parent->dv_xname); + } +} + +int +weasel_wdog_setmode(struct sysmon_wdog *smw) +{ + struct weasel_handle *wh = smw->smw_cookie; + int error = 0; + + if ((smw->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) { + if (wh->wh_wdog_armed) + error = weasel_wdog_toggle(wh); + } else { + if (smw->smw_period == WDOG_PERIOD_DEFAULT) + smw->smw_period = wh->wh_wdog_period; + else if (smw->smw_period != wh->wh_wdog_period) { + /* Can't change the period on the Weasel. */ + return (EINVAL); + } + if (wh->wh_wdog_armed == 0) + error = weasel_wdog_toggle(wh); + else + weasel_wdog_tickle(smw); + } + + return (error); +} + +int +weasel_wdog_tickle(struct sysmon_wdog *smw) +{ + struct weasel_handle *wh = smw->smw_cookie; + u_int8_t reg; + int s; + + s = splhigh(); + reg = bus_space_read_1(wh->wh_st, wh->wh_sh, WEASEL_WDT_SEMAPHORE); + bus_space_write_1(wh->wh_st, wh->wh_sh, WEASEL_WDT_SEMAPHORE, ~reg); + splx(s); + + return (0); +} + +int +weasel_wdog_toggle(struct weasel_handle *wh) +{ + u_int8_t reg; + int i, s, new_state, error = 0; + + s = splhigh(); + + for (i = 0, new_state = wh->wh_wdog_armed; + new_state == wh->wh_wdog_armed && i < 5000; i++) { + bus_space_write_1(wh->wh_st, wh->wh_sh, + WEASEL_WDT_SEMAPHORE, 0x22); + delay(1500); + reg = bus_space_read_1(wh->wh_st, wh->wh_sh, + WEASEL_WDT_SEMAPHORE); + if (reg == 0xea) { + bus_space_write_1(wh->wh_st, wh->wh_sh, + WEASEL_WDT_SEMAPHORE, 0x2f); + delay(1500); + reg = bus_space_read_1(wh->wh_st, wh->wh_sh, + WEASEL_WDT_SEMAPHORE); + if (reg == 0xae) { + bus_space_write_1(wh->wh_st, wh->wh_sh, + WEASEL_WDT_SEMAPHORE, 0x37); + delay(1500); + new_state = bus_space_read_1(wh->wh_st, + wh->wh_sh, WEASEL_WDT_SEMAPHORE); + } + } + } + + /* Canonicalize. */ + if (new_state) + new_state = 1; + + if (new_state == wh->wh_wdog_armed) + error = EIO; + else + wh->wh_wdog_armed = new_state; + + splx(s); + + return (error); +} diff --git a/sys/dev/isa/weaselvar.h b/sys/dev/isa/weaselvar.h new file mode 100644 index 000000000000..709f9d399585 --- /dev/null +++ b/sys/dev/isa/weaselvar.h @@ -0,0 +1,55 @@ +/* $NetBSD: weaselvar.h,v 1.1 2000/11/04 18:47:20 thorpej Exp $ */ + +/*- + * Copyright (c) 2000 Zembu Labs, Inc. + * All rights reserved. + * + * Author: Jason R. Thorpe + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Zembu Labs, Inc. + * 4. Neither the name of Zembu Labs nor the names of its employees may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ZEMBU LABS, INC. ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WAR- + * RANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DIS- + * CLAIMED. IN NO EVENT SHALL ZEMBU LABS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Interface definitions for the Middle Digital, Inc. PC-Weasel + * serial console board. + */ + +#include + +struct weasel_handle { + struct device *wh_parent; /* backpointer to parent */ + + bus_space_tag_t wh_st; + bus_space_handle_t wh_sh; + + struct sysmon_wdog wh_smw; + + int wh_wdog_armed; + u_int wh_wdog_period; +}; + +void weasel_init(struct weasel_handle *);