xref: /original-bsd/sys/vax/vax/cons.c (revision 1eabc47f)
1 /*
2  * Copyright (c) 1982, 1986 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  *
6  *	@(#)cons.c	7.8 (Berkeley) 09/05/89
7  */
8 
9 /*
10  * VAX console driver (and floppy interface)
11  */
12 #include "param.h"
13 #include "conf.h"
14 #include "dir.h"
15 #include "user.h"
16 #include "proc.h"
17 #include "ioctl.h"
18 #include "tty.h"
19 #include "systm.h"
20 #include "uio.h"
21 
22 #include "cpu.h"
23 #include "cons.h"
24 #include "mtpr.h"
25 
26 /*
27  * On some machines (e.g. MicroVAX), a secondary console
28  * such as a display may supercede the standard serial console.
29  * On such machines, consops will be set to point to the cdevsw
30  * entry for the secondary console, and the standard console device
31  * (minor number 0) will be redirected.  Other minor numbers still
32  * refer to the standard console serial line.
33  *
34  * Also, console output may be redirected to another tty
35  * (e.g. a window); if so, constty will point to the current
36  * virtual console.
37  */
38 struct	cdevsw *consops = 0;
39 struct	tty *constty = 0;
40 struct	tty cons;
41 int	cnstart();
42 int	ttrstrt();
43 char	partab[];
44 
45 /*ARGSUSED*/
46 cnopen(dev, flag)
47 	dev_t dev;
48 {
49 	register struct tty *tp = &cons;
50 
51 	if (consops && minor(dev) == 0)
52 		return ((*consops->d_open)(dev, flag));
53 	tp->t_oproc = cnstart;
54 	if ((tp->t_state&TS_ISOPEN) == 0) {
55 		ttychars(tp);
56 		tp->t_iflag = TTYDEF_IFLAG|ICRNL;
57 		tp->t_oflag = TTYDEF_OFLAG|OPOST|ONLCR;
58 		tp->t_lflag = TTYDEF_LFLAG;
59 		tp->t_cflag = CS8|CREAD;
60 		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
61 		tp->t_state = TS_ISOPEN|TS_CARR_ON;
62 		ttsetwater(tp);
63 	}
64 	if (tp->t_state&TS_XCLUDE && u.u_uid != 0)
65 		return (EBUSY);
66 	mtpr(RXCS, mfpr(RXCS)|RXCS_IE);
67 	mtpr(TXCS, mfpr(TXCS)|TXCS_IE);
68 	return ((*linesw[tp->t_line].l_open)(dev, tp));
69 }
70 
71 /*ARGSUSED*/
72 cnclose(dev)
73 	dev_t dev;
74 {
75 	register struct tty *tp = &cons;
76 
77 	if (consops && minor(dev) == 0)
78 		return ((*consops->d_close)(dev));
79 	(*linesw[tp->t_line].l_close)(tp);
80 	ttyclose(tp);
81 	return (0);
82 }
83 
84 /*ARGSUSED*/
85 cnread(dev, uio, flag)
86 	dev_t dev;
87 	struct uio *uio;
88 	int flag;
89 {
90 	register struct tty *tp = &cons;
91 
92 	if (consops && minor(dev) == 0)
93 		return ((*consops->d_read)(dev, uio, flag));
94 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
95 }
96 
97 /*ARGSUSED*/
98 cnwrite(dev, uio, flag)
99 	dev_t dev;
100 	struct uio *uio;
101 	int flag;
102 {
103 	register struct tty *tp = &cons;
104 
105 	if (minor(dev) == 0) {
106 		if (constty && (constty->t_state & (TS_CARR_ON | TS_ISOPEN)) ==
107 		    (TS_CARR_ON | TS_ISOPEN))
108 			tp = constty;
109 		else if (consops)
110 			return ((*consops->d_write)(dev, uio, flag));
111 	}
112 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
113 }
114 
115 static	int cnpolling = 0;
116 /*
117  * Got a level-20 receive interrupt -
118  * the LSI wants to give us a character.
119  * Catch the character, and see who it goes to.
120  */
121 /*ARGSUSED*/
122 cnrint(dev)
123 	dev_t dev;
124 {
125 	register int c;
126 	register struct tty *tp;
127 
128 	if (cnpolling)
129 		return;
130 	c = mfpr(RXDB)&0xff;
131 	if (c&RXDB_ID) {
132 #if VAX780
133 		if (cpu == VAX_780)
134 			cnrfl(c);
135 #endif
136 		return;
137 	}
138 	tp = &cons;
139 #ifdef KADB
140 	if (!kdbrintr(c, tp))
141 #endif
142 	if ((tp->t_cflag&CSIZE) == CS7) {
143 #ifdef notyet
144 		if (tp->t_cflag&PARENB) {
145 			if ((tp->t_cflag&PARODD) &&
146 			    (partab[c&0177]&0200) == (c&0200))
147 				c |= TTY_PE;
148 			else if ((partab[c&0177]&0200) != (c&0200))
149 				c |= TTY_PE;
150 		}
151 #endif
152 		c &= ~0200;
153 	}
154 	(*linesw[tp->t_line].l_rint)(c, tp);
155 }
156 
157 /*ARGSUSED*/
158 cnioctl(dev, cmd, addr, flag)
159 	dev_t dev;
160 	caddr_t addr;
161 {
162 	register struct tty *tp = &cons;
163 	int error;
164 
165 	if (consops && minor(dev) == 0)
166 		return ((*consops->d_ioctl)(dev, cmd, addr, flag));
167 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr);
168 	if (error >= 0)
169 		return (error);
170 	error = ttioctl(tp, cmd, addr, flag);
171 	if (error < 0)
172 		error = ENOTTY;
173 	return (error);
174 }
175 
176 int	consdone = 1;
177 /*
178  * Got a level-20 transmission interrupt -
179  * the LSI wants another character.  First,
180  * see if we can send something to the typewriter.
181  * If not, try the floppy.
182  */
183 /*ARGSUSED*/
184 cnxint(dev)
185 	dev_t dev;
186 {
187 	register struct tty *tp = &cons;
188 
189 	consdone++;
190 	tp->t_state &= ~TS_BUSY;
191 	if (tp->t_line)
192 		(*linesw[tp->t_line].l_start)(tp);
193 	else
194 		cnstart(tp);
195 #if VAX780
196 	if (cpu==VAX_780 && (tp->t_state & TS_BUSY) == 0)
197 		conxfl();
198 #endif
199 }
200 
201 cnstart(tp)
202 	register struct tty *tp;
203 {
204 	register int c, s;
205 
206 	s = spl5();
207 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
208 		goto out;
209 	if (tp->t_outq.c_cc <= tp->t_lowat) {
210 		if (tp->t_state&TS_ASLEEP) {
211 			tp->t_state &= ~TS_ASLEEP;
212 			wakeup((caddr_t)&tp->t_outq);
213 		}
214 		if (tp->t_wsel) {
215 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
216 			tp->t_wsel = 0;
217 			tp->t_state &= ~TS_WCOLL;
218 		}
219 	}
220 	if (tp->t_outq.c_cc == 0)
221 		goto out;
222 	if (consdone == 0)
223 		goto out;
224 	c = getc(&tp->t_outq) & 0xff;
225 #ifdef notdef
226 	if (tp->t_cflag&PARENB && ((tp->t_cflag&CSIZE)==CS7)) {
227 		c &= 0177;
228 		c |= (tp->t_cflag&PARODD ? ~partab[c] : partab[c]) & 0200;
229 		}
230 #else
231 	if ((tp->t_cflag&CSIZE) == CS7) {
232 #ifdef notyet
233 		if (tp->t_cflag&PARENB) {
234 			if (tp->t_cflag&PARODD)
235 				c = (~(partab[c&0177])&0200)|(c&0177);
236 			else
237 				c = (partab[c&0177]&0200)|(c&0177);
238 		} else
239 #endif
240 			c &= 0177;
241 	}
242 #endif
243 	mtpr(TXDB, c);
244 	consdone = 0;
245 	tp->t_state |= TS_BUSY;
246 out:
247 	splx(s);
248 }
249 
250 /*
251  * Print a character on console.
252  * Attempts to save and restore device
253  * status.
254  */
255 cnputc(c)
256 	register int c;
257 {
258 	register int s, timo;
259 
260 	timo = 30000;
261 	/*
262 	 * Try waiting for the console tty to come ready,
263 	 * otherwise give up after a reasonable time.
264 	 */
265 	while ((mfpr(TXCS)&TXCS_RDY) == 0)
266 		if(--timo == 0)
267 			break;
268 	if (c == 0)
269 		return;
270 	s = mfpr(TXCS);
271 	mtpr(TXCS, 0);
272 	mtpr(TXDB, c&0xff);
273 	if (c == '\n')
274 		cnputc('\r');
275 	cnputc(0);
276 	mtpr(TXCS, s);
277 }
278 
279 #if (defined(KADB) || defined(GENERIC)) && !defined(lint)
280 /*
281  * Get character from console.
282  */
283 cngetc()
284 {
285 	register int c, s;
286 
287 	s = splhigh();
288 	while ((mfpr(RXCS)&RXCS_DONE) == 0 || (c = mfpr(RXDB)&0177) <= 0)
289 		;
290 	if (c == '\r')
291 		c = '\n';
292 	(void) splx(s);
293 	return (c);
294 }
295 #endif
296 
297 #ifdef KADB
298 cnpoll(onoff)
299 	int onoff;
300 {
301 
302 	cnpolling = onoff;
303 }
304 #endif
305