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