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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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