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