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