xref: /original-bsd/sys/vax/stand/qvcons.c (revision b7cc7b86)
1 /*
2  * Copyright (c) 1988 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)qvcons.c	7.7 (Berkeley) 12/16/90
8  */
9 
10 /*
11  *	derived from: @(#)qvcons.c	4.1 11/23/87
12  */
13 
14 /************************************************************************
15  *									*
16  *			Copyright (c) 1985 by				*
17  *		Digital Equipment Corporation, Maynard, MA		*
18  *			All rights reserved.				*
19  *									*
20  *   This software is furnished under a license and may be used and	*
21  *   copied  only  in accordance with the terms of such license and	*
22  *   with the  inclusion  of  the  above  copyright  notice.   This	*
23  *   software  or  any  other copies thereof may not be provided or	*
24  *   otherwise made available to any other person.  No title to and	*
25  *   ownership of the software is hereby transferred.			*
26  *									*
27  *   This software is  derived  from  software  received  from  the	*
28  *   University    of   California,   Berkeley,   and   from   Bell	*
29  *   Laboratories.  Use, duplication, or disclosure is  subject  to	*
30  *   restrictions  under  license  agreements  with  University  of	*
31  *   California and with AT&T.						*
32  *									*
33  *   The information in this software is subject to change  without	*
34  *   notice  and should not be construed as a commitment by Digital	*
35  *   Equipment Corporation.						*
36  *									*
37  *   Digital assumes no responsibility for the use  or  reliability	*
38  *   of its software on equipment which is not supplied by Digital.	*
39  *									*
40  ************************************************************************/
41 
42 /* ---------------------------------------------------------------------
43  * Modification History - moved to sccs log
44  *
45  *  7 Jul 84 --  rjl
46  *	Initial version to support the qvss as the system console
47  *	during the boot process.
48  *
49  * ---------------------------------------------------------------------
50  */
51 
52 #include "sys/types.h"
53 #define KERNEL
54 #include "../uba/qvioctl.h"
55 #undef KERNEL
56 #include "../include/cpu.h"
57 
58 /*
59  * MicroVAX-II q-bus memory base
60  */
61 #define QMEMBASE 0x30000000
62 #define QVMAXEVQ	64
63 #define QVSSCSR 0x20001e80
64 
65 /*
66  * Screen initialization tables. qv_def_scn is used as an index into the
67  * table to select the proper initialization parameters.
68  */
69 int qv_def_scn = 1;			/* Screen initialization flag	*/
70 
71 char	qv_scrn_15[]= {
72 	31,25,27,0142,31,13,30,31,4,15,040,0,0,0,0,0
73 };
74 
75 char	qv_scrn_19s[]= {
76 	39,30,31,0264,55,5,54,54,4,15,040,0,0,0,0,0
77 };
78 
79 char	*qv_init_tbl[]= {
80 	qv_scrn_15,
81 	qv_scrn_19s,
82 };
83 
84 struct qv_info qv_scn_defaults[] = {
85 	{0, {0, 0}, 0, {0, 0}, 0, 0, 30, 80, 768, 480, 768-16, 480-16,
86 	 0, 0, 0, 0, 0, QVMAXEVQ, 0, 0, {0, 0}, {0, 0, 0, 0}, 2, 4},
87 	{0, {0, 0}, 0, {0, 0}, 0, 0, 55, 120, 960, 864, 960-16, 864-16,
88 	 0, 0, 0, 0, 0, QVMAXEVQ, 0, 0, {0, 0}, {0, 0, 0, 0}, 2, 4},
89 	{0, {0, 0}, 0, {0, 0}, 0, 0, 56, 120,1024, 864,1024-16, 864-16,
90 	 0, 0, 0, 0, 0, QVMAXEVQ, 0, 0, {0, 0}, {0, 0, 0, 0}, 2, 4}
91 };
92 
93 struct qv_info  qv_scn;
94 
95 struct qv_keyboard {
96 	int shift;			/* state variables	*/
97 	int cntrl;
98 	int lock;
99 	char last;			/* last character	*/
100 } qv_keyboard;
101 
102 int qvputc(),qvgetc();
103 
104 /*
105  * Keyboard translation and font tables
106  */
107 extern  char q_key[],q_shift_key[],*q_special[],q_font[];
108 extern	short q_cursor[];
109 
110 extern (*v_putc)(),(*v_getc)();
111 
112 /*
113  * Routine called to init a qvss.
114  */
115 qv_init()
116 {
117 	struct qvdevice *qvaddr = (struct qvdevice *)QVSSCSR;
118 	char *qvssmem;
119 	short *scanline;
120 	int i;
121 	short scan;
122 	char *ptr;
123 	extern int cpu;
124 
125         if( badaddr( qvaddr, sizeof(short) ) )
126                 return(0);
127 
128         if( qvaddr->qv_csr & QV_19INCH )
129                 qv_def_scn = 1;
130         else
131                 qv_def_scn = 0;
132         qv_scn = qv_scn_defaults[ qv_def_scn ];
133 	qv_scn.qvaddr = qvaddr;
134 
135 	/*
136 	 * Initialize the screen.
137 	 */
138 	ptr = qv_init_tbl[ qv_def_scn ];
139 	for( i=0 ; i<16 ; i++ ) {
140 		qvaddr->qv_crtaddr = i;
141 		qvaddr->qv_crtdata = *ptr++;
142 	}
143 
144 	/*
145 	 * Turn on the keyboard.
146 	 */
147 	qvaddr->qv_uartcmd = 0x15;	/* set mode pntr/enable rx/tx	*/
148 	qvaddr->qv_uartmode = 0x17;	/* noparity, 8-bit		*/
149 	qvaddr->qv_uartmode = 0x07;	/* 1 stop bit			*/
150 	qvaddr->qv_uartstatus = 0x99;	/* 4800 baud xmit/recv 		*/
151 
152 	qvssmem = (char *)((qvaddr->qv_csr & QV_MEM_BANK) << 7);
153 	if( cpu == VAX_630 )
154 		qvssmem += QMEMBASE;
155 
156 	qv_scn.bitmap = qvssmem;
157 	qv_scn.scanmap = (short *)((int)qvssmem + ( 254 * 1024 ));
158 	qv_scn.cursorbits = (short *)((int)qvssmem + ( 256 * 1024 ) - 32);
159 
160 	/*
161 	 * Setup the cursor.
162 	 */
163 	for( i=0 ; i<16 ; i++ )
164 		qv_scn.cursorbits[i] = q_cursor[i];
165 
166 	/*
167 	 * Clear the bit map
168 	 */
169 	for( i=0 , ptr = qv_scn.bitmap ; i<254 ; i += 2 , ptr += 2048)
170 		bzero( ptr, 2048 );
171 
172 	/*
173 	 * Reinitialize the scanmap
174 	 */
175 	scan = qv_scn.qvaddr->qv_csr & QV_MEM_BANK;
176 	scanline = qv_scn.scanmap;
177 	for(i = 0 ; i < qv_scn.max_y ; i++ )
178 		*scanline++ = scan++;
179 
180 	/*
181 	 * Home the cursor
182 	 */
183 	qv_scn.row = qv_scn.col = 0;
184 
185 	/*
186 	 * Turn it on.
187 	 */
188 	v_getc = qvgetc;
189 	v_putc = qvputc;
190 	qvaddr->qv_csr |= QV_CUR_MODE | QV_VIDEO_ENA;
191 	return 1;
192 }
193 
194 /*
195  * Routine to display a character on the screen.  The model used is a
196  * glass tty.  It is assummed that the user will only use this emulation
197  * during system boot and that the screen will be eventually controlled
198  * by a window manager.
199  */
200 qvputc( c )
201 char c;
202 {
203 
204 	char *b_row, *f_row;
205 	int i, j;
206 	short *scanline;
207 
208 	c &= 0x7f;
209 
210 	switch ( c ) {
211 	case '\t':				/* tab		*/
212 		for( j = 8 - (qv_scn.col & 0x7) ; j > 0 ; j-- )
213 			qvputc( ' ' );
214 		break;
215 
216 	case '\r':				/* return	*/
217 		qv_scn.col = 0;
218 		break;
219 
220 	case '\010':				/* backspace	*/
221 		if( --qv_scn.col < 0 )
222 			qv_scn.col = 0;
223 		break;
224 
225 	case '\n':				/* linefeed	*/
226 		if( qv_scn.row+1 >= qv_scn.max_row )
227 			qvscroll();
228 		else
229 			qv_scn.row++;
230 		break;
231 
232 	case '\007':				/* bell		*/
233 		if( qv_scn.qvaddr )
234 			qv_key_out( LK_BELL_ENABLE );
235 		return;
236 
237 	default:
238 		if( c >= ' ' && c <= '~' ) {
239 			scanline = qv_scn.scanmap;
240 			b_row = qv_scn.bitmap+(scanline[qv_scn.row*15]&0x3ff)*128+qv_scn.col;
241 			i = c - ' ';
242 			if( i < 0 || i > 95 )
243 				i = 0;
244 			else
245 				i *= 15;
246 			f_row = (char *)((int)q_font + i);
247 
248 			for( i=0 ; i<15 ; i++ , b_row += 128, f_row++ )
249 				*b_row = *f_row;
250 
251 			if( ++qv_scn.col >= qv_scn.max_col ) {
252 				qv_scn.col = 0 ;
253 				if( qv_scn.row+1 >= qv_scn.max_row )
254 					qvscroll();
255 				else
256 					qv_scn.row++;
257 			}
258 		}
259 		break;
260 	}
261 	/*
262 	 * Position the cursor to the next character location.
263 	 */
264 	qv_pos_cur( qv_scn.col*8, qv_scn.row*15 );
265 }
266 
267 /*
268  * Position the cursor to a particular spot.
269  */
270 qv_pos_cur( x, y)
271 int x,y;
272 {
273 	struct qvdevice *qvaddr;
274 
275 	if( qvaddr = qv_scn.qvaddr ) {
276 		if( y < 0 || y > qv_scn.max_cur_y )
277 			y = qv_scn.max_cur_y;
278 		if( x < 0 || x > qv_scn.max_cur_x )
279 			x = qv_scn.max_cur_x;
280 
281 		qvaddr->qv_crtaddr = 10;	/* select cursor start reg */
282 		qvaddr->qv_crtdata = y & 0xf;
283 		qvaddr->qv_crtaddr = 11;	/* select cursor end reg */
284 		qvaddr->qv_crtdata = y & 0xf;
285 		qvaddr->qv_crtaddr = 14;	/* select cursor y pos. */
286 		qvaddr->qv_crtdata = y >> 4;
287 		qvaddr->qv_xcur = x;		/* pos x axis	*/
288 	}
289 }
290 /*
291  * Scroll the bitmap by moving the scanline map words. This could
292  * be done by moving the bitmap but it's much too slow for a full screen.
293  * The only drawback is that the scanline map must be reset when the user
294  * wants to do graphics.
295  */
296 qvscroll()
297 {
298 	int i;
299 	short tmpscanlines[15];
300 	char *b_row;
301 	short *scanline;
302 
303 
304 	/*
305 	 * Save the first 15 scanlines so that we can put them at
306 	 * the bottom when done.
307 	 */
308 	bcopy( qv_scn.scanmap, tmpscanlines, sizeof tmpscanlines );
309 
310 	/*
311 	 * Clear the wrapping line so that it won't flash on the bottom
312 	 * of the screen.
313 	 */
314 	scanline = qv_scn.scanmap;
315 	b_row = qv_scn.bitmap+(*scanline&0x3ff)*128;
316 	bzero( b_row, 1920 );
317 
318 	/*
319 	 * Now move the scanlines down
320 	 */
321 	bcopy( qv_scn.scanmap+15, qv_scn.scanmap, (qv_scn.row * 15) * sizeof (short) );
322 
323 	/*
324 	 * Now put the other lines back
325 	 */
326 	bcopy( tmpscanlines, qv_scn.scanmap+(qv_scn.row * 15), sizeof tmpscanlines );
327 
328 }
329 
330 /*
331  * QVSS keyboard interrupt.
332  */
333 qvgetc()
334 {
335 	int c;
336 	struct qvdevice *qvaddr;
337 	char *string;
338 	int j;
339 
340 	qvaddr = qv_scn.qvaddr;
341 	/*
342 	 * Get a character from the keyboard.
343 	 */
344 loop:
345 	while( (qvaddr->qv_uartstatus & 0x01) == 0 )
346 		;
347 	j = qvaddr->qv_uartdata & 0xff;
348 	/*
349 	 * See if its a state change key
350 	 */
351 	switch ( j ) {
352 	case LOCK:
353 		qv_keyboard.lock ^= 0xffff;	/* toggle */
354 		if( qv_keyboard.lock )
355 			qv_key_out( LK_LED_ENABLE );
356 		else
357 			qv_key_out( LK_LED_DISABLE );
358 		qv_key_out( LED_3 );
359 		goto loop;
360 	case SHIFT:
361 		qv_keyboard.shift ^= 0xffff;
362 		goto loop;
363 	case CNTRL:
364 		qv_keyboard.cntrl ^= 0xffff;
365 		goto loop;
366 	case ALLUP:
367 		qv_keyboard.cntrl = qv_keyboard.shift = 0;
368 		goto loop;
369 	case REPEAT:
370 		c = qv_keyboard.last;
371 		break;
372 	default:
373 		/*
374 		 * Test for control characters. If set, see if the character
375 		 * is elligible to become a control character.
376 		 */
377 		if( qv_keyboard.cntrl ) {
378 			c = q_key[ j ];
379 			if( c >= ' ' && c <= '~' )
380 				c &= 0x1f;
381 		} else if( qv_keyboard.lock || qv_keyboard.shift )
382 			c = q_shift_key[ j ];
383 		else
384 			c = q_key[ j ];
385 		break;
386 	}
387 
388 	qv_keyboard.last = c;
389 
390 	/*
391 	 * Check for special function keys
392 	 */
393 	if( c & 0x80 )
394 		return 0;
395 	else
396 		return c;
397 }
398 
399 /*
400  * Output to the keyboard. This routine status polls the transmitter on the
401  * keyboard to output a code. The timer is to avoid hanging on a bad device.
402  */
403 qv_key_out( c )
404 char c;
405 {
406 	int timer = 30000;
407 
408 	if( qv_scn.qvaddr ) {
409 		while( (qv_scn.qvaddr->qv_uartstatus & 0x4) == 0  && timer-- )
410 			;
411 		qv_scn.qvaddr->qv_uartdata = c;
412 	}
413 }
414 
415