Commit | Line | Data |
---|---|---|
42a69a9d | 1 | /* |
c0441c16 KB |
2 | * Copyright (c) 1988 Regents of the University of California. |
3 | * All rights reserved. | |
42a69a9d | 4 | * |
c0441c16 KB |
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. | |
42a69a9d | 16 | * |
c0441c16 KB |
17 | * @(#)qvcons.c 7.4 (Berkeley) %G% |
18 | */ | |
19 | ||
20 | /* | |
42a69a9d MT |
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 | |
978f8b9b | 64 | #include "../vaxuba/qvioctl.h" |
42a69a9d MT |
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 |