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