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