xref: /original-bsd/sys/vax/vax/cons.c (revision c577960b)
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.5 (Berkeley) 05/07/88
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_state = TS_ISOPEN|TS_CARR_ON;
57 		tp->t_flags = EVENP|ECHO|XTABS|CRMOD;
58 	}
59 	if (tp->t_state&TS_XCLUDE && u.u_uid != 0)
60 		return (EBUSY);
61 	mtpr(RXCS, mfpr(RXCS)|RXCS_IE);
62 	mtpr(TXCS, mfpr(TXCS)|TXCS_IE);
63 	return ((*linesw[tp->t_line].l_open)(dev, tp));
64 }
65 
66 /*ARGSUSED*/
67 cnclose(dev)
68 	dev_t dev;
69 {
70 	register struct tty *tp = &cons;
71 
72 	if (consops && minor(dev) == 0)
73 		return ((*consops->d_close)(dev));
74 	(*linesw[tp->t_line].l_close)(tp);
75 	ttyclose(tp);
76 	return (0);
77 }
78 
79 /*ARGSUSED*/
80 cnread(dev, uio)
81 	dev_t dev;
82 	struct uio *uio;
83 {
84 	register struct tty *tp = &cons;
85 
86 	if (consops && minor(dev) == 0)
87 		return ((*consops->d_read)(dev, uio));
88 	return ((*linesw[tp->t_line].l_read)(tp, uio));
89 }
90 
91 /*ARGSUSED*/
92 cnwrite(dev, uio)
93 	dev_t dev;
94 	struct uio *uio;
95 {
96 	register struct tty *tp = &cons;
97 
98 	if (minor(dev) == 0) {
99 		if (constty && (constty->t_state & (TS_CARR_ON | TS_ISOPEN)) ==
100 		    (TS_CARR_ON | TS_ISOPEN))
101 			tp = constty;
102 		else if (consops)
103 			return ((*consops->d_write)(dev, uio));
104 	}
105 	return ((*linesw[tp->t_line].l_write)(tp, uio));
106 }
107 
108 static	int cnpolling = 0;
109 /*
110  * Got a level-20 receive interrupt -
111  * the LSI wants to give us a character.
112  * Catch the character, and see who it goes to.
113  */
114 /*ARGSUSED*/
115 cnrint(dev)
116 	dev_t dev;
117 {
118 	register int c;
119 	register struct tty *tp;
120 
121 	if (cnpolling)
122 		return;
123 	c = mfpr(RXDB);
124 	if (c&RXDB_ID) {
125 #if VAX780
126 		if (cpu == VAX_780)
127 			cnrfl(c);
128 #endif
129 		return;
130 	}
131 	tp = &cons;
132 #ifdef KADB
133 	if (!kdbrintr(c, tp))
134 #endif
135 	(*linesw[tp->t_line].l_rint)(c, tp);
136 }
137 
138 /*ARGSUSED*/
139 cnioctl(dev, cmd, addr, flag)
140 	dev_t dev;
141 	caddr_t addr;
142 {
143 	register struct tty *tp = &cons;
144 	int error;
145 
146 	if (consops && minor(dev) == 0)
147 		return ((*consops->d_ioctl)(dev, cmd, addr, flag));
148 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr);
149 	if (error >= 0)
150 		return (error);
151 	error = ttioctl(tp, cmd, addr, flag);
152 	if (error < 0)
153 		error = ENOTTY;
154 	return (error);
155 }
156 
157 int	consdone = 1;
158 /*
159  * Got a level-20 transmission interrupt -
160  * the LSI wants another character.  First,
161  * see if we can send something to the typewriter.
162  * If not, try the floppy.
163  */
164 /*ARGSUSED*/
165 cnxint(dev)
166 	dev_t dev;
167 {
168 	register struct tty *tp = &cons;
169 
170 	consdone++;
171 	tp->t_state &= ~TS_BUSY;
172 	if (tp->t_line)
173 		(*linesw[tp->t_line].l_start)(tp);
174 	else
175 		cnstart(tp);
176 #if VAX780
177 	if (cpu==VAX_780 && (tp->t_state & TS_BUSY) == 0)
178 		conxfl();
179 #endif
180 }
181 
182 cnstart(tp)
183 	register struct tty *tp;
184 {
185 	register int c, s;
186 
187 	s = spl5();
188 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
189 		goto out;
190 	if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
191 		if (tp->t_state&TS_ASLEEP) {
192 			tp->t_state &= ~TS_ASLEEP;
193 			wakeup((caddr_t)&tp->t_outq);
194 		}
195 		if (tp->t_wsel) {
196 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
197 			tp->t_wsel = 0;
198 			tp->t_state &= ~TS_WCOLL;
199 		}
200 	}
201 	if (tp->t_outq.c_cc == 0)
202 		goto out;
203 	if (consdone == 0)
204 		goto out;
205 	c = getc(&tp->t_outq) & 0xff;
206 	if ((tp->t_flags & (RAW|LITOUT)) == 0) {
207 		if (c <= 0177)
208 			c |= (partab[c] & 0200);
209 		else {
210 			timeout(ttrstrt, (caddr_t)tp, (c&0177));
211 			tp->t_state |= TS_TIMEOUT;
212 			goto out;
213 		}
214 	}
215 	mtpr(TXDB, c);
216 	consdone = 0;
217 	tp->t_state |= TS_BUSY;
218 out:
219 	splx(s);
220 }
221 
222 /*
223  * Print a character on console.
224  * Attempts to save and restore device
225  * status.
226  */
227 cnputc(c)
228 	register int c;
229 {
230 	register int s, timo;
231 
232 	timo = 30000;
233 	/*
234 	 * Try waiting for the console tty to come ready,
235 	 * otherwise give up after a reasonable time.
236 	 */
237 	while ((mfpr(TXCS)&TXCS_RDY) == 0)
238 		if(--timo == 0)
239 			break;
240 	if (c == 0)
241 		return;
242 	s = mfpr(TXCS);
243 	mtpr(TXCS, 0);
244 	mtpr(TXDB, c&0xff);
245 	if (c == '\n')
246 		cnputc('\r');
247 	cnputc(0);
248 	mtpr(TXCS, s);
249 }
250 
251 #if (defined(KADB) || defined(GENERIC)) && !defined(lint)
252 /*
253  * Get character from console.
254  */
255 cngetc()
256 {
257 	register int c, s;
258 
259 	s = splhigh();
260 	while ((mfpr(RXCS)&RXCS_DONE) == 0 || (c = mfpr(RXDB)&0177) <= 0)
261 		;
262 	if (c == '\r')
263 		c = '\n';
264 	(void) splx(s);
265 	return (c);
266 }
267 #endif
268 
269 #ifdef KADB
270 cnpoll(onoff)
271 	int onoff;
272 {
273 
274 	cnpolling = onoff;
275 }
276 #endif
277