1 /*
2 * Copyright (c) 1992 OMRON Corporation.
3 * Copyright (c) 1992, 1993
4 * The Regents of the University of California. All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * OMRON Corporation.
8 *
9 * %sccs.include.redist.c%
10 *
11 * @(#)kbd.c 8.2 (Berkeley) 12/06/93
12 */
13
14 /*
15 * kbd.c -- keyboard device driver
16 * remade by A.Fujita, DEC-21-1992
17 */
18
19 #define NKBD 2
20
21 #include <sys/param.h>
22 #include <sys/systm.h>
23 #include <sys/ioctl.h>
24 #include <sys/proc.h>
25 #include <sys/tty.h>
26 #include <sys/conf.h>
27 #include <sys/file.h>
28 #include <sys/uio.h>
29 #include <sys/kernel.h>
30 #include <sys/syslog.h>
31
32 #include <luna68k/dev/device.h>
33 #include <luna68k/dev/sioreg.h>
34 #include <luna68k/dev/siovar.h>
35 #include <luna68k/dev/kbio.h>
36
37 extern struct sio_portc *sio_port_assign();
38 extern struct sio_portc *sio_port_get();
39
40 struct sio_softc kbd_softc[NKBD];
41 struct sio_portc kbd_sport;
42 struct sio_portc *kbd_pc;
43
44 int kbdopen();
45 void kbdstart();
46 int kbdparam();
47 int kbdintr();
48
49 struct tty kbd_tty[NKBD];
50
51 int kbddefaultrate = B9600; /* speed of console line is fixed */
52 int kbdmajor = 14;
53 int kbd_state = 0;
54
55 #define kbdunit(x) minor(x)
56
57 /*
58 * entry routines
59 */
60
61 /* ARGSUSED */
62 #ifdef __STDC__
kbdopen(dev_t dev,int flag,int mode,struct proc * p)63 kbdopen(dev_t dev, int flag, int mode, struct proc *p)
64 #else
65 kbdopen(dev, flag, mode, p)
66 dev_t dev;
67 int flag, mode;
68 struct proc *p;
69 #endif
70 {
71 register struct tty *tp;
72 register int unit, s;
73 register struct sio_portc *pc;
74 int error = 0;
75
76 unit = kbdunit(dev);
77
78 if (unit != 0)
79 return (ENXIO);
80
81 if (kbd_state == 0) {
82 s = splhigh();
83 pc = sio_port_get(1);
84 kbd_sport = *pc;
85 kbd_pc = sio_port_assign(1, kbdmajor, unit, kbdintr);
86 splx(s);
87 }
88 kbd_softc[unit].sc_pc = kbd_pc;
89 kbd_state |= 1 << unit;
90
91 tp = &kbd_tty[unit];
92 tp->t_oproc = kbdstart;
93 tp->t_param = kbdparam;
94 tp->t_dev = dev;
95 if ((tp->t_state & TS_ISOPEN) == 0) {
96 tp->t_state |= TS_WOPEN;
97 ttychars(tp);
98 if (tp->t_ispeed == 0) {
99 /*
100 tp->t_iflag = TTYDEF_IFLAG;
101 tp->t_oflag = TTYDEF_OFLAG;
102 tp->t_cflag = TTYDEF_CFLAG;
103 tp->t_lflag = TTYDEF_LFLAG;
104 */
105 tp->t_iflag = 0;
106 tp->t_oflag = 0;
107 tp->t_cflag = (CREAD | CS8 | HUPCL);
108 tp->t_lflag = 0;
109
110 tp->t_ispeed = tp->t_ospeed = kbddefaultrate;
111 }
112 ttsetwater(tp);
113 } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
114 return (EBUSY);
115
116 tp->t_state |= TS_CARR_ON;
117
118 if (error == 0)
119 error = (*linesw[tp->t_line].l_open)(dev, tp);
120
121 return (error);
122 }
123
124 /*ARGSUSED*/
kbdclose(dev,flag,mode,p)125 kbdclose(dev, flag, mode, p)
126 dev_t dev;
127 int flag, mode;
128 struct proc *p;
129 {
130 register struct siodevice *sio = kbd_pc->pc_addr;
131 register struct sio_portc *pc;
132 register struct tty *tp;
133 register int unit, s;
134 int code, rr;
135
136 unit = kbdunit(dev);
137
138 tp = &kbd_tty[unit];
139 (*linesw[tp->t_line].l_close)(tp, flag);
140 ttyclose(tp);
141
142 kbd_state &= ~(1 << unit);
143
144 if (kbd_state == 0) {
145 s = splhigh();
146
147 while((rr = siogetreg(sio)) & RR_RXRDY) {
148 code = sio->sio_data;
149 DELAY(100);
150 }
151
152 pc = &kbd_sport;
153 (void) sio_port_assign(1, pc->pc_major, pc->pc_unit, pc->pc_intr);
154 splx(s);
155 }
156
157 return (0);
158 }
159
kbdread(dev,uio,flag)160 kbdread(dev, uio, flag)
161 dev_t dev;
162 struct uio *uio;
163 {
164 register struct tty *tp = &kbd_tty[kbdunit(dev)];
165
166 return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
167 }
168
169 int
kbdparam(tp,t)170 kbdparam(tp, t)
171 register struct tty *tp;
172 register struct termios *t;
173 {
174 int unit = kbdunit(tp->t_dev);
175 register struct sio_softc *sc = &kbd_softc[unit];
176 register int cflag = t->c_cflag;
177
178 /* and copy to tty */
179 tp->t_ispeed = t->c_ispeed;
180 tp->t_ospeed = t->c_ospeed;
181 tp->t_cflag = cflag;
182
183 /*
184 * change line speed
185 */
186
187 /*
188 * parity
189 */
190
191 /*
192 * stop bit
193 */
194
195 return (0);
196 }
197
kbdioctl(dev,cmd,data,flag,p)198 kbdioctl(dev, cmd, data, flag, p)
199 dev_t dev;
200 int cmd;
201 caddr_t data;
202 int flag;
203 struct proc *p;
204 {
205 register struct siodevice *sio = kbd_pc->pc_addr;
206 register struct tty *tp;
207 register int unit = kbdunit(dev);
208 register int error;
209 int code, rr, s;
210
211 tp = &kbd_tty[unit];
212 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
213 if (error >= 0)
214 return (error);
215 error = ttioctl(tp, cmd, data, flag);
216 if (error >= 0)
217 return (error);
218
219 switch (cmd) {
220
221 case KIOCMOUSE:
222 if (*((int *) data)) {
223 sio->sio_data = 0x60; /* enable mouse tracking */
224 } else {
225 s = splhigh();
226 sio->sio_data = 0x20; /* disable mouse tracking */
227 while((rr = siogetreg(sio)) & RR_RXRDY) {
228 code = sio->sio_data;
229 DELAY(100);
230 }
231 splx(s);
232 }
233 break;
234
235 default:
236 return (ENOTTY);
237 }
238 return (0);
239 }
240
241 /*
242 *
243 */
244 void
kbdstart(tp)245 kbdstart(tp)
246 register struct tty *tp;
247 {
248 register int unit;
249 register struct siodevice *sio = kbd_pc->pc_addr;
250 register int rr;
251 int s, c;
252
253 s = spltty();
254
255 if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP))
256 goto out;
257
258 if (tp->t_outq.c_cc <= tp->t_lowat) {
259 if (tp->t_state&TS_ASLEEP) {
260 tp->t_state &= ~TS_ASLEEP;
261 wakeup((caddr_t)&tp->t_outq);
262 }
263 selwakeup(&tp->t_wsel);
264 }
265
266 if (tp->t_outq.c_cc != 0)
267 c = getc(&tp->t_outq);
268
269 out:
270 splx(s);
271 }
272
273 /*
274 * interrupt handling
275 */
276
kbdintr(unit)277 kbdintr(unit)
278 register int unit;
279 {
280 register struct siodevice *sio = kbd_pc->pc_addr;
281 register struct tty *tp;
282 register u_char code;
283 int s, rr;
284
285 tp = &kbd_tty[0]; /* Keyboard */
286 rr = siogetreg(sio);
287
288 if (rr & RR_RXRDY) {
289 code = sio->sio_data;
290 if ((tp->t_state & TS_ISOPEN) != 0)
291 (*linesw[tp->t_line].l_rint)(code, tp);
292
293 while ((rr = siogetreg(sio)) & RR_RXRDY) {
294 code = sio->sio_data;
295 if ((tp->t_state & TS_ISOPEN) != 0)
296 (*linesw[tp->t_line].l_rint)(code, tp);
297 }
298 }
299
300 if (rr & RR_TXRDY) {
301 sio->sio_cmd = WR0_RSTPEND;
302 }
303 }
304