1 /* 2 * Copyright (c) 1988 Regents of the University of California. 3 * All rights reserved. 4 * 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. 16 * 17 * @(#)qvcons.c 7.4 (Berkeley) 08/09/88 18 */ 19 20 /* 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 64 #include "../vaxuba/qvioctl.h" 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 425