kbd.c revision 1.18 1 /* $NetBSD: kbd.c,v 1.18 1996/04/21 21:12:05 veego 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 #include <amiga/amiga/cia.h>
52 #include <amiga/dev/itevar.h>
53 #include <amiga/dev/kbdreg.h>
54 #include <amiga/dev/kbdmap.h>
55 #include <amiga/dev/event_var.h>
56 #include <amiga/dev/vuid_event.h>
57 #include "kbd.h"
58
59 #include <sys/conf.h>
60 #include <machine/conf.h>
61
62 struct kbd_softc {
63 int k_event_mode; /* if true, collect events, else pass to ite */
64 struct evvar k_events; /* event queue state */
65 };
66 struct kbd_softc kbd_softc;
67
68 int kbdmatch __P((struct device *, void *, void *));
69 void kbdattach __P((struct device *, struct device *, void *));
70 void kbdintr __P((int));
71
72 struct cfattach kbd_ca = {
73 sizeof(struct device), kbdmatch, kbdattach
74 };
75
76 struct cfdriver kbd_cd = {
77 NULL, "kbd", DV_DULL, NULL, 0
78 };
79
80 /*ARGSUSED*/
81 int
82 kbdmatch(pdp, match, auxp)
83 struct device *pdp;
84 void *match, *auxp;
85 {
86
87 if (matchname((char *)auxp, "kbd"))
88 return(1);
89 return(0);
90 }
91
92 /*ARGSUSED*/
93 void
94 kbdattach(pdp, dp, auxp)
95 struct device *pdp, *dp;
96 void *auxp;
97 {
98 printf("\n");
99 }
100
101 /* definitions for amiga keyboard encoding. */
102 #define KEY_CODE(c) ((c) & 0x7f)
103 #define KEY_UP(c) ((c) & 0x80)
104
105 void
106 kbdenable()
107 {
108 int s;
109
110 /*
111 * collides with external ints from SCSI, watch out for this when
112 * enabling/disabling interrupts there !!
113 */
114 s = spltty();
115 custom.intena = INTF_SETCLR | INTF_PORTS;
116 ciaa.icr = CIA_ICR_IR_SC | CIA_ICR_SP; /* SP interrupt enable */
117 ciaa.cra &= ~(1<<6); /* serial line == input */
118 kbd_softc.k_event_mode = 0;
119 kbd_softc.k_events.ev_io = 0;
120 splx(s);
121 }
122
123
124 int
125 kbdopen(dev, flags, mode, p)
126 dev_t dev;
127 int flags, mode;
128 struct proc *p;
129 {
130
131 if (kbd_softc.k_events.ev_io)
132 return EBUSY;
133
134 kbd_softc.k_events.ev_io = p;
135 ev_init(&kbd_softc.k_events);
136 return (0);
137 }
138
139 int
140 kbdclose(dev, flags, mode, p)
141 dev_t dev;
142 int flags, mode;
143 struct proc *p;
144 {
145
146 /* Turn off event mode, dump the queue */
147 kbd_softc.k_event_mode = 0;
148 ev_fini(&kbd_softc.k_events);
149 kbd_softc.k_events.ev_io = NULL;
150 return (0);
151 }
152
153 int
154 kbdread(dev, uio, flags)
155 dev_t dev;
156 struct uio *uio;
157 int flags;
158 {
159 return ev_read (&kbd_softc.k_events, uio, flags);
160 }
161
162 int
163 kbdioctl(dev, cmd, data, flag, p)
164 dev_t dev;
165 u_long cmd;
166 register caddr_t data;
167 int flag;
168 struct proc *p;
169 {
170 register struct kbd_softc *k = &kbd_softc;
171
172 switch (cmd) {
173 case KIOCTRANS:
174 if (*(int *)data == TR_UNTRANS_EVENT)
175 return 0;
176 break;
177
178 case KIOCGTRANS:
179 /* Get translation mode */
180 *(int *)data = TR_UNTRANS_EVENT;
181 return 0;
182
183 case KIOCSDIRECT:
184 k->k_event_mode = *(int *)data;
185 return 0;
186
187 case FIONBIO: /* we will remove this someday (soon???) */
188 return 0;
189
190 case FIOASYNC:
191 k->k_events.ev_async = *(int *)data != 0;
192 return 0;
193
194 case TIOCSPGRP:
195 if (*(int *)data != k->k_events.ev_io->p_pgid)
196 return EPERM;
197 return 0;
198
199 default:
200 return ENOTTY;
201 }
202
203 /* We identified the ioctl, but we do not handle it. */
204 return EOPNOTSUPP; /* misuse, but what the heck */
205 }
206
207 int
208 kbdselect(dev, rw, p)
209 dev_t dev;
210 int rw;
211 struct proc *p;
212 {
213 return ev_select (&kbd_softc.k_events, rw, p);
214 }
215
216
217 void
218 kbdintr(mask)
219 int mask;
220 {
221 u_char c;
222 struct kbd_softc *k = &kbd_softc;
223 struct firm_event *fe;
224 int put;
225 #ifdef KBDRESET
226 static int reset_warn;
227 #endif
228
229 /* now only invoked from generic CIA interrupt handler if there *is*
230 * a keyboard interrupt pending
231 */
232
233 c = ~ciaa.sdr; /* keyboard data is inverted */
234 /* ack */
235 ciaa.cra |= (1 << 6); /* serial line output */
236 #ifdef KBDRESET
237 if (reset_warn && c == 0xf0) {
238 #ifdef DEBUG
239 printf ("kbdintr: !!!! Reset Warning !!!!\n");
240 #endif
241 bootsync();
242 reset_warn = 0;
243 DELAY(30000000);
244 }
245 #endif
246 /* wait 200 microseconds (for bloody Cherry keyboards..) */
247 DELAY(2000); /* fudge delay a bit for some keyboards */
248 ciaa.cra &= ~(1 << 6);
249
250 /* process the character */
251 c = (c >> 1) | (c << 7); /* rotate right once */
252
253 #ifdef KBDRESET
254 if (c == 0x78) {
255 #ifdef DEBUG
256 printf ("kbdintr: Reset Warning started\n");
257 #endif
258 ++reset_warn;
259 return;
260 }
261 #endif
262 /* if not in event mode, deliver straight to ite to process key stroke */
263 if (! k->k_event_mode) {
264 ite_filter (c, ITEFILT_TTY);
265 return;
266 }
267
268 /* Keyboard is generating events. Turn this keystroke into an
269 * event and put it in the queue. If the queue is full, the
270 * keystroke is lost (sorry!).
271 */
272
273 put = k->k_events.ev_put;
274 fe = &k->k_events.ev_q[put];
275 put = (put + 1) % EV_QSIZE;
276 if (put == k->k_events.ev_get) {
277 log(LOG_WARNING, "keyboard event queue overflow\n"); /* ??? */
278 return;
279 }
280 fe->id = KEY_CODE(c);
281 fe->value = KEY_UP(c) ? VKEY_UP : VKEY_DOWN;
282 fe->time = time;
283 k->k_events.ev_put = put;
284 EV_WAKEUP(&k->k_events);
285 }
286
287
288 int
289 kbdgetcn()
290 {
291 int s = spltty ();
292 u_char ints, mask, c, in;
293
294 for (ints = 0; ! ((mask = ciaa.icr) & CIA_ICR_SP); ints |= mask) ;
295
296 in = ciaa.sdr;
297 c = ~in;
298
299 /* ack */
300 ciaa.cra |= (1 << 6); /* serial line output */
301 ciaa.sdr = 0xff; /* ack */
302 /* wait 200 microseconds */
303 DELAY(2000); /* XXXX only works as long as DELAY doesn't use a timer and waits.. */
304 ciaa.cra &= ~(1 << 6);
305 ciaa.sdr = in;
306
307 splx (s);
308 c = (c >> 1) | (c << 7);
309
310 /* take care that no CIA-interrupts are lost */
311 if (ints)
312 dispatch_cia_ints (0, ints);
313
314 return c;
315 }
316