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