kbd.c revision 1.30 1 /* $NetBSD: kbd.c,v 1.30 1998/02/23 00:47:31 is 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 * kbd.c
36 */
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/device.h>
40 #include <sys/ioctl.h>
41 #include <sys/tty.h>
42 #include <sys/proc.h>
43 #include <sys/file.h>
44 #include <sys/kernel.h>
45 #include <sys/syslog.h>
46 #include <sys/signalvar.h>
47 #include <dev/cons.h>
48 #include <machine/cpu.h>
49 #include <amiga/amiga/device.h>
50 #include <amiga/amiga/custom.h>
51 #ifdef DRACO
52 #include <amiga/amiga/drcustom.h>
53 #endif
54 #include <amiga/amiga/cia.h>
55 #include <amiga/dev/itevar.h>
56 #include <amiga/dev/kbdreg.h>
57 #include <amiga/dev/kbdmap.h>
58 #include <amiga/dev/event_var.h>
59 #include <amiga/dev/vuid_event.h>
60 #include "kbd.h"
61
62 #include <sys/conf.h>
63 #include <machine/conf.h>
64
65 struct kbd_softc {
66 int k_event_mode; /* if true, collect events, else pass to ite */
67 struct evvar k_events; /* event queue state */
68 #ifdef DRACO
69 u_char k_rlprfx; /* MF-II rel. prefix has been seen */
70 #endif
71 };
72 struct kbd_softc kbd_softc;
73
74 int kbdmatch __P((struct device *, struct cfdata *, void *));
75 void kbdattach __P((struct device *, struct device *, void *));
76 void kbdintr __P((int));
77 void kbdstuffchar __P((u_char));
78
79 struct cfattach kbd_ca = {
80 sizeof(struct device), kbdmatch, kbdattach
81 };
82
83 /*ARGSUSED*/
84 int
85 kbdmatch(pdp, cfp, auxp)
86 struct device *pdp;
87 struct cfdata *cfp;
88 void *auxp;
89 {
90
91 if (matchname((char *)auxp, "kbd"))
92 return(1);
93 return(0);
94 }
95
96 /*ARGSUSED*/
97 void
98 kbdattach(pdp, dp, auxp)
99 struct device *pdp, *dp;
100 void *auxp;
101 {
102 #ifdef DRACO
103 /*
104 * XXX Must be kept in sync with kbdenable() switch.
105 * XXX This should be probed, but this way we dont need to initialize
106 * the keyboards.
107 */
108 switch (is_draco()) {
109 case 0:
110 case 1:
111 case 2:
112 printf(": CIA A type Amiga\n");
113 break;
114 case 3:
115 case 4:
116 default:
117 printf(": QuickLogic type MF-II\n");
118 break;
119 }
120 #else
121 printf(": CIA A type Amiga\n");
122 #endif
123
124 }
125
126 /* definitions for amiga keyboard encoding. */
127 #define KEY_CODE(c) ((c) & 0x7f)
128 #define KEY_UP(c) ((c) & 0x80)
129
130 void
131 kbdenable()
132 {
133 static int kbd_inited = 0;
134
135 int s;
136
137 #ifdef DRACO
138 u_char c;
139 #endif
140 /*
141 * collides with external ints from SCSI, watch out for this when
142 * enabling/disabling interrupts there !!
143 */
144 s = splhigh(); /* don't lower; might be called from early ddb */
145 if (kbd_inited) {
146 splx(s);
147 return;
148 }
149 kbd_inited = 1;
150 #ifdef DRACO
151 switch (is_draco()) {
152 case 0:
153 custom.intena = INTF_SETCLR | INTF_PORTS;
154
155 ciaa.icr = CIA_ICR_IR_SC | CIA_ICR_SP;
156 /* SP interrupt enable */
157 ciaa.cra &= ~(1<<6); /* serial line == input */
158 break;
159 case 1:
160 case 2:
161 /* XXX: tobedone: conditionally enable that one */
162 /* XXX: for now, just enable DraCo ports and CIA */
163 *draco_intena |= DRIRQ_INT2;
164 ciaa.icr = CIA_ICR_IR_SC | CIA_ICR_SP;
165 /* SP interrupt enable */
166 ciaa.cra &= ~(1<<6); /* serial line == input */
167 break;
168
169 case 3:
170 ciaa.icr = CIA_ICR_SP; /* CIA SP interrupt disable */
171 ciaa.cra &= ~(1<<6); /* serial line == input */
172 /* FALLTHROUGH */
173 case 4:
174 default:
175 /* XXX: for now: always enable own keyboard */
176
177 while (draco_ioct->io_status & DRSTAT_KBDRECV) {
178 c = draco_ioct->io_kbddata;
179 draco_ioct->io_kbdrst = 0;
180 DELAY(2000);
181 }
182
183 draco_ioct->io_control &= ~DRCNTRL_KBDINTENA;
184 break;
185 }
186 #else
187 custom.intena = INTF_SETCLR | INTF_PORTS;
188 ciaa.icr = CIA_ICR_IR_SC | CIA_ICR_SP; /* SP interrupt enable */
189 ciaa.cra &= ~(1<<6); /* serial line == input */
190 #endif
191 kbd_softc.k_event_mode = 0;
192 kbd_softc.k_events.ev_io = 0;
193 splx(s);
194 }
195
196
197 int
198 kbdopen(dev, flags, mode, p)
199 dev_t dev;
200 int flags, mode;
201 struct proc *p;
202 {
203
204 kbdenable();
205 if (kbd_softc.k_events.ev_io)
206 return EBUSY;
207
208 kbd_softc.k_events.ev_io = p;
209 ev_init(&kbd_softc.k_events);
210 return (0);
211 }
212
213 int
214 kbdclose(dev, flags, mode, p)
215 dev_t dev;
216 int flags, mode;
217 struct proc *p;
218 {
219
220 /* Turn off event mode, dump the queue */
221 kbd_softc.k_event_mode = 0;
222 ev_fini(&kbd_softc.k_events);
223 kbd_softc.k_events.ev_io = NULL;
224 return (0);
225 }
226
227 int
228 kbdread(dev, uio, flags)
229 dev_t dev;
230 struct uio *uio;
231 int flags;
232 {
233 return ev_read (&kbd_softc.k_events, uio, flags);
234 }
235
236 int
237 kbdioctl(dev, cmd, data, flag, p)
238 dev_t dev;
239 u_long cmd;
240 register caddr_t data;
241 int flag;
242 struct proc *p;
243 {
244 register struct kbd_softc *k = &kbd_softc;
245
246 switch (cmd) {
247 case KIOCTRANS:
248 if (*(int *)data == TR_UNTRANS_EVENT)
249 return 0;
250 break;
251
252 case KIOCGTRANS:
253 /* Get translation mode */
254 *(int *)data = TR_UNTRANS_EVENT;
255 return 0;
256
257 case KIOCSDIRECT:
258 k->k_event_mode = *(int *)data;
259 return 0;
260
261 case FIONBIO: /* we will remove this someday (soon???) */
262 return 0;
263
264 case FIOASYNC:
265 k->k_events.ev_async = *(int *)data != 0;
266 return 0;
267
268 case TIOCSPGRP:
269 if (*(int *)data != k->k_events.ev_io->p_pgid)
270 return EPERM;
271 return 0;
272
273 default:
274 return ENOTTY;
275 }
276
277 /* We identified the ioctl, but we do not handle it. */
278 return EOPNOTSUPP; /* misuse, but what the heck */
279 }
280
281 int
282 kbdpoll(dev, events, p)
283 dev_t dev;
284 int events;
285 struct proc *p;
286 {
287 return ev_poll (&kbd_softc.k_events, events, p);
288 }
289
290
291 void
292 kbdintr(mask)
293 int mask;
294 {
295 u_char c;
296 #ifdef KBDRESET
297 static int reset_warn;
298 #endif
299
300 /*
301 * now only invoked from generic CIA interrupt handler if there *is*
302 * a keyboard interrupt pending
303 */
304
305 c = ~ciaa.sdr; /* keyboard data is inverted */
306 /* ack */
307 ciaa.cra |= (1 << 6); /* serial line output */
308 #ifdef KBDRESET
309 if (reset_warn && c == 0xf0) {
310 #ifdef DEBUG
311 printf ("kbdintr: !!!! Reset Warning !!!!\n");
312 #endif
313 bootsync();
314 reset_warn = 0;
315 DELAY(30000000);
316 }
317 #endif
318 /* wait 200 microseconds (for bloody Cherry keyboards..) */
319 DELAY(2000); /* fudge delay a bit for some keyboards */
320 ciaa.cra &= ~(1 << 6);
321
322 /* process the character */
323 c = (c >> 1) | (c << 7); /* rotate right once */
324
325 #ifdef KBDRESET
326 if (c == 0x78) {
327 #ifdef DEBUG
328 printf ("kbdintr: Reset Warning started\n");
329 #endif
330 ++reset_warn;
331 return;
332 }
333 #endif
334 kbdstuffchar(c);
335 }
336
337 #ifdef DRACO
338 /* maps MF-II keycodes to Amiga keycodes */
339
340 const u_char drkbdtab[] = {
341 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x50,
342 0x45, 0xff, 0xff, 0xff, 0xff, 0x42, 0x00, 0x51,
343
344 0xff, 0x64, 0x60, 0x30, 0x63, 0x10, 0x01, 0x52,
345 0xff, 0x66, 0x31, 0x21, 0x20, 0x11, 0x02, 0x53,
346
347 0xff, 0x33, 0x32, 0x22, 0x12, 0x04, 0x03, 0x54,
348 0xff, 0x40, 0x34, 0x23, 0x14, 0x13, 0x05, 0x55,
349
350 0xff, 0x36, 0x35, 0x25, 0x24, 0x15, 0x06, 0x56,
351 0xff, 0x67, 0x37, 0x26, 0x16, 0x07, 0x08, 0x57,
352 /* --- */
353 0xff, 0x38, 0x27, 0x17, 0x18, 0x0a, 0x09, 0x58,
354 0xff, 0x39, 0x3a, 0x28, 0x29, 0x19, 0x0b, 0x59,
355
356 0xff, 0xff, 0x2a, 0x2b, 0x1a, 0x0c, 0x4b, 0xff,
357 0x65, 0x61, 0x44, 0x1b, 0xff, 0xff, 0x6f, 0xff,
358
359 0x4d, 0x4f, 0xff, 0x4c, 0x0d, 0xff, 0x41, 0x46,
360 0xff, 0x1d, 0x4e, 0x2d, 0x3d, 0x4a, 0x5f, 0x62,
361
362 0x0f, 0x3c, 0x1e, 0x2e, 0x2f, 0x3e, 0x5a, 0x5b,
363 0xff, 0x43, 0x1f, 0xff, 0x5e, 0x3f, 0x5c, 0xff,
364 /* --- */
365 0xff, 0xff, 0xff, 0xff, 0x5d
366 };
367 #endif
368
369
370 int
371 kbdgetcn ()
372 {
373 int s;
374 u_char ints, mask, c, in;
375
376 #ifdef DRACO
377 /*
378 * XXX todo: if CIA DraCo, get from cia if cia kbd
379 * installed.
380 */
381 if (is_draco()) {
382 c = 0;
383 s = spltty ();
384 while ((draco_ioct->io_status & DRSTAT_KBDRECV) == 0);
385 in = draco_ioct->io_kbddata;
386 draco_ioct->io_kbdrst = 0;
387 if (in == 0xF0) { /* release prefix */
388 c = 0x80;
389 while ((draco_ioct->io_status & DRSTAT_KBDRECV) == 0);
390 in = draco_ioct->io_kbddata;
391 draco_ioct->io_kbdrst = 0;
392 }
393 splx(s);
394 #ifdef DRACORAWKEYDEBUG
395 printf("<%02x>", in);
396 #endif
397 return (in>=sizeof(drkbdtab) ? 0xff : drkbdtab[in]|c);
398 }
399 #endif
400 s = spltty();
401 for (ints = 0; ! ((mask = ciaa.icr) & CIA_ICR_SP);
402 ints |= mask) ;
403
404 in = ciaa.sdr;
405 c = ~in;
406
407 /* ack */
408 ciaa.cra |= (1 << 6); /* serial line output */
409 ciaa.sdr = 0xff; /* ack */
410 /* wait 200 microseconds */
411 DELAY(2000); /* XXXX only works as long as DELAY doesn't
412 * use a timer and waits.. */
413 ciaa.cra &= ~(1 << 6);
414 ciaa.sdr = in;
415
416 splx (s);
417 c = (c >> 1) | (c << 7);
418
419 /* take care that no CIA-interrupts are lost */
420 if (ints)
421 dispatch_cia_ints (0, ints);
422
423 return c;
424 }
425
426 void
427 kbdstuffchar(c)
428 u_char c;
429 {
430 struct firm_event *fe;
431 struct kbd_softc *k = &kbd_softc;
432 int put;
433
434 /*
435 * If not in event mode, deliver straight to ite to process
436 * key stroke
437 */
438
439 if (! k->k_event_mode) {
440 ite_filter (c, ITEFILT_TTY);
441 return;
442 }
443
444 /*
445 * Keyboard is generating events. Turn this keystroke into an
446 * event and put it in the queue. If the queue is full, the
447 * keystroke is lost (sorry!).
448 */
449
450 put = k->k_events.ev_put;
451 fe = &k->k_events.ev_q[put];
452 put = (put + 1) % EV_QSIZE;
453 if (put == k->k_events.ev_get) {
454 log(LOG_WARNING, "keyboard event queue overflow\n");
455 /* ??? */
456 return;
457 }
458 fe->id = KEY_CODE(c);
459 fe->value = KEY_UP(c) ? VKEY_UP : VKEY_DOWN;
460 fe->time = time;
461 k->k_events.ev_put = put;
462 EV_WAKEUP(&k->k_events);
463 }
464
465
466 #ifdef DRACO
467 void
468 drkbdintr()
469 {
470 u_char in;
471 struct kbd_softc *k = &kbd_softc;
472
473 in = draco_ioct->io_kbddata;
474 draco_ioct->io_kbdrst = 0;
475
476 if (in == 0xF0)
477 k->k_rlprfx = 0x80;
478 else {
479 kbdstuffchar(in>=sizeof(drkbdtab) ? 0xff :
480 drkbdtab[in] | k->k_rlprfx);
481 k->k_rlprfx = 0;
482 }
483 }
484
485 #endif
486