kbd.c revision 1.5 1 /*
2 * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * kbd.c
34 */
35
36 #include "ite.h"
37
38 #if NITE > 0
39 #include "sys/param.h"
40 #include "sys/systm.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
50 #include "device.h"
51 #include "kbdreg.h"
52 #include "itevar.h"
53 #include "machine/cpu.h"
54
55 #include "../amiga/custom.h"
56 #include "../amiga/cia.h"
57
58 /* for sun-like event mode, if you go thru /dev/kbd. */
59 #include "event_var.h"
60 #include "vuid_event.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 } kbd_softc;
66
67 /* definitions for amiga keyboard encoding. */
68 #define KEY_CODE(c) ((c) & 0x7f)
69 #define KEY_UP(c) ((c) & 0x80)
70
71 void
72 kbdenable ()
73 {
74 int s = spltty();
75
76 /* collides with external ints from SCSI, watch out for this when
77 enabling/disabling interrupts there !! */
78 custom.intena = INTF_SETCLR | INTF_PORTS;
79 ciaa.icr = CIA_ICR_IR_SC | CIA_ICR_SP; /* SP interrupt enable */
80 ciaa.cra &= ~(1<<6); /* serial line == input */
81 kbd_softc.k_event_mode = 0;
82 kbd_softc.k_events.ev_io = 0;
83
84 splx (s);
85 }
86
87
88 int
89 kbdopen (dev_t dev, int flags, int mode, struct proc *p)
90 {
91 int s, error;
92
93 if (kbd_softc.k_events.ev_io)
94 return EBUSY;
95
96 kbd_softc.k_events.ev_io = p;
97 ev_init(&kbd_softc.k_events);
98 return (0);
99 }
100
101 int
102 kbdclose (dev_t dev, int flags, int mode, struct proc *p)
103 {
104 /* Turn off event mode, dump the queue */
105 kbd_softc.k_event_mode = 0;
106 ev_fini(&kbd_softc.k_events);
107 kbd_softc.k_events.ev_io = NULL;
108 return (0);
109 }
110
111 int
112 kbdread (dev_t dev, struct uio *uio, int flags)
113 {
114 return ev_read (&kbd_softc.k_events, uio, flags);
115 }
116
117 /* this routine should not exist, but is convenient to write here for now */
118 int
119 kbdwrite (dev_t dev, struct uio *uio, int flags)
120 {
121 return EOPNOTSUPP;
122 }
123
124 int
125 kbdioctl (dev_t dev, int cmd, register caddr_t data, int flag, struct proc *p)
126 {
127 register struct kbd_softc *k = &kbd_softc;
128
129 switch (cmd)
130 {
131 case KIOCTRANS:
132 if (*(int *)data == TR_UNTRANS_EVENT)
133 return 0;
134 break;
135
136 case KIOCGTRANS:
137 /*
138 * Get translation mode
139 */
140 *(int *)data = TR_UNTRANS_EVENT;
141 return 0;
142
143 case KIOCSDIRECT:
144 k->k_event_mode = *(int *)data;
145 return 0;
146
147 case FIONBIO: /* we will remove this someday (soon???) */
148 return 0;
149
150 case FIOASYNC:
151 k->k_events.ev_async = *(int *)data != 0;
152 return 0;
153
154 case TIOCSPGRP:
155 if (*(int *)data != k->k_events.ev_io->p_pgid)
156 return EPERM;
157 return 0;
158
159 default:
160 return ENOTTY;
161 }
162
163 /*
164 * We identified the ioctl, but we do not handle it.
165 */
166 return EOPNOTSUPP; /* misuse, but what the heck */
167 }
168
169 int
170 kbdselect (dev_t dev, int rw, struct proc *p)
171 {
172 return ev_select (&kbd_softc.k_events, rw, p);
173 }
174
175
176 int
177 kbdintr (mask)
178 int mask;
179 {
180 u_char c, in;
181 struct kbd_softc *k = &kbd_softc;
182 struct firm_event *fe;
183 int put;
184
185 /* now only invoked from generic CIA interrupt handler if there *is*
186 a keyboard interrupt pending */
187
188 in = ciaa.sdr;
189 /* ack */
190 ciaa.cra |= (1 << 6); /* serial line output */
191 /* wait 200 microseconds (for bloody Cherry keyboards..) */
192 DELAY(200);
193 ciaa.cra &= ~(1 << 6);
194
195 c = ~in; /* keyboard data is inverted */
196
197 /* process the character */
198
199 c = (c >> 1) | (c << 7); /* rotate right once */
200
201
202 /* XXX THIS IS WRONG!!! The screenblanker should route thru ite.c, which
203 should call thru it's driver table, ie. we need a new driver-dependant
204 function for this feature! */
205
206 cc_unblank ();
207
208 /* if not in event mode, deliver straight to ite to process key stroke */
209 if (! k->k_event_mode)
210 {
211 itefilter (c, ITEFILT_TTY);
212 return;
213 }
214
215 /* Keyboard is generating events. Turn this keystroke into an
216 event and put it in the queue. If the queue is full, the
217 keystroke is lost (sorry!). */
218
219 put = k->k_events.ev_put;
220 fe = &k->k_events.ev_q[put];
221 put = (put + 1) % EV_QSIZE;
222 if (put == k->k_events.ev_get)
223 {
224 log(LOG_WARNING, "keyboard event queue overflow\n"); /* ??? */
225 return;
226 }
227 fe->id = KEY_CODE(c);
228 fe->value = KEY_UP(c) ? VKEY_UP : VKEY_DOWN;
229 fe->time = time;
230 k->k_events.ev_put = put;
231 EV_WAKEUP(&k->k_events);
232 }
233
234
235 int
236 kbdbell()
237 {
238 /* nice, mykes provided audio-support! */
239 cc_bell ();
240 }
241
242
243 int
244 kbdgetcn ()
245 {
246 int s = spltty ();
247 u_char ints, mask, c, in;
248
249 for (ints = 0; ! ((mask = ciaa.icr) & CIA_ICR_SP); ints |= mask) ;
250
251 in = ciaa.sdr;
252 c = ~in;
253
254 /* ack */
255 ciaa.cra |= (1 << 6); /* serial line output */
256 ciaa.sdr = 0xff; /* ack */
257 /* wait 200 microseconds */
258 DELAY(200); /* XXXX only works as long as DELAY doesn't use a timer and waits.. */
259 ciaa.cra &= ~(1 << 6);
260 ciaa.sdr = in;
261
262 splx (s);
263 c = (c >> 1) | (c << 7);
264
265 /* take care that no CIA-interrupts are lost */
266 if (ints)
267 dispatch_cia_ints (0, ints);
268
269 return c;
270 }
271
272 void
273 kbdattach() {}
274 #endif
275