1 1.32 riastrad /* $NetBSD: sunkbd.c,v 1.32 2022/10/26 23:47:55 riastradh Exp $ */ 2 1.1 eeh 3 1.1 eeh /* 4 1.1 eeh * Copyright (c) 1992, 1993 5 1.1 eeh * The Regents of the University of California. All rights reserved. 6 1.1 eeh * 7 1.1 eeh * This software was developed by the Computer Systems Engineering group 8 1.1 eeh * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 9 1.1 eeh * contributed to Berkeley. 10 1.1 eeh * 11 1.1 eeh * All advertising materials mentioning features or use of this software 12 1.1 eeh * must display the following acknowledgement: 13 1.1 eeh * This product includes software developed by the University of 14 1.1 eeh * California, Lawrence Berkeley Laboratory. 15 1.1 eeh * 16 1.1 eeh * Redistribution and use in source and binary forms, with or without 17 1.1 eeh * modification, are permitted provided that the following conditions 18 1.1 eeh * are met: 19 1.1 eeh * 1. Redistributions of source code must retain the above copyright 20 1.1 eeh * notice, this list of conditions and the following disclaimer. 21 1.1 eeh * 2. Redistributions in binary form must reproduce the above copyright 22 1.1 eeh * notice, this list of conditions and the following disclaimer in the 23 1.1 eeh * documentation and/or other materials provided with the distribution. 24 1.19 agc * 3. Neither the name of the University nor the names of its contributors 25 1.1 eeh * may be used to endorse or promote products derived from this software 26 1.1 eeh * without specific prior written permission. 27 1.1 eeh * 28 1.1 eeh * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 1.1 eeh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 1.1 eeh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 1.1 eeh * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 1.1 eeh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 1.1 eeh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 1.1 eeh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 1.1 eeh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 1.1 eeh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 1.1 eeh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 1.1 eeh * SUCH DAMAGE. 39 1.1 eeh * 40 1.1 eeh * @(#)kbd.c 8.2 (Berkeley) 10/30/93 41 1.1 eeh */ 42 1.1 eeh 43 1.1 eeh /* 44 1.13 uwe * /dev/kbd lower layer for sun keyboard off a tty (line discipline). 45 1.13 uwe * This driver uses kbdsun middle layer to hook up to /dev/kbd. 46 1.1 eeh */ 47 1.1 eeh 48 1.1 eeh /* 49 1.1 eeh * Keyboard interface line discipline. 50 1.1 eeh * 51 1.1 eeh */ 52 1.7 lukem 53 1.7 lukem #include <sys/cdefs.h> 54 1.32 riastrad __KERNEL_RCSID(0, "$NetBSD: sunkbd.c,v 1.32 2022/10/26 23:47:55 riastradh Exp $"); 55 1.1 eeh 56 1.1 eeh #include <sys/param.h> 57 1.1 eeh #include <sys/systm.h> 58 1.1 eeh #include <sys/conf.h> 59 1.1 eeh #include <sys/device.h> 60 1.1 eeh #include <sys/kernel.h> 61 1.1 eeh #include <sys/proc.h> 62 1.1 eeh #include <sys/signal.h> 63 1.1 eeh #include <sys/signalvar.h> 64 1.1 eeh #include <sys/time.h> 65 1.1 eeh #include <sys/select.h> 66 1.1 eeh #include <sys/syslog.h> 67 1.1 eeh #include <sys/fcntl.h> 68 1.1 eeh #include <sys/tty.h> 69 1.1 eeh 70 1.1 eeh #include <dev/cons.h> 71 1.1 eeh #include <machine/vuid_event.h> 72 1.1 eeh #include <machine/kbd.h> 73 1.1 eeh #include <dev/sun/event_var.h> 74 1.1 eeh #include <dev/sun/kbd_xlate.h> 75 1.1 eeh #include <dev/sun/kbdvar.h> 76 1.13 uwe #include <dev/sun/kbdsunvar.h> 77 1.1 eeh #include <dev/sun/kbd_ms_ttyvar.h> 78 1.1 eeh 79 1.1 eeh /**************************************************************** 80 1.1 eeh * Interface to the lower layer (ttycc) 81 1.1 eeh ****************************************************************/ 82 1.1 eeh 83 1.27 tsutsui static int sunkbd_match(device_t, cfdata_t, void *); 84 1.27 tsutsui static void sunkbd_attach(device_t, device_t, void *); 85 1.13 uwe static void sunkbd_write_data(struct kbd_sun_softc *, int); 86 1.27 tsutsui static int sunkbdiopen(device_t, int mode); 87 1.1 eeh 88 1.15 martin #if NWSKBD > 0 89 1.15 martin void kbd_wskbd_attach(struct kbd_softc *k, int isconsole); 90 1.15 martin #endif 91 1.15 martin 92 1.1 eeh int sunkbdinput(int, struct tty *); 93 1.1 eeh int sunkbdstart(struct tty *); 94 1.1 eeh 95 1.8 pk /* Default keyboard baud rate */ 96 1.8 pk int sunkbd_bps = KBD_DEFAULT_BPS; 97 1.1 eeh 98 1.27 tsutsui CFATTACH_DECL_NEW(kbd_tty, sizeof(struct kbd_sun_softc), 99 1.12 thorpej sunkbd_match, sunkbd_attach, NULL, NULL); 100 1.1 eeh 101 1.22 thorpej struct linesw sunkbd_disc = { 102 1.22 thorpej .l_name = "sunkbd", 103 1.22 thorpej .l_open = ttylopen, 104 1.22 thorpej .l_close = ttylclose, 105 1.22 thorpej .l_read = ttyerrio, 106 1.22 thorpej .l_write = ttyerrio, 107 1.22 thorpej .l_ioctl = ttynullioctl, 108 1.22 thorpej .l_rint = sunkbdinput, 109 1.22 thorpej .l_start = sunkbdstart, 110 1.22 thorpej .l_modem = nullmodem, 111 1.22 thorpej .l_poll = ttpoll 112 1.22 thorpej }; 113 1.3 eeh 114 1.15 martin 115 1.1 eeh /* 116 1.1 eeh * sunkbd_match: how is this tty channel configured? 117 1.1 eeh */ 118 1.2 pk int 119 1.27 tsutsui sunkbd_match(device_t parent, cfdata_t cf, void *aux) 120 1.1 eeh { 121 1.1 eeh struct kbd_ms_tty_attach_args *args = aux; 122 1.1 eeh 123 1.1 eeh if (strcmp(args->kmta_name, "keyboard") == 0) 124 1.27 tsutsui return 1; 125 1.1 eeh 126 1.1 eeh return 0; 127 1.1 eeh } 128 1.1 eeh 129 1.2 pk void 130 1.27 tsutsui sunkbd_attach(device_t parent, device_t self, void *aux) 131 1.1 eeh { 132 1.24 thorpej struct kbd_sun_softc *k = device_private(self); 133 1.1 eeh struct kbd_ms_tty_attach_args *args = aux; 134 1.1 eeh struct tty *tp = args->kmta_tp; 135 1.1 eeh struct cons_channel *cc; 136 1.1 eeh 137 1.27 tsutsui k->k_kbd.k_dev = self; 138 1.27 tsutsui 139 1.1 eeh /* Set up the proper line discipline. */ 140 1.22 thorpej if (ttyldisc_attach(&sunkbd_disc) != 0) 141 1.3 eeh panic("sunkbd_attach: sunkbd_disc"); 142 1.22 thorpej ttyldisc_release(tp->t_linesw); 143 1.22 thorpej tp->t_linesw = ttyldisc_lookup(sunkbd_disc.l_name); 144 1.22 thorpej KASSERT(tp->t_linesw == &sunkbd_disc); 145 1.1 eeh tp->t_oflag &= ~OPOST; 146 1.1 eeh tp->t_dev = args->kmta_dev; 147 1.30 martin SET(tp->t_state, TS_KERN_ONLY); 148 1.1 eeh 149 1.1 eeh /* link the structures together. */ 150 1.1 eeh k->k_priv = tp; 151 1.27 tsutsui tp->t_sc = k; 152 1.1 eeh 153 1.14 uwe /* provide our middle layer with a link to the lower layer (i.e. us) */ 154 1.1 eeh k->k_deviopen = sunkbdiopen; 155 1.1 eeh k->k_deviclose = NULL; 156 1.1 eeh k->k_write_data = sunkbd_write_data; 157 1.1 eeh 158 1.14 uwe /* provide upper layer with a link to our middle layer */ 159 1.14 uwe k->k_kbd.k_ops = &kbd_ops_sun; 160 1.14 uwe 161 1.14 uwe /* alloc console input channel */ 162 1.14 uwe if ((cc = kbd_cc_alloc(&k->k_kbd)) == NULL) 163 1.1 eeh return; 164 1.1 eeh 165 1.1 eeh if (args->kmta_consdev) { 166 1.4 eeh char magic[4]; 167 1.1 eeh 168 1.1 eeh /* 169 1.1 eeh * Hookup ourselves as the console input channel 170 1.1 eeh */ 171 1.8 pk args->kmta_baud = sunkbd_bps; 172 1.1 eeh args->kmta_cflag = CLOCAL|CS8; 173 1.1 eeh cons_attach_input(cc, args->kmta_consdev); 174 1.1 eeh 175 1.1 eeh /* Tell our parent what the console should be. */ 176 1.1 eeh args->kmta_consdev = cn_tab; 177 1.13 uwe k->k_kbd.k_isconsole = 1; 178 1.27 tsutsui aprint_normal(" (console input)"); 179 1.4 eeh 180 1.4 eeh /* Set magic to "L1-A" */ 181 1.4 eeh magic[0] = KBD_L1; 182 1.4 eeh magic[1] = KBD_A; 183 1.4 eeh magic[2] = 0; 184 1.4 eeh cn_set_magic(magic); 185 1.1 eeh } else { 186 1.1 eeh extern void kd_attach_input(struct cons_channel *); 187 1.1 eeh 188 1.1 eeh kd_attach_input(cc); 189 1.1 eeh } 190 1.1 eeh 191 1.15 martin 192 1.27 tsutsui aprint_normal("\n"); 193 1.15 martin 194 1.15 martin #if NWSKBD > 0 195 1.15 martin kbd_wskbd_attach(&k->k_kbd, args->kmta_consdev != NULL); 196 1.15 martin #endif 197 1.1 eeh 198 1.1 eeh /* Do this before any calls to kbd_rint(). */ 199 1.13 uwe kbd_xlate_init(&k->k_kbd.k_state); 200 1.1 eeh 201 1.1 eeh /* Magic sequence. */ 202 1.1 eeh k->k_magic1 = KBD_L1; 203 1.1 eeh k->k_magic2 = KBD_A; 204 1.1 eeh } 205 1.1 eeh 206 1.1 eeh /* 207 1.1 eeh * Internal open routine. This really should be inside com.c 208 1.1 eeh * But I'm putting it here until we have a generic internal open 209 1.1 eeh * mechanism. 210 1.1 eeh */ 211 1.1 eeh int 212 1.27 tsutsui sunkbdiopen(device_t dev, int flags) 213 1.1 eeh { 214 1.27 tsutsui struct kbd_sun_softc *k = device_private(dev); 215 1.27 tsutsui struct tty *tp = k->k_priv; 216 1.23 christos struct lwp *l = curlwp ? curlwp : &lwp0; 217 1.1 eeh struct termios t; 218 1.2 pk int error; 219 1.1 eeh 220 1.1 eeh /* Open the lower device */ 221 1.30 martin CLR(tp->t_state, TS_KERN_ONLY); 222 1.25 ad if ((error = cdev_open(tp->t_dev, O_NONBLOCK|flags, 223 1.23 christos 0/* ignored? */, l)) != 0) 224 1.2 pk return (error); 225 1.1 eeh 226 1.1 eeh /* Now configure it for the console. */ 227 1.1 eeh tp->t_ospeed = 0; 228 1.8 pk t.c_ispeed = sunkbd_bps; 229 1.8 pk t.c_ospeed = sunkbd_bps; 230 1.1 eeh t.c_cflag = CLOCAL|CS8; 231 1.1 eeh (*tp->t_param)(tp, &t); 232 1.30 martin SET(tp->t_state, TS_KERN_ONLY); 233 1.1 eeh 234 1.2 pk return (0); 235 1.1 eeh } 236 1.1 eeh 237 1.1 eeh /* 238 1.1 eeh * TTY interface to handle input. 239 1.1 eeh */ 240 1.1 eeh int 241 1.27 tsutsui sunkbdinput(int c, struct tty *tp) 242 1.1 eeh { 243 1.27 tsutsui struct kbd_sun_softc *k = tp->t_sc; 244 1.1 eeh int error; 245 1.1 eeh 246 1.1 eeh /* 247 1.1 eeh * Handle exceptional conditions (break, parity, framing). 248 1.1 eeh */ 249 1.1 eeh if ((error = ((c & TTY_ERRORMASK))) != 0) { 250 1.1 eeh /* 251 1.1 eeh * After garbage, flush pending input, and 252 1.1 eeh * send a reset to resync key translation. 253 1.1 eeh */ 254 1.1 eeh log(LOG_ERR, "%s: input error (0x%x)\n", 255 1.27 tsutsui device_xname(k->k_kbd.k_dev), c); 256 1.1 eeh c &= TTY_CHARMASK; 257 1.28 jym if (!(k->k_txflags & K_TXBUSY)) { 258 1.1 eeh ttyflush(tp, FREAD | FWRITE); 259 1.1 eeh goto send_reset; 260 1.1 eeh } 261 1.1 eeh } 262 1.1 eeh 263 1.1 eeh /* 264 1.1 eeh * Check for input buffer overflow 265 1.1 eeh */ 266 1.1 eeh if (tp->t_rawq.c_cc + tp->t_canq.c_cc >= TTYHOG) { 267 1.1 eeh log(LOG_ERR, "%s: input overrun\n", 268 1.27 tsutsui device_xname(k->k_kbd.k_dev)); 269 1.1 eeh goto send_reset; 270 1.1 eeh } 271 1.1 eeh 272 1.1 eeh /* Pass this up to the "middle" layer. */ 273 1.20 heas return(kbd_sun_input(k, c)); 274 1.1 eeh 275 1.1 eeh send_reset: 276 1.1 eeh /* Send a reset to resync translation. */ 277 1.13 uwe kbd_sun_output(k, KBD_CMD_RESET); 278 1.1 eeh return (ttstart(tp)); 279 1.1 eeh 280 1.1 eeh } 281 1.1 eeh 282 1.1 eeh int 283 1.27 tsutsui sunkbdstart(struct tty *tp) 284 1.1 eeh { 285 1.27 tsutsui struct kbd_sun_softc *k = tp->t_sc; 286 1.1 eeh 287 1.1 eeh /* 288 1.1 eeh * Transmit done. Try to send more, or 289 1.1 eeh * clear busy and wakeup drain waiters. 290 1.1 eeh */ 291 1.1 eeh k->k_txflags &= ~K_TXBUSY; 292 1.13 uwe kbd_sun_start_tx(k); 293 1.1 eeh ttstart(tp); 294 1.2 pk return (0); 295 1.1 eeh } 296 1.1 eeh /* 297 1.13 uwe * used by kbd_sun_start_tx(); 298 1.1 eeh */ 299 1.1 eeh void 300 1.27 tsutsui sunkbd_write_data(struct kbd_sun_softc *k, int c) 301 1.1 eeh { 302 1.27 tsutsui struct tty *tp = k->k_priv; 303 1.2 pk 304 1.32 riastrad ttylock(tp); 305 1.1 eeh ttyoutput(c, tp); 306 1.1 eeh ttstart(tp); 307 1.32 riastrad ttyunlock(tp); 308 1.1 eeh } 309