diff options
-rw-r--r-- | sys/arch/sgi/conf/GENERIC-IP22 | 20 | ||||
-rw-r--r-- | sys/arch/sgi/conf/RAMDISK-IP22 | 14 | ||||
-rw-r--r-- | sys/arch/sgi/hpc/files.hpc | 8 | ||||
-rw-r--r-- | sys/arch/sgi/hpc/wskbdmap_sgi.c | 147 | ||||
-rw-r--r-- | sys/arch/sgi/hpc/z8530kbd.c | 593 | ||||
-rw-r--r-- | sys/arch/sgi/hpc/z8530ms.c | 337 |
6 files changed, 1096 insertions, 23 deletions
diff --git a/sys/arch/sgi/conf/GENERIC-IP22 b/sys/arch/sgi/conf/GENERIC-IP22 index ac9503fc7fb..e277f1cf84b 100644 --- a/sys/arch/sgi/conf/GENERIC-IP22 +++ b/sys/arch/sgi/conf/GENERIC-IP22 @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC-IP22,v 1.8 2012/04/17 15:36:52 miod Exp $ +# $OpenBSD: GENERIC-IP22,v 1.9 2012/04/17 22:06:33 miod Exp $ # # THIS KERNEL IS FOR INDIGO (IP20), INDY (IP22) AND INDIGO2 (IP24) SYSTEMS ONLY. # @@ -62,26 +62,24 @@ panel* at hpc? # Indy front panel buttons pckbc* at hpc? # Indy/Indigo2 keyboard and mouse zs0 at hpc0 -#zs1 at hpc0 +zs1 at hpc0 zstty* at zs0 # Serial ports -#zskbd* at zs1 channel 0 -#wskbd* at zskbd? mux 1 -#zsms* at zs1 channel 1 -#wsmouse* at zsms? mux 0 +zskbd* at zs1 channel 0 +wskbd* at zskbd? mux 1 +zsms* at zs1 channel 1 +wsmouse* at zsms? mux 0 pckbd* at pckbc? wskbd* at pckbd? mux 1 pms* at pckbc? wsmouse* at pms? mux 0 -newport* at gio? # Indy Newport and Indigo2 XL graphics -wsdisplay* at newport? - -#grtwo* at gio? disable # Express (GR2) graphics +#grtwo* at gio? # Express (GR2) graphics #wsdisplay* at grtwo? - light* at gio? # Light/Starter/Entry (LG1/LG2) graphics wsdisplay* at light? +newport* at gio? # Indy Newport and Indigo2 XL graphics +wsdisplay* at newport? #audio* at haltwo? diff --git a/sys/arch/sgi/conf/RAMDISK-IP22 b/sys/arch/sgi/conf/RAMDISK-IP22 index 6db3c73b0b5..99b29b2d2c4 100644 --- a/sys/arch/sgi/conf/RAMDISK-IP22 +++ b/sys/arch/sgi/conf/RAMDISK-IP22 @@ -1,4 +1,4 @@ -# $OpenBSD: RAMDISK-IP22,v 1.5 2012/04/17 15:36:52 miod Exp $ +# $OpenBSD: RAMDISK-IP22,v 1.6 2012/04/17 22:06:33 miod Exp $ # # THIS KERNEL IS FOR INDIGO (IP20), INDY (IP22) AND INDIGO2 (IP24) SYSTEMS ONLY. @@ -69,10 +69,10 @@ wdsc* at hpc? # On-board SCSI or GIO32 SCSI adapter pckbc* at hpc? # Indy/Indigo2 keyboard and mouse zs0 at hpc0 -#zs1 at hpc0 +zs1 at hpc0 zstty* at zs0 # Serial ports -#zskbd* at zs1 channel 0 -#wskbd* at zskbd? mux 1 +zskbd* at zs1 channel 0 +wskbd* at zskbd? mux 1 #zsms* at zs1 channel 1 #wsmouse* at zsms? mux 0 @@ -81,14 +81,12 @@ wskbd* at pckbd? mux 1 #pms* at pckbc? #wsmouse* at pms? mux 0 -newport* at gio? # Indy Newport graphics -wsdisplay* at newport? - #grtwo* at gio? # Express (GR2) graphics #wsdisplay* at grtwo? - light* at gio? # Light/Starter/Entry (LG1/LG2) graphics wsdisplay* at light? +newport* at gio? # Indy Newport and Indigo2 XL graphics +wsdisplay* at newport? scsibus* at scsi? sd* at scsibus? diff --git a/sys/arch/sgi/hpc/files.hpc b/sys/arch/sgi/hpc/files.hpc index 4463f066a45..1fed4498bf1 100644 --- a/sys/arch/sgi/hpc/files.hpc +++ b/sys/arch/sgi/hpc/files.hpc @@ -1,4 +1,4 @@ -# $OpenBSD: files.hpc,v 1.1 2012/03/28 20:44:23 miod Exp $ +# $OpenBSD: files.hpc,v 1.2 2012/04/17 22:06:33 miod Exp $ # $NetBSD: files.hpc,v 1.14 2009/05/14 01:10:19 macallan Exp $ # IP20 RTC @@ -37,12 +37,12 @@ file arch/sgi/hpc/z8530tty.c zstty needs-flag device zskbd: wskbddev attach zskbd at zs -file arch/sgi/hpc/zs_kbd.c zskbd needs-flag -file arch/sgi/dev/wskbdmap_sgi.c zskbd +file arch/sgi/hpc/z8530kbd.c zskbd needs-flag +file arch/sgi/hpc/wskbdmap_sgi.c zskbd device zsms: wsmousedev attach zsms at zs -file arch/sgi/hpc/zs_ms.c zsms +file arch/sgi/hpc/z8530ms.c zsms attach pckbc at hpc with pckbc_hpc file arch/sgi/hpc/pckbc_hpc.c pckbc_hpc diff --git a/sys/arch/sgi/hpc/wskbdmap_sgi.c b/sys/arch/sgi/hpc/wskbdmap_sgi.c new file mode 100644 index 00000000000..0a8d43391c4 --- /dev/null +++ b/sys/arch/sgi/hpc/wskbdmap_sgi.c @@ -0,0 +1,147 @@ +/* $OpenBSD: wskbdmap_sgi.c,v 1.1 2012/04/17 22:06:33 miod Exp $ */ +/* $NetBSD: wskbdmap_sgi.c,v 1.5 2006/12/26 17:37:22 rumble Exp $ */ + +/* + * Copyright (c) 2004 Steve Rumble + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR 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. + */ + +#include <sys/types.h> +#include <dev/wscons/wsksymdef.h> +#include <dev/wscons/wsksymvar.h> + +#define KC(n) KS_KEYCODE(n) + +static const keysym_t wssgi_keydesctab_us[] = { +/* pos command normal shifted */ + KC(0x02), KS_Cmd1, KS_Control_L, + KC(0x03), KS_Caps_Lock, + KC(0x04), KS_Shift_R, + KC(0x05), KS_Shift_L, + KC(0x06), KS_Cmd_Debugger, KS_Escape, + KC(0x07), KS_1, KS_exclam, + KC(0x08), KS_Tab, + KC(0x09), KS_q, + KC(0x0A), KS_a, + KC(0x0B), KS_s, + KC(0x0D), KS_2, KS_at, + KC(0x0E), KS_3, KS_numbersign, + KC(0x0F), KS_w, + KC(0x10), KS_e, + KC(0x11), KS_d, + KC(0x12), KS_f, + KC(0x13), KS_z, + KC(0x14), KS_x, + KC(0x15), KS_4, KS_dollar, + KC(0x16), KS_5, KS_percent, + KC(0x17), KS_r, + KC(0x18), KS_t, + KC(0x19), KS_g, + KC(0x1A), KS_h, + KC(0x1B), KS_c, + KC(0x1C), KS_v, + KC(0x1D), KS_6, KS_asciicircum, + KC(0x1E), KS_7, KS_ampersand, + KC(0x1F), KS_y, + KC(0x20), KS_u, + KC(0x21), KS_j, + KC(0x22), KS_k, + KC(0x23), KS_b, + KC(0x24), KS_n, + KC(0x25), KS_8, KS_asterisk, + KC(0x26), KS_9, KS_parenleft, + KC(0x27), KS_i, + KC(0x28), KS_o, + KC(0x29), KS_l, + KC(0x2A), KS_semicolon, KS_colon, + KC(0x2B), KS_m, + KC(0x2C), KS_comma, KS_less, + KC(0x2D), KS_0, KS_parenright, + KC(0x2E), KS_minus, KS_underscore, + KC(0x2F), KS_p, + KC(0x30), KS_bracketleft, KS_braceleft, + KC(0x31), KS_apostrophe, KS_quotedbl, + KC(0x32), KS_Return, + KC(0x33), KS_period, KS_greater, + KC(0x34), KS_slash, KS_question, + KC(0x35), KS_equal, KS_plus, + KC(0x36), KS_grave, KS_asciitilde, + KC(0x37), KS_bracketright,KS_braceright, + KC(0x38), KS_backslash, KS_bar, + KC(0x39), KS_KP_End, KS_KP_1, + KC(0x3A), KS_KP_Insert, KS_KP_0, + KC(0x3C), KS_Delete, + KC(0x3D), KS_Delete, + KC(0x3E), KS_KP_Left, KS_KP_4, + KC(0x3F), KS_KP_Down, KS_KP_2, + KC(0x40), KS_KP_Next, KS_KP_3, + KC(0x41), KS_KP_Delete, KS_KP_Decimal, + KC(0x42), KS_KP_Home, KS_KP_7, + KC(0x43), KS_KP_Up, KS_KP_8, + KC(0x44), KS_KP_Begin, KS_KP_5, + KC(0x45), KS_KP_Right, KS_KP_6, + KC(0x48), KS_Left, + KC(0x49), KS_Down, + KC(0x4A), KS_KP_Prior, KS_KP_9, + KC(0x4B), KS_KP_Subtract, + KC(0x4F), KS_Right, + KC(0x50), KS_Up, + KC(0x51), KS_KP_Enter, + KC(0x52), KS_space, + KC(0x53), KS_Cmd2, KS_Alt_L, + KC(0x54), KS_Cmd2, KS_Alt_R, KS_Multi_key, + KC(0x55), KS_Cmd1, KS_Control_R, + KC(0x56), KS_f1, + KC(0x57), KS_f2, + KC(0x58), KS_f3, + KC(0x59), KS_f4, + KC(0x5A), KS_f5, + KC(0x5B), KS_f6, + KC(0x5C), KS_f7, + KC(0x5D), KS_f8, + KC(0x5E), KS_f9, + KC(0x5F), KS_f10, + KC(0x60), KS_f11, + KC(0x61), KS_f12, + KC(0x62), KS_Print_Screen, + KC(0x63), KS_Hold_Screen, + KC(0x64), KS_Pause, + KC(0x65), KS_Insert, + KC(0x66), KS_Home, + KC(0x67), KS_Prior, + KC(0x68), KS_End, + KC(0x69), KS_Next, + KC(0x6A), KS_Num_Lock, + KC(0x6B), KS_KP_Divide, + KC(0x6C), KS_KP_Multiply, + KC(0x6D), KS_KP_Add, +}; + +#define KBD_MAP(name, base, map) \ + { name, base, sizeof(map)/sizeof(keysym_t), map } + +const struct wscons_keydesc wssgi_keydesctab[] = { + KBD_MAP(KB_US, 0, wssgi_keydesctab_us) +}; diff --git a/sys/arch/sgi/hpc/z8530kbd.c b/sys/arch/sgi/hpc/z8530kbd.c new file mode 100644 index 00000000000..282e6fd575b --- /dev/null +++ b/sys/arch/sgi/hpc/z8530kbd.c @@ -0,0 +1,593 @@ +/* $OpenBSD: z8530kbd.c,v 1.1 2012/04/17 22:06:33 miod Exp $ */ +/* $NetBSD: zs_kbd.c,v 1.8 2008/03/29 19:15:35 tsutsui Exp $ */ + +/* + * Copyright (c) 2004 Steve Rumble + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR 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. + */ + +/* + * IP20 serial keyboard driver attached to zs channel 0 at 600bps. + * This layer is the parent of wskbd. + */ + +#include <sys/param.h> +#include <sys/malloc.h> +#include <sys/systm.h> +#include <sys/conf.h> +#include <sys/device.h> + +#include <dev/wscons/wsconsio.h> +#include <dev/wscons/wskbdvar.h> +#include <dev/wscons/wsksymdef.h> +#include <dev/wscons/wsksymvar.h> + +#include <machine/autoconf.h> +#include <mips64/archtype.h> + +#include <dev/ic/z8530reg.h> +#include <machine/z8530var.h> + +#define ZSKBD_BAUD 600 +#define ZSKBD_TXQ_LEN 16 /* power of 2 */ +#define ZSKBD_RXQ_LEN 64 /* power of 2 */ + +#define ZSKBD_DIP_SYNC 0x6e +#define ZSKBD_KEY_UP 0x80 +#define ZSKBD_KEY_ALL_UP 0xf0 + +#ifdef ZSKBD_DEBUG +int zskbd_debug = 0; + +#define DPRINTF(_x) if (zskbd_debug) printf _x +#else +#define DPRINTF(_x) +#endif + +struct zskbd_softc { + struct device sc_dev; + + struct zskbd_devconfig *sc_dc; + +#ifdef WSDISPLAY_COMPAT_RAWKBD + int sc_rawkbd; +#endif +}; + +struct zskbd_devconfig { + /* transmit tail-chasing fifo */ + uint8_t txq[ZSKBD_TXQ_LEN]; + u_int txq_head; + u_int txq_tail; + + /* receive tail-chasing fifo */ + uint8_t rxq[ZSKBD_RXQ_LEN]; + u_int rxq_head; + u_int rxq_tail; + + /* state */ +#define TX_READY 0x1 +#define RX_DIP 0x2 + u_int state; + + /* keyboard configuration */ +#define ZSKBD_CTRL_A 0x0 +#define ZSKBD_CTRL_A_SBEEP 0x2 /* 200 ms */ +#define ZSKBD_CTRL_A_LBEEP 0x4 /* 1000 ms */ +#define ZSKBD_CTRL_A_NOCLICK 0x8 /* turn off keyboard click */ +#define ZSKBD_CTRL_A_RCB 0x10 /* request config byte */ +#define ZSKBD_CTRL_A_NUMLK 0x20 /* num lock led */ +#define ZSKBD_CTRL_A_CAPSLK 0x40 /* caps lock led */ +#define ZSKBD_CTRL_A_AUTOREP 0x80 /* auto-repeat after 650 ms, 28x/sec */ + +#define ZSKBD_CTRL_B 0x1 +#define ZSKBD_CTRL_B_CMPL_DS1_2 0x2 /* complement of ds1+ds2 (num+capslk) */ +#define ZSKBD_CTRL_B_SCRLK 0x4 /* scroll lock light */ +#define ZSKBD_CTRL_B_L1 0x8 /* user-configurable lights */ +#define ZSKBD_CTRL_B_L2 0x10 +#define ZSKBD_CTRL_B_L3 0x20 +#define ZSKBD_CTRL_B_L4 0x40 + uint8_t kbd_conf[2]; + + /* dip switch settings */ + uint8_t dip; + + /* wscons glue */ + struct device *wskbddev; + int enabled; +}; + +int zskbd_match(struct device *, void *, void *); +void zskbd_attach(struct device *, struct device *, void *); + +struct cfdriver zskbd_cd = { + NULL, "zskbd", DV_DULL +}; + +const struct cfattach zskbd_ca = { + sizeof(struct zskbd_softc), zskbd_match, zskbd_attach +}; + +void zskbd_rxint(struct zs_chanstate *); +void zskbd_stint(struct zs_chanstate *, int); +void zskbd_txint(struct zs_chanstate *); +void zskbd_softint(struct zs_chanstate *); +void zskbd_send(struct zs_chanstate *, uint8_t *, u_int); +void zskbd_ctrl(struct zs_chanstate *, uint8_t, uint8_t, uint8_t, uint8_t); + +void zskbd_wskbd_input(struct zs_chanstate *, uint8_t); +int zskbd_wskbd_enable(void *, int); +void zskbd_wskbd_set_leds(void *, int); +int zskbd_wskbd_get_leds(void *); +void zskbd_wskbd_set_keyclick(void *, int); +int zskbd_wskbd_get_keyclick(void *); +int zskbd_wskbd_ioctl(void *, u_long, caddr_t, int, struct proc *); + +void zskbd_cnattach(int, int); +void zskbd_wskbd_getc(void *, u_int *, int *); +void zskbd_wskbd_pollc(void *, int); +void zskbd_wskbd_bell(void *, u_int, u_int, u_int); + +extern struct zschan *zs_get_chan_addr(int, int); +extern int zs_getc(void *); +extern void zs_putc(void *, int); + +static struct zsops zskbd_zsops = { + zskbd_rxint, + zskbd_stint, + zskbd_txint, + zskbd_softint +}; + +extern const struct wscons_keydesc wssgi_keydesctab[]; +const struct wskbd_mapdata sgikbd_wskbd_keymapdata = { + wssgi_keydesctab, + KB_US +}; + +const struct wskbd_accessops zskbd_wskbd_accessops = { + zskbd_wskbd_enable, + zskbd_wskbd_set_leds, + zskbd_wskbd_ioctl +}; + +const struct wskbd_consops zskbd_wskbd_consops = { + zskbd_wskbd_getc, + zskbd_wskbd_pollc, + zskbd_wskbd_bell +}; + +struct zskbd_devconfig zskbd_console_dc; +int zskbd_is_console = 0; + +int +zskbd_match(struct device *parent, void *vcf, void *aux) +{ + if (sys_config.system_type == SGI_IP20) { + struct zsc_attach_args *args = aux; + + if (args->channel == 0) + return 1; + } + + return 0; +} + +void +zskbd_attach(struct device *parent, struct device *self, void *aux) +{ + struct zskbd_softc *sc = (struct zskbd_softc *)self; + struct zsc_softc *zsc = (struct zsc_softc *)parent; + struct zsc_attach_args *args = aux; + struct zs_chanstate *cs; + struct wskbddev_attach_args wskaa; + int s, channel; + + /* Establish ourself with the MD z8530 driver */ + channel = args->channel; + cs = zsc->zsc_cs[channel]; + cs->cs_ops = &zskbd_zsops; + cs->cs_private = sc; + + if (zskbd_is_console) { + sc->sc_dc = &zskbd_console_dc; + sc->sc_dc->enabled = 1; + } else { + sc->sc_dc = malloc(sizeof(struct zskbd_devconfig), M_DEVBUF, + M_WAITOK | M_ZERO); + sc->sc_dc->state = TX_READY; + } + + printf("\n"); + + s = splzs(); + zs_write_reg(cs, 9, (channel == 0) ? ZSWR9_A_RESET : ZSWR9_B_RESET); + cs->cs_preg[1] = ZSWR1_RIE | ZSWR1_TIE; + cs->cs_preg[4] = (cs->cs_preg[4] & ZSWR4_CLK_MASK) | + (ZSWR4_ONESB | ZSWR4_PARENB); /* 1 stop, odd parity */ + zs_set_speed(cs, ZSKBD_BAUD); + zs_loadchannelregs(cs); + + /* request DIP switch settings just in case */ + zskbd_ctrl(cs, ZSKBD_CTRL_A_RCB, 0, 0, 0); + + /* disable key click by default */ + zskbd_ctrl(cs, ZSKBD_CTRL_A_NOCLICK, 0, 0, 0); + + splx(s); + + /* attach wskbd */ + wskaa.console = zskbd_is_console; + wskaa.keymap = &sgikbd_wskbd_keymapdata; + wskaa.accessops = &zskbd_wskbd_accessops; + wskaa.accesscookie = cs; + sc->sc_dc->wskbddev = config_found(self, &wskaa, wskbddevprint); +} + +void +zskbd_rxint(struct zs_chanstate *cs) +{ + struct zskbd_softc *sc = cs->cs_private; + struct zskbd_devconfig *dc = sc->sc_dc; + uint8_t c, r; + + /* clear errors */ + r = zs_read_reg(cs, 1); + if (r & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) + zs_write_csr(cs, ZSWR0_RESET_ERRORS); + + /* read byte and append to our queue */ + c = zs_read_data(cs); + + dc->rxq[dc->rxq_tail] = c; + dc->rxq_tail = (dc->rxq_tail + 1) & ~ZSKBD_RXQ_LEN; + + cs->cs_softreq = 1; +} + +void +zskbd_stint(struct zs_chanstate *cs, int force) +{ + zs_write_csr(cs, ZSWR0_RESET_STATUS); + cs->cs_softreq = 1; +} + +void +zskbd_txint(struct zs_chanstate *cs) +{ + struct zskbd_softc *sc = cs->cs_private; + + zs_write_reg(cs, 0, ZSWR0_RESET_TXINT); + sc->sc_dc->state |= TX_READY; + cs->cs_softreq = 1; +} + +void +zskbd_softint(struct zs_chanstate *cs) +{ + struct zskbd_softc *sc = cs->cs_private; + struct zskbd_devconfig *dc = sc->sc_dc; + + /* handle pending transmissions */ + if (dc->txq_head != dc->txq_tail && (dc->state & TX_READY)) { + int s; + + dc->state &= ~TX_READY; + + s = splzs(); + zs_write_data(cs, dc->txq[dc->txq_head]); + splx(s); + + dc->txq_head = (dc->txq_head + 1) & ~ZSKBD_TXQ_LEN; + } + + /* don't bother if nobody is listening */ + if (!dc->enabled) { + dc->rxq_head = dc->rxq_tail; + return; + } + + /* handle incoming keystrokes/config */ + while (dc->rxq_head != dc->rxq_tail) { + uint8_t key = dc->rxq[dc->rxq_head]; + + if (dc->state & RX_DIP) { + dc->dip = key; + dc->state &= ~RX_DIP; + } else if (key == ZSKBD_DIP_SYNC) { + dc->state |= RX_DIP; + } else { + /* toss wskbd a bone */ + zskbd_wskbd_input(cs, key); + } + + dc->rxq_head = (dc->rxq_head + 1) & ~ZSKBD_RXQ_LEN; + } +} + +/* expects to be in splzs() */ +void +zskbd_send(struct zs_chanstate *cs, uint8_t *c, u_int len) +{ + struct zskbd_softc *sc = cs->cs_private; + struct zskbd_devconfig *dc = sc->sc_dc; + u_int i; + + for (i = 0; i < len; i++) { + if (dc->state & TX_READY) { + zs_write_data(cs, c[i]); + dc->state &= ~TX_READY; + } else { + dc->txq[dc->txq_tail] = c[i]; + dc->txq_tail = (dc->txq_tail + 1) & ~ZSKBD_TXQ_LEN; + cs->cs_softreq = 1; + } + } +} + +/* expects to be in splzs() */ +void +zskbd_ctrl(struct zs_chanstate *cs, uint8_t a_on, uint8_t a_off, uint8_t b_on, + uint8_t b_off) +{ + struct zskbd_softc *sc = cs->cs_private; + struct zskbd_devconfig *dc = sc->sc_dc; + + dc->kbd_conf[ZSKBD_CTRL_A] |= a_on; + dc->kbd_conf[ZSKBD_CTRL_A] &= ~(a_off | ZSKBD_CTRL_B); + dc->kbd_conf[ZSKBD_CTRL_B] &= ~b_off; + dc->kbd_conf[ZSKBD_CTRL_B] |= (b_on | ZSKBD_CTRL_B); + + zskbd_send(cs, dc->kbd_conf, 2); + + /* make sure we don't resend these each time */ + dc->kbd_conf[ZSKBD_CTRL_A] &= ~(ZSKBD_CTRL_A_RCB | ZSKBD_CTRL_A_SBEEP | + ZSKBD_CTRL_A_LBEEP); +} + +/****************************************************************************** + * wskbd glue + ******************************************************************************/ + +void +zskbd_wskbd_input(struct zs_chanstate *cs, uint8_t key) +{ + struct zskbd_softc *sc = cs->cs_private; + u_int type; +#ifdef WSDISPLAY_COMPAT_RAWKBD + int s; +#endif + + if (sc->sc_dc->wskbddev == NULL) + return; /* why bother */ + + if (key & ZSKBD_KEY_UP) { + if (key & ZSKBD_KEY_ALL_UP) + type = WSCONS_EVENT_ALL_KEYS_UP; + else + type = WSCONS_EVENT_KEY_UP; + } else + type = WSCONS_EVENT_KEY_DOWN; + + wskbd_input(sc->sc_dc->wskbddev, type, (key & ~ZSKBD_KEY_UP)); + + DPRINTF(("zskbd_wskbd_input: inputted key 0x%x\n", key)); + +#ifdef WSDISPLAY_COMPAT_RAWKBD + if (sc->sc_rawkbd && + type != WSCONS_EVENT_ALL_KEYS_UP) { + s = spltty(); + wskbd_rawinput(sc->sc_dc->wskbddev, &key, 1); + splx(s); + } +#endif +} + +int +zskbd_wskbd_enable(void *cookie, int on) +{ + struct zs_chanstate *cs = cookie; + struct zskbd_softc *sc = cs->cs_private; + + if (on) { + if (sc->sc_dc->enabled) + return (EBUSY); + else + sc->sc_dc->enabled = 1; + } else + sc->sc_dc->enabled = 0; + + DPRINTF(("zskbd_wskbd_enable: %s\n", on ? "enabled" : "disabled")); + + return (0); +} + +void +zskbd_wskbd_set_leds(void *cookie, int leds) +{ + struct zs_chanstate *cs = cookie; + int s; + uint8_t a_on, a_off, b_on, b_off; + + a_on = a_off = b_on = b_off = 0; + + if (leds & WSKBD_LED_CAPS) + a_on |= ZSKBD_CTRL_A_CAPSLK; + else + a_off |= ZSKBD_CTRL_A_CAPSLK; + + if (leds & WSKBD_LED_NUM) + a_on |= ZSKBD_CTRL_A_NUMLK; + else + a_off |= ZSKBD_CTRL_A_NUMLK; + + if (leds & WSKBD_LED_SCROLL) + b_on |= ZSKBD_CTRL_B_SCRLK; + else + b_off |= ZSKBD_CTRL_B_SCRLK; + + s = splzs(); + zskbd_ctrl(cs, a_on, a_off, b_on, b_off); + splx(s); +} + +int +zskbd_wskbd_get_leds(void *cookie) +{ + struct zs_chanstate *cs = cookie; + struct zskbd_softc *sc = cs->cs_private; + int leds; + + leds = 0; + + if (sc->sc_dc->kbd_conf[ZSKBD_CTRL_A] & ZSKBD_CTRL_A_NUMLK) + leds |= WSKBD_LED_NUM; + + if (sc->sc_dc->kbd_conf[ZSKBD_CTRL_A] & ZSKBD_CTRL_A_CAPSLK) + leds |= WSKBD_LED_CAPS; + + if (sc->sc_dc->kbd_conf[ZSKBD_CTRL_B] & ZSKBD_CTRL_B_SCRLK) + leds |= WSKBD_LED_SCROLL; + + return (leds); +} + +#if 0 +void +zskbd_wskbd_set_keyclick(void *cookie, int on) +{ + struct zs_chanstate *cs = cookie; + int s; + + if (on) { + if (!zskbd_wskbd_get_keyclick(cookie)) { + s = splzs(); + zskbd_ctrl(cs, 0, ZSKBD_CTRL_A_NOCLICK, 0, 0); + splx(s); + } + } else { + if (zskbd_wskbd_get_keyclick(cookie)) { + s = splzs(); + zskbd_ctrl(cs, ZSKBD_CTRL_A_NOCLICK, 0, 0, 0); + splx(s); + } + } +} + +int +zskbd_wskbd_get_keyclick(void *cookie) +{ + struct zs_chanstate *cs = cookie; + struct zskbd_softc *sc = cs->cs_private; + + if (sc->sc_dc->kbd_conf[ZSKBD_CTRL_A] & ZSKBD_CTRL_A_NOCLICK) + return (0); + else + return (1); +} +#endif + +int +zskbd_wskbd_ioctl(void *cookie, u_long cmd, caddr_t data, int flag, + struct proc *p) +{ + struct zs_chanstate *cs = cookie; +#ifdef WSDISPLAY_COMPAT_RAWKBD + struct zskbd_softc *sc = cs->cs_private; +#endif + + switch (cmd) { + case WSKBDIO_GTYPE: + *(int *)data = WSKBD_TYPE_SGI; + break; + case WSKBDIO_SETLEDS: + zskbd_wskbd_set_leds(cs, *(int *)data); + break; + case WSKBDIO_GETLEDS: + *(int *)data = zskbd_wskbd_get_leds(cs); + break; +#if 0 + case WSKBDIO_SETKEYCLICK: + zskbd_wskbd_set_keyclick(cs, *(int *)data); + break; + case WSKBDIO_GETKEYCLICK: + *(int *)data = zskbd_wskbd_get_keyclick(cs); + break; +#endif +#ifdef WSDISPLAY_COMPAT_RAWKBD + case WSKBDIO_SETMODE: + sc->sc_rawkbd = *(int *)data == WSKBD_RAW; + break; +#endif + default: + return -1; + } + + return 0; +} + +/* + * console routines + */ +void +zskbd_cnattach(int zsunit, int zschan) +{ + wskbd_cnattach(&zskbd_wskbd_consops, zs_get_chan_addr(zsunit, zschan), + &sgikbd_wskbd_keymapdata); + zskbd_is_console = 1; +} + +void +zskbd_wskbd_getc(void *cookie, u_int *type, int *data) +{ + int key; + + key = zs_getc(cookie); + + if (key & ZSKBD_KEY_UP) + *type = WSCONS_EVENT_KEY_UP; + else + *type = WSCONS_EVENT_KEY_DOWN; + + *data = key & ~ZSKBD_KEY_UP; +} + +void +zskbd_wskbd_pollc(void *cookie, int on) +{ +} + +void +zskbd_wskbd_bell(void *cookie, u_int pitch, u_int period, u_int volume) +{ + /* + * Since we don't have any state, this'll nuke our lights, + * key click, and other bits in ZSKBD_CTRL_A. + */ + if (period >= 1000) + zs_putc(cookie, ZSKBD_CTRL_A_LBEEP); + else + zs_putc(cookie, ZSKBD_CTRL_A_SBEEP); +} diff --git a/sys/arch/sgi/hpc/z8530ms.c b/sys/arch/sgi/hpc/z8530ms.c new file mode 100644 index 00000000000..4c6bdb43217 --- /dev/null +++ b/sys/arch/sgi/hpc/z8530ms.c @@ -0,0 +1,337 @@ +/* $OpenBSD: z8530ms.c,v 1.1 2012/04/17 22:06:33 miod Exp $ */ +/* $NetBSD: zs_ms.c,v 1.7 2008/03/29 19:15:35 tsutsui Exp $ */ + +/* + * Copyright (c) 2004 Steve Rumble + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR 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. + */ + +/* + * IP20 serial mouse driver attached to zs channel 1 at 4800bps. + * This layer feeds wsmouse. + * + * 5 byte packets: sync, x1, y1, x2, y2 + * sync format: binary 10000LMR (left, middle, right) 0 is down + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/conf.h> +#include <sys/device.h> + +#include <dev/wscons/wsconsio.h> +#include <dev/wscons/wsmousevar.h> + +#include <machine/autoconf.h> +#include <mips64/archtype.h> + +#include <dev/ic/z8530reg.h> +#include <machine/z8530var.h> + +#define ZSMS_BAUD 4800 +#define ZSMS_RXQ_LEN 64 /* power of 2 */ + +/* protocol */ +#define ZSMS_SYNC 0x80 +#define ZSMS_SYNC_MASK 0xf8 +#define ZSMS_SYNC_BTN_R 0x01 +#define ZSMS_SYNC_BTN_M 0x02 +#define ZSMS_SYNC_BTN_L 0x04 +#define ZSMS_SYNC_BTN_MASK 0x07 + +struct zsms_softc { + struct device sc_dev; + + /* tail-chasing fifo */ + uint8_t rxq[ZSMS_RXQ_LEN]; + uint8_t rxq_head; + uint8_t rxq_tail; + + /* 5-byte packet as described above */ +#define ZSMS_PACKET_SYNC 0 +#define ZSMS_PACKET_X1 1 +#define ZSMS_PACKET_Y1 2 +#define ZSMS_PACKET_X2 3 +#define ZSMS_PACKET_Y2 4 + int8_t packet[5]; + +#define ZSMS_STATE_SYNC 0x01 +#define ZSMS_STATE_X1 0x02 +#define ZSMS_STATE_Y1 0x04 +#define ZSMS_STATE_X2 0x08 +#define ZSMS_STATE_Y2 0x10 + uint8_t state; + + /* wsmouse bits */ + int enabled; + struct device *wsmousedev; +}; + +int zsms_match(struct device *, void *, void *); +void zsms_attach(struct device *, struct device *, void *); + +struct cfdriver zsms_cd = { + NULL, "zsms", DV_DULL +}; + +const struct cfattach zsms_ca = { + sizeof(struct zsms_softc), zsms_match, zsms_attach +}; + +void zsms_rxint(struct zs_chanstate *); +void zsms_txint(struct zs_chanstate *); +void zsms_stint(struct zs_chanstate *, int); +void zsms_softint(struct zs_chanstate *); + +void zsms_wsmouse_input(struct zsms_softc *); +int zsms_wsmouse_enable(void *); +void zsms_wsmouse_disable(void *); +int zsms_wsmouse_ioctl(void *, u_long, caddr_t, int, struct proc *); + +static struct zsops zsms_zsops = { + zsms_rxint, + zsms_stint, + zsms_txint, + zsms_softint +}; + +static const struct wsmouse_accessops zsms_wsmouse_accessops = { + zsms_wsmouse_enable, + zsms_wsmouse_ioctl, + zsms_wsmouse_disable +}; + +int +zsms_match(struct device *parent, void *vcf, void *aux) +{ + if (sys_config.system_type == SGI_IP20) { + struct zsc_attach_args *args = aux; + + if (args->channel == 1) + return (1); + } + + return (0); +} + +void +zsms_attach(struct device *parent, struct device *self, void *aux) +{ + struct zsc_softc *zsc = (struct zsc_softc *)parent; + struct zsms_softc *sc = (struct zsms_softc *)self; + struct zsc_attach_args *args = aux; + struct zs_chanstate *cs; + int s, channel; + struct wsmousedev_attach_args wsmaa; + + /* Establish ourself with the MD z8530 driver */ + channel = args->channel; + cs = zsc->zsc_cs[channel]; + cs->cs_ops = &zsms_zsops; + cs->cs_private = sc; + + sc->enabled = 0; + sc->rxq_head = 0; + sc->rxq_tail = 0; + sc->state = ZSMS_STATE_SYNC; + + printf("\n"); + + s = splzs(); + zs_write_reg(cs, 9, (channel == 0) ? ZSWR9_A_RESET : ZSWR9_B_RESET); + cs->cs_preg[1] = ZSWR1_RIE; + zs_set_speed(cs, ZSMS_BAUD); + zs_loadchannelregs(cs); + splx(s); + + /* attach wsmouse */ + wsmaa.accessops = &zsms_wsmouse_accessops; + wsmaa.accesscookie = sc; + sc->wsmousedev = config_found(self, &wsmaa, wsmousedevprint); +} + +void +zsms_rxint(struct zs_chanstate *cs) +{ + struct zsms_softc *sc = cs->cs_private; + uint8_t c, r; + + /* clear errors */ + r = zs_read_reg(cs, 1); + if (r & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) + zs_write_csr(cs, ZSWR0_RESET_ERRORS); + + /* read byte and append to our queue */ + c = zs_read_data(cs); + + sc->rxq[sc->rxq_tail] = c; + sc->rxq_tail = (sc->rxq_tail + 1) & ~ZSMS_RXQ_LEN; + + cs->cs_softreq = 1; +} + +/* We should never get here. */ +void +zsms_txint(struct zs_chanstate *cs) +{ + zs_write_reg(cs, 0, ZSWR0_RESET_TXINT); + + /* disable tx interrupts */ + CLR(cs->cs_preg[1], ZSWR1_TIE); + zs_loadchannelregs(cs); +} + +void +zsms_stint(struct zs_chanstate *cs, int force) +{ + zs_write_csr(cs, ZSWR0_RESET_STATUS); + cs->cs_softreq = 1; +} + +void +zsms_softint(struct zs_chanstate *cs) +{ + struct zsms_softc *sc = cs->cs_private; + + /* No need to keep score if nobody is listening */ + if (!sc->enabled) { + sc->rxq_head = sc->rxq_tail; + return; + } + + /* + * Here's the real action. Read a full packet and + * then let wsmouse know what has happened. + */ + while (sc->rxq_head != sc->rxq_tail) { + int8_t c = sc->rxq[sc->rxq_head]; + + switch (sc->state) { + case ZSMS_STATE_SYNC: + if ((c & ZSMS_SYNC_MASK) == ZSMS_SYNC) { + sc->packet[ZSMS_PACKET_SYNC] = c; + sc->state = ZSMS_STATE_X1; + } + break; + + case ZSMS_STATE_X1: + sc->packet[ZSMS_PACKET_X1] = c; + sc->state = ZSMS_STATE_Y1; + break; + + case ZSMS_STATE_Y1: + sc->packet[ZSMS_PACKET_Y1] = c; + sc->state = ZSMS_STATE_X2; + break; + + case ZSMS_STATE_X2: + sc->packet[ZSMS_PACKET_X2] = c; + sc->state = ZSMS_STATE_Y2; + break; + + case ZSMS_STATE_Y2: + sc->packet[ZSMS_PACKET_Y2] = c; + + /* tweak wsmouse */ + zsms_wsmouse_input(sc); + + sc->state = ZSMS_STATE_SYNC; + } + + sc->rxq_head = (sc->rxq_head + 1) & ~ZSMS_RXQ_LEN; + } +} + +/****************************************************************************** + * wsmouse glue + ******************************************************************************/ + +void +zsms_wsmouse_input(struct zsms_softc *sc) +{ + u_int btns; + int bl, bm, br; + int x, y; + + if (sc->wsmousedev == NULL) + return; + + btns = (uint8_t)sc->packet[ZSMS_PACKET_SYNC] & ZSMS_SYNC_BTN_MASK; + + bl = (btns & ZSMS_SYNC_BTN_L) == 0; + bm = (btns & ZSMS_SYNC_BTN_M) == 0; + br = (btns & ZSMS_SYNC_BTN_R) == 0; + + /* for wsmouse(4), 1 is down, 0 is up, the most left button is LSB */ + btns = 0; + if (bl) + btns |= 1 << 0; + if (bm) + btns |= 1 << 1; + if (br) + btns |= 1 << 2; + + x = (int)sc->packet[ZSMS_PACKET_X1] + (int)sc->packet[ZSMS_PACKET_X2]; + y = (int)sc->packet[ZSMS_PACKET_Y1] + (int)sc->packet[ZSMS_PACKET_Y2]; + + wsmouse_input(sc->wsmousedev, btns, x, y, 0, 0, WSMOUSE_INPUT_DELTA); +} + +int +zsms_wsmouse_enable(void *cookie) +{ + struct zsms_softc *sc = cookie; + + if (sc->enabled) + return (EBUSY); + + sc->state = ZSMS_STATE_SYNC; + sc->enabled = 1; + + return (0); +} + +void +zsms_wsmouse_disable(void *cookie) +{ + struct zsms_softc *sc = cookie; + + sc->enabled = 0; +} + +int +zsms_wsmouse_ioctl(void *cookie, u_long cmd, caddr_t data, int flag, + struct proc *p) +{ + switch (cmd) { + case WSMOUSEIO_GTYPE: + *(u_int *)data = WSMOUSE_TYPE_SGI; + break; + default: + return -1; + } + + return 0; +} |