kbd.c revision 1.7 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 * $Id: kbd.c,v 1.7 1994/02/13 21:10:48 chopps Exp $
35 */
36
37 #include "ite.h"
38
39 #if NITE > 0
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/ioctl.h>
43 #include <sys/tty.h>
44 #include <sys/proc.h>
45 #include <sys/conf.h>
46 #include <sys/file.h>
47 #include <sys/uio.h>
48 #include <sys/kernel.h>
49 #include <sys/syslog.h>
50
51 #include <amiga/dev/device.h>
52 #include <amiga/dev/kbdreg.h>
53 #include <amiga/dev/itevar.h>
54 #include <machine/cpu.h>
55
56 #include <amiga/amiga/custom.h>
57 #include <amiga/amiga/cia.h>
58
59 /* for sun-like event mode, if you go thru /dev/kbd. */
60 #include <amiga/dev/event_var.h>
61 #include <amiga/dev/vuid_event.h>
62
63 struct kbd_softc {
64 int k_event_mode; /* if true, collect events, else pass to ite */
65 struct evvar k_events; /* event queue state */
66 } kbd_softc;
67
68 /* definitions for amiga keyboard encoding. */
69 #define KEY_CODE(c) ((c) & 0x7f)
70 #define KEY_UP(c) ((c) & 0x80)
71
72 void
73 kbdenable ()
74 {
75 int s = spltty();
76
77 /* collides with external ints from SCSI, watch out for this when
78 enabling/disabling interrupts there !! */
79 custom.intena = INTF_SETCLR | INTF_PORTS;
80 ciaa.icr = CIA_ICR_IR_SC | CIA_ICR_SP; /* SP interrupt enable */
81 ciaa.cra &= ~(1<<6); /* serial line == input */
82 kbd_softc.k_event_mode = 0;
83 kbd_softc.k_events.ev_io = 0;
84
85 splx (s);
86 }
87
88
89 int
90 kbdopen (dev_t dev, int flags, int mode, struct proc *p)
91 {
92 int s, error;
93
94 if (kbd_softc.k_events.ev_io)
95 return EBUSY;
96
97 kbd_softc.k_events.ev_io = p;
98 ev_init(&kbd_softc.k_events);
99 return (0);
100 }
101
102 int
103 kbdclose (dev_t dev, int flags, int mode, struct proc *p)
104 {
105 /* Turn off event mode, dump the queue */
106 kbd_softc.k_event_mode = 0;
107 ev_fini(&kbd_softc.k_events);
108 kbd_softc.k_events.ev_io = NULL;
109 return (0);
110 }
111
112 int
113 kbdread (dev_t dev, struct uio *uio, int flags)
114 {
115 return ev_read (&kbd_softc.k_events, uio, flags);
116 }
117
118 /* this routine should not exist, but is convenient to write here for now */
119 int
120 kbdwrite (dev_t dev, struct uio *uio, int flags)
121 {
122 return EOPNOTSUPP;
123 }
124
125 int
126 kbdioctl (dev_t dev, int cmd, register caddr_t data, int flag, struct proc *p)
127 {
128 register struct kbd_softc *k = &kbd_softc;
129
130 switch (cmd)
131 {
132 case KIOCTRANS:
133 if (*(int *)data == TR_UNTRANS_EVENT)
134 return 0;
135 break;
136
137 case KIOCGTRANS:
138 /*
139 * Get translation mode
140 */
141 *(int *)data = TR_UNTRANS_EVENT;
142 return 0;
143
144 case KIOCSDIRECT:
145 k->k_event_mode = *(int *)data;
146 return 0;
147
148 case FIONBIO: /* we will remove this someday (soon???) */
149 return 0;
150
151 case FIOASYNC:
152 k->k_events.ev_async = *(int *)data != 0;
153 return 0;
154
155 case TIOCSPGRP:
156 if (*(int *)data != k->k_events.ev_io->p_pgid)
157 return EPERM;
158 return 0;
159
160 default:
161 return ENOTTY;
162 }
163
164 /*
165 * We identified the ioctl, but we do not handle it.
166 */
167 return EOPNOTSUPP; /* misuse, but what the heck */
168 }
169
170 int
171 kbdselect (dev_t dev, int rw, struct proc *p)
172 {
173 return ev_select (&kbd_softc.k_events, rw, p);
174 }
175
176
177 int
178 kbdintr (mask)
179 int mask;
180 {
181 u_char c, in;
182 struct kbd_softc *k = &kbd_softc;
183 struct firm_event *fe;
184 int put;
185
186 /* now only invoked from generic CIA interrupt handler if there *is*
187 a keyboard interrupt pending */
188
189 in = ciaa.sdr;
190 /* ack */
191 ciaa.cra |= (1 << 6); /* serial line output */
192 /* wait 200 microseconds (for bloody Cherry keyboards..) */
193 DELAY(200);
194 ciaa.cra &= ~(1 << 6);
195
196 c = ~in; /* keyboard data is inverted */
197
198 /* process the character */
199
200 c = (c >> 1) | (c << 7); /* rotate right once */
201
202
203 /* XXX THIS IS WRONG!!! The screenblanker should route thru ite.c, which
204 should call thru it's driver table, ie. we need a new driver-dependant
205 function for this feature! */
206
207 cc_unblank ();
208
209 /* if not in event mode, deliver straight to ite to process key stroke */
210 if (! k->k_event_mode)
211 {
212 itefilter (c, ITEFILT_TTY);
213 return;
214 }
215
216 /* Keyboard is generating events. Turn this keystroke into an
217 event and put it in the queue. If the queue is full, the
218 keystroke is lost (sorry!). */
219
220 put = k->k_events.ev_put;
221 fe = &k->k_events.ev_q[put];
222 put = (put + 1) % EV_QSIZE;
223 if (put == k->k_events.ev_get)
224 {
225 log(LOG_WARNING, "keyboard event queue overflow\n"); /* ??? */
226 return;
227 }
228 fe->id = KEY_CODE(c);
229 fe->value = KEY_UP(c) ? VKEY_UP : VKEY_DOWN;
230 fe->time = time;
231 k->k_events.ev_put = put;
232 EV_WAKEUP(&k->k_events);
233 }
234
235
236 int
237 kbdbell()
238 {
239 /* nice, mykes provided audio-support! */
240 cc_bell ();
241 }
242
243
244 int
245 kbdgetcn ()
246 {
247 int s = spltty ();
248 u_char ints, mask, c, in;
249
250 for (ints = 0; ! ((mask = ciaa.icr) & CIA_ICR_SP); ints |= mask) ;
251
252 in = ciaa.sdr;
253 c = ~in;
254
255 /* ack */
256 ciaa.cra |= (1 << 6); /* serial line output */
257 ciaa.sdr = 0xff; /* ack */
258 /* wait 200 microseconds */
259 DELAY(200); /* XXXX only works as long as DELAY doesn't use a timer and waits.. */
260 ciaa.cra &= ~(1 << 6);
261 ciaa.sdr = in;
262
263 splx (s);
264 c = (c >> 1) | (c << 7);
265
266 /* take care that no CIA-interrupts are lost */
267 if (ints)
268 dispatch_cia_ints (0, ints);
269
270 return c;
271 }
272
273 void
274 kbdattach() {}
275 #endif
276