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 * @(#)qdcons.c 7.2 (Berkeley) 08/27/88 18 */ 19 20 /* 21 * derived from: @(#)qdcons.c 4.1 (ULTRIX 11/23/87 22 */ 23 24 /************************************************************************ 25 * 26 * ULTRIX QDSS STANDALONE BOOT DEVICE DRIVER... 27 * device driver to boot system with QDSS as console 28 * 29 *************************************************************************/ 30 /************************************************************************ 31 * * 32 * Copyright (c) 1985 by * 33 * Digital Equipment Corporation, Maynard, MA * 34 * All rights reserved. * 35 * * 36 * This software is furnished under a license and may be used and * 37 * copied only in accordance with the terms of such license and * 38 * with the inclusion of the above copyright notice. This * 39 * software or any other copies thereof may not be provided or * 40 * otherwise made available to any other person. No title to and * 41 * ownership of the software is hereby transferred. * 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 * revision history: (should be moved into sccs comments) 52 ************************************************************************* 53 * 54 * 09 oct 85 longo added uVAXII console ROM cursor reset to bottom of 55 * the screen. Also spruced up qdputc() & scroll_up() 56 * 02 oct 85 longo changed references to ADDRESS to be ADDRESS_COMPLETE 57 * 23 aug 85 longo changed I/O page CSR address to be 0x1F00 58 * 20 aug 85 longo created 59 * 60 ************************************************************************/ 61 62 #include "../h/types.h" 63 #include "../vax/cpu.h" 64 #define KERNEL 65 #include "../vaxuba/qdioctl.h" 66 #include "../vaxuba/qevent.h" 67 #include "../vaxuba/qduser.h" 68 #include "../vaxuba/qdreg.h" 69 #undef KERNEL 70 71 /*----------------------------------------------------------------------- 72 * constants used to set VAX ROM's cursor to bottom the of the screen */ 73 74 #define NVR_ADRS 0x200B8024 75 76 #define CURRENT_ROW 0x4C /* these are offsets to the ROM's scratch.. */ 77 #define ROW_MIN 0x4D /* ..RAM start adrs as picked up out of NVR */ 78 #define ROW_MAX 0x4E 79 #define CURRENT_COL 0x50 80 #define COL_MIN 0x51 81 #define COL_MAX 0x52 82 83 /*---------------------------------------- 84 * LK201 keyboard state tracking struct */ 85 86 struct q_keyboard { 87 88 int shift; /* state variables */ 89 int cntrl; 90 int lock; 91 char last; /* last character */ 92 93 } q_keyboard; 94 95 int qdputc(), qdgetc(); 96 97 extern (*v_putc)(),(*v_getc)(); 98 99 /*---------------------------- 100 * general purpose defines */ 101 102 #define BAD -1 103 #define GOOD 0 104 105 /*---------------------------------------------- 106 * console cursor bitmap (block cursor type) */ 107 108 short cons_cursor[32] = { /* white block cursor */ 109 110 /* A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 111 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 112 /* B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 113 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF 114 115 }; 116 117 /*------------------------------------- 118 * constants used in font operations */ 119 120 #define CHARS 95 /* # of chars in the font */ 121 #define CHAR_HEIGHT 15 /* char height in pixels */ 122 #define CHAR_WIDTH 8 /* char width in pixels*/ 123 #define FONT_WIDTH (CHAR_WIDTH * CHARS) /* font width in pixels */ 124 #define ROWS CHAR_HEIGHT 125 126 #define FONT_X 0 /* font's off screen adrs */ 127 #define FONT_Y (2047 - CHAR_HEIGHT) 128 /* 129 #define FONT_Y 200 130 */ 131 132 extern char q_font[]; /* reference font object code */ 133 134 extern char q_key[]; /* reference key xlation tables */ 135 extern char q_shift_key[]; 136 extern char *q_special[]; 137 138 /*---------------------------- 139 * console cursor structure */ 140 141 struct cons_cur { 142 int x; 143 int y; 144 } cursor; 145 146 /*------------------------------------------ 147 * MicroVAX-II q-bus addressing constants */ 148 149 #define QMEMBASE 0x30000000 150 #define QDSSCSR 0x20001F00 151 152 #define CHUNK (64 * 1024) 153 #define QMEMSIZE (1024 * 1024 * 4) 154 #define QDBASE (QMEMBASE + QMEMSIZE - CHUNK) 155 156 /*------------------------------------------------------------------ 157 * QDSS register address offsets from start of QDSS address space */ 158 159 #define QDSIZE (52 * 1024) /* size of entire QDSS foot print */ 160 161 #define TMPSIZE (16 * 1024) /* template RAM is 8k SHORT WORDS */ 162 #define TMPSTART 0x8000 /* offset of template RAM from base adrs */ 163 164 #define REGSIZE (5 * 512) /* regs touch 2.5k (5 pages) of addr space */ 165 #define REGSTART 0xC000 /* offset of reg pages from base adrs */ 166 167 #define ADDER (REGSTART+0x000) 168 #define DGA (REGSTART+0x200) 169 #define DUART (REGSTART+0x400) 170 #define MEMCSR (REGSTART+0x800) 171 172 #define CLRSIZE (3 * 512) /* color map size */ 173 #define CLRSTART (REGSTART+0xA00) /* color map start offset from base */ 174 /* 0x0C00 really */ 175 #define RED (CLRSTART+0x000) 176 #define BLUE (CLRSTART+0x200) 177 #define GREEN (CLRSTART+0x400) 178 179 /*--------------------------------------- 180 * QDSS register address map structure */ 181 182 struct qdmap qdmap; 183 184 /************************************************************************ 185 ************************************************************************* 186 ************************************************************************* 187 * 188 * EXTERNALLY CALLED ROUTINES START HERE: 189 * 190 ************************************************************************* 191 ************************************************************************* 192 ************************************************************************/ 193 194 /************************************************************************ 195 * 196 * qd_init()... init the QDSS into a physical memory system 197 * 198 ************************************************************************/ 199 200 qd_init() 201 { 202 register char *ROM_console; 203 register short *NVR; 204 register int i; 205 206 caddr_t qdaddr; 207 struct dga *dga; 208 extern int cpu; 209 210 qdaddr = (caddr_t) QDSSCSR; 211 if (badaddr(qdaddr, sizeof(short))) 212 return(0); 213 214 *(short *)qdaddr = (short) (QDBASE >> 16); 215 216 /*---------------------------------------------------------------------- 217 * load qdmap struct with the physical addresses of the QDSS elements */ 218 219 qdmap.template = (caddr_t) QDBASE + TMPSTART; 220 qdmap.adder = (caddr_t) QDBASE + ADDER; 221 qdmap.dga = (caddr_t) QDBASE + DGA; 222 qdmap.duart = (caddr_t) QDBASE + DUART; 223 qdmap.memcsr = (caddr_t) QDBASE + MEMCSR; 224 qdmap.red = (caddr_t) QDBASE + RED; 225 qdmap.blue = (caddr_t) QDBASE + BLUE; 226 qdmap.green = (caddr_t) QDBASE + GREEN; 227 228 /*-------------------------- 229 * no interrupts allowed! */ 230 231 dga = (struct dga *) qdmap.dga; 232 dga->csr = HALT; 233 dga->csr |= CURS_ENB; 234 235 /*---------------------------- 236 * init the default values */ 237 238 q_keyboard.shift = 0; /* init keyboard state tracking */ 239 q_keyboard.lock = 0; 240 q_keyboard.cntrl = 0; 241 q_keyboard.last = 0; 242 243 cursor.x = 0; /* init cursor to top left */ 244 cursor.y = 0; 245 246 set_defaults(); /* setup the default device */ 247 ldfont(); /* PtoB the font into off-screen */ 248 249 /*-------------------------------------------------------------------- 250 * tell the VAX ROM that the cursor is at the bottom of the screen */ 251 252 if (cpu == VAX_630) { 253 NVR = (short *) NVR_ADRS; 254 255 i = *NVR++ & 0xFF; 256 i |= (*NVR++ & 0xFF) << 8; 257 i |= (*NVR++ & 0xFF) << 16; 258 i |= (*NVR++ & 0xFF) << 24; 259 260 ROM_console = (char *) i; 261 262 ROM_console[CURRENT_COL] = ROM_console[COL_MIN]; 263 ROM_console[CURRENT_ROW] = ROM_console[ROW_MAX]; 264 } 265 266 /*---------------------------------------------------------- 267 * smash system virtual console service routine addresses */ 268 269 printf("switching console to QDSS display...\n"); 270 v_getc = qdgetc; 271 v_putc = qdputc; 272 273 return(1); 274 275 } /* qd_init */ 276 277 /******************************************************************* 278 * 279 * qdputc()... output a character to the QDSS screen 280 * 281 ******************************************************************** 282 * 283 * calling convention: 284 * 285 * qdputc(chr); 286 * char chr; ;character to be displayed 287 * 288 ********/ 289 290 qdputc(chr) 291 char chr; 292 { 293 register struct adder *adder; 294 register struct dga *dga; 295 register int i; 296 297 short x; 298 299 adder = (struct adder *) qdmap.adder; 300 dga = (struct dga *) qdmap.dga; 301 302 /*--------------------------- 303 * non display character? */ 304 305 chr &= 0x7F; 306 307 switch (chr) { 308 309 case '\r': /* return char */ 310 cursor.x = 0; 311 dga->x_cursor = TRANX(cursor.x); 312 return(0); 313 314 case '\t': /* tab char */ 315 316 for (i = 8 - ((cursor.x >> 3) & 0x07); i > 0; --i) { 317 qdputc(' '); 318 } 319 return(0); 320 321 case '\n': /* line feed char */ 322 323 if ((cursor.y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) { 324 cursor.y -= CHAR_HEIGHT; 325 scroll_up(adder); 326 } 327 dga->y_cursor = TRANY(cursor.y); 328 return(0); 329 330 case '\b': /* backspace char */ 331 if (cursor.x > 0) { 332 cursor.x -= CHAR_WIDTH; 333 qdputc(' '); 334 cursor.x -= CHAR_WIDTH; 335 dga->x_cursor = TRANX(cursor.x); 336 } 337 return(0); 338 339 default: 340 if (chr < ' ' || chr > '~') { 341 return(0); 342 } 343 } 344 345 /*------------------------------------------ 346 * setup VIPER operand control registers */ 347 348 write_ID(adder, CS_UPDATE_MASK, 0x0001); /* select plane #0 */ 349 write_ID(adder, SRC1_OCR_B, 350 EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY); 351 352 write_ID(adder, CS_UPDATE_MASK, 0x00FE); /* select other planes */ 353 write_ID(adder, SRC1_OCR_B, 354 EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY); 355 356 write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */ 357 write_ID(adder, DST_OCR_B, 358 EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 359 360 write_ID(adder, MASK_1, 0xFFFF); 361 write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1); 362 write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 363 364 /*---------------------------------------- 365 * load DESTINATION origin and vectors */ 366 367 adder->fast_dest_dy = 0; 368 adder->slow_dest_dx = 0; 369 adder->error_1 = 0; 370 adder->error_2 = 0; 371 372 adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL; 373 374 wait_status(adder, RASTEROP_COMPLETE); 375 376 adder->destination_x = cursor.x; 377 adder->fast_dest_dx = CHAR_WIDTH; 378 379 adder->destination_y = cursor.y; 380 adder->slow_dest_dy = CHAR_HEIGHT; 381 382 /*----------------------------------- 383 * load SOURCE origin and vectors */ 384 385 adder->source_1_x = FONT_X + ((chr - ' ') * CHAR_WIDTH); 386 adder->source_1_y = FONT_Y; 387 388 adder->source_1_dx = CHAR_WIDTH; 389 adder->source_1_dy = CHAR_HEIGHT; 390 391 write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 392 adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE; 393 394 /*------------------------------------- 395 * update console cursor coordinates */ 396 397 cursor.x += CHAR_WIDTH; 398 dga->x_cursor = TRANX(cursor.x); 399 400 if (cursor.x > (1024 - CHAR_WIDTH)) { 401 qdputc('\r'); 402 qdputc('\n'); 403 } 404 405 } /* qdputc */ 406 407 /******************************************************************* 408 * 409 * qdgetc()... get a character from the LK201 410 * 411 *******************************************************************/ 412 413 qdgetc() 414 { 415 register short key; 416 register char chr; 417 register struct duart *duart; 418 419 u_int status; 420 421 duart = (struct duart *) qdmap.duart; 422 423 /*-------------------------------------- 424 * Get a character from the keyboard. */ 425 426 LOOP: 427 while (!((status = duart->statusA) & RCV_RDY)) 428 ; 429 430 key = duart->dataA; 431 key &= 0xFF; 432 433 /*-------------------------------------- 434 * Check for various keyboard errors */ 435 436 if( key == LK_POWER_ERROR || key == LK_KDOWN_ERROR || 437 key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) { 438 printf("Keyboard error, code = %x\n", key); 439 return(0); 440 } 441 442 if (key < LK_LOWEST) 443 return(0); 444 445 /*--------------------------------- 446 * See if its a state change key */ 447 448 switch (key) { 449 450 case LOCK: 451 q_keyboard.lock ^= 0xffff; /* toggle */ 452 if (q_keyboard.lock) 453 led_control(LK_LED_ENABLE, LK_LED_LOCK); 454 else 455 led_control(LK_LED_DISABLE, LK_LED_LOCK); 456 goto LOOP; 457 458 case SHIFT: 459 q_keyboard.shift ^= 0xFFFF; 460 goto LOOP; 461 462 case CNTRL: 463 q_keyboard.cntrl ^= 0xFFFF; 464 goto LOOP; 465 466 case ALLUP: 467 q_keyboard.cntrl = 0; 468 q_keyboard.shift = 0; 469 goto LOOP; 470 471 case REPEAT: 472 chr = q_keyboard.last; 473 break; 474 475 /*------------------------------------------------------- 476 * Test for cntrl characters. If set, see if the character 477 * is elligible to become a control character. */ 478 479 default: 480 481 if (q_keyboard.cntrl) { 482 chr = q_key[key]; 483 if (chr >= ' ' && chr <= '~') 484 chr &= 0x1F; 485 } 486 else if ( q_keyboard.lock || q_keyboard.shift ) 487 chr = q_shift_key[key]; 488 else 489 chr = q_key[key]; 490 break; 491 } 492 493 if (chr < ' ' && chr > '~') /* if input is non-displayable */ 494 return(0); /* ..then pitch it! */ 495 496 q_keyboard.last = chr; 497 498 /*----------------------------------- 499 * Check for special function keys */ 500 501 if (chr & 0x80) /* pitch the function keys */ 502 return(0); 503 else 504 return(chr); 505 506 } /* qdgetc */ 507 508 /************************************************************************ 509 ************************************************************************* 510 ************************************************************************* 511 * 512 * INTERNALLY USED ROUTINES START HERE: 513 * 514 ************************************************************************* 515 ************************************************************************* 516 ************************************************************************/ 517 518 /******************************************************************** 519 * 520 * ldcursor()... load the mouse cursor's template RAM bitmap 521 * 522 ********************************************************************/ 523 524 ldcursor() 525 { 526 register struct dga *dga; 527 register short *temp; 528 register int i; 529 530 int cursor; 531 532 dga = (struct dga *) qdmap.dga; 533 temp = (short *) qdmap.template; 534 535 temp += (8 * 1024) - 32; /* cursor is 32 WORDS from the end */ 536 /* ..of the 8k WORD template space */ 537 for (i = 0; i < 32; ++i) 538 *temp++ = cons_cursor[i]; 539 540 return(0); 541 542 } /* ldcursor */ 543 544 /********************************************************************** 545 * 546 * ldfont()... put the console font in the QDSS off-screen memory 547 * 548 **********************************************************************/ 549 550 ldfont() 551 { 552 register struct adder *adder; 553 554 int i; /* scratch variables */ 555 int j; 556 int k; 557 short packed; 558 559 adder = (struct adder *) qdmap.adder; 560 561 /*------------------------------------------ 562 * setup VIPER operand control registers */ 563 564 write_ID(adder, MASK_1, 0xFFFF); 565 write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 566 write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 567 568 write_ID(adder, SRC1_OCR_B, 569 EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY); 570 write_ID(adder, SRC2_OCR_B, 571 EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY); 572 write_ID(adder, DST_OCR_B, 573 EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 574 575 adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL; 576 577 /*-------------------------- 578 * load destination data */ 579 580 wait_status(adder, RASTEROP_COMPLETE); 581 582 adder->destination_x = FONT_X; 583 adder->destination_y = FONT_Y; 584 adder->fast_dest_dx = FONT_WIDTH; 585 adder->slow_dest_dy = CHAR_HEIGHT; 586 587 /*--------------------------------------- 588 * setup for processor to bitmap xfer */ 589 590 write_ID(adder, CS_UPDATE_MASK, 0x0001); 591 adder->cmd = PBT | OCRB | 2 | DTE | 2; 592 593 /*----------------------------------------------- 594 * iteratively do the processor to bitmap xfer */ 595 596 for (i = 0; i < ROWS; ++i) { 597 598 /* PTOB a scan line */ 599 600 for (j = 0, k = i; j < 48; ++j) { 601 602 /* PTOB one scan of a char cell */ 603 604 packed = q_font[k]; 605 k += ROWS; 606 packed |= ((short)q_font[k] << 8); 607 k += ROWS; 608 609 wait_status(adder, TX_READY); 610 adder->id_data = packed; 611 } 612 } 613 614 } /* ldfont */ 615 616 /********************************************************************* 617 * 618 * led_control()... twiddle LK-201 LED's 619 * 620 ********************************************************************** 621 * 622 * led_control(cmd, led_mask); 623 * int cmd; LED enable/disable command 624 * int led_mask; which LED(s) to twiddle 625 * 626 *************/ 627 628 led_control(cmd, led_mask) 629 int cmd; 630 int led_mask; 631 { 632 register int i; 633 register int status; 634 register struct duart *duart; 635 636 duart = (struct duart *) qdmap.duart; 637 638 for (i = 1000; i > 0; --i) { 639 if ((status = duart->statusA) & XMT_RDY) { 640 duart->dataA = cmd; 641 break; 642 } 643 } 644 645 for (i = 1000; i > 0; --i) { 646 if ((status = duart->statusA) & XMT_RDY) { 647 duart->dataA = led_mask; 648 break; 649 } 650 } 651 652 if (i == 0) 653 return(BAD); 654 655 return(GOOD); 656 657 } /* led_control */ 658 659 /******************************************************************* 660 * 661 * scroll_up()... move the screen up one character height 662 * 663 ******************************************************************** 664 * 665 * calling convention: 666 * 667 * scroll_up(adder); 668 * struct adder *adder; ;address of adder 669 * 670 ********/ 671 672 scroll_up(adder) 673 register struct adder *adder; 674 { 675 676 /*------------------------------------------ 677 * setup VIPER operand control registers */ 678 679 wait_status(adder, ADDRESS_COMPLETE); 680 681 write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */ 682 683 write_ID(adder, MASK_1, 0xFFFF); 684 write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 685 write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 686 687 write_ID(adder, SRC1_OCR_B, 688 EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY); 689 write_ID(adder, DST_OCR_B, 690 EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 691 692 /*---------------------------------------- 693 * load DESTINATION origin and vectors */ 694 695 adder->fast_dest_dy = 0; 696 adder->slow_dest_dx = 0; 697 adder->error_1 = 0; 698 adder->error_2 = 0; 699 700 adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL; 701 702 adder->destination_x = 0; 703 adder->fast_dest_dx = 1024; 704 705 adder->destination_y = 0; 706 adder->slow_dest_dy = 864 - CHAR_HEIGHT; 707 708 /*----------------------------------- 709 * load SOURCE origin and vectors */ 710 711 adder->source_1_x = 0; 712 adder->source_1_dx = 1024; 713 714 adder->source_1_y = 0 + CHAR_HEIGHT; 715 adder->source_1_dy = 864 - CHAR_HEIGHT; 716 717 write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 718 adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE; 719 720 /*-------------------------------------------- 721 * do a rectangle clear of last screen line */ 722 723 write_ID(adder, MASK_1, 0xffff); 724 write_ID(adder, SOURCE, 0xffff); 725 write_ID(adder,DST_OCR_B, 726 (EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY)); 727 write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0); 728 adder->error_1 = 0; 729 adder->error_2 = 0; 730 adder->slow_dest_dx = 0; /* set up the width of */ 731 adder->slow_dest_dy = CHAR_HEIGHT; /* rectangle */ 732 733 adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ; 734 wait_status(adder, RASTEROP_COMPLETE); 735 adder->destination_x = 0; 736 adder->destination_y = 864 - CHAR_HEIGHT; 737 738 adder->fast_dest_dx = 1024; /* set up the height */ 739 adder->fast_dest_dy = 0; /* of rectangle */ 740 741 write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE)); 742 adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ; 743 744 } /* scroll_up */ 745 746 /********************************************************************** 747 * 748 * set_defaults()... init the QDSS device and driver defaults 749 * 750 **********************************************************************/ 751 752 set_defaults() 753 { 754 setup_input(); /* init the DUART */ 755 setup_dragon(); /* init the ADDER/VIPER stuff */ 756 ldcursor(); /* load default cursor map */ 757 758 } /* set_defaults */ 759 760 /********************************************************************* 761 * 762 * setup_dragon()... init the ADDER, VIPER, bitmaps, & color map 763 * 764 *********************************************************************/ 765 766 setup_dragon() 767 { 768 769 register struct adder *adder; 770 register struct dga *dga; 771 short *memcsr; 772 773 int i; /* general purpose variables */ 774 int status; 775 776 short top; /* clipping/scrolling boundaries */ 777 short bottom; 778 short right; 779 short left; 780 781 short *red; /* color map pointers */ 782 short *green; 783 short *blue; 784 785 /*------------------ 786 * init for setup */ 787 788 adder = (struct adder *) qdmap.adder; 789 dga = (struct dga *) qdmap.dga; 790 memcsr = (short *) qdmap.memcsr; 791 792 *memcsr = SYNC_ON; /* blank screen and turn off LED's */ 793 adder->command = CANCEL; 794 795 /*---------------------- 796 * set monitor timing */ 797 798 adder->x_scan_count_0 = 0x2800; 799 adder->x_scan_count_1 = 0x1020; 800 adder->x_scan_count_2 = 0x003A; 801 adder->x_scan_count_3 = 0x38F0; 802 adder->x_scan_count_4 = 0x6128; 803 adder->x_scan_count_5 = 0x093A; 804 adder->x_scan_count_6 = 0x313C; 805 adder->sync_phase_adj = 0x0100; 806 adder->x_scan_conf = 0x00C8; 807 808 /*--------------------------------------------------------- 809 * got a bug in secound pass ADDER! lets take care of it */ 810 811 /* normally, just use the code in the following bug fix code, but to 812 * make repeated demos look pretty, load the registers as if there was 813 * no bug and then test to see if we are getting sync */ 814 815 adder->y_scan_count_0 = 0x135F; 816 adder->y_scan_count_1 = 0x3363; 817 adder->y_scan_count_2 = 0x2366; 818 adder->y_scan_count_3 = 0x0388; 819 820 /* if no sync, do the bug fix code */ 821 822 if (wait_status(adder, VSYNC) == BAD) { 823 824 /* first load all Y scan registers with very short frame and 825 * wait for scroll service. This guarantees at least one SYNC 826 * to fix the pass 2 Adder initialization bug (synchronizes 827 * XCINCH with DMSEEDH) */ 828 829 adder->y_scan_count_0 = 0x01; 830 adder->y_scan_count_1 = 0x01; 831 adder->y_scan_count_2 = 0x01; 832 adder->y_scan_count_3 = 0x01; 833 834 wait_status(adder, VSYNC); /* delay at least 1 full frame time */ 835 wait_status(adder, VSYNC); 836 837 /* now load the REAL sync values (in reverse order just to 838 * be safe. */ 839 840 adder->y_scan_count_3 = 0x0388; 841 adder->y_scan_count_2 = 0x2366; 842 adder->y_scan_count_1 = 0x3363; 843 adder->y_scan_count_0 = 0x135F; 844 } 845 846 /*---------------------------- 847 * zero the index registers */ 848 849 adder->x_index_pending = 0; 850 adder->y_index_pending = 0; 851 adder->x_index_new = 0; 852 adder->y_index_new = 0; 853 adder->x_index_old = 0; 854 adder->y_index_old = 0; 855 856 adder->pause = 0; 857 858 /*---------------------------------------- 859 * set rasterop mode to normal pen down */ 860 861 adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL; 862 863 /*-------------------------------------------------- 864 * set the rasterop registers to a default values */ 865 866 adder->source_1_dx = 1; 867 adder->source_1_dy = 1; 868 adder->source_1_x = 0; 869 adder->source_1_y = 0; 870 adder->destination_x = 0; 871 adder->destination_y = 0; 872 adder->fast_dest_dx = 1; 873 adder->fast_dest_dy = 0; 874 adder->slow_dest_dx = 0; 875 adder->slow_dest_dy = 1; 876 adder->error_1 = 0; 877 adder->error_2 = 0; 878 879 /*------------------------ 880 * scale factor = unity */ 881 882 adder->fast_scale = UNITY; 883 adder->slow_scale = UNITY; 884 885 /*------------------------------- 886 * set the source 2 parameters */ 887 888 adder->source_2_x = 0; 889 adder->source_2_y = 0; 890 adder->source_2_size = 0x0022; 891 892 /*----------------------------------------------- 893 * initialize plane addresses for eight vipers */ 894 895 write_ID(adder, CS_UPDATE_MASK, 0x0001); 896 write_ID(adder, PLANE_ADDRESS, 0x0000); 897 898 write_ID(adder, CS_UPDATE_MASK, 0x0002); 899 write_ID(adder, PLANE_ADDRESS, 0x0001); 900 901 write_ID(adder, CS_UPDATE_MASK, 0x0004); 902 write_ID(adder, PLANE_ADDRESS, 0x0002); 903 904 write_ID(adder, CS_UPDATE_MASK, 0x0008); 905 write_ID(adder, PLANE_ADDRESS, 0x0003); 906 907 write_ID(adder, CS_UPDATE_MASK, 0x0010); 908 write_ID(adder, PLANE_ADDRESS, 0x0004); 909 910 write_ID(adder, CS_UPDATE_MASK, 0x0020); 911 write_ID(adder, PLANE_ADDRESS, 0x0005); 912 913 write_ID(adder, CS_UPDATE_MASK, 0x0040); 914 write_ID(adder, PLANE_ADDRESS, 0x0006); 915 916 write_ID(adder, CS_UPDATE_MASK, 0x0080); 917 write_ID(adder, PLANE_ADDRESS, 0x0007); 918 919 /* initialize the external registers. */ 920 921 write_ID(adder, CS_UPDATE_MASK, 0x00FF); 922 write_ID(adder, CS_SCROLL_MASK, 0x00FF); 923 924 /* initialize resolution mode */ 925 926 write_ID(adder, MEMORY_BUS_WIDTH, 0x000C); /* bus width = 16 */ 927 write_ID(adder, RESOLUTION_MODE, 0x0000); /* one bit/pixel */ 928 929 /* initialize viper registers */ 930 931 write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP); 932 write_ID(adder, SCROLL_FILL, 0x0000); 933 934 /*---------------------------------------------------- 935 * set clipping and scrolling limits to full screen */ 936 937 for ( i = 1000, adder->status = 0 938 ; i > 0 && !((status = adder->status) & ADDRESS_COMPLETE) 939 ; --i); 940 941 if (i == 0) 942 printf("timeout trying to setup clipping\n"); 943 944 top = 0; 945 bottom = 2048; 946 left = 0; 947 right = 1024; 948 949 adder->x_clip_min = left; 950 adder->x_clip_max = right; 951 adder->y_clip_min = top; 952 adder->y_clip_max = bottom; 953 954 adder->scroll_x_min = left; 955 adder->scroll_x_max = right; 956 adder->scroll_y_min = top; 957 adder->scroll_y_max = bottom; 958 959 wait_status(adder, VSYNC); /* wait at LEAST 1 full frame */ 960 wait_status(adder, VSYNC); 961 962 adder->x_index_pending = left; 963 adder->y_index_pending = top; 964 adder->x_index_new = left; 965 adder->y_index_new = top; 966 adder->x_index_old = left; 967 adder->y_index_old = top; 968 969 for ( i = 1000, adder->status = 0 970 ; i > 0 && !((status = adder->status) & ADDRESS_COMPLETE) 971 ; --i); 972 973 if (i == 0) 974 printf("timeout waiting for ADDRESS_COMPLETE bit\n"); 975 976 write_ID(adder, LEFT_SCROLL_MASK, 0x0000); 977 write_ID(adder, RIGHT_SCROLL_MASK, 0x0000); 978 979 /*------------------------------------------------------------ 980 * set source and the mask register to all ones (ie: white) */ 981 982 write_ID(adder, SOURCE, 0xFFFF); 983 write_ID(adder, MASK_1, 0xFFFF); 984 write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 985 write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 986 987 /*-------------------------------------------------------------- 988 * initialize Operand Control Register banks for fill command */ 989 990 write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2 | NO_ID | WAIT); 991 write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT); 992 write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE | NO_ID | NO_WAIT); 993 994 write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT); 995 write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2 | NO_ID | NO_WAIT); 996 write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT); 997 998 /*------------------------------------------------------------------ 999 * init Logic Unit Function registers, (these are just common values, 1000 * and may be changed as required). */ 1001 1002 write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 1003 write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE | INV_M1_M2); 1004 write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S); 1005 write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S); 1006 1007 /*---------------------------------------- 1008 * load the color map for black & white */ 1009 1010 for ( i = 0, adder->status = 0 1011 ; i < 10000 && !((status = adder->status) & VSYNC) 1012 ; ++i); 1013 1014 if (i == 0) 1015 printf("timeout waiting for VSYNC bit\n"); 1016 1017 red = (short *) qdmap.red; 1018 green = (short *) qdmap.green; 1019 blue = (short *) qdmap.blue; 1020 1021 *red++ = 0x00; /* black */ 1022 *green++ = 0x00; 1023 *blue++ = 0x00; 1024 1025 *red-- = 0xFF; /* white */ 1026 *green-- = 0xFF; 1027 *blue-- = 0xFF; 1028 1029 /*---------------------------------- 1030 * set color map for mouse cursor */ 1031 1032 red += 254; 1033 green += 254; 1034 blue += 254; 1035 1036 *red++ = 0x00; /* black */ 1037 *green++ = 0x00; 1038 *blue++ = 0x00; 1039 1040 *red = 0xFF; /* white */ 1041 *green = 0xFF; 1042 *blue = 0xFF; 1043 1044 /*--------------------------------------------------------------------------- 1045 * clear the bitmap a piece at a time. Since the fast scroll clear only clears 1046 * the current displayed portion of the bitmap put a temporary value in the y 1047 * limit register so we can access whole bitmap */ 1048 1049 adder->x_limit = 1024; 1050 adder->y_limit = 2048 - CHAR_HEIGHT; 1051 adder->y_offset_pending = 0; 1052 1053 wait_status(adder, VSYNC); /* wait at LEAST 1 full frame */ 1054 wait_status(adder, VSYNC); 1055 1056 adder->y_scroll_constant = SCROLL_ERASE; 1057 1058 wait_status(adder, VSYNC); 1059 wait_status(adder, VSYNC); 1060 1061 adder->y_offset_pending = 864; 1062 1063 wait_status(adder, VSYNC); 1064 wait_status(adder, VSYNC); 1065 1066 adder->y_scroll_constant = SCROLL_ERASE; 1067 1068 wait_status(adder, VSYNC); 1069 wait_status(adder, VSYNC); 1070 1071 adder->y_offset_pending = 1728; 1072 1073 wait_status(adder, VSYNC); 1074 wait_status(adder, VSYNC); 1075 1076 adder->y_scroll_constant = SCROLL_ERASE; 1077 1078 wait_status(adder, VSYNC); 1079 wait_status(adder, VSYNC); 1080 1081 adder->y_offset_pending = 0; /* back to normal */ 1082 1083 wait_status(adder, VSYNC); 1084 wait_status(adder, VSYNC); 1085 1086 adder->x_limit = MAX_SCREEN_X; 1087 adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT; 1088 1089 *memcsr = SYNC_ON | UNBLANK; /* turn off leds and turn on video */ 1090 return(0); 1091 1092 } /* setup_dragon */ 1093 1094 /****************************************************************** 1095 * 1096 * setup_input()... init the DUART and set defaults in input 1097 * devices 1098 * 1099 ******************************************************************/ 1100 1101 setup_input() 1102 { 1103 register struct duart *duart; /* DUART register structure pointer */ 1104 register int bits; 1105 int i, j; /* scratch variables */ 1106 1107 short status; 1108 1109 /*--------------- 1110 * init stuff */ 1111 1112 duart = (struct duart *) qdmap.duart; 1113 1114 /*--------------------------------------------- 1115 * setup the DUART for kbd & pointing device */ 1116 1117 duart->cmdA = RESET_M; /* reset mode reg ptr for kbd */ 1118 duart->modeA = 0x13; /* 8 bits, no parity, rcv IE, */ 1119 /* no RTS control,char error mode */ 1120 duart->modeA = 0x07; /* 1 stop bit,CTS does not IE XMT */ 1121 /* no RTS control,no echo or loop */ 1122 duart->auxctl = 0x00; /* baud rate set 1 */ 1123 1124 duart->clkselA = 0x99; /* 4800 baud for kbd */ 1125 1126 /* reset everything for keyboard */ 1127 1128 for (bits = RESET_M; bits < START_BREAK; bits += 0x10) 1129 duart->cmdA = bits; 1130 1131 duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */ 1132 1133 /*-------------------------- 1134 * init keyboard defaults */ 1135 /* 1136 for (i = 500; i > 0; --i) { 1137 if ((status = duart->statusA) & XMT_RDY) { 1138 duart->dataA = LK_DEFAULTS; 1139 break; 1140 } 1141 } 1142 1143 for (j = 0; j < 3; ++j) { 1144 for (i = 50000; i > 0; --i) { 1145 if ((status = duart->statusA) & RCV_RDY) { 1146 status = duart->dataA; 1147 break; 1148 } 1149 } 1150 } 1151 1152 if (i == 0) 1153 printf("LK-201 init error\n"); 1154 */ 1155 1156 /*-------- 1157 * exit */ 1158 1159 return(0); 1160 1161 } /* setup_input */ 1162 1163 /********************************************************************** 1164 * 1165 * wait_status()... delay for at least one display frame time 1166 * 1167 *********************************************************************** 1168 * 1169 * calling convention: 1170 * 1171 * wait_status(adder, mask); 1172 * struct *adder adder; 1173 * int mask; 1174 * 1175 * return: BAD means that we timed out without ever seeing the 1176 * vertical sync status bit 1177 * GOOD otherwise 1178 * 1179 **************/ 1180 1181 wait_status(adder, mask) 1182 register struct adder *adder; 1183 register int mask; 1184 { 1185 register short status; 1186 int i; 1187 1188 for ( i = 10000, adder->status = 0 1189 ; i > 0 && !((status = adder->status) & mask) 1190 ; --i); 1191 1192 if (i == 0) { 1193 printf("timeout polling for 0x%x in adder->status\n", mask); 1194 return(BAD); 1195 } 1196 1197 return(GOOD); 1198 1199 } /* wait_status */ 1200 1201 /********************************************************************** 1202 * 1203 * write_ID()... write out onto the ID bus 1204 * 1205 *********************************************************************** 1206 * 1207 * calling convention: 1208 * 1209 * struct *adder adder; ;pntr to ADDER structure 1210 * short adrs; ;VIPER address 1211 * short data; ;data to be written 1212 * write_ID(adder); 1213 * 1214 * return: BAD means that we timed out waiting for status bits 1215 * VIPER-access-specific status bits 1216 * GOOD otherwise 1217 * 1218 **************/ 1219 1220 write_ID(adder, adrs, data) 1221 register struct adder *adder; 1222 register short adrs; 1223 register short data; 1224 { 1225 int i; 1226 short status; 1227 1228 for ( i = 100000, adder->status = 0 1229 ; i > 0 && !((status = adder->status) & ADDRESS_COMPLETE) 1230 ; --i); 1231 1232 if (i == 0) 1233 goto ERR; 1234 1235 for ( i = 100000, adder->status = 0 1236 ; i > 0 && !((status = adder->status) & TX_READY) 1237 ; --i); 1238 1239 if (i > 0) { 1240 adder->id_data = data; 1241 adder->command = ID_LOAD | adrs; 1242 return(GOOD); 1243 } 1244 1245 ERR: 1246 printf("timeout trying to write to VIPER\n"); 1247 return(BAD); 1248 1249 } /* write_ID */ 1250