1 /* $NetBSD: kbd.c,v 1.11 2001/06/12 15:17:21 wiz Exp $ */ 2 3 /* 4 * Copyright (c) 1982, 1986, 1990 The Regents of the University of California. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include "ite.h" 37 #include "bell.h" 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/device.h> 42 #include <sys/ioctl.h> 43 #include <sys/tty.h> 44 #include <sys/proc.h> 45 #include <sys/conf.h> 46 #include <sys/file.h> 47 #include <sys/uio.h> 48 #include <sys/kernel.h> 49 #include <sys/syslog.h> 50 #include <sys/signalvar.h> 51 52 #include <machine/cpu.h> 53 #include <machine/bus.h> 54 55 #include <arch/x68k/dev/intiovar.h> 56 #include <arch/x68k/dev/mfp.h> 57 #include <arch/x68k/dev/itevar.h> 58 59 /* for sun-like event mode, if you go thru /dev/kbd. */ 60 #include <arch/x68k/dev/event_var.h> 61 62 #include <machine/kbio.h> 63 #include <machine/kbd.h> 64 #include <machine/vuid_event.h> 65 66 struct kbd_softc { 67 struct device sc_dev; 68 69 int sc_event_mode; /* if true, collect events, else pass to ite */ 70 struct evvar sc_events; /* event queue state */ 71 }; 72 73 void kbdenable __P((int)); 74 int kbdopen __P((dev_t, int, int, struct proc *)); 75 int kbdclose __P((dev_t, int, int, struct proc *)); 76 int kbdread __P((dev_t, struct uio *, int)); 77 int kbdwrite __P((dev_t, struct uio *, int)); 78 int kbdioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); 79 int kbdpoll __P((dev_t, int, struct proc *)); 80 int kbdintr __P((void *)); 81 void kbdsoftint __P((void)); 82 void kbd_bell __P((int)); 83 int kbdcngetc __P((void)); 84 void kbd_setLED __P((void)); 85 int kbd_send_command __P((int)); 86 87 88 static int kbdmatch __P((struct device *, struct cfdata *, void *)); 89 static void kbdattach __P((struct device *, struct device *, void *)); 90 91 struct cfattach kbd_ca = { 92 sizeof(struct kbd_softc), kbdmatch, kbdattach 93 }; 94 95 96 static int 97 kbdmatch(parent, cf, aux) 98 struct device *parent; 99 struct cfdata *cf; 100 void *aux; 101 { 102 if (strcmp(aux, "kbd") != 0) 103 return (0); 104 if (cf->cf_unit != 0) 105 return (0); 106 107 return (1); 108 } 109 110 static void 111 kbdattach(parent, self, aux) 112 struct device *parent, *self; 113 void *aux; 114 { 115 struct kbd_softc *k = (void*) self; 116 struct mfp_softc *mfp = (void*) parent; 117 int s = spltty(); 118 119 /* MFP interrupt #12 is for USART receive buffer full */ 120 intio_intr_establish(mfp->sc_intr + 12, "kbd", kbdintr, self); 121 122 kbdenable(1); 123 k->sc_event_mode = 0; 124 k->sc_events.ev_io = 0; 125 splx(s); 126 127 printf("\n"); 128 } 129 130 131 /* definitions for x68k keyboard encoding. */ 132 #define KEY_CODE(c) ((c) & 0x7f) 133 #define KEY_UP(c) ((c) & 0x80) 134 135 void 136 kbdenable(mode) 137 int mode; /* 1: interrupt, 0: poll */ 138 { 139 intio_set_sysport_keyctrl(8); 140 mfp_bit_clear_iera(MFP_INTR_RCV_FULL | MFP_INTR_TIMER_B); 141 mfp_set_tbcr(MFP_TIMERB_RESET | MFP_TIMERB_STOP); 142 mfp_set_tbdr(13); /* Timer B interrupt interval */ 143 mfp_set_tbcr(1); /* 1/4 delay mode */ 144 mfp_set_ucr(MFP_UCR_CLKX16 | MFP_UCR_RW_8 | MFP_UCR_ONESB); 145 mfp_set_rsr(MFP_RSR_RE); /* USART receive enable */ 146 mfp_set_tsr(MFP_TSR_TE); /* USART transmit enable */ 147 148 if (mode) { 149 mfp_bit_set_iera(MFP_INTR_RCV_FULL); 150 /* 151 * Perform null read in case that an input byte is in the 152 * receiver buffer, which prevents further interrupts. 153 * We could save the input, but probably not so valuable. 154 */ 155 (void) mfp_get_udr(); 156 } 157 158 kbdled = 0; /* all keyboard LED turn off. */ 159 kbd_setLED(); 160 161 if (!(intio_get_sysport_keyctrl() & 8)) 162 printf(" (no connected keyboard)"); 163 } 164 165 extern struct cfdriver kbd_cd; 166 167 int 168 kbdopen(dev, flags, mode, p) 169 dev_t dev; 170 int flags, mode; 171 struct proc *p; 172 { 173 struct kbd_softc *k; 174 int unit = minor(dev); 175 176 if (unit >= kbd_cd.cd_ndevs) 177 return (ENXIO); 178 k = kbd_cd.cd_devs[minor(dev)]; 179 if (k == NULL) 180 return (ENXIO); 181 182 if (k->sc_events.ev_io) 183 return (EBUSY); 184 k->sc_events.ev_io = p; 185 ev_init(&k->sc_events); 186 187 return (0); 188 } 189 190 int 191 kbdclose(dev, flags, mode, p) 192 dev_t dev; 193 int flags, mode; 194 struct proc *p; 195 { 196 struct kbd_softc *k = kbd_cd.cd_devs[minor(dev)]; 197 198 /* Turn off event mode, dump the queue */ 199 k->sc_event_mode = 0; 200 ev_fini(&k->sc_events); 201 k->sc_events.ev_io = NULL; 202 203 return (0); 204 } 205 206 207 int 208 kbdread(dev, uio, flags) 209 dev_t dev; 210 struct uio *uio; 211 int flags; 212 { 213 struct kbd_softc *k = kbd_cd.cd_devs[minor(dev)]; 214 215 return ev_read(&k->sc_events, uio, flags); 216 } 217 218 /* this routine should not exist, but is convenient to write here for now */ 219 int 220 kbdwrite(dev, uio, flags) 221 dev_t dev; 222 struct uio *uio; 223 int flags; 224 { 225 return EOPNOTSUPP; 226 } 227 228 #if NBELL > 0 229 struct bell_info; 230 int opm_bell_setup __P((struct bell_info *)); 231 void opm_bell_on __P((void)); 232 void opm_bell_off __P((void)); 233 #endif 234 235 int 236 kbdioctl(dev, cmd, data, flag, p) 237 dev_t dev; 238 u_long cmd; 239 caddr_t data; 240 int flag; 241 struct proc *p; 242 { 243 register struct kbd_softc *k = kbd_cd.cd_devs[minor(dev)]; 244 int cmd_data; 245 246 switch (cmd) { 247 case KIOCTRANS: 248 if (*(int *)data == TR_UNTRANS_EVENT) 249 return (0); 250 break; 251 252 case KIOCGTRANS: 253 /* 254 * Get translation mode 255 */ 256 *(int *)data = TR_UNTRANS_EVENT; 257 return (0); 258 259 case KIOCSDIRECT: 260 k->sc_event_mode = *(int *)data; 261 return (0); 262 263 case KIOCCMD: 264 cmd_data = *(int *)data; 265 return kbd_send_command(cmd_data); 266 267 case KIOCSLED: 268 kbdled = *(char *)data; 269 kbd_setLED(); 270 return (0); 271 272 case KIOCGLED: 273 *(char *)data = kbdled; 274 return (0); 275 276 case KIOCSBELL: 277 #if NBELL > 0 278 return opm_bell_setup((struct bell_info *)data); 279 #else 280 return (0); /* allways success */ 281 #endif 282 283 case FIONBIO: /* we will remove this someday (soon???) */ 284 return (0); 285 286 case FIOASYNC: 287 k->sc_events.ev_async = *(int *)data != 0; 288 return (0); 289 290 case TIOCSPGRP: 291 if (*(int *)data != k->sc_events.ev_io->p_pgid) 292 return (EPERM); 293 return (0); 294 295 default: 296 return (ENOTTY); 297 } 298 299 /* 300 * We identified the ioctl, but we do not handle it. 301 */ 302 return (EOPNOTSUPP); /* misuse, but what the heck */ 303 } 304 305 306 int 307 kbdpoll(dev, events, p) 308 dev_t dev; 309 int events; 310 struct proc *p; 311 { 312 struct kbd_softc *k; 313 314 k = kbd_cd.cd_devs[minor(dev)]; 315 return (ev_poll(&k->sc_events, events, p)); 316 } 317 318 319 #define KBDBUFMASK 63 320 #define KBDBUFSIZ 64 321 static u_char kbdbuf[KBDBUFSIZ]; 322 static int kbdputoff = 0; 323 static int kbdgetoff = 0; 324 325 int 326 kbdintr(arg) 327 void *arg; 328 { 329 u_char c, st; 330 struct kbd_softc *k = arg; /* XXX */ 331 struct firm_event *fe; 332 int put; 333 334 /* clear receiver error if any */ 335 st = mfp_get_rsr(); 336 337 c = mfp_get_udr(); 338 339 if ((st & MFP_RSR_BF) == 0) 340 return 0; /* intr caused by an err -- no char received */ 341 342 /* if not in event mode, deliver straight to ite to process key stroke */ 343 if (! k->sc_event_mode) { 344 kbdbuf[kbdputoff++ & KBDBUFMASK] = c; 345 setsoftkbd(); 346 return 0; 347 } 348 349 /* Keyboard is generating events. Turn this keystroke into an 350 event and put it in the queue. If the queue is full, the 351 keystroke is lost (sorry!). */ 352 353 put = k->sc_events.ev_put; 354 fe = &k->sc_events.ev_q[put]; 355 put = (put + 1) % EV_QSIZE; 356 if (put == k->sc_events.ev_get) { 357 log(LOG_WARNING, "keyboard event queue overflow\n"); /* ??? */ 358 return 0; 359 } 360 fe->id = KEY_CODE(c); 361 fe->value = KEY_UP(c) ? VKEY_UP : VKEY_DOWN; 362 fe->time = time; 363 k->sc_events.ev_put = put; 364 EV_WAKEUP(&k->sc_events); 365 366 return 0; 367 } 368 369 void 370 kbdsoftint() /* what if ite is not configured? */ 371 { 372 int s = spltty(); 373 374 while(kbdgetoff < kbdputoff) 375 ite_filter(kbdbuf[kbdgetoff++ & KBDBUFMASK]); 376 kbdgetoff = kbdputoff = 0; 377 378 splx(s); 379 } 380 381 void 382 kbd_bell(mode) 383 int mode; 384 { 385 #if NBELL > 0 386 if (mode) 387 opm_bell_on(); 388 else 389 opm_bell_off(); 390 #endif 391 } 392 393 unsigned char kbdled; 394 void 395 kbd_setLED() 396 { 397 mfp_send_usart(~kbdled | 0x80); 398 } 399 400 int 401 kbd_send_command(cmd) 402 int cmd; 403 { 404 switch (cmd) { 405 case KBD_CMD_RESET: 406 /* XXX */ 407 return 0; 408 409 case KBD_CMD_BELL: 410 kbd_bell(1); 411 return 0; 412 413 case KBD_CMD_NOBELL: 414 kbd_bell(0); 415 return 0; 416 417 default: 418 return ENOTTY; 419 } 420 } 421 422 /* 423 * for console 424 */ 425 #include "ite.h" 426 #if NITE > 0 427 int 428 kbdcngetc() 429 { 430 int s; 431 u_char ints, c; 432 433 s = splhigh(); 434 ints = mfp_get_iera(); 435 436 mfp_bit_clear_iera(MFP_INTR_RCV_FULL); 437 mfp_set_rsr(mfp_get_rsr() | MFP_RSR_RE); 438 c = mfp_receive_usart(); 439 440 mfp_set_iera(ints); 441 splx(s); 442 443 return c; 444 } 445 #endif 446