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