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 */
qv_init()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 */
qvputc(c)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 */
qv_pos_cur(x,y)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 */
qvscroll()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 */
qvgetc()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 */
qv_key_out(c)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