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