1 1.14 tsutsui /* $NetBSD: ewskbd.c,v 1.14 2021/09/18 15:14:40 tsutsui Exp $ */ 2 1.9 tsutsui 3 1.9 tsutsui /*- 4 1.9 tsutsui * Copyright (c) 2005 Izumi Tsutsui. All rights reserved. 5 1.9 tsutsui * 6 1.9 tsutsui * Redistribution and use in source and binary forms, with or without 7 1.9 tsutsui * modification, are permitted provided that the following conditions 8 1.9 tsutsui * are met: 9 1.9 tsutsui * 1. Redistributions of source code must retain the above copyright 10 1.9 tsutsui * notice, this list of conditions and the following disclaimer. 11 1.9 tsutsui * 2. Redistributions in binary form must reproduce the above copyright 12 1.9 tsutsui * notice, this list of conditions and the following disclaimer in the 13 1.9 tsutsui * documentation and/or other materials provided with the distribution. 14 1.9 tsutsui * 15 1.9 tsutsui * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 1.9 tsutsui * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 1.9 tsutsui * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 1.9 tsutsui * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 1.9 tsutsui * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 1.9 tsutsui * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 1.9 tsutsui * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 1.9 tsutsui * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 1.9 tsutsui * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 1.9 tsutsui * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 1.9 tsutsui */ 26 1.1 tsutsui 27 1.1 tsutsui /* 28 1.1 tsutsui * Copyright (c) 2004 Steve Rumble 29 1.1 tsutsui * All rights reserved. 30 1.1 tsutsui * 31 1.1 tsutsui * Redistribution and use in source and binary forms, with or without 32 1.1 tsutsui * modification, are permitted provided that the following conditions 33 1.1 tsutsui * are met: 34 1.1 tsutsui * 1. Redistributions of source code must retain the above copyright 35 1.1 tsutsui * notice, this list of conditions and the following disclaimer. 36 1.1 tsutsui * 2. Redistributions in binary form must reproduce the above copyright 37 1.1 tsutsui * notice, this list of conditions and the following disclaimer in the 38 1.1 tsutsui * documentation and/or other materials provided with the distribution. 39 1.1 tsutsui * 3. The name of the author may not be used to endorse or promote products 40 1.1 tsutsui * derived from this software without specific prior written permission. 41 1.1 tsutsui * 42 1.1 tsutsui * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 43 1.1 tsutsui * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 44 1.1 tsutsui * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 45 1.1 tsutsui * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 46 1.1 tsutsui * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 47 1.1 tsutsui * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 48 1.1 tsutsui * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 49 1.1 tsutsui * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 50 1.1 tsutsui * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 51 1.1 tsutsui * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 52 1.1 tsutsui */ 53 1.1 tsutsui 54 1.1 tsutsui /* 55 1.1 tsutsui * EWS4800 serial keyboard driver attached to zs channel 0 at 4800 bps. 56 1.1 tsutsui * This layer is the parent of wskbd. 57 1.1 tsutsui * 58 1.1 tsutsui * This driver is taken from sgimips. 59 1.1 tsutsui */ 60 1.1 tsutsui 61 1.1 tsutsui #include <sys/cdefs.h> 62 1.14 tsutsui __KERNEL_RCSID(0, "$NetBSD: ewskbd.c,v 1.14 2021/09/18 15:14:40 tsutsui Exp $"); 63 1.1 tsutsui 64 1.1 tsutsui #include <sys/param.h> 65 1.11 thorpej #include <sys/kmem.h> 66 1.1 tsutsui #include <sys/systm.h> 67 1.1 tsutsui #include <sys/conf.h> 68 1.1 tsutsui #include <sys/device.h> 69 1.1 tsutsui 70 1.1 tsutsui #include <dev/wscons/wsconsio.h> 71 1.1 tsutsui #include <dev/wscons/wskbdvar.h> 72 1.1 tsutsui #include <dev/wscons/wsksymdef.h> 73 1.1 tsutsui #include <dev/wscons/wsksymvar.h> 74 1.1 tsutsui 75 1.1 tsutsui #include <dev/ic/z8530reg.h> 76 1.1 tsutsui #include <machine/z8530var.h> 77 1.1 tsutsui 78 1.1 tsutsui #include <ews4800mips/dev/ews4800keymap.h> 79 1.1 tsutsui 80 1.1 tsutsui #define EWSKBD_BAUD 4800 81 1.1 tsutsui 82 1.1 tsutsui #define EWSKBD_TXQ_LEN 16 /* power of 2 */ 83 1.1 tsutsui #define EWSKBD_TXQ_LEN_MASK (EWSKBD_TXQ_LEN - 1) 84 1.1 tsutsui #define EWSKBD_NEXTTXQ(x) (((x) + 1) & EWSKBD_TXQ_LEN_MASK) 85 1.1 tsutsui 86 1.1 tsutsui #define EWSKBD_RXQ_LEN 64 /* power of 2 */ 87 1.1 tsutsui #define EWSKBD_RXQ_LEN_MASK (EWSKBD_RXQ_LEN - 1) 88 1.1 tsutsui #define EWSKBD_NEXTRXQ(x) (((x) + 1) & EWSKBD_RXQ_LEN_MASK) 89 1.1 tsutsui 90 1.1 tsutsui #define EWSKBD_KEY_UP 0x80 91 1.1 tsutsui #define EWSKBD_KEY_MASK 0x7f 92 1.1 tsutsui 93 1.1 tsutsui #ifdef EWSKBD_DEBUG 94 1.1 tsutsui int ewskbd_debug = 0; 95 1.1 tsutsui #define DPRINTF(_x) if (ewskbd_debug) printf _x 96 1.1 tsutsui #else 97 1.1 tsutsui #define DPRINTF(_x) 98 1.1 tsutsui #endif 99 1.1 tsutsui 100 1.1 tsutsui struct ewskbd_softc { 101 1.7 tsutsui device_t sc_dev; 102 1.1 tsutsui struct ewskbd_devconfig *sc_dc; 103 1.1 tsutsui }; 104 1.1 tsutsui 105 1.1 tsutsui struct ewskbd_devconfig { 106 1.1 tsutsui /* transmit tail-chasing fifo */ 107 1.1 tsutsui uint8_t txq[EWSKBD_TXQ_LEN]; 108 1.1 tsutsui u_int txq_head; 109 1.1 tsutsui u_int txq_tail; 110 1.1 tsutsui 111 1.1 tsutsui /* receive tail-chasing fifo */ 112 1.1 tsutsui uint8_t rxq[EWSKBD_RXQ_LEN]; 113 1.1 tsutsui u_int rxq_head; 114 1.1 tsutsui u_int rxq_tail; 115 1.1 tsutsui 116 1.1 tsutsui /* state */ 117 1.1 tsutsui u_int state; 118 1.1 tsutsui #define TX_READY 0x01 119 1.1 tsutsui 120 1.1 tsutsui /* LED status */ 121 1.1 tsutsui uint8_t leds; 122 1.1 tsutsui #define EWSKBD_SETLEDS 0x90 123 1.1 tsutsui #define EWSKBD_CAPSLOCK 0x02 124 1.1 tsutsui #define EWSKBD_KANA 0x04 125 1.1 tsutsui 126 1.1 tsutsui /* wscons glue */ 127 1.10 tsutsui device_t wskbddev; 128 1.1 tsutsui int enabled; 129 1.1 tsutsui }; 130 1.1 tsutsui 131 1.7 tsutsui static int ewskbd_zsc_match(device_t, cfdata_t, void *); 132 1.7 tsutsui static void ewskbd_zsc_attach(device_t, device_t, void *); 133 1.1 tsutsui static int ewskbd_zsc_init(struct zs_chanstate *); 134 1.1 tsutsui static void ewskbd_zsc_rxint(struct zs_chanstate *); 135 1.1 tsutsui static void ewskbd_zsc_stint(struct zs_chanstate *, int); 136 1.1 tsutsui static void ewskbd_zsc_txint(struct zs_chanstate *); 137 1.1 tsutsui static void ewskbd_zsc_softint(struct zs_chanstate *); 138 1.1 tsutsui static void ewskbd_zsc_send(struct zs_chanstate *, uint8_t *, u_int); 139 1.1 tsutsui 140 1.1 tsutsui static void ewskbd_wskbd_input(struct zs_chanstate *, u_char); 141 1.1 tsutsui static int ewskbd_wskbd_enable(void *, int); 142 1.1 tsutsui static void ewskbd_wskbd_set_leds(void *, int); 143 1.1 tsutsui static int ewskbd_wskbd_get_leds(void *); 144 1.4 christos static int ewskbd_wskbd_ioctl(void *, u_long, void *, int, struct lwp *); 145 1.1 tsutsui 146 1.1 tsutsui void ewskbd_zsc_cnattach(uint32_t, uint32_t, int); 147 1.1 tsutsui static void ewskbd_zsc_wskbd_getc(void *, u_int *, int *); 148 1.1 tsutsui static void ewskbd_wskbd_pollc(void *, int); 149 1.1 tsutsui static void ewskbd_wskbd_bell(void *, u_int, u_int, u_int); 150 1.1 tsutsui 151 1.7 tsutsui CFATTACH_DECL_NEW(ewskbd_zsc, sizeof(struct ewskbd_softc), 152 1.1 tsutsui ewskbd_zsc_match, ewskbd_zsc_attach, NULL, NULL); 153 1.1 tsutsui 154 1.1 tsutsui static struct zsops ewskbd_zsops = { 155 1.1 tsutsui ewskbd_zsc_rxint, 156 1.1 tsutsui ewskbd_zsc_stint, 157 1.1 tsutsui ewskbd_zsc_txint, 158 1.1 tsutsui ewskbd_zsc_softint 159 1.1 tsutsui }; 160 1.1 tsutsui 161 1.1 tsutsui const struct wskbd_mapdata ews4800kbd_wskbd_keymapdata = { 162 1.1 tsutsui ews4800kbd_keydesctab, 163 1.1 tsutsui KB_JP 164 1.1 tsutsui }; 165 1.1 tsutsui 166 1.1 tsutsui const struct wskbd_accessops ewskbd_wskbd_accessops = { 167 1.1 tsutsui ewskbd_wskbd_enable, 168 1.1 tsutsui ewskbd_wskbd_set_leds, 169 1.1 tsutsui ewskbd_wskbd_ioctl 170 1.1 tsutsui }; 171 1.1 tsutsui 172 1.1 tsutsui const struct wskbd_consops ewskbd_wskbd_consops = { 173 1.1 tsutsui ewskbd_zsc_wskbd_getc, 174 1.1 tsutsui ewskbd_wskbd_pollc, 175 1.1 tsutsui ewskbd_wskbd_bell 176 1.1 tsutsui }; 177 1.1 tsutsui 178 1.1 tsutsui static struct ewskbd_devconfig ewskbd_console_dc; 179 1.1 tsutsui static struct zs_chanstate conschan; 180 1.1 tsutsui static int ewskbd_is_console; 181 1.1 tsutsui 182 1.1 tsutsui static int 183 1.7 tsutsui ewskbd_zsc_match(device_t parent, cfdata_t cf, void *aux) 184 1.1 tsutsui { 185 1.1 tsutsui struct zsc_attach_args *zsc_args = aux; 186 1.8 tsutsui struct zsc_softc *zsc = device_private(parent); 187 1.1 tsutsui 188 1.1 tsutsui /* keyboard is on channel B */ 189 1.1 tsutsui if ((zsc->zsc_flags & 0x0001 /* kbms port */) != 0 && 190 1.1 tsutsui zsc_args->channel == 1) 191 1.1 tsutsui /* prior to generic zstty(4) */ 192 1.1 tsutsui return 3; 193 1.1 tsutsui 194 1.1 tsutsui return 0; 195 1.1 tsutsui } 196 1.1 tsutsui 197 1.1 tsutsui static void 198 1.10 tsutsui ewskbd_zsc_attach(device_t parent, device_t self, void *aux) 199 1.1 tsutsui { 200 1.1 tsutsui struct ewskbd_softc *sc; 201 1.7 tsutsui struct zsc_softc *zsc; 202 1.1 tsutsui struct zs_chanstate *cs; 203 1.1 tsutsui struct zsc_attach_args *zsc_args; 204 1.1 tsutsui struct wskbddev_attach_args wskaa; 205 1.1 tsutsui int channel; 206 1.1 tsutsui 207 1.7 tsutsui sc = device_private(self); 208 1.8 tsutsui zsc = device_private(parent); 209 1.7 tsutsui sc->sc_dev = self; 210 1.1 tsutsui zsc_args = aux; 211 1.1 tsutsui 212 1.1 tsutsui /* Establish ourself with the MD z8530 driver */ 213 1.1 tsutsui channel = zsc_args->channel; 214 1.1 tsutsui cs = zsc->zsc_cs[channel]; 215 1.1 tsutsui 216 1.1 tsutsui if (ewskbd_is_console) { 217 1.1 tsutsui sc->sc_dc = &ewskbd_console_dc; 218 1.1 tsutsui wskaa.console = 1; 219 1.1 tsutsui sc->sc_dc->enabled = 1; 220 1.1 tsutsui } else { 221 1.1 tsutsui wskaa.console = 0; 222 1.1 tsutsui 223 1.11 thorpej sc->sc_dc = kmem_zalloc(sizeof(struct ewskbd_devconfig), 224 1.11 thorpej KM_SLEEP); 225 1.1 tsutsui if (sc->sc_dc == NULL) { 226 1.1 tsutsui printf(": can't allocate memory\n"); 227 1.1 tsutsui return; 228 1.1 tsutsui } 229 1.1 tsutsui sc->sc_dc->enabled = 0; 230 1.1 tsutsui } 231 1.1 tsutsui cs->cs_defspeed = EWSKBD_BAUD; 232 1.1 tsutsui cs->cs_ops = &ewskbd_zsops; 233 1.1 tsutsui cs->cs_private = sc; 234 1.1 tsutsui 235 1.1 tsutsui sc->sc_dc->txq_head = 0; 236 1.1 tsutsui sc->sc_dc->txq_tail = 0; 237 1.1 tsutsui sc->sc_dc->rxq_head = 0; 238 1.1 tsutsui sc->sc_dc->rxq_tail = 0; 239 1.1 tsutsui sc->sc_dc->state = TX_READY; 240 1.1 tsutsui sc->sc_dc->leds = 0; 241 1.1 tsutsui 242 1.1 tsutsui ewskbd_zsc_init(cs); 243 1.1 tsutsui 244 1.1 tsutsui /* set default LED */ 245 1.1 tsutsui ewskbd_wskbd_set_leds(cs, 0); 246 1.1 tsutsui 247 1.1 tsutsui printf(": baud rate %d\n", EWSKBD_BAUD); 248 1.1 tsutsui 249 1.1 tsutsui /* attach wskbd */ 250 1.1 tsutsui wskaa.keymap = &ews4800kbd_wskbd_keymapdata; 251 1.1 tsutsui wskaa.accessops = &ewskbd_wskbd_accessops; 252 1.1 tsutsui wskaa.accesscookie = cs; 253 1.12 thorpej sc->sc_dc->wskbddev = config_found(self, &wskaa, wskbddevprint, 254 1.13 thorpej CFARGS_NONE); 255 1.1 tsutsui } 256 1.1 tsutsui 257 1.1 tsutsui static int 258 1.1 tsutsui ewskbd_zsc_init(struct zs_chanstate *cs) 259 1.1 tsutsui { 260 1.1 tsutsui int s; 261 1.1 tsutsui 262 1.1 tsutsui s = splzs(); 263 1.1 tsutsui 264 1.1 tsutsui zs_write_reg(cs, 9, ZSWR9_B_RESET); 265 1.1 tsutsui DELAY(100); 266 1.1 tsutsui zs_write_reg(cs, 9, ZSWR9_MASTER_IE | ZSWR9_NO_VECTOR); 267 1.1 tsutsui 268 1.1 tsutsui cs->cs_preg[1] = ZSWR1_RIE | ZSWR1_TIE; 269 1.1 tsutsui cs->cs_preg[2] = 0; 270 1.1 tsutsui cs->cs_preg[3] = ZSWR3_RX_8 | ZSWR3_RX_ENABLE; 271 1.1 tsutsui cs->cs_preg[4] = ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_PARENB; 272 1.1 tsutsui cs->cs_preg[5] = ZSWR5_TX_8 | ZSWR5_RTS | ZSWR5_TX_ENABLE; 273 1.1 tsutsui cs->cs_preg[6] = 0; 274 1.1 tsutsui cs->cs_preg[7] = 0; 275 1.1 tsutsui cs->cs_preg[8] = 0; 276 1.1 tsutsui cs->cs_preg[9] = ZSWR9_MASTER_IE | ZSWR9_NO_VECTOR; 277 1.1 tsutsui cs->cs_preg[10] = 0; 278 1.1 tsutsui cs->cs_preg[11] = ZSWR11_RXCLK_BAUD | ZSWR11_TXCLK_BAUD | 279 1.1 tsutsui ZSWR11_TRXC_OUT_ENA | ZSWR11_TRXC_BAUD; 280 1.1 tsutsui /* reg[11] and reg[12] are set by zs_set_speed() with cs_brg_clk */ 281 1.1 tsutsui zs_set_speed(cs, EWSKBD_BAUD); 282 1.1 tsutsui cs->cs_preg[14] = ZSWR14_BAUD_FROM_PCLK | ZSWR14_BAUD_ENA; 283 1.1 tsutsui cs->cs_preg[15] = 0; 284 1.1 tsutsui 285 1.1 tsutsui zs_loadchannelregs(cs); 286 1.1 tsutsui 287 1.1 tsutsui splx(s); 288 1.1 tsutsui 289 1.1 tsutsui return 0; 290 1.1 tsutsui } 291 1.1 tsutsui 292 1.1 tsutsui static void 293 1.1 tsutsui ewskbd_zsc_rxint(struct zs_chanstate *cs) 294 1.1 tsutsui { 295 1.1 tsutsui struct ewskbd_softc *sc; 296 1.1 tsutsui struct ewskbd_devconfig *dc; 297 1.1 tsutsui uint8_t c, r; 298 1.1 tsutsui 299 1.1 tsutsui sc = cs->cs_private; 300 1.1 tsutsui dc = sc->sc_dc; 301 1.1 tsutsui 302 1.1 tsutsui /* clear errors */ 303 1.1 tsutsui r = zs_read_reg(cs, 1); 304 1.1 tsutsui if (r & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) 305 1.1 tsutsui zs_write_csr(cs, ZSWR0_RESET_ERRORS); 306 1.1 tsutsui 307 1.1 tsutsui /* read byte and append to our queue */ 308 1.1 tsutsui c = zs_read_data(cs); 309 1.1 tsutsui 310 1.1 tsutsui dc->rxq[dc->rxq_tail] = c; 311 1.1 tsutsui dc->rxq_tail = EWSKBD_NEXTRXQ(dc->rxq_tail); 312 1.1 tsutsui 313 1.1 tsutsui cs->cs_softreq = 1; 314 1.1 tsutsui } 315 1.1 tsutsui 316 1.1 tsutsui static void 317 1.1 tsutsui ewskbd_zsc_stint(struct zs_chanstate *cs, int force) 318 1.1 tsutsui { 319 1.1 tsutsui 320 1.1 tsutsui zs_write_csr(cs, ZSWR0_RESET_STATUS); 321 1.1 tsutsui cs->cs_softreq = 1; 322 1.1 tsutsui } 323 1.1 tsutsui 324 1.1 tsutsui static void 325 1.1 tsutsui ewskbd_zsc_txint(struct zs_chanstate *cs) 326 1.1 tsutsui { 327 1.1 tsutsui struct ewskbd_softc *sc; 328 1.1 tsutsui 329 1.1 tsutsui sc = cs->cs_private; 330 1.1 tsutsui zs_write_reg(cs, 0, ZSWR0_RESET_TXINT); 331 1.1 tsutsui sc->sc_dc->state |= TX_READY; 332 1.1 tsutsui cs->cs_softreq = 1; 333 1.1 tsutsui } 334 1.1 tsutsui 335 1.1 tsutsui static void 336 1.1 tsutsui ewskbd_zsc_softint(struct zs_chanstate *cs) 337 1.1 tsutsui { 338 1.1 tsutsui struct ewskbd_softc *sc; 339 1.1 tsutsui struct ewskbd_devconfig *dc; 340 1.1 tsutsui 341 1.1 tsutsui sc = cs->cs_private; 342 1.1 tsutsui dc = sc->sc_dc; 343 1.1 tsutsui 344 1.1 tsutsui /* handle pending transmissions */ 345 1.1 tsutsui if (dc->txq_head != dc->txq_tail && (dc->state & TX_READY)) { 346 1.1 tsutsui int s; 347 1.1 tsutsui 348 1.1 tsutsui dc->state &= ~TX_READY; 349 1.1 tsutsui 350 1.1 tsutsui s = splzs(); 351 1.1 tsutsui zs_write_data(cs, dc->txq[dc->txq_head]); 352 1.1 tsutsui splx(s); 353 1.1 tsutsui 354 1.1 tsutsui dc->txq_head = EWSKBD_NEXTTXQ(dc->txq_head); 355 1.1 tsutsui } 356 1.1 tsutsui 357 1.1 tsutsui /* don't bother if nobody is listening */ 358 1.1 tsutsui if (!dc->enabled) { 359 1.1 tsutsui dc->rxq_head = dc->rxq_tail; 360 1.1 tsutsui return; 361 1.1 tsutsui } 362 1.1 tsutsui 363 1.1 tsutsui /* handle incoming keystrokes/config */ 364 1.1 tsutsui while (dc->rxq_head != dc->rxq_tail) { 365 1.1 tsutsui uint8_t key = dc->rxq[dc->rxq_head]; 366 1.1 tsutsui 367 1.1 tsutsui /* toss wskbd a bone */ 368 1.1 tsutsui ewskbd_wskbd_input(cs, key); 369 1.1 tsutsui 370 1.1 tsutsui dc->rxq_head = EWSKBD_NEXTRXQ(dc->rxq_head); 371 1.1 tsutsui } 372 1.1 tsutsui } 373 1.1 tsutsui 374 1.1 tsutsui /* expects to be in splzs() */ 375 1.1 tsutsui static void 376 1.1 tsutsui ewskbd_zsc_send(struct zs_chanstate *cs, uint8_t *c, u_int len) 377 1.1 tsutsui { 378 1.1 tsutsui struct ewskbd_softc *sc; 379 1.1 tsutsui struct ewskbd_devconfig *dc; 380 1.1 tsutsui int i; 381 1.1 tsutsui 382 1.1 tsutsui sc = cs->cs_private; 383 1.1 tsutsui dc = sc->sc_dc; 384 1.1 tsutsui 385 1.1 tsutsui for (i = 0; i < len; i++) { 386 1.1 tsutsui if (dc->state & TX_READY) { 387 1.1 tsutsui zs_write_data(cs, c[i]); 388 1.1 tsutsui dc->state &= ~TX_READY; 389 1.1 tsutsui } else { 390 1.1 tsutsui dc->txq[dc->txq_tail] = c[i]; 391 1.1 tsutsui dc->txq_tail = EWSKBD_NEXTTXQ(dc->txq_tail); 392 1.1 tsutsui cs->cs_softreq = 1; 393 1.1 tsutsui } 394 1.1 tsutsui } 395 1.1 tsutsui } 396 1.1 tsutsui 397 1.1 tsutsui /****************************************************************************** 398 1.1 tsutsui * wskbd glue 399 1.1 tsutsui ******************************************************************************/ 400 1.1 tsutsui 401 1.1 tsutsui static void 402 1.1 tsutsui ewskbd_wskbd_input(struct zs_chanstate *cs, uint8_t key) 403 1.1 tsutsui { 404 1.1 tsutsui struct ewskbd_softc *sc; 405 1.1 tsutsui u_int type; 406 1.1 tsutsui 407 1.1 tsutsui sc = cs->cs_private; 408 1.1 tsutsui 409 1.1 tsutsui if (key & EWSKBD_KEY_UP) 410 1.1 tsutsui type = WSCONS_EVENT_KEY_UP; 411 1.1 tsutsui else 412 1.1 tsutsui type = WSCONS_EVENT_KEY_DOWN; 413 1.1 tsutsui 414 1.1 tsutsui wskbd_input(sc->sc_dc->wskbddev, type, (key & EWSKBD_KEY_MASK)); 415 1.1 tsutsui 416 1.1 tsutsui DPRINTF(("ewskbd_wskbd_input: inputted key 0x%x\n", key)); 417 1.1 tsutsui 418 1.1 tsutsui #ifdef WSDISPLAY_COMPAT_RAWKBD 419 1.1 tsutsui wskbd_rawinput(sc->sc_dc->wskbddev, &key, 1); 420 1.1 tsutsui #endif 421 1.1 tsutsui } 422 1.1 tsutsui 423 1.1 tsutsui static int 424 1.1 tsutsui ewskbd_wskbd_enable(void *cookie, int on) 425 1.1 tsutsui { 426 1.1 tsutsui struct zs_chanstate *cs; 427 1.1 tsutsui struct ewskbd_softc *sc; 428 1.1 tsutsui 429 1.1 tsutsui cs = cookie; 430 1.1 tsutsui sc = cs->cs_private; 431 1.1 tsutsui 432 1.1 tsutsui if (on) { 433 1.1 tsutsui if (sc->sc_dc->enabled) 434 1.1 tsutsui return EBUSY; 435 1.1 tsutsui else 436 1.1 tsutsui sc->sc_dc->enabled = 1; 437 1.1 tsutsui } else 438 1.1 tsutsui sc->sc_dc->enabled = 0; 439 1.1 tsutsui 440 1.1 tsutsui DPRINTF(("ewskbd_wskbd_enable: %s\n", on ? "enabled" : "disabled")); 441 1.1 tsutsui 442 1.1 tsutsui return 0; 443 1.1 tsutsui } 444 1.1 tsutsui 445 1.1 tsutsui static void 446 1.1 tsutsui ewskbd_wskbd_set_leds(void *cookie, int leds) 447 1.1 tsutsui { 448 1.1 tsutsui struct zs_chanstate *cs; 449 1.1 tsutsui struct ewskbd_softc *sc; 450 1.1 tsutsui int s; 451 1.1 tsutsui uint8_t cmd; 452 1.1 tsutsui 453 1.1 tsutsui cs = cookie; 454 1.1 tsutsui sc = cs->cs_private; 455 1.1 tsutsui cmd = 0; 456 1.1 tsutsui 457 1.1 tsutsui if (leds & WSKBD_LED_CAPS) 458 1.1 tsutsui cmd |= EWSKBD_CAPSLOCK; 459 1.1 tsutsui 460 1.1 tsutsui sc->sc_dc->leds = cmd; 461 1.1 tsutsui 462 1.1 tsutsui cmd |= EWSKBD_SETLEDS; 463 1.1 tsutsui 464 1.1 tsutsui s = splzs(); 465 1.1 tsutsui ewskbd_zsc_send(cs, &cmd, 1); 466 1.1 tsutsui splx(s); 467 1.1 tsutsui } 468 1.1 tsutsui 469 1.1 tsutsui static int 470 1.1 tsutsui ewskbd_wskbd_get_leds(void *cookie) 471 1.1 tsutsui { 472 1.1 tsutsui struct zs_chanstate *cs; 473 1.1 tsutsui struct ewskbd_softc *sc; 474 1.1 tsutsui int leds; 475 1.1 tsutsui 476 1.1 tsutsui cs = cookie; 477 1.1 tsutsui sc = cs->cs_private; 478 1.1 tsutsui leds = 0; 479 1.1 tsutsui 480 1.1 tsutsui if (sc->sc_dc->leds & EWSKBD_CAPSLOCK) 481 1.1 tsutsui leds |= WSKBD_LED_CAPS; 482 1.1 tsutsui 483 1.1 tsutsui return leds; 484 1.1 tsutsui } 485 1.1 tsutsui 486 1.1 tsutsui static int 487 1.4 christos ewskbd_wskbd_ioctl(void *cookie, u_long cmd, void *data, int flag, 488 1.1 tsutsui struct lwp *l) 489 1.1 tsutsui { 490 1.1 tsutsui 491 1.1 tsutsui switch (cmd) { 492 1.1 tsutsui case WSKBDIO_GTYPE: 493 1.1 tsutsui *(int *)data = WSKBD_TYPE_EWS4800; 494 1.1 tsutsui break; 495 1.1 tsutsui 496 1.1 tsutsui #ifdef notyet 497 1.1 tsutsui case WSKBDIO_COMPLEXBELL: 498 1.1 tsutsui case WSKBDIO_SETKEYREPEAT: 499 1.1 tsutsui case WSKBDIO_GETKEYREPEAT: 500 1.1 tsutsui case WSKBDIO_SETDEFAULTKEYREPEAT: 501 1.1 tsutsui case WSKBDIO_GETDEFAULTKEYREPEAT: 502 1.1 tsutsui #endif 503 1.1 tsutsui 504 1.1 tsutsui case WSKBDIO_SETLEDS: 505 1.1 tsutsui ewskbd_wskbd_set_leds(cookie, *(int *)data); 506 1.1 tsutsui break; 507 1.1 tsutsui 508 1.1 tsutsui case WSKBDIO_GETLEDS: 509 1.1 tsutsui *(int *)data = ewskbd_wskbd_get_leds(cookie); 510 1.1 tsutsui break; 511 1.1 tsutsui 512 1.1 tsutsui #ifdef notyet 513 1.1 tsutsui case WSKBDIO_GETMAP: 514 1.1 tsutsui case WSKBDIO_SETMAP: 515 1.1 tsutsui case WSKBDIO_GETENCODING: 516 1.1 tsutsui case WSKBDIO_SETENCODING: 517 1.1 tsutsui case WSKBDIO_SETMODE: 518 1.1 tsutsui case WSKBDIO_GETMODE: 519 1.1 tsutsui case WSKBDIO_SETKEYCLICK: 520 1.1 tsutsui case WSKBDIO_GETKEYCLICK: 521 1.1 tsutsui #endif 522 1.1 tsutsui 523 1.1 tsutsui default: 524 1.1 tsutsui return EPASSTHROUGH; 525 1.1 tsutsui } 526 1.1 tsutsui 527 1.1 tsutsui return 0; 528 1.1 tsutsui } 529 1.1 tsutsui 530 1.1 tsutsui /* 531 1.1 tsutsui * console routines 532 1.1 tsutsui */ 533 1.1 tsutsui void 534 1.1 tsutsui ewskbd_zsc_cnattach(uint32_t csr, uint32_t data, int pclk) 535 1.1 tsutsui { 536 1.1 tsutsui struct zs_chanstate *cs; 537 1.1 tsutsui 538 1.1 tsutsui cs = &conschan; 539 1.1 tsutsui 540 1.1 tsutsui cs->cs_reg_csr = (void *)csr; 541 1.1 tsutsui cs->cs_reg_data = (void *)data; 542 1.1 tsutsui cs->cs_brg_clk = pclk / 16; 543 1.1 tsutsui cs->cs_defspeed = EWSKBD_BAUD; 544 1.1 tsutsui 545 1.1 tsutsui ewskbd_zsc_init(cs); 546 1.1 tsutsui 547 1.1 tsutsui zs_putc(cs, EWSKBD_SETLEDS); 548 1.1 tsutsui 549 1.1 tsutsui wskbd_cnattach(&ewskbd_wskbd_consops, cs, &ews4800kbd_wskbd_keymapdata); 550 1.1 tsutsui ewskbd_is_console = 1; 551 1.1 tsutsui } 552 1.1 tsutsui 553 1.1 tsutsui static void 554 1.1 tsutsui ewskbd_zsc_wskbd_getc(void *cookie, u_int *type, int *data) 555 1.1 tsutsui { 556 1.1 tsutsui int key; 557 1.1 tsutsui 558 1.1 tsutsui key = zs_getc(cookie); 559 1.1 tsutsui 560 1.1 tsutsui if (key & EWSKBD_KEY_UP) 561 1.1 tsutsui *type = WSCONS_EVENT_KEY_UP; 562 1.1 tsutsui else 563 1.1 tsutsui *type = WSCONS_EVENT_KEY_DOWN; 564 1.1 tsutsui 565 1.1 tsutsui *data = key & EWSKBD_KEY_MASK; 566 1.1 tsutsui } 567 1.1 tsutsui 568 1.1 tsutsui static void 569 1.1 tsutsui ewskbd_wskbd_pollc(void *cookie, int on) 570 1.1 tsutsui { 571 1.1 tsutsui 572 1.3 thorpej static bool __polling = false; 573 1.1 tsutsui static int s; 574 1.1 tsutsui 575 1.1 tsutsui if (on && !__polling) { 576 1.1 tsutsui /* disable interrupt driven I/O */ 577 1.1 tsutsui s = splhigh(); 578 1.5 tsutsui __polling = true; 579 1.1 tsutsui } else if (!on && __polling) { 580 1.1 tsutsui /* enable interrupt driven I/O */ 581 1.3 thorpej __polling = false; 582 1.1 tsutsui splx(s); 583 1.1 tsutsui } 584 1.1 tsutsui } 585 1.1 tsutsui 586 1.1 tsutsui static void 587 1.1 tsutsui ewskbd_wskbd_bell(void *cookie, u_int pitch, u_int period, u_int volume) 588 1.1 tsutsui { 589 1.1 tsutsui 590 1.1 tsutsui /* nothing */ 591 1.1 tsutsui } 592