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