kbd.c revision 1.18 1 1.18 veego /* $NetBSD: kbd.c,v 1.18 1996/04/21 21:12:05 veego Exp $ */
2 1.11 cgd
3 1.1 mw /*
4 1.1 mw * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
5 1.1 mw * All rights reserved.
6 1.1 mw *
7 1.1 mw * Redistribution and use in source and binary forms, with or without
8 1.1 mw * modification, are permitted provided that the following conditions
9 1.1 mw * are met:
10 1.1 mw * 1. Redistributions of source code must retain the above copyright
11 1.1 mw * notice, this list of conditions and the following disclaimer.
12 1.1 mw * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 mw * notice, this list of conditions and the following disclaimer in the
14 1.1 mw * documentation and/or other materials provided with the distribution.
15 1.1 mw * 3. All advertising materials mentioning features or use of this software
16 1.1 mw * must display the following acknowledgement:
17 1.1 mw * This product includes software developed by the University of
18 1.1 mw * California, Berkeley and its contributors.
19 1.1 mw * 4. Neither the name of the University nor the names of its contributors
20 1.1 mw * may be used to endorse or promote products derived from this software
21 1.1 mw * without specific prior written permission.
22 1.1 mw *
23 1.1 mw * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 1.1 mw * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 1.1 mw * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 1.1 mw * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 1.1 mw * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 1.1 mw * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 1.1 mw * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 1.1 mw * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 1.1 mw * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 1.1 mw * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 1.1 mw * SUCH DAMAGE.
34 1.1 mw *
35 1.4 mw * kbd.c
36 1.1 mw */
37 1.7 chopps #include <sys/param.h>
38 1.7 chopps #include <sys/systm.h>
39 1.9 chopps #include <sys/device.h>
40 1.7 chopps #include <sys/ioctl.h>
41 1.7 chopps #include <sys/tty.h>
42 1.7 chopps #include <sys/proc.h>
43 1.7 chopps #include <sys/file.h>
44 1.7 chopps #include <sys/kernel.h>
45 1.7 chopps #include <sys/syslog.h>
46 1.18 veego #include <sys/signalvar.h>
47 1.8 chopps #include <dev/cons.h>
48 1.7 chopps #include <machine/cpu.h>
49 1.9 chopps #include <amiga/amiga/device.h>
50 1.7 chopps #include <amiga/amiga/custom.h>
51 1.7 chopps #include <amiga/amiga/cia.h>
52 1.9 chopps #include <amiga/dev/itevar.h>
53 1.9 chopps #include <amiga/dev/kbdreg.h>
54 1.18 veego #include <amiga/dev/kbdmap.h>
55 1.7 chopps #include <amiga/dev/event_var.h>
56 1.7 chopps #include <amiga/dev/vuid_event.h>
57 1.9 chopps #include "kbd.h"
58 1.5 mw
59 1.18 veego #include <sys/conf.h>
60 1.18 veego #include <machine/conf.h>
61 1.18 veego
62 1.5 mw struct kbd_softc {
63 1.9 chopps int k_event_mode; /* if true, collect events, else pass to ite */
64 1.9 chopps struct evvar k_events; /* event queue state */
65 1.9 chopps };
66 1.9 chopps struct kbd_softc kbd_softc;
67 1.9 chopps
68 1.17 mhitch int kbdmatch __P((struct device *, void *, void *));
69 1.17 mhitch void kbdattach __P((struct device *, struct device *, void *));
70 1.18 veego void kbdintr __P((int));
71 1.9 chopps
72 1.16 thorpej struct cfattach kbd_ca = {
73 1.16 thorpej sizeof(struct device), kbdmatch, kbdattach
74 1.16 thorpej };
75 1.16 thorpej
76 1.16 thorpej struct cfdriver kbd_cd = {
77 1.16 thorpej NULL, "kbd", DV_DULL, NULL, 0
78 1.16 thorpej };
79 1.9 chopps
80 1.9 chopps /*ARGSUSED*/
81 1.9 chopps int
82 1.16 thorpej kbdmatch(pdp, match, auxp)
83 1.9 chopps struct device *pdp;
84 1.16 thorpej void *match, *auxp;
85 1.9 chopps {
86 1.16 thorpej
87 1.9 chopps if (matchname((char *)auxp, "kbd"))
88 1.9 chopps return(1);
89 1.9 chopps return(0);
90 1.9 chopps }
91 1.9 chopps
92 1.9 chopps /*ARGSUSED*/
93 1.9 chopps void
94 1.9 chopps kbdattach(pdp, dp, auxp)
95 1.9 chopps struct device *pdp, *dp;
96 1.9 chopps void *auxp;
97 1.9 chopps {
98 1.9 chopps printf("\n");
99 1.9 chopps }
100 1.5 mw
101 1.5 mw /* definitions for amiga keyboard encoding. */
102 1.5 mw #define KEY_CODE(c) ((c) & 0x7f)
103 1.5 mw #define KEY_UP(c) ((c) & 0x80)
104 1.5 mw
105 1.1 mw void
106 1.18 veego kbdenable()
107 1.1 mw {
108 1.9 chopps int s;
109 1.1 mw
110 1.9 chopps /*
111 1.9 chopps * collides with external ints from SCSI, watch out for this when
112 1.9 chopps * enabling/disabling interrupts there !!
113 1.9 chopps */
114 1.9 chopps s = spltty();
115 1.9 chopps custom.intena = INTF_SETCLR | INTF_PORTS;
116 1.9 chopps ciaa.icr = CIA_ICR_IR_SC | CIA_ICR_SP; /* SP interrupt enable */
117 1.9 chopps ciaa.cra &= ~(1<<6); /* serial line == input */
118 1.9 chopps kbd_softc.k_event_mode = 0;
119 1.9 chopps kbd_softc.k_events.ev_io = 0;
120 1.9 chopps splx(s);
121 1.1 mw }
122 1.1 mw
123 1.1 mw
124 1.1 mw int
125 1.18 veego kbdopen(dev, flags, mode, p)
126 1.18 veego dev_t dev;
127 1.18 veego int flags, mode;
128 1.18 veego struct proc *p;
129 1.5 mw {
130 1.5 mw
131 1.18 veego if (kbd_softc.k_events.ev_io)
132 1.18 veego return EBUSY;
133 1.5 mw
134 1.18 veego kbd_softc.k_events.ev_io = p;
135 1.18 veego ev_init(&kbd_softc.k_events);
136 1.18 veego return (0);
137 1.5 mw }
138 1.5 mw
139 1.5 mw int
140 1.18 veego kbdclose(dev, flags, mode, p)
141 1.18 veego dev_t dev;
142 1.18 veego int flags, mode;
143 1.18 veego struct proc *p;
144 1.5 mw {
145 1.18 veego
146 1.18 veego /* Turn off event mode, dump the queue */
147 1.18 veego kbd_softc.k_event_mode = 0;
148 1.18 veego ev_fini(&kbd_softc.k_events);
149 1.18 veego kbd_softc.k_events.ev_io = NULL;
150 1.18 veego return (0);
151 1.5 mw }
152 1.5 mw
153 1.5 mw int
154 1.18 veego kbdread(dev, uio, flags)
155 1.18 veego dev_t dev;
156 1.18 veego struct uio *uio;
157 1.18 veego int flags;
158 1.5 mw {
159 1.18 veego return ev_read (&kbd_softc.k_events, uio, flags);
160 1.5 mw }
161 1.5 mw
162 1.5 mw int
163 1.18 veego kbdioctl(dev, cmd, data, flag, p)
164 1.18 veego dev_t dev;
165 1.18 veego u_long cmd;
166 1.18 veego register caddr_t data;
167 1.18 veego int flag;
168 1.18 veego struct proc *p;
169 1.5 mw {
170 1.18 veego register struct kbd_softc *k = &kbd_softc;
171 1.18 veego
172 1.18 veego switch (cmd) {
173 1.18 veego case KIOCTRANS:
174 1.18 veego if (*(int *)data == TR_UNTRANS_EVENT)
175 1.18 veego return 0;
176 1.18 veego break;
177 1.18 veego
178 1.18 veego case KIOCGTRANS:
179 1.18 veego /* Get translation mode */
180 1.18 veego *(int *)data = TR_UNTRANS_EVENT;
181 1.18 veego return 0;
182 1.18 veego
183 1.18 veego case KIOCSDIRECT:
184 1.18 veego k->k_event_mode = *(int *)data;
185 1.18 veego return 0;
186 1.18 veego
187 1.18 veego case FIONBIO: /* we will remove this someday (soon???) */
188 1.18 veego return 0;
189 1.18 veego
190 1.18 veego case FIOASYNC:
191 1.18 veego k->k_events.ev_async = *(int *)data != 0;
192 1.18 veego return 0;
193 1.18 veego
194 1.18 veego case TIOCSPGRP:
195 1.18 veego if (*(int *)data != k->k_events.ev_io->p_pgid)
196 1.18 veego return EPERM;
197 1.18 veego return 0;
198 1.18 veego
199 1.18 veego default:
200 1.18 veego return ENOTTY;
201 1.18 veego }
202 1.5 mw
203 1.18 veego /* We identified the ioctl, but we do not handle it. */
204 1.18 veego return EOPNOTSUPP; /* misuse, but what the heck */
205 1.5 mw }
206 1.5 mw
207 1.5 mw int
208 1.18 veego kbdselect(dev, rw, p)
209 1.18 veego dev_t dev;
210 1.18 veego int rw;
211 1.18 veego struct proc *p;
212 1.5 mw {
213 1.18 veego return ev_select (&kbd_softc.k_events, rw, p);
214 1.5 mw }
215 1.5 mw
216 1.5 mw
217 1.18 veego void
218 1.18 veego kbdintr(mask)
219 1.18 veego int mask;
220 1.1 mw {
221 1.18 veego u_char c;
222 1.18 veego struct kbd_softc *k = &kbd_softc;
223 1.18 veego struct firm_event *fe;
224 1.18 veego int put;
225 1.13 chopps #ifdef KBDRESET
226 1.18 veego static int reset_warn;
227 1.13 chopps #endif
228 1.1 mw
229 1.18 veego /* now only invoked from generic CIA interrupt handler if there *is*
230 1.18 veego * a keyboard interrupt pending
231 1.18 veego */
232 1.1 mw
233 1.18 veego c = ~ciaa.sdr; /* keyboard data is inverted */
234 1.18 veego /* ack */
235 1.18 veego ciaa.cra |= (1 << 6); /* serial line output */
236 1.13 chopps #ifdef KBDRESET
237 1.18 veego if (reset_warn && c == 0xf0) {
238 1.13 chopps #ifdef DEBUG
239 1.18 veego printf ("kbdintr: !!!! Reset Warning !!!!\n");
240 1.13 chopps #endif
241 1.18 veego bootsync();
242 1.18 veego reset_warn = 0;
243 1.18 veego DELAY(30000000);
244 1.18 veego }
245 1.13 chopps #endif
246 1.18 veego /* wait 200 microseconds (for bloody Cherry keyboards..) */
247 1.18 veego DELAY(2000); /* fudge delay a bit for some keyboards */
248 1.18 veego ciaa.cra &= ~(1 << 6);
249 1.18 veego
250 1.18 veego /* process the character */
251 1.18 veego c = (c >> 1) | (c << 7); /* rotate right once */
252 1.1 mw
253 1.13 chopps #ifdef KBDRESET
254 1.18 veego if (c == 0x78) {
255 1.13 chopps #ifdef DEBUG
256 1.18 veego printf ("kbdintr: Reset Warning started\n");
257 1.13 chopps #endif
258 1.18 veego ++reset_warn;
259 1.18 veego return;
260 1.18 veego }
261 1.13 chopps #endif
262 1.18 veego /* if not in event mode, deliver straight to ite to process key stroke */
263 1.18 veego if (! k->k_event_mode) {
264 1.18 veego ite_filter (c, ITEFILT_TTY);
265 1.18 veego return;
266 1.18 veego }
267 1.18 veego
268 1.18 veego /* Keyboard is generating events. Turn this keystroke into an
269 1.18 veego * event and put it in the queue. If the queue is full, the
270 1.18 veego * keystroke is lost (sorry!).
271 1.18 veego */
272 1.18 veego
273 1.18 veego put = k->k_events.ev_put;
274 1.18 veego fe = &k->k_events.ev_q[put];
275 1.18 veego put = (put + 1) % EV_QSIZE;
276 1.18 veego if (put == k->k_events.ev_get) {
277 1.18 veego log(LOG_WARNING, "keyboard event queue overflow\n"); /* ??? */
278 1.18 veego return;
279 1.18 veego }
280 1.18 veego fe->id = KEY_CODE(c);
281 1.18 veego fe->value = KEY_UP(c) ? VKEY_UP : VKEY_DOWN;
282 1.18 veego fe->time = time;
283 1.18 veego k->k_events.ev_put = put;
284 1.18 veego EV_WAKEUP(&k->k_events);
285 1.1 mw }
286 1.1 mw
287 1.1 mw
288 1.1 mw int
289 1.18 veego kbdgetcn()
290 1.1 mw {
291 1.18 veego int s = spltty ();
292 1.18 veego u_char ints, mask, c, in;
293 1.18 veego
294 1.18 veego for (ints = 0; ! ((mask = ciaa.icr) & CIA_ICR_SP); ints |= mask) ;
295 1.1 mw
296 1.18 veego in = ciaa.sdr;
297 1.18 veego c = ~in;
298 1.1 mw
299 1.18 veego /* ack */
300 1.18 veego ciaa.cra |= (1 << 6); /* serial line output */
301 1.18 veego ciaa.sdr = 0xff; /* ack */
302 1.18 veego /* wait 200 microseconds */
303 1.18 veego DELAY(2000); /* XXXX only works as long as DELAY doesn't use a timer and waits.. */
304 1.18 veego ciaa.cra &= ~(1 << 6);
305 1.18 veego ciaa.sdr = in;
306 1.18 veego
307 1.18 veego splx (s);
308 1.18 veego c = (c >> 1) | (c << 7);
309 1.18 veego
310 1.18 veego /* take care that no CIA-interrupts are lost */
311 1.18 veego if (ints)
312 1.18 veego dispatch_cia_ints (0, ints);
313 1.3 mw
314 1.18 veego return c;
315 1.1 mw }
316