Annotation of 43BSDTahoe/sys/vaxstand/qdcons.c, revision 1.1.1.1

1.1       root        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.3  Berkeley  6/29/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 "../vaxuba/qdioctl.h"
                     53: #include "../vaxuba/qevent.h"
                     54: #include "../vaxuba/qduser.h"
                     55: #include "../vaxuba/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 */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.