xref: /original-bsd/sys/luna68k/dev/kbd.c (revision 21eed380)
1 /*
2  * Copyright (c) 1992 OMRON Corporation.
3  * Copyright (c) 1992 The Regents of the University of California.
4  * 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	7.6 (Berkeley) 02/04/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__
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*/
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 
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
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 
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
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 
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 
305 kbdselect(dev, rw, p)
306 	dev_t dev;
307 	int rw;
308 	struct proc *p;
309 {
310 	register int unit = kbdunit(dev);
311 	register struct tty *tp;
312 	int nread;
313 	int s = spltty();
314 
315 	tp = &kbd_tty[unit];
316 
317 	switch (rw) {
318 
319 	case FREAD:
320 		nread = ttnread(tp);
321 		if (nread > 0 || ((tp->t_cflag&CLOCAL) == 0 && (tp->t_state&TS_CARR_ON) == 0))
322 			goto win;
323 
324 		selrecord(p, &tp->t_rsel);
325 		break;
326 
327 	case FWRITE:
328 		if (tp->t_outq.c_cc <= tp->t_lowat)
329 			goto win;
330 		selrecord(p, &tp->t_wsel);
331 		break;
332 	}
333 	splx(s);
334 	return (0);
335 win:
336 	splx(s);
337 	return (1);
338 }
339