Annotation of researchv8dc/sys/kdi/main.s, revision 1.1

1.1     ! root        1: /*
        !             2:  * This version of kmc-cpu interface uses two circular buffers.
        !             3:  * Cmdbuf is used to pass command to kmc;
        !             4:  * statbuf is used to report status.
        !             5:  * Csr4~5 are the head/tail of the cmdbuf, and csr6~7 for statbuf.
        !             6:  *
        !             7:  * When csr0 is 0, kmc is idle and does nothing.
        !             8:  * The cpu will set csr to 1 and pass cmdbuf/statbuf addresses
        !             9:  * in csr4~7.
        !            10:  * Then the kmc will set csr0 to 2 and stay at this state forever.
        !            11:  *
        !            12:  *
        !            13:  * Permanently assigned registers:
        !            14:  *
        !            15:  * Channel dependent assigned registers:
        !            16:  *
        !            17:  *     r14 - free kmc queue pointer
        !            18:  *     r9 - channel #
        !            19:  *     r8 - group number currently being serviced
        !            20:  *     r10 - address of current line-table entry
        !            21:  */
        !            22: 
        !            23: #define        C_RLEN          0       /* read length */
        !            24: #define        C_RADDR         2       /* read address */
        !            25: #define        C_RULEN         5       /* uncheck input in RADDR */
        !            26: #define        C_XLEN          7       /* write length */
        !            27: #define        C_XADDR         9       /* write address */
        !            28: #define        C_RQ            12      /* un-ack input: in host memory */
        !            29: #define        C_RBLEN         13      /* length */
        !            30: #define        C_RB            15      /* un-check input: waiting for trailer */
        !            31: #define        C_S             16      /* next seq# to be sent */
        !            32: #define        C_R             17      /* last seq# echoed */
        !            33: #define        C_A             18      /* last seq# acked */
        !            34: #define        C_C             19      /* last seq# received */
        !            35: #define        C_TA0           20      /* trailer: BOT/BOTM/BOTS/SOI */
        !            36: #define        C_TA1           21      /* len of trailer data */
        !            37: #define        C_TA2           22      /* 1st byte of trailer/SOI data */
        !            38: #define        C_TA3           23      /* 2nd byte of trailer/SOI data */
        !            39: #define        C_RSEQ          24      /* seq# for this block */
        !            40: #define        C_XCNTL         25      /* cntl char following the data */
        !            41: #define        C_X             26      /* state of the chan */
        !            42: #define        C_X1            27      /* state of the chan (ovf from C_X) */
        !            43: #define        C_Y             28      /* input state */
        !            44: #define        C_ITIME         29      /* timer for last char input */
        !            45: #define        C_INITIM        30      /* initial value for ITIME */
        !            46:  
        !            47: /*
        !            48:  * define bits in C_X
        !            49:  * bits 0-2 are exclusive
        !            50:  */
        !            51: #define        XIDLE   (1<<0)  /* chan is uninitialized */
        !            52: #define        XACT    (1<<1)  /* chan is initialized */
        !            53: #define        XINIT   (1<<2)  /* chan is in the init stage */
        !            54: /*
        !            55:  * define bits in C_X1 (overflowed from C_X)
        !            56:  */
        !            57: #define        XNIL    (1<<0)  /* send trailer only */
        !            58: #define        XREJ    (1<<3)  /* hasn't rcv ECHO since last REJ */
        !            59: #define        XBLK    (1<<4)  /* set if block mode, else char mode */
        !            60: #define        XENQ    (1<<5)  /* has sent ENQ and not rcv ECHO yet */
        !            61: #define        XACK    (1<<6)  /* C_S has been incremented since ENQ/CHECK */
        !            62: #define        XBOTM   (1<<7)  /* send BOTM (instead of BOT) */
        !            63: /*
        !            64:  * define bits in C_Y
        !            65:  */
        !            66: #define        YTIMACT (1<<0)  /* timer active */
        !            67: #define        YEXPIRE (1<<1)  /* timer expires */
        !            68: #define        YBLOCK  (1<<5)  /* rcv return on block boundary */
        !            69: #define        YTIME   (1<<6)  /* rcv return on time expires */
        !            70: /*
        !            71:  * Define useful constants
        !            72:  */
        !            73: #define        NIL     0377
        !            74: #define        NULL    0377
        !            75: #define        NUL     0377
        !            76: #define        ZERO    0
        !            77: /*
        !            78:  * Datakit and protocol related constant
        !            79:  */
        !            80: #define        DKCHUNK         16      /* packet size - don't change */
        !            81: #define        CHANMODS        96      /* # of channels per module */
        !            82: #define        NGRP            CHANMODS/8-1 /* # of bytes for bit map */
        !            83: #define        BUFSIZ          10      /* size of cmdbuf, statbuf, etc */
        !            84: #define        MAXBADPK        64      /* bad packet received before complaining */
        !            85: #define        DKBMASK         03      /* seq # is  0 to 3 */
        !            86: #define        WINDOW          07      /* max window size */
        !            87: #define        DKBLOCK         28      /* block size before trailer */
        !            88: #define        BSIZE           64      /* size (9-bits) of each host buffer */
        !            89: #define        BSIZE2          BSIZE*2 /* size in bytes */
        !            90: /*
        !            91:  * protocol cntl patterns
        !            92:  */
        !            93: #define        I_SEQ           0010    /* 8 sequence numbers to end trailers */
        !            94: #define        I_ECHO          0020    /* 8 echoes, data given to host */
        !            95: #define        I_REJ           0030    /* 8 rejections, transmission error */
        !            96: #define        I_ACK           0040    /* first of 8 acks, correct reception */
        !            97: #define        I_BOT           0050    /* normal beginning of trailer */
        !            98: #define        I_BOTM          0051    /* trailer with more data to follow */
        !            99: #define        I_BOTS          0052    /* seq update algorithm on this trailer */
        !           100: #define        I_SOI           0053    /* start of interrupt trailer */
        !           101: #define        I_EOI           0054    /* end of interrupt trailer */
        !           102: #define        I_ENQ           0055    /* xmitter request flow/error status */
        !           103: #define        I_CHECK         0056    /* xmitter request error status */
        !           104: #define        I_INITREQ       0057    /* request initialization */
        !           105: #define        I_INIT0         0060    /* disable trailer processing */
        !           106: #define        I_INIT1         0061    /* enable trailer processing */
        !           107: #define        I_AINIT         0062    /* response to INIT0/INIT1 */
        !           108: /*
        !           109:  * command type
        !           110:  */
        !           111: #define        KC_INIT         1       /* init: 0,0,0,0 */
        !           112: #define        KC_SEND         2       /* send: len, cntl, mode, addr */
        !           113: #define        KC_RCVB         3       /* rcv: len, time, mode, addr */
        !           114: #define        KC_CLOSE        4       /* close: 0, 0, 0, 0 */
        !           115: #define        KC_XINIT        5       /* re-init xmitter: 0, 0, 0, 0 */
        !           116: #define        KC_CMD          6       /* cmd to kmc: cmd, 0, 0, 0 */
        !           117: #define        KC_FLAG         7       /* i/oflag: iflag, oflaghi, oflaglo, 0 */
        !           118: #define        KC_SOI          8       /* send express: (byte2<<8)|byte1, 0, 0, 0 */
        !           119: #define        KC_TDK          9       /* send to tdk: ctl, 0, 0, 0 */
        !           120: /*
        !           121:  * report type
        !           122:  */
        !           123: #define        KS_SEND         20      /* send: 0, 0, 0, 0 */
        !           124: #define        KS_RDB          21      /* rcv: residue len, cntl, mode, 0 */
        !           125: #define        KS_EOI          22      /* rcv express: (byte2<<8)|byte1, 0, 0, 0 */
        !           126: #define        KS_CNTL         23      /* rcv tdk cntl: 0, cntl, 0, 0 */
        !           127: #define        KS_ERR          24      /* error: code, 0, 0, 0 */
        !           128: /*
        !           129:  * sub command bits for KC_CMD
        !           130:  */
        !           131: #define        OFLUSH  (1<<1)  /* Flush output */
        !           132: #define        OSPND   (1<<2)  /* Suspend output */
        !           133: #define        ORSME   (1<<3)  /* Resume output */
        !           134: /*
        !           135:  * KC_RCVB mode
        !           136:  */
        !           137: #define        CBLOCK  (1<<5)  /* return on block boundary */
        !           138: #define        CTIME   (1<<6)  /* return on time expires */
        !           139: /*
        !           140:  * KS_RDB mode
        !           141:  */
        !           142: #define        SFULL   (1<<0)  /* buffer full */
        !           143: #define        SCNTL   (1<<1)  /* cntl char rcv */
        !           144: #define        SABORT  (1<<3)  /* rcv aborted */
        !           145: #define        SBLOCK  (1<<5)  /* block boundary */
        !           146: #define        STIME   (1<<6)  /* timer expires */
        !           147: /* 
        !           148:  * define bit pattern 
        !           149:  */
        !           150: #define        BIT0    (1<<0)
        !           151: #define        BIT1    (1<<1)
        !           152: #define        BIT2    (1<<2)
        !           153: #define        BIT3    (1<<3)
        !           154: #define        BIT4    (1<<4)
        !           155: #define        BIT5    (1<<5)
        !           156: #define        BIT6    (1<<6)
        !           157: #define        BIT7    (1<<7)
        !           158: 
        !           159: #define        CLT0            0
        !           160: #define        CLT1            010
        !           161: #define        CLK1MS          16
        !           162: #define        R_TIMER         6       /* multiple of 50 us (300us here) */
        !           163: /*
        !           164:  * head/tail of circular buffers
        !           165:  */
        !           166: #define        HC              csr4    /* head of cmdbuf */
        !           167: #define        TC              csr5    /* tail of cmdbuf */
        !           168: #define        HS              csr6    /* head of statbuf */
        !           169: #undef TS
        !           170: #define        TS              csr7    /* tail of statbuf */
        !           171: /*
        !           172:  * Define bits in npr
        !           173:  */
        !           174: #define NRQ (1<<0)
        !           175: #define OUT (1<<4)
        !           176: #define BYTE (1<<7)
        !           177: /*
        !           178:  * Define bits in nprx
        !           179:  */
        !           180: #define NEM (1<<0)
        !           181: #define ACLO (1<<1)
        !           182: #define PCLK (1<<4)
        !           183: #define VEC4 (1<<6)
        !           184: #define BRQ (1<<7)
        !           185: /*
        !           186:  * Define check point code
        !           187:  */
        !           188: #define        B0_KCSO (1<<0)  /* enter KC_SOI cmd */
        !           189: #define        B0_KCCM (1<<1)  /* enter KC_CMD cmd */
        !           190: #define        B0_KCFG (1<<2)  /* enter KC_FLAG cmd */
        !           191: #define        B0_KC1  (1<<3)  /* enter KC_ONE cmd */
        !           192: #define        B0_KCSD (1<<4)  /* enter KC_SEND cmd */
        !           193: #define        B0_KCRB (1<<5)  /* enter KC_RCVB cmd */
        !           194: #define        B0_KCIT (1<<6)  /* enter KC_INIT cmd */
        !           195: #define        B0_KCCS (1<<7)  /* enter KC_CLOSE cmd */
        !           196: 
        !           197: #define        B1_ENT  (1<<0)  /* enter output seg */
        !           198: #define        B1_CNTL (1<<1)  /* send XCNTL */
        !           199: #define        B1_ERO  (1<<2)  /* enter robin */
        !           200: #define        B1_SPK  (1<<4)  /* issue D_XPACK */
        !           201: #define        B1_ENRO (1<<5)  /* endrobin */
        !           202: #define        B1_EXIT (1<<7)  /* exit output */
        !           203: 
        !           204: #define        B2_ENT  (1<<0)  /* enter input seq */
        !           205: #define        B2_CNTL (1<<1)  /* control packet */
        !           206: #define        B2_SUP  (1<<2)  /* rcv sup cntl char */
        !           207: #define        B2_NWWT (1<<3)  /* rcv not well form trailer */
        !           208: #define        B2_REP  (1<<4)  /* KS_RDB interrupt */
        !           209: #define        B2_DATA (1<<6)  /* data packet */
        !           210: #define        B2_EXIT (1<<7)  /* exit input seg */
        !           211: 
        !           212: #define        B3_SEQ  (1<<0)  /* rcv SEQ */
        !           213: #define        B3_ECHO (1<<1)  /* rcv ECHO */
        !           214: #define        B3_ACK  (1<<2)  /* rcv ACK */
        !           215: #define        B3_REJ  (1<<3)  /* rcv REJ */
        !           216: #define        B3_CHK  (1<<4)  /* rcv CHK */
        !           217: #define        B3_ENQ  (1<<5)  /* rcv ENQ */
        !           218: 
        !           219: #define        B4_EOI  (1<<0)  /* rcv EOI */
        !           220: #define        B4_BOT  (1<<1)  /* rcv BOT */
        !           221: #define        B4_IN1  (1<<2)  /* rcv INIT1 */
        !           222: #define        B4_IN0  (1<<3)  /* rcv INIT0 */
        !           223: #define        B4_AIN  (1<<4)  /* rcv AINIT*/
        !           224: #define        B4_IREQ (1<<5)  /* rcv INITREQ */
        !           225: 
        !           226: #define        B5_ENT  (1<<0)  /* enter rcv */
        !           227: #define        B5_PLEN (1<<1)  /* plen >= RLEN */
        !           228: #define        B5_ODD  (1<<2)  /* r_odd */
        !           229: #define        B5_REP  (1<<3)  /* report READ comp */
        !           230: #define        B5_MOVE (1<<4)  /* partial buffer */
        !           231: #define        B5_AJAX (1<<5)  /* enter clean() */
        !           232: #define        B5_EXIT (1<<6)  /* exit rcv */
        !           233: #define        B5_TIME (1<<7)  /* timer expires */
        !           234: 
        !           235: #define        B6_POST (1<<0)  /* output postprocessing */
        !           236: #define        B6_NL   (1<<1)  /* NL */
        !           237: #define        B6_CR   (1<<2)  /* CR */
        !           238: #define        B6_TAB  (1<<3)  /* TAB */
        !           239: #define        B6_BS   (1<<4)  /* back space */
        !           240: #define        B6_VT   (1<<5)  /* VT */
        !           241: #define        B6_FF   (1<<6)  /* FF */
        !           242: 
        !           243: #define        B7_IFL  (1<<0)  /* flush input */
        !           244: #define        B7_OFL  (1<<1)  /* flush output */
        !           245: #define        B7_OSP  (1<<2)  /* suspend output */
        !           246: #define        B7_ORE  (1<<3)  /* resume output */
        !           247: #define        B7_IUB  (1<<4)  /* unblock input */
        !           248: #define        B7_IBL  (1<<5)  /* block input */
        !           249: #define        B7_BRK  (1<<6)  /* send break */
        !           250: 
        !           251: /*
        !           252:  * Define error codes
        !           253:  */
        !           254: #define        E_SW            00      /* dispatcher switch */
        !           255: #define        E_BUS           01      /* Unibus error */
        !           256: #define        E_IPANIC        02      /* input routine panic */
        !           257: #define        E_CMD           03      /* command unknown */
        !           258: #define        E_NOQB          04      /* run out of queue or buffer */
        !           259: #define        E_DUP           05      /* duplicate SEND */
        !           260: #define        E_ODKOVF        06      /* output routine panic */
        !           261: #define        E_UMETA         07      /* un-recognized cntl char */
        !           262: #define        E_SYS1          041     /* system error 1 */
        !           263: #define        E_SYS2          042     /* system error 2 */
        !           264:  
        !           265: #ifdef DR11C
        !           266: /*
        !           267:  * specific declarations for dr11-c
        !           268:  */
        !           269: #define        DKRDONE (1<<7)  /* 15-th bit */
        !           270: #define        DKTDONE (1<<7)  /* 7-th bit */
        !           271: #define        DKCOM   (3<<0)  /* 01 bits */
        !           272: #define        DKTENAB (1<<6)  /* 6-th bit */
        !           273: #define        DKRENAB (1<<5)  /* 5-th bit */
        !           274: #define DKDATA (1<<0)  /* 8-th bit */
        !           275: #define        DKMARK  (1<<1)  /* 9-th bit */
        !           276: #define        ILO     idl
        !           277: #define        IHI     idh
        !           278: #define        OLO     odl
        !           279: #define        OHI     odh
        !           280: #define        D_OSEQ  0
        !           281: #define        D_READ  1
        !           282: #define        D_WRITE 2
        !           283: #define        D_XPACK 3
        !           284: #define        D_WHEAD (1<<1)          /* 9-th bit */
        !           285: #define        D_WDATA (1<<0)          /* data byte */
        !           286: #define        D_WCNTL 0               /* control byte */
        !           287: #endif
        !           288: #ifdef KDI
        !           289: /*
        !           290:  * specific declarations for dki board
        !           291:  */
        !           292: #define        ILO     lur0
        !           293: #define        IHI     lur5
        !           294: #define        OLO     lur0
        !           295: #define        OHI     lur1
        !           296: #define        DKFRDY  (1<<0)  /* data from dk ready */
        !           297: #define        TRQRDY  (1<<1)  /* seq# rdy: xmit done */
        !           298: #define        D_OSEQ  (0<<6)
        !           299: #define        D_RESET (0<<6)
        !           300: #define        D_READ  (1<<6)
        !           301: #define        D_WHEAD 0202
        !           302: #define        D_WDATA 0201
        !           303: #define        D_WCNTL 0200
        !           304: #define        D_XPACK 0301
        !           305: #endif
        !           306: 
        !           307: /*
        !           308:  * MACRO definition
        !           309:  */
        !           310:  
        !           311: /*
        !           312:  * Define the "BUSWAIT" macro
        !           313:  * not test NMEM is dangereous if memory does not exist, but fast
        !           314:  */
        !           315: #define        BUSWAIT\
        !           316: 5:     mov     npr,brg;\
        !           317:        br0     5b              /* loop until ~NRQ */
        !           318: 
        !           319: /*
        !           320:  * Macros to get and release queue entries
        !           321:  * r14 points to the list of available queue entries
        !           322:  */
        !           323: #define        FREEQ(X)\
        !           324:        mov     03,brg;\
        !           325:        and     brg,X,%mar;\
        !           326:        mov     ~03,brg;\
        !           327:        and     brg,X,mar;\
        !           328:        mov     r14,mem;\
        !           329:        mov     X,brg;\
        !           330:        mov     brg,r14
        !           331: 
        !           332: #define        GETQ(X,Y)\
        !           333:        mov     r14,brg;\
        !           334:        brz     Y;\
        !           335:        mov     brg,X;\
        !           336:        mov     03,brg;\
        !           337:        and     brg,X,%mar;\
        !           338:        mov     ~03,brg;\
        !           339:        and     brg,X,mar;\
        !           340:        mov     mem,r14
        !           341:  
        !           342: /*
        !           343:  * QA(REG) : QA converts a queue pointer to mar & %mar form.
        !           344:  *     REG is a scratch pad register and has the format:
        !           345:  *     bits 7-2 from REG + 00 forms the offset within a page
        !           346:  *     bits 1-0 is the page number
        !           347:  *     Queues are 4-byte long, so it always fall in 4-byte boundary
        !           348:  *     Queues can only be located in the first 4 pages
        !           349:  */
        !           350: #define        QA(REG)\
        !           351:        mov     ~03,brg;\
        !           352:        and     brg,REG,mar;\
        !           353:        mov     03,brg;\
        !           354:        and     brg,REG,%mar
        !           355: 
        !           356: /*
        !           357:  * GEBI(X,ADDR) : get a free buffer index
        !           358:  *     'bmap' to 'bmap'+16 indicate 128 buffers, each 128 bytes.
        !           359:  *     A '1' in i-th bit postion indicates i-th buffer is buzy
        !           360:  *     GEBI finds the first free buffer and returns its number
        !           361:  *     in register X. If no buffer is free, jump to ADDR
        !           362:  *     Turn on i-th bit
        !           363:  *     X can't be r0
        !           364:  *     using r0, X, brg, mar, %mar
        !           365:  */
        !           366: #define GEBI(X,ADDR)\
        !           367:        mov     0,brg;\
        !           368:        mov     brg,X;\
        !           369:        mov     1,brg;\
        !           370:        mov     brg,r0;\
        !           371:        mov     bmap,mar;\
        !           372:        mov     %bmap,%mar;\
        !           373: 5:     mov     mem,brg;\
        !           374:        brz     8f;\
        !           375: 6:     br0     7f;\
        !           376:        br      9f;\
        !           377: 7:     inc     X;\
        !           378:        asl     r0;\
        !           379:        mov     0,brg>>;\
        !           380:        br      6b;\
        !           381: 8:     mov     8,brg|mar++;\
        !           382:        add     brg,X,X|brg;\
        !           383:        br7     ADDR;\
        !           384:        br      5b;\
        !           385: 9:     or      mem,r0,mem
        !           386: 
        !           387: /*
        !           388:  * IBEG(X) : return buffer index X to pool (i.e. turn off bit in 'bmap')
        !           389:  *     X can't be r0
        !           390:  *     using r0, X, brg, mar, %mar
        !           391:  */
        !           392: #define        IBEG(X)\
        !           393:        mov     X,brg;\
        !           394:        brz     9f;\
        !           395:        mov     bmap0,mar;\
        !           396:        mov     %bmap0,%mar;\
        !           397: 6:     mov     8,brg|mar++;\
        !           398:        sub     brg,X;\
        !           399:        brc     6b;\
        !           400:        add     brg,X;\
        !           401:        mov     1,brg;\
        !           402:        mov     brg,r0;\
        !           403: 7:     dec     X;\
        !           404:        brz     8f;\
        !           405:        asl     r0,r0|brg;\
        !           406:        br      7b;\
        !           407: 8:     mov     0,r0;\
        !           408:        addn    brg,r0;\
        !           409:        and     mem,r0,mem;\
        !           410: 9:
        !           411: 
        !           412: /*
        !           413:  * BITA(I,X,Y,Z): buffer index (in I) to address (X:LSB, Y, Z:MSB)
        !           414:  */
        !           415: #define        BITA(I,X,Y,Z)\
        !           416:        mov     baddr,mar;\
        !           417:        mov     %baddr,%mar;\
        !           418:        mov     mem,X|mar++;\
        !           419:        mov     mem,Y|mar++;\
        !           420:        mov     mem,Z;\
        !           421: 8:     dec     I;\
        !           422:        brz     9f;\
        !           423:        mov     BSIZE2,brg;\
        !           424:        add     brg,X;\
        !           425:        adc     Y;\
        !           426:        adc     Z;\
        !           427:        br      8b;\
        !           428: 9:
        !           429: 
        !           430: /*
        !           431:  * Subroutine CALL and RETURN macros
        !           432:  */
        !           433: #define        CALL(X,SAVE)\
        !           434:        mov     %SAVE,%mar;\
        !           435:        mov     SAVE,mar;\
        !           436:        mov     %9f,mem|mar++;\
        !           437:        mov     9f,mem;\
        !           438:        mov     %X,brg;\
        !           439:        mov     brg,pcr;\
        !           440:        jmp     X;\
        !           441: 9:
        !           442: 
        !           443: #define        RETURN(SAVE)    \
        !           444:        mov     %SAVE,%mar;\
        !           445:        mov     SAVE,mar;\
        !           446:        mov     mem,pcr|mar++;\
        !           447:        jmp     (mem)
        !           448: 
        !           449: /*
        !           450:  * ERROR(X) --- store error code in brg, jump to errlog
        !           451:  */
        !           452: #define        ERROR(X) \
        !           453:        mov     %errlog,brg;\
        !           454:        mov     brg,pcr;\
        !           455:        mov     X,brg;\
        !           456:        jmp     errlog
        !           457:  
        !           458: /*
        !           459:  * Macro BRB(X,Y,Z): if bit Y is on in X, then branch to Z
        !           460:  *     X is a scratch pat register
        !           461:  * Macro BRP(X,Y,Z): if bit Y is on in X, then branch to Z
        !           462:  *     X may not be a scratch pat register
        !           463:  */
        !           464: #define        BRB(X,Y,Z)      \
        !           465:        mov     ~Y,brg;\
        !           466:        or      brg,X,-;\
        !           467:        brz     Z
        !           468: #define        BRP(X,Y,Z)      \
        !           469:        mov     X,r0;\
        !           470:        mov     ~Y,brg;\
        !           471:        or      brg,r0,-;\
        !           472:        brz     Z
        !           473:  
        !           474: /*
        !           475:  * CHK(X,Y): set flag X on Y-th check word
        !           476:  */
        !           477: #ifdef CHECK
        !           478: #define        CHK(X,Y)\
        !           479:        mov     Y,brg;\
        !           480:        mov     brg,r0;\
        !           481:        mov     check,brg;\
        !           482:        add     brg,r0,mar;\
        !           483:        mov     %check,%mar;\
        !           484:        mov     X,brg;\
        !           485:        mov     brg,r0;\
        !           486:        or      mem,r0,mem
        !           487: #else
        !           488: #define        CHK(X,Y)
        !           489: #endif
        !           490:  
        !           491: /*
        !           492:  * CHK1(X,Y): set flag X on Y-th check word
        !           493:  * same as CHK except restore page register (r8)
        !           494:  */
        !           495: #ifdef CHECK
        !           496: #define        CHK1(X,Y)\
        !           497:        CHK(X,Y);\
        !           498:        mov     r8,%mar
        !           499: #else
        !           500: #define        CHK1(X,Y)
        !           501: #endif
        !           502: 
        !           503: /*
        !           504:  * GLTE(CHAN) : CHAN is the channel #
        !           505:  *     LTE size is 32 bytes for each channel
        !           506:  *     When exit, r8(%mar), r10(mar) = addr of LTE
        !           507:  *     Using r8, r10, brg, mar, mem
        !           508:  */
        !           509: #define        GLTE(CHAN)\
        !           510:        mov     CHAN,brg;\
        !           511:        mov     brg,brg>>;\
        !           512:        mov     brg,brg>>;\
        !           513:        mov     brg,brg>>;\
        !           514:        mov     brg,r8;\
        !           515:        mov     0340,brg;\
        !           516:        and     brg,r8,brg;\
        !           517:        mov     brg,r10|mar;\
        !           518:        mov     037,brg;\
        !           519:        and     brg,r8;\
        !           520:        mov     %dzst,brg;\
        !           521:        add     brg,r8,r8|%mar
        !           522:  
        !           523: /*
        !           524:  * INCA(X,Y,Z,AMOUNT) - inc the content of registers X, Y, Z
        !           525:  *     (Z most significant) by AMOUNT
        !           526:  *     X, Y, Z are scratch pad registers
        !           527:  *     Using X, Y, Z, brg
        !           528:  */
        !           529: #define        INCA(X,Y,Z,AMOUNT)\
        !           530:        mov     AMOUNT,brg;\
        !           531:        add     brg,X;\
        !           532:        adc     Y;\
        !           533:        adc     Z
        !           534: 
        !           535: /*
        !           536:  * SPUTTWO(Z,ERR) - put two bytes from odl & odh to cpu
        !           537:  *     cpu addresses are in oal (bits 7-0), oah (bits 15-8),
        !           538:  *     and Z (bits 17-16)
        !           539:  *     If error, go to ERR.
        !           540:  *     When exit, cpu addresses are NOT incremented by 2
        !           541:  *     Does NOT wait for UNIBUS to complete
        !           542:  *     Using r0, r1, brg, npr, oal, oah, odl, odh, mar, mem, X, Y, Z.
        !           543:  */
        !           544: #define        SPUTTWO(Z,ERR)\
        !           545:        asl     Z,brg;\
        !           546:        mov     brg,r0;\
        !           547:        asl     r0;\
        !           548:        mov     nprx,r1;\
        !           549:        mov     ~(BRQ|ACLO|(3<<2)),brg;\
        !           550:        and     brg,r1,brg;\
        !           551:        or      brg,r0,nprx     /* set up bits 17-16 */;\
        !           552:        mov     NRQ|OUT,brg;\
        !           553:        mov     brg,npr         /* issue unibus request */;\
        !           554:        BUSWAIT
        !           555:  
        !           556: /*
        !           557:  * PUTTWO(X,Y,Z,ERR) - put two bytes from odl & odh to cpu
        !           558:  *     cpu addresses are stored in X (bits 7-0)
        !           559:  *             Y (bits 15-8) and Z (bits 17-16)
        !           560:  *     If error, go to ERR.
        !           561:  *     When exit, cpu addresses are incremented by 2
        !           562:  *     Using r0, r1, brg, npr, oal, oah, odl, odh, mar, mem, X, Y, Z.
        !           563:  */
        !           564: #define        PUTTWO(X,Y,Z,ERR)\
        !           565:        mov     X,brg;\
        !           566:        mov     brg,oal;\
        !           567:        mov     Y,brg;\
        !           568:        mov     brg,oah;\
        !           569:        SPUTTWO(Z,ERR);\
        !           570:        INCA(X,Y,Z,2);\
        !           571:        BUSWAIT
        !           572:  
        !           573: /*
        !           574:  * SPUTONE(Z,ERR) - put one bytes from odl/odh to cpu
        !           575:  *     cpu addresses are in oal (bits 7-0), oah (bits 15-8),
        !           576:  *     and Z (bits 17-16)
        !           577:  *     If error, go to ERR.
        !           578:  *     When exit, cpu addresses are NOT incremented by 1
        !           579:  *     Does NOT wait for UNIBUS to complete
        !           580:  *     Using r0, r1, brg, npr, oal, oah, odl, odh, mar, mem, Z.
        !           581:  */
        !           582: #define        SPUTONE(Z,ERR)\
        !           583:        asl     Z,brg;\
        !           584:        mov     brg,r0;\
        !           585:        asl     r0;\
        !           586:        mov     nprx,r1;\
        !           587:        mov     ~(BRQ|ACLO|(3<<2)),brg;\
        !           588:        and     brg,r1,brg;\
        !           589:        or      brg,r0,nprx     /* set up bits 17-16 */;\
        !           590:        mov     NRQ|OUT|BYTE,brg;\
        !           591:        mov     brg,npr         /* issue unibus request */;\
        !           592:        BUSWAIT
        !           593:  
        !           594: /*
        !           595:  * PUTONE(X,Y,Z,ERR) - put one bytes from odl/odh to cpu
        !           596:  *     cpu addresses are stored in X (bits 7-0)
        !           597:  *             Y (bits 15-8) and Z (bits 17-16)
        !           598:  *     If error, go to ERR.
        !           599:  *     When exit, cpu addresses are incremented by 1
        !           600:  *     Using r0, r1, brg, npr, oal, oah, odl, odh, mar, mem, X, Y, Z.
        !           601:  */
        !           602: #define        PUTONE(X,Y,Z,ERR)\
        !           603:        mov     X,brg;\
        !           604:        mov     brg,oal;\
        !           605:        mov     Y,brg;\
        !           606:        mov     brg,oah;\
        !           607:        SPUTONE(Z,ERR);\
        !           608:        INCA(X,Y,Z,1);\
        !           609:        BUSWAIT
        !           610:  
        !           611: /*
        !           612:  * SGETTWO(X,Y,Z,ERR) - get two bytes into idl & idh from cpu
        !           613:  *     cpu addresses are stored in X (bits 7-0)
        !           614:  *             Y (bits 15-8) and Z (bits 17-16)
        !           615:  *     If error, go to ERR.
        !           616:  *     Does NOT wait for UNIBUS to complete
        !           617:  *     When exit, cpu addresses are incremented by 2
        !           618:  *     Using r0, brg, npr, ial, iah, idl, idh, mar, mem, X, Y, Z.
        !           619:  */
        !           620: #define        SGETTWO(X,Y,Z,ERR)\
        !           621:        mov     X,brg;\
        !           622:        mov     brg,ial;\
        !           623:        mov     Y,brg;\
        !           624:        mov     brg,iah;\
        !           625:        asl     Z,brg;\
        !           626:        mov     brg,r0;\
        !           627:        asl     r0;\
        !           628:        mov     NRQ,brg;\
        !           629:        or      brg,r0,npr;\
        !           630:        INCA(X,Y,Z,2);\
        !           631:        BUSWAIT
        !           632:  
        !           633: /*
        !           634:  * GETTWO(X,Y,Z,ERR) - get two bytes into idl & idh from cpu
        !           635:  *     cpu addresses are stored in X (bits 7-0)
        !           636:  *             Y (bits 15-8) and Z (bits 17-16)
        !           637:  *     If error, go to ERR.
        !           638:  *     When exit, cpu addresses are incremented by 2
        !           639:  *     Using r0, brg, npr, ial, iah, idl, idh, mar, mem, X, Y, Z.
        !           640:  */
        !           641: #define        GETTWO(X,Y,Z,ERR)\
        !           642:        SGETTWO(X,Y,Z,ERR);\
        !           643:        BUSWAIT
        !           644:  
        !           645: /*
        !           646:  * MOD1(X,Y,Z) : Z = (X==Y)? 0 : X
        !           647:  * X, Y, Z are scratch pad registers
        !           648:  * X, Y won't be changed when returned
        !           649:  * Using brg
        !           650:  */
        !           651: #define        MOD1(X,Y,Z)\
        !           652:        mov     X,brg;\
        !           653:        addn    brg,Y,-;\
        !           654:        brz     8f;\
        !           655:        br      9f;\
        !           656: 8:     mov     0,brg;\
        !           657: 9:     mov     brg,Z
        !           658: 
        !           659: /*
        !           660:  * MOD0(X,Y,Z) - Z = (X<0)? (X+Y) : (X)
        !           661:  * X, Y, Z are scratch pad registers
        !           662:  * X, Y won't be changed when returned
        !           663:  * Using brg
        !           664:  */
        !           665: #define        MOD0(X,Y,Z)\
        !           666:        mov     X,brg;\
        !           667:        br7     8f;\
        !           668:        br      9f;\
        !           669: 8:     add     brg,Y,brg;\
        !           670: 9:     mov     brg,Z
        !           671: 
        !           672: /*
        !           673:  * TIMES(W,X,Y,Z) - Y(hibyte)Z(low) = W * X
        !           674:  * W, X, Y, Z are scratch pad registers
        !           675:  * W, X, Y, Z can't be the same
        !           676:  * X, Y, Z can't be r0
        !           677:  * X, W won't be changed when returned
        !           678:  * Using brg, r0
        !           679:  */
        !           680: #define        TIMES(W,X,Y,Z)\
        !           681:        mov     0,brg;\
        !           682:        mov     brg,Y;\
        !           683:        mov     brg,Z;\
        !           684:        mov     W,brg;\
        !           685:        mov     brg,r0;\
        !           686:        mov     X,brg;\
        !           687: 8:     dec     r0;\
        !           688:        brz     9f;\
        !           689:        add     brg,Z;\
        !           690:        adc     Y;\
        !           691:        br      8b;\
        !           692: 9:
        !           693: 
        !           694: /*
        !           695:  * BIT(X,Y) - bit pattern - Y = (1 << (x))
        !           696:  * X, Y are scratch pat registers and can't be the same
        !           697:  * usually 0 <= X <= 7
        !           698:  */
        !           699: #define        BIT(X,Y)\
        !           700:        mov     1,brg;\
        !           701:        mov     brg,Y;\
        !           702: 8:     dec     X;\
        !           703:        brz     9f;\
        !           704:        asl     Y;\
        !           705:        br      8b;\
        !           706: 9:
        !           707: 
        !           708: /*
        !           709:  * SENDDATA(HI,LO) : send HI to lur1 and LO to lur0
        !           710:  *     using brg, lur0, lur1, lur2 (if KDI)
        !           711:  *     using brg, odl, odh, oal, oah, mem, mar, npr, nprx, r0 (DR11C)
        !           712:  */
        !           713: #define        SENDDATA(HI,LO) \
        !           714:        mov     HI,brg;\
        !           715:        mov     brg,OHI;\
        !           716:        mov     LO,brg;\
        !           717:        mov     brg,OLO;\
        !           718:        SENDD
        !           719: 
        !           720: #ifdef KDI
        !           721: #ifdef CPM422
        !           722: /*
        !           723:  *     cpm422 can't send an envelop within 2us
        !           724:  *     using brg, r0
        !           725:  */
        !           726: #define D422(X)        DELAY(X)
        !           727: #else
        !           728: #define        D422(X)
        !           729: #endif
        !           730: /*
        !           731:  * DELAY(X):  some time
        !           732:  *     delay 400*(X+1) ns
        !           733:  *     using r0, brg
        !           734:  */
        !           735: #define        DELAY(X) \
        !           736:        mov     X,brg;\
        !           737:        mov     brg,r0;\
        !           738: 9:     dec     r0;\
        !           739:        brc     9b
        !           740: 
        !           741: /*
        !           742:  * READDATA(LOC) : read data in lur0 (lo byte) and lur5 (hi byte)
        !           743:  *     if data is not ready (i.e. DKFRDY (bit 0) is not set), goto LOC.
        !           744:  *     using lur0, lur1, lur5, lur6, brg
        !           745:  */
        !           746: #define        READDATA(LOC)   \
        !           747:        mov     lur6,brg;\
        !           748:        br0     8f;\
        !           749:        br      LOC;\
        !           750: 8:
        !           751: 
        !           752: /*
        !           753:  * SENDD : OLO and OHI have been loaded, just trigger lur2
        !           754:  */
        !           755: #define        SENDD\
        !           756:        mov     0,brg;\
        !           757:        mov     brg,lur2        /* strobe */
        !           758: 
        !           759: /*
        !           760:  * SENDHEAD(CHAN): send DKMARK with channel #
        !           761:  *     using brg, lur0, lur1, lur2
        !           762:  */
        !           763: #define        SENDHEAD(CHAN)\
        !           764:        SENDDATA(D_WHEAD,CHAN)
        !           765: 
        !           766: /*
        !           767:  * SENDPACK(SEQ) : send seq# to seq fifo
        !           768:  *     SEQ is in a scratch pad register
        !           769:  *     using brg, lur1, lur2, SEQ
        !           770: * using also lur6 to check that the transmitter becomes
        !           771: * ready again.  We busy wait until it does.
        !           772: * We the read the sequence number so that the busy
        !           773: * wait loop will be valid the next time
        !           774:  */
        !           775: #define        SENDPACK(SEQ)   \
        !           776:        mov     D_XPACK,brg;\
        !           777:        mov     brg,lur1;\
        !           778:        SENDD;\
        !           779: 1:     mov     lur6,brg;\
        !           780:        br1     1f;\
        !           781:        br      1b;\
        !           782: 1:     mov     D_OSEQ,brg;\
        !           783:        mov     brg,lur1;\
        !           784:        mov     lur1,brg        /*read strobe*/
        !           785: 
        !           786: /*
        !           787:  * SENDCMD(CMD)
        !           788:  */
        !           789: #define        SENDCMD(CMD)\
        !           790:        mov     CMD,brg;\
        !           791:        mov     brg,lur1;\
        !           792:        D422(3)
        !           793: 
        !           794: #else
        !           795: /*
        !           796:  * DR11-C specific macros
        !           797:  */
        !           798: /*
        !           799:  * DELAY(X): DR11C is slow enough and don't need delay
        !           800:  */
        !           801: #define DELAY(X)
        !           802: 
        !           803: /*
        !           804:  * READCMD : read csr word in the DR-11C
        !           805:  * Input: csraddr is the csr unibus address
        !           806:  * Output: idl (low-byte) and idh (hi-byte) of the csr
        !           807:  * Using ial, iah, mar, mem, r0, brg, npr
        !           808:  */
        !           809: #define        READCMD\
        !           810:        mov     %csraddr,%mar;\
        !           811:        mov     csraddr,mar;\
        !           812:        READDR
        !           813:  
        !           814: /*
        !           815:  * READDATA : read dki word of the DR-11C
        !           816:  * Input: dkiaddr is the dki unibus address
        !           817:  * Output: idl (low-byte) and idh (hi-byte) of the dki
        !           818:  * Using ial, iah, mar, mem, r0, brg, npr
        !           819:  */
        !           820: #define        READDATA(LOC)\
        !           821:        READCMD;\
        !           822:        mov     idh,brg;\
        !           823:        br7     9f;\
        !           824:        br      LOC;\
        !           825: 9:;\
        !           826:        mov     %dkiaddr,%mar;\
        !           827:        mov     dkiaddr,mar;\
        !           828:        READDR
        !           829:  
        !           830: /*
        !           831:  * READDR : read a word whose unibus addr is pointed by mar
        !           832:  */
        !           833: #define        READDR\
        !           834:        mov     mem,ial|mar++;\
        !           835:        mov     mem,iah|mar++;\
        !           836:        mov     mem,r0;\
        !           837:        asl     r0;\
        !           838:        asl     r0;\
        !           839:        mov     NRQ,brg;\
        !           840:        or      brg,r0,npr;\
        !           841:        BUSWAIT
        !           842:  
        !           843: /*
        !           844: /*
        !           845:  * WRITEDR : write odl and odh to unibus addr pointed by mar
        !           846:  */
        !           847: #define        WRITEDR\
        !           848:        mov     nprx,r0;\
        !           849:        mov     ~(BRQ|ACLO|(3<<2)),brg;\
        !           850:        and     brg,r0,brg;\
        !           851:        mov     mem,oal|mar++;\
        !           852:        mov     mem,oah|mar++;\
        !           853:        mov     mem,r0;\
        !           854:        asl     r0;\
        !           855:        asl     r0;\
        !           856:        or      brg,r0,nprx;\
        !           857:        mov     OUT|NRQ,brg;\
        !           858:        mov     brg,npr;\
        !           859:        BUSWAIT
        !           860:  
        !           861: /*
        !           862:  * SENDCMD : Issue a DR-11C command by outputing csr
        !           863:  * Using odl, odh, oal, oah, mar, mem, brg, npr, nprx, r0
        !           864:  */
        !           865: #define        SENDCMD(CMD)\
        !           866:        mov     CMD,brg;\
        !           867:        mov     brg,odl;\
        !           868:        mov     0,brg;\
        !           869:        mov     brg,odh;\
        !           870:        mov     %csraddr,%mar;\
        !           871:        mov     csraddr,mar;\
        !           872:        WRITEDR
        !           873: 
        !           874: /*
        !           875:  * SENDD: OHI, OLO have been loaded
        !           876:  * Using odl, odh, oal, oah, mar, mem, brg, npr, nprx, r0
        !           877:  */
        !           878: #define        SENDD\
        !           879:        mov     %dkoaddr,%mar;\
        !           880:        mov     dkoaddr,mar;\
        !           881:        WRITEDR
        !           882: 
        !           883: /*
        !           884:  * SENDHEAD(CHAN) : send DKMARK with channel #
        !           885:  *     channel # can't be in r0
        !           886:  *     using odl, odh, oal, oah, mar, %mar, mem, brg, npr, nprx, r0
        !           887:  */
        !           888: #define        SENDHEAD(CHAN) \
        !           889:        SENDCMD(D_WRITE);\
        !           890:        SENDDATA(D_WHEAD,CHAN)
        !           891: 
        !           892: /*
        !           893:  * SENDPACK(SEQ) : send seq# to seq fifo
        !           894:  *     SEQ can't be in r0
        !           895:  *     using odl, odh, oal, oah, mar, %mar, mem, brg, npr, nprx, r0
        !           896:  */
        !           897: #define        SENDPACK(SEQ) \
        !           898:        SENDCMD(D_XPACK);\
        !           899:        SENDDATA(SEQ,ZERO)
        !           900: 
        !           901: #endif
        !           902: 
        !           903: /*
        !           904:  * Data definitions
        !           905:  */
        !           906:        .data
        !           907: /*
        !           908:  * Global data structures
        !           909:  */
        !           910:        .org    0
        !           911: /*
        !           912:  * check point code
        !           913:  */
        !           914: check: .byte   0,0,0,0,0,0,0
        !           915: /*
        !           916:  * 1 ms timer
        !           917:  * 16 times 50-us timer expires ==> set this timer
        !           918:  */
        !           919: clk1ms:                .byte   0
        !           920: /*
        !           921:  * 5 sec timer : 4096 * 1ms
        !           922:  * Every time clk1ms expires (1ms gone by), clk5s gets decremented
        !           923:  */
        !           924: clk5s:         .byte   0,0
        !           925: /*
        !           926:  * temp storage
        !           927:  */
        !           928: tmp:   .byte   0,0,0,0,0,0,0,0,0,0,0,0
        !           929: /*
        !           930:  * return code: code, lenlo, lenhi, cntl, mode
        !           931:  */
        !           932: repinfo:       .byte   0
        !           933: replen:                .byte   0,0
        !           934: repctl:                .byte   0
        !           935: repmode:       .byte   0
        !           936: /*
        !           937:  * report seq#
        !           938:  */
        !           939: kseq:          .byte   0
        !           940: /*
        !           941:  * # of bad packets received so far
        !           942:  */
        !           943: badpack:       .byte   0
        !           944: /*
        !           945:  * temp storage for output routine
        !           946:  */
        !           947: blklen:                .byte   0
        !           948: /*
        !           949:  * a flag indicates a cntl char was rcv (used in subr.s)
        !           950:  */
        !           951: icntl:         .byte   0
        !           952: /*
        !           953:  * input state: bit7 - RBLEN>0; bit0 - 1st byte of a pair is now in odl
        !           954:  */
        !           955: iflag:         .byte   0
        !           956: /*
        !           957:  * chan#
        !           958:  */
        !           959: chan:          .byte   0
        !           960: /*
        !           961:  * seq#
        !           962:  */
        !           963: pseq:          .byte   0
        !           964: /*
        !           965:  * save r13/r12/r1/... when calling 'rcv'
        !           966:  */
        !           967: rcvsave:       .byte   0,0,0,0
        !           968: /*
        !           969:  * save area for r12 in report
        !           970:  */
        !           971: repsave:       .byte   0,0,0,0
        !           972: /*
        !           973:  * buffer map: 16 locations indicate 16*8 (128) buffers, each 128 bytes
        !           974:  */
        !           975: bmap0:         .byte   0
        !           976: bmap:          .org    .+16
        !           977: /*
        !           978:  * timer map: for max 96 channels
        !           979:  */
        !           980: timemap:       .org    .+12
        !           981: /*
        !           982:  * bit pattern
        !           983:  */
        !           984: bitpatt:       .byte   BIT0,BIT1,BIT2,BIT3,BIT4,BIT5,BIT6,BIT7
        !           985: /*
        !           986:  * starting addresses of host buffer
        !           987:  */
        !           988: baddr:         .byte   0,0,0
        !           989: /*
        !           990:  * Addresses for cmdbuf, tail of cmdbuf, statbuf, head of statbuf,
        !           991:  */
        !           992: cbaddr:                .byte   0,0,0
        !           993: cbtail:                .byte   0,0,0
        !           994: sbaddr:                .byte   0,0,0
        !           995: sbhead:                .byte   0,0,0
        !           996: /*
        !           997:  * CALL/RETURN return address
        !           998:  */
        !           999: s.send:                .byte   0,0
        !          1000: s.rcv:         .byte   0,0
        !          1001: s.report:      .byte   0,0
        !          1002: s.clean:       .byte   0,0
        !          1003: s.copy1:       .byte   0,0
        !          1004: s.cktimer:     .byte   0,0
        !          1005: s.strailer:    .byte   0,0
        !          1006: /*
        !          1007:  * dr11c specific
        !          1008:  */
        !          1009: #ifdef DR11C
        !          1010: /*
        !          1011:  * every time PCLK expires, r_timer gets decremented.
        !          1012:  * if r_timer reaches -1, then read CSR to check R/TDONE
        !          1013:  */
        !          1014: r_timer:       .byte   0
        !          1015: /*
        !          1016:  * UNIBUS addresses for the DR11C
        !          1017:  * Bits 7-0 in 1st byte, 15-8 in 2nd, 17-16 in 3rd (right-adjust)
        !          1018:  */
        !          1019: csraddr:       .byte   0,0,0
        !          1020: dkoaddr:       .byte   0,0,0
        !          1021: dkiaddr:       .byte   0,0,0
        !          1022: #endif
        !          1023: /*
        !          1024:  * output active queue
        !          1025:  */
        !          1026: outq:          .byte   NIL
        !          1027: outq1:         .byte   NIL             /* work area */
        !          1028:  
        !          1029: /*
        !          1030:  * Queue entries
        !          1031:  */
        !          1032: inqueue:
        !          1033:        .org    4*256
        !          1034: /*
        !          1035:  * LTE tables from page 4 to 15, each entry is 32 bytes
        !          1036:  */
        !          1037: dzst:
        !          1038: /*
        !          1039:  * Instruction text starts here
        !          1040:  */
        !          1041:        .text
        !          1042: /*
        !          1043:  * Segment 0
        !          1044:  *
        !          1045:  * This is the main segment
        !          1046:  */
        !          1047:        .org    0
        !          1048: seg0:
        !          1049: init:
        !          1050: /*
        !          1051:  * Set csr0 to idle state (i.e. 0)
        !          1052:  */
        !          1053:        mov     0,brg
        !          1054:        mov     brg,csr0
        !          1055: /*
        !          1056:  * initialize all global variables
        !          1057:  */
        !          1058:        mov     brg,mar
        !          1059:        mov     brg,%mar
        !          1060:        mov     inqueue-1,brg
        !          1061:        mov     brg,r0
        !          1062: init1:
        !          1063:        mov     0,mem|mar++
        !          1064:        dec     r0
        !          1065:        brc     init1
        !          1066: /*
        !          1067:  * initialize special variables (~0)
        !          1068:  */
        !          1069:        mov     outq,mar
        !          1070:        mov     %outq,%mar
        !          1071:        mov     NIL,mem|mar++
        !          1072:        mov     NIL,mem|mar++
        !          1073:        mov     %bitpatt,%mar
        !          1074:        mov     bitpatt,mar
        !          1075:        mov     7,r7
        !          1076:        mov     1,r1
        !          1077: 1:
        !          1078:        mov     r1,mem|mar++
        !          1079:        dec     r7
        !          1080:        brz     2f
        !          1081:        asl     r1
        !          1082:        br      1b
        !          1083: 2:
        !          1084: /*
        !          1085:  * Initialize the free-buffer list
        !          1086:  * page 0-7 is for global data and queues
        !          1087:  * page 8-15 for LTE entries
        !          1088:  */
        !          1089: #define        NLTE    (CHANMODS+7)/8
        !          1090: #define        NPQ     4
        !          1091: #define        NQE     ((NPQ*256-((inqueue+3)&~3))/4)
        !          1092: /*
        !          1093:  * Initialize the list of available queue entries
        !          1094:  */
        !          1095:        mov     NIL,brg
        !          1096:        mov     brg,r14
        !          1097:        mov     (inqueue+3)&~3,brg
        !          1098:        mov     brg,r0
        !          1099:        mov     NQE-2,brg
        !          1100:        mov     brg,r1
        !          1101: init4:
        !          1102:        FREEQ(r0)
        !          1103:        mov     4,brg           /* queue is 4-byte long */
        !          1104:        add     brg,r0
        !          1105:        adc     r0
        !          1106:        dec     r1
        !          1107:        brc     init4
        !          1108: /*
        !          1109:  * Initialize LTE queue pointers
        !          1110:  */
        !          1111:        mov     CHANMODS-1,brg
        !          1112:        mov     brg,r9
        !          1113: init6:
        !          1114: /*
        !          1115:  * reset all LTE values: (can be done globally)
        !          1116:  */
        !          1117:        GLTE(r9)
        !          1118:        mov     31,brg                  /* 32: size of LTE */
        !          1119:        mov     brg,r0
        !          1120: 1:
        !          1121:        mov     0,mem|mar++
        !          1122:        dec     r0
        !          1123:        brc     1b
        !          1124: /*
        !          1125:  * initialized C_X to idle and RQ/RB to nil
        !          1126:  * initailize whatever else is needed
        !          1127:  */
        !          1128:        mov     r8,%mar
        !          1129:        mov     C_X,brg
        !          1130:        add     brg,r10,mar
        !          1131:        mov     XIDLE,mem
        !          1132:        mov     C_RQ,brg
        !          1133:        add     brg,r10,mar
        !          1134:        mov     NIL,mem
        !          1135:        mov     C_RB,brg
        !          1136:        add     brg,r10,mar
        !          1137:        mov     NIL,mem
        !          1138:        dec     r9
        !          1139:        brc     init6
        !          1140: /*
        !          1141:  * Go to disp
        !          1142:  */
        !          1143:        br      disp
        !          1144: /*
        !          1145:  * Dispatcher loop--keep looking for something to do
        !          1146:  */
        !          1147: disp:
        !          1148: /*
        !          1149:  * If csr0 == 0, does nothing and loop.
        !          1150:  * If csr0 == 1, read addresses from csr2~7.
        !          1151:  * If csr0 == 2, normal operation (i.e. take command from
        !          1152:  *     cmdbuff and put report to statbuf).
        !          1153:  */
        !          1154:        mov     csr0,brg
        !          1155:        mov     3,r3
        !          1156:        and     brg,r3,brg
        !          1157:        br1     disp2           /* normal operation */
        !          1158:        br0     disp1           /* direct command */
        !          1159:        mov     brg,r0
        !          1160:        dec     r0,-
        !          1161:        brz     disp            /* idle */
        !          1162:        ERROR(E_SW)
        !          1163: disp1:
        !          1164: /*
        !          1165:  * Get init information from structure pointed by csr2~4
        !          1166:  * struct init {
        !          1167:  *     paddr_t *cmdaddr;
        !          1168:  *     paddr_t *stataddr;
        !          1169:  *     paddr_t *bufaddr
        !          1170:  *     paddr_t *csraddr
        !          1171:  * };
        !          1172:  */
        !          1173:        mov     csr2,r13
        !          1174:        mov     csr3,r12
        !          1175:        mov     csr4,r11
        !          1176:        GETTWO(r13,r12,r11,err_bus)
        !          1177:        mov     idl,r5
        !          1178:        GETTWO(r13,r12,r11,err_bus)
        !          1179:        mov     cbaddr,mar
        !          1180:        mov     %cbaddr,%mar
        !          1181:        mov     idl,mem|mar++           /* cbaddr */
        !          1182:        mov     idh,mem|mar++
        !          1183:        mov     r5,mem|mar++
        !          1184:        mov     idl,mem|mar++           /* cbtail */
        !          1185:        mov     idh,mem|mar++
        !          1186:        mov     r5,mem|mar++
        !          1187:        GETTWO(r13,r12,r11,err_bus)
        !          1188:        mov     idl,r5
        !          1189:        GETTWO(r13,r12,r11,err_bus)
        !          1190:        mov     sbaddr,mar
        !          1191:        mov     %sbaddr,%mar
        !          1192:        mov     idl,mem|mar++           /* sbaddr */
        !          1193:        mov     idh,mem|mar++
        !          1194:        mov     r5,mem|mar++
        !          1195:        mov     idl,mem|mar++           /* sbhead */
        !          1196:        mov     idh,mem|mar++
        !          1197:        mov     r5,mem|mar++
        !          1198:        GETTWO(r13,r12,r11,err_bus)
        !          1199:        mov     idl,r5
        !          1200:        GETTWO(r13,r12,r11,err_bus)
        !          1201:        mov     baddr,mar
        !          1202:        mov     %baddr,%mar
        !          1203:        mov     idl,mem|mar++           /* bufaddr */
        !          1204:        mov     idh,mem|mar++
        !          1205:        mov     r5,mem|mar++
        !          1206: #ifdef KDI
        !          1207: /*
        !          1208:  * Issue D_RESET command and set dko to 0 to clear all fifo's
        !          1209:  */
        !          1210:        mov     D_RESET,brg
        !          1211:        mov     brg,lur1
        !          1212:        mov     brg,lur2
        !          1213: #else
        !          1214: /*
        !          1215:  * Record the unibus address (csr) for this DR-11
        !          1216:  * addr(dko) = addr(csr) + 2
        !          1217:  * addr(dki) = addr(csr) + 4
        !          1218:  */
        !          1219:        GETTWO(r13,r12,r11,err_bus)
        !          1220:        mov     idl,r5
        !          1221:        GETTWO(r13,r12,r11,err_bus)
        !          1222:        mov     idl,r7
        !          1223:        mov     idh,r6
        !          1224:        mov     3,brg
        !          1225:        mov     brg,r5          /* io page */
        !          1226:        mov     %csraddr,%mar
        !          1227:        mov     csraddr,mar
        !          1228:        mov     r7,mem|mar++
        !          1229:        mov     r6,mem|mar++
        !          1230:        mov     r5,mem|mar++
        !          1231: /*
        !          1232:  * Now mar points to dkoaddr
        !          1233:  */
        !          1234:        mov     2,brg
        !          1235:        add     brg,r7,mem|mar++
        !          1236:        adc     r6,mem|mar++
        !          1237:        adc     r5,mem|mar++
        !          1238: /*
        !          1239:  * Now mar points to dkiaddr
        !          1240:  */
        !          1241:        mov     4,brg
        !          1242:        add     brg,r7,mem|mar++
        !          1243:        adc     r6,mem|mar++
        !          1244:        adc     r5,mem
        !          1245: /*
        !          1246:  * Issue D_OSEQ command and set dko to 0 to clear all fifo's
        !          1247:  */
        !          1248:        mov     D_OSEQ,brg
        !          1249:        mov     brg,odl
        !          1250:        mov     0,brg
        !          1251:        mov     brg,odh
        !          1252:        SENDCMD(D_OSEQ)
        !          1253:        SENDDATA(ZERO,ZERO)
        !          1254: #endif
        !          1255: /*
        !          1256:  * Now set csr0 to 2 (i.e. normal operation)
        !          1257:  * Set head/tail of all circular buffers to 0
        !          1258:  */
        !          1259:        mov     0,brg
        !          1260:        mov     brg,csr2
        !          1261:        mov     brg,csr3
        !          1262:        mov     brg,csr4
        !          1263:        mov     brg,csr5
        !          1264:        mov     brg,csr6
        !          1265:        mov     brg,csr7
        !          1266:        mov     2,brg
        !          1267:        mov     brg,csr0
        !          1268:        br      disp
        !          1269: 
        !          1270: disp2:
        !          1271: /*
        !          1272:  * This is normal operation loop
        !          1273:  */
        !          1274:        mov     csr0,brg
        !          1275:        br0     disp2
        !          1276: /*
        !          1277:  * assume kmc is fast enough so that cmdbuf never overflows
        !          1278:  * If HC==TC, then no command available and loop
        !          1279:  */
        !          1280:        mov     HC,brg          /* head of cmdbuf */
        !          1281:        mov     TC,r0           /* tail of cmdbuf */
        !          1282:        addn    brg,r0,-
        !          1283:        brz     disp3
        !          1284: /*
        !          1285:  * Read the command pointed by TC
        !          1286:  * Put k_type in r1, k_chan in r9, k_len in r7-r6,
        !          1287:  * k_ctl/time in r5, k_mode in r4, k_addr in r3-r2-idl-idh
        !          1288:  */
        !          1289:        mov     cbtail,mar
        !          1290:        mov     %cbtail,%mar
        !          1291:        mov     mem,r13|mar++
        !          1292:        mov     mem,r12|mar++
        !          1293:        mov     mem,r11|mar++
        !          1294:        GETTWO(r13,r12,r11,err_bus)
        !          1295:        mov     idl,r1
        !          1296:        GETTWO(r13,r12,r11,err_bus)
        !          1297:        mov     idl,r9
        !          1298:        GETTWO(r13,r12,r11,err_bus)
        !          1299:        mov     idl,r7
        !          1300:        mov     idh,r6
        !          1301:        GETTWO(r13,r12,r11,err_bus)
        !          1302:        mov     idl,r5
        !          1303:        mov     idh,r4
        !          1304:        GETTWO(r13,r12,r11,err_bus)
        !          1305:        mov     idl,r3
        !          1306:        mov     idh,r2
        !          1307:        GETTWO(r13,r12,r11,err_bus)
        !          1308: /*
        !          1309:  * Now modify TC and cbtail.
        !          1310:  * If TC==BUFSIZ-1, then TC=0 and cbtail=cbaddr
        !          1311:  */
        !          1312:        mov     TC,r0
        !          1313:        mov     BUFSIZ-1,brg
        !          1314:        sub     brg,r0,-        /* TC-(BUFSIZ-1) */
        !          1315:        brc     1f
        !          1316:        inc     r0,TC
        !          1317:        br      2f
        !          1318: 1:     mov     0,brg           /* reset TC */
        !          1319:        mov     brg,TC
        !          1320:        mov     cbaddr,mar
        !          1321:        mov     %cbaddr,%mar
        !          1322:        mov     mem,r13|mar++
        !          1323:        mov     mem,r12|mar++
        !          1324:        mov     mem,r11
        !          1325: 2:
        !          1326: /*
        !          1327:  * Restore cbtail
        !          1328:  */
        !          1329:        mov     cbtail,mar
        !          1330:        mov     %cbtail,%mar
        !          1331:        mov     r13,mem|mar++
        !          1332:        mov     r12,mem|mar++
        !          1333:        mov     r11,mem|mar++
        !          1334: /*
        !          1335:  * Decode the command
        !          1336:  * switch (k_type) {
        !          1337:  * case        KC_SEND:        goto kc_send;
        !          1338:  * case        KC_RCVB:        goto kc_rcvb;
        !          1339:  * case        KC_SOI:         goto kc_soi;
        !          1340:  * case KC_CMD:                goto kc_cmd;
        !          1341:  * case KC_FLAG:       goto kc_flag;
        !          1342:  * case KC_TDK:                goto kc_tdk;
        !          1343:  * case KC_XINIT:      goto kc_xinit;
        !          1344:  * case KC_CLOSE:      goto kc_close;
        !          1345:  * case KC_INIT:       goto kc_init;
        !          1346:  * }
        !          1347:  */
        !          1348:        GLTE(r9)                /* set up r8/r10 */
        !          1349:        mov     KC_SEND,brg
        !          1350:        addn    brg,r1,-
        !          1351:        brz     kc_send
        !          1352:        mov     KC_RCVB,brg
        !          1353:        addn    brg,r1,-
        !          1354:        brz     kc_rcvb
        !          1355:        mov     KC_SOI,brg
        !          1356:        addn    brg,r1,-
        !          1357:        brz     kc_soi
        !          1358:        mov     KC_CMD,brg
        !          1359:        addn    brg,r1,-
        !          1360:        brz     kc_cmd
        !          1361:        mov     KC_FLAG,brg
        !          1362:        addn    brg,r1,-
        !          1363:        brz     kc_flag
        !          1364:        mov     KC_TDK,brg
        !          1365:        addn    brg,r1,-
        !          1366:        brz     kc_tdk
        !          1367:        mov     KC_XINIT,brg
        !          1368:        addn    brg,r1,-
        !          1369:        brz     kc_xinit
        !          1370:        mov     KC_CLOSE,brg
        !          1371:        addn    brg,r1,-
        !          1372:        brz     kc_close
        !          1373:        mov     KC_INIT,brg
        !          1374:        addn    brg,r1,-
        !          1375:        brz     kc_init
        !          1376:        ERROR(E_CMD)
        !          1377:        br      disp3
        !          1378: 
        !          1379: kc_init:
        !          1380: /*
        !          1381:  * Process a KC_INIT command
        !          1382:  *     r5 is either D_CALL or D_IDL1
        !          1383:  *     C_X = XINIT; goto kc_reset
        !          1384:  */
        !          1385:        CHK1(B0_KCIT,0)
        !          1386:        mov     C_X,brg
        !          1387:        add     brg,r10,mar
        !          1388:        mov     XINIT,mem
        !          1389:        br      kc_reset                /* expect to rcv D_TALK from ty-4 */
        !          1390: 
        !          1391: kc_xinit:
        !          1392: /*
        !          1393:  * Process a KC_XINIT command
        !          1394:  *     C_X = XINIT; C_XLEN = 0; send(INIT1);
        !          1395:  */
        !          1396:        CHK1(B0_KCIT,0)
        !          1397:        mov     C_X,brg
        !          1398:        add     brg,r10,mar
        !          1399:        mov     XINIT,mem|mar++
        !          1400: /*
        !          1401:        mov     0,mem
        !          1402:  */
        !          1403:        mov     C_XLEN,brg
        !          1404:        add     brg,r10,mar
        !          1405:        mov     0,mem|mar++
        !          1406:        mov     0,mem
        !          1407:        mov     C_XCNTL,brg
        !          1408:        add     brg,r10,mar
        !          1409:        mov     0,mem
        !          1410:        mov     I_INIT1,brg
        !          1411:        mov     brg,r1
        !          1412:        CALL(send,s.send)               /* can simply goto 'time' */
        !          1413:        br      disp3
        !          1414: 
        !          1415: kc_close:
        !          1416: /*
        !          1417:  * process KC_CLOSE command
        !          1418:  *     k_chan is the channel #
        !          1419:  *     if (C_RLEN) report(KS_RDB, chan);
        !          1420:  *     goto kc_reset
        !          1421:  */
        !          1422:        CHK1(B0_KCCS,0)
        !          1423:        mov     C_X,brg
        !          1424:        add     brg,r10,mar
        !          1425:        mov     XIDLE,mem|mar++
        !          1426:        mov     0,mem           /* C_X1 = 0 */
        !          1427:        mov     C_RLEN,brg
        !          1428:        add     brg,r10,mar
        !          1429:        mov     mem,r7|brg
        !          1430:        mov     brg,r0|mar++
        !          1431:        mov     mem,r6
        !          1432:        or      mem,r0
        !          1433:        dec     r0,-
        !          1434:        brz     kc_reset
        !          1435: /*
        !          1436:  * report (KS_RDB,chan) with mode SABORT
        !          1437:  */
        !          1438:        mov     repinfo,mar
        !          1439:        mov     %repinfo,%mar
        !          1440:        mov     KS_RDB,mem|mar++
        !          1441:        mov     r7,mem|mar++            /* residue length */
        !          1442:        mov     r6,mem|mar++
        !          1443:        mov     0,mem|mar++             /* cntl char */
        !          1444:        mov     SABORT,mem              /* RCV mode */
        !          1445:        CALL(report,s.report)
        !          1446: kc_reset:
        !          1447: /*
        !          1448:  * Reset RLEN, XLEN.
        !          1449:  * while (RQ!=NIL) free the queues and buffers
        !          1450:  */
        !          1451:        mov     r8,%mar
        !          1452:        mov     C_RLEN,brg
        !          1453:        add     brg,r10,mar
        !          1454:        mov     0,mem|mar++
        !          1455:        mov     0,mem
        !          1456:        mov     C_RBLEN,brg
        !          1457:        add     brg,r10,mar
        !          1458:        mov     0,mem|mar++
        !          1459:        mov     0,mem
        !          1460:        mov     C_TA0,brg
        !          1461:        add     brg,r10,mar
        !          1462:        mov     0,mem|mar++
        !          1463:        mov     0,mem
        !          1464:        mov     C_C,brg
        !          1465:        add     brg,r10,mar
        !          1466:        mov     0,mem
        !          1467:        mov     C_RQ,brg
        !          1468:        add     brg,r10,mar
        !          1469:        mov     mem,r2
        !          1470:        brz     kc_rs2
        !          1471:        mov     NIL,mem
        !          1472:        CALL(clean,s.clean)
        !          1473:        mov     r8,%mar
        !          1474: kc_rs2:
        !          1475:        mov     C_RB,brg
        !          1476:        add     brg,r10,mar
        !          1477:        mov     mem,r2
        !          1478:        brz     kc_rs4
        !          1479:        mov     NIL,mem
        !          1480:        CALL(clean,s.clean)
        !          1481: kc_rs4:
        !          1482:        mov     r8,%mar
        !          1483:        mov     C_XLEN,brg
        !          1484:        add     brg,r10,mar
        !          1485:        mov     0,mem|mar++
        !          1486:        mov     0,mem
        !          1487:        mov     C_XCNTL,brg
        !          1488:        add     brg,r10,mar
        !          1489:        mov     0,mem
        !          1490: /*
        !          1491:  * remove chan# from 'outq'
        !          1492:  * r2 is running pointer for outq (currently looked at)
        !          1493:  * r3 is the next outq entry
        !          1494:  * r4 is the running pointer for outq1
        !          1495:  */
        !          1496:        mov     outq,mar
        !          1497:        mov     %outq,%mar
        !          1498:        mov     mem,r2
        !          1499: kc_rs6:
        !          1500:        brz     kc_rs14
        !          1501:        QA(r2)
        !          1502:        mov     mem,r3
        !          1503:        mov     NIL,mem|mar++
        !          1504:        addn    mem,r9,-
        !          1505:        brz     kc_rs12                 /* delete this chan# */
        !          1506:        mov     outq1,mar
        !          1507:        mov     %outq1,%mar
        !          1508: kc_rs8:
        !          1509:        mov     mem,r4
        !          1510:        brz     kc_rs10
        !          1511:        QA(r4)
        !          1512:        br      kc_rs8                  /* try to find the end of outq1 */
        !          1513: kc_rs10:
        !          1514: /*
        !          1515:  * found the end of outq1, append r2 here
        !          1516:  */
        !          1517:        mov     r2,mem
        !          1518: kc_rs11:
        !          1519: /*
        !          1520:  * put r3 in r2 position
        !          1521:  */
        !          1522:        mov     r3,brg
        !          1523:        mov     brg,r2
        !          1524:        br      kc_rs6
        !          1525: kc_rs12:
        !          1526:        FREEQ(r2)
        !          1527:        br      kc_rs11
        !          1528: kc_rs14:
        !          1529: /*
        !          1530:  * restore outq from outq1
        !          1531:  */
        !          1532:        mov     outq1,mar
        !          1533:        mov     %outq1,%mar
        !          1534:        mov     mem,brg
        !          1535:        mov     outq,mar
        !          1536:        mov     %outq,%mar
        !          1537:        mov     brg,mem|mar++
        !          1538:        mov     NIL,mem
        !          1539:        br      disp3
        !          1540: kc_soi:
        !          1541: /*
        !          1542:  * Process a KC_SOI command
        !          1543:  *     send 2 bytes in r7 (lo) and r6 (hi) to chan r9
        !          1544:  *     bypass error/flow control mechanism
        !          1545:  */
        !          1546:        CHK1(B0_KCSO,0)
        !          1547:        mov     tmp,mar
        !          1548:        mov     %tmp,%mar
        !          1549:        mov     r9,mem|mar++
        !          1550:        mov     D_WHEAD,mem|mar++
        !          1551:        mov     I_SOI,mem|mar++
        !          1552:        mov     D_WCNTL,mem|mar++
        !          1553:        mov     r7,mem|mar++
        !          1554:        mov     D_WDATA,mem|mar++
        !          1555:        mov     r6,mem|mar++
        !          1556:        mov     D_WDATA,mem|mar++
        !          1557:        mov     I_EOI,mem|mar++
        !          1558:        mov     D_WCNTL,mem|mar++
        !          1559:        mov     ZERO,mem|mar++          /* seq# */
        !          1560:        mov     D_XPACK,mem|mar++
        !          1561: #ifdef DR11C
        !          1562:        SENDCMD(D_WRITE)                /* for dr11-c */
        !          1563: #endif
        !          1564:        mov     0,brg
        !          1565:        mov     brg,r5
        !          1566: kc_so1:
        !          1567:        mov     %tmp,%mar
        !          1568:        mov     tmp,brg
        !          1569:        add     brg,r5,mar
        !          1570:        mov     mem,OLO|mar++
        !          1571:        mov     mem,OHI|mar++
        !          1572:        SENDD
        !          1573:        inc     r5
        !          1574:        inc     r5
        !          1575:        mov     10,brg
        !          1576:        addn    brg,r5,-
        !          1577:        brz     kc_so3          /* issue XPACK */
        !          1578:        brc     disp3
        !          1579:        br      kc_so1
        !          1580: kc_so3:
        !          1581:        SENDCMD(D_XPACK)        /* dor dr11-c */
        !          1582:        br      kc_so1
        !          1583: 
        !          1584: kc_send:
        !          1585: /*
        !          1586:  * Process a KC_SEND command
        !          1587:  * The format is:
        !          1588:  *     k_chan is the chan #
        !          1589:  *     r7-r6: XLEN; r5: XCNTL; r4: mode; idl-idh-r3: XADDR;
        !          1590:  */
        !          1591:        CHK1(B0_KCSD,0)
        !          1592: /*
        !          1593:  * If this chan already in output waiting (C_XLEN!=0), error
        !          1594:  */
        !          1595:        mov     C_XLEN,brg
        !          1596:        add     brg,r10,mar
        !          1597:        mov     mem,r0|mar++
        !          1598:        or      mem,r0
        !          1599:        mov     C_XCNTL,brg
        !          1600:        add     brg,r10,mar
        !          1601:        or      mem,r0
        !          1602:        dec     r0,-
        !          1603:        brz     1f
        !          1604:        br      err_dup
        !          1605: 1:
        !          1606: /*
        !          1607:  * Fill LTE info
        !          1608:  */
        !          1609:        mov     C_XLEN,brg
        !          1610:        add     brg,r10,mar
        !          1611:        mov     r7,mem|mar++    /* C_XLEN */
        !          1612:        mov     r6,mem|mar++
        !          1613:        mov     idl,mem|mar++   /* C_XADDR */
        !          1614:        mov     idh,mem|mar++
        !          1615:        mov     r3,mem|mar++
        !          1616:        mov     C_XCNTL,brg
        !          1617:        add     brg,r10,mar
        !          1618:        mov     r5,mem
        !          1619: /*
        !          1620:  * if mode = XBOTM (i.e. 1<<7), set this bit in C_X1;
        !          1621:  * otherwise reset this bit
        !          1622:  */
        !          1623:        mov     C_X1,brg
        !          1624:        add     brg,r10,mar
        !          1625:        mov     mem,r0
        !          1626:        mov     ~XBOTM,brg
        !          1627:        or      brg,r4,-
        !          1628:        brz     1f
        !          1629:        and     brg,r0,mem
        !          1630:        br      2f
        !          1631: 1:
        !          1632:        orn     brg,r0,mem
        !          1633: 2:
        !          1634: /*
        !          1635:  * if xlen (r7,r6) and xcntl (r5) are all 0, set XNIL for sending
        !          1636:  * trailer only
        !          1637:  */
        !          1638:        mov     r7,brg
        !          1639:        or      brg,r6,brg
        !          1640:        or      brg,r5
        !          1641:        dec     r5,-
        !          1642:        brz     kc_sn6
        !          1643: /*
        !          1644:  * if the channel is not active (i.e. hasn't rcv ainit)
        !          1645:  */
        !          1646:        mov     C_X,brg
        !          1647:        add     brg,r10,mar
        !          1648:        mov     mem,brg
        !          1649:        br1     kc_sn2          /* XACT is set */
        !          1650:        br      disp3
        !          1651: kc_sn2:
        !          1652: /*
        !          1653:  * this channel is output active: put it in 'outq'
        !          1654:  */
        !          1655:        GETQ(r1,noqb)
        !          1656:        mov     NIL,mem|mar++
        !          1657:        mov     r9,mem
        !          1658:        mov     outq,mar
        !          1659:        mov     %outq,%mar
        !          1660: kc_sn3:
        !          1661:        mov     mem,r2
        !          1662:        brz     kc_sn5
        !          1663:        QA(r2)
        !          1664:        br      kc_sn3
        !          1665: kc_sn5:
        !          1666:        mov     r1,mem
        !          1667:        br      disp3
        !          1668: kc_sn6:
        !          1669: /*
        !          1670:  * send trailer mode is on (i.e. 0 data byte, no cntl byte)
        !          1671:  */
        !          1672:        mov     C_X,brg
        !          1673:        add     brg,r10,mar
        !          1674:        mov     mem,brg|mar++
        !          1675:        mov     mem,r7
        !          1676:        mov     XNIL,mem
        !          1677:        or      mem,r7,mem
        !          1678:        br1     kc_sn7
        !          1679:        br      disp3           /* hasn't rcv ainit */
        !          1680: kc_sn7:
        !          1681:        CALL(strailer,s.strailer)
        !          1682:        br      disp3
        !          1683: 
        !          1684: kc_rcvb:
        !          1685: /*
        !          1686:  * process a receive-buffer command
        !          1687:  * The format is:
        !          1688:  *     k_chan is the chan# to be input
        !          1689:  *     r7-r6: RLEN; r5: INITIM; r4: mode; idl-idh-r3: RADDR;
        !          1690:  */
        !          1691:        CHK1(B0_KCRB,0)
        !          1692:        mov     C_RLEN,brg
        !          1693:        add     brg,r10,mar
        !          1694:        mov     mem,r13
        !          1695:        mov     r7,mem|mar++
        !          1696:        mov     mem,r12
        !          1697:        mov     r6,mem|mar++
        !          1698:        mov     idl,mem|mar++           /* RADDR */
        !          1699:        mov     idh,mem|mar++
        !          1700:        mov     r3,mem
        !          1701:        mov     C_INITIM,brg
        !          1702:        add     brg,r10,mar
        !          1703:        mov     r5,mem
        !          1704:        mov     C_Y,brg
        !          1705:        add     brg,r10,mar
        !          1706:        mov     r4,mem
        !          1707: /*
        !          1708:  * If there was an unfinished read-buf, report it
        !          1709:  * i.e. if C_RLEN > 0
        !          1710:  */
        !          1711:        mov     r13,brg
        !          1712:        or      brg,r12,brg
        !          1713:        mov     brg,r0
        !          1714:        dec     r0,-
        !          1715:        brz     kc_rc4
        !          1716: /*
        !          1717:  * abort the old pending read
        !          1718:  * report whatever having been received
        !          1719:  */
        !          1720:        mov     %repinfo,%mar
        !          1721:        mov     repinfo,mar
        !          1722:        mov     KS_RDB,mem|mar++
        !          1723:        mov     r13,mem|mar++
        !          1724:        mov     r12,mem|mar++           /* residue length */
        !          1725:        mov     0,mem|mar++             /* cntl */
        !          1726:        mov     SABORT,mem              /* mode */
        !          1727:        CALL(report,s.report)
        !          1728: kc_rc4:
        !          1729: /*
        !          1730:  * if (char mode && YTIME && (RB != NULL))  set YEXPIRE
        !          1731:  */
        !          1732:        mov     r8,%mar
        !          1733:        mov     C_X1,brg
        !          1734:        add     brg,r10,mar
        !          1735:        mov     mem,r0
        !          1736:        mov     XBLK,brg
        !          1737:        orn     brg,r0,-
        !          1738:        brz     kc_rc7
        !          1739:        mov     C_Y,brg
        !          1740:        add     brg,r10,mar
        !          1741:        mov     mem,r0
        !          1742:        mov     YTIME,brg
        !          1743:        orn     brg,r0,-
        !          1744:        brz     1f
        !          1745:        mov     C_RB,brg
        !          1746:        br      kc_rc8
        !          1747: 1:
        !          1748:        mov     C_RB,brg
        !          1749:        add     brg,r10,mar
        !          1750:        mov     mem,brg
        !          1751:        brz     disp3
        !          1752: /*
        !          1753:  * set YEXPIRE
        !          1754:  */
        !          1755:        mov     C_Y,brg
        !          1756:        add     brg,r10,mar
        !          1757:        mov     mem,r0
        !          1758:        mov     YEXPIRE,brg
        !          1759:        or      brg,r0,mem
        !          1760: kc_rc6:
        !          1761: /*
        !          1762:  * call rcv to copy RQ/RB to RADDR
        !          1763:  */
        !          1764:        CALL(rcv,s.rcv)                 /* copy C_RQ to RADDR */
        !          1765:        br      disp3
        !          1766: kc_rc7:        mov     C_RQ,brg
        !          1767: kc_rc8:        add     brg,r10,mar
        !          1768:        mov     mem,brg
        !          1769:        brz     disp3
        !          1770:        br      kc_rc6
        !          1771: 
        !          1772: kc_cmd:
        !          1773: /*
        !          1774:  * process KC_CMD command
        !          1775:  *     k_chan is the chan #
        !          1776:  *     r7 is the subcommand
        !          1777:  *     only OFLUSH is implemented, others will be added later
        !          1778:  */
        !          1779:        CHK1(B0_KCCM,0)
        !          1780:        br      kc_rs4
        !          1781: 
        !          1782: kc_flag:
        !          1783: /*
        !          1784:  * process KC_FLAG command
        !          1785:  *     k_chan is the chan #
        !          1786:  *     1st two bytes (r7-r6) are iflag, next two (r5-r4) are oflag
        !          1787:  * TO BE DONE LATER
        !          1788:        CHK1(B0_KCFG,0)
        !          1789:  */
        !          1790: br disp3
        !          1791: 
        !          1792: kc_one:
        !          1793: /*
        !          1794:  * process KC_ONE command
        !          1795:  *     k_chan is the chan #
        !          1796:  *     send one byte (control byte) in r7 to ty-4
        !          1797:  * TO BE ADDED LATER
        !          1798:        CHK1(B0_KC1,0)
        !          1799:  */
        !          1800: br disp3
        !          1801: 
        !          1802: kc_tdk:
        !          1803: /*
        !          1804:  * process KC_TDK command
        !          1805:  *     k_chan is the chan #
        !          1806:  * TO BE ADDED LATER
        !          1807:  */
        !          1808: br disp3
        !          1809: 
        !          1810: kc_stime:
        !          1811: /*
        !          1812:  * process KC_STIME command
        !          1813:  *     k_chan is the chan #
        !          1814:  *     r7 is the timer value
        !          1815:  * TO BE ADDED LATER
        !          1816:  */
        !          1817: br disp3
        !          1818: 
        !          1819: disp3:
        !          1820: #ifdef KDI
        !          1821: /*
        !          1822:  * check input data ready and output completion
        !          1823:  * input ready is indicated by DKFRDY (bit 0)
        !          1824:  * output ready is indicated by TRQRDY (bit 1)
        !          1825:  */
        !          1826:        mov     lur6,brg
        !          1827:        br0     csrck2
        !          1828: /*
        !          1829:  * since we are not reading seq fifo, bit 1 is always set
        !          1830:        br1     csrck4
        !          1831:  */
        !          1832: #endif
        !          1833:        BRP(nprx,PCLK,tick)
        !          1834:        br      disp2
        !          1835: 
        !          1836: tick:
        !          1837: /*
        !          1838:  * 50-us timer expires, restart the timer
        !          1839:  */
        !          1840:        mov     nprx,r0
        !          1841:        mov     ~(BRQ|ACLO),brg
        !          1842:        and     brg,r0
        !          1843:        mov     PCLK,brg
        !          1844:        or      brg,r0,nprx
        !          1845: #ifdef DR11C
        !          1846: /*
        !          1847:  * Dec the r_timer, and goto r_expire if r_timer reaches -1
        !          1848:  */
        !          1849:        mov     r_timer,mar
        !          1850:        mov     %r_timer,%mar
        !          1851:        mov     mem,r0
        !          1852:        dec     r0,mem
        !          1853:        brz     r_expire
        !          1854:        br      tick1
        !          1855: 
        !          1856: r_expire:
        !          1857: /*
        !          1858:  * reset r_timer
        !          1859:  */
        !          1860:        mov     R_TIMER,mem
        !          1861: /*
        !          1862:  * check input data ready, then output completion
        !          1863:  */
        !          1864:        READCMD                 /* get csr in idl & idh */
        !          1865: /*
        !          1866:  * If there is an input character available then go to csrck2
        !          1867:  * DKRDONE is 1<<15 in dkcsr
        !          1868:  */
        !          1869:        mov     idh,brg
        !          1870:        br7     csrck2
        !          1871: /*
        !          1872:  * If there is an output data request then go to csrck4
        !          1873:  * DKTDONE is 1<<7 in dkcsr
        !          1874:        mov     idl,brg
        !          1875:        br7     csrck4
        !          1876:  */
        !          1877: #endif
        !          1878: tick1:
        !          1879: /*
        !          1880:  * dec the 1ms timer and return if the result is non-negative
        !          1881:  */
        !          1882:        mov     clk1ms,mar
        !          1883:        mov     %clk1ms,%mar
        !          1884:        mov     mem,r0
        !          1885:        dec     r0,mem
        !          1886:        brc     tick10
        !          1887:        mov     CLK1MS,mem      /* restore timer */
        !          1888:        mov     NGRP,brg
        !          1889:        mov     brg,r6
        !          1890: tick2:
        !          1891: /*
        !          1892:  * 1ms timer expires: dec ITIME for each input chan which on timemap
        !          1893:  * r6: row, r7: column, r5: map itself
        !          1894:  */
        !          1895:        mov     %timemap,%mar
        !          1896:        mov     timemap,brg
        !          1897:        add     brg,r6,mar
        !          1898:        mov     mem,r5|brg|mar++
        !          1899:        mov     7,r7
        !          1900: tick3:
        !          1901:        dec     r5,-
        !          1902:        brz     tick4
        !          1903: tick3.2:
        !          1904:        br7     tick5
        !          1905:        asl     r5,r5|brg
        !          1906:        dec     r7
        !          1907:        br      tick3.2
        !          1908: tick3.5:
        !          1909:        asl     r5,r5|brg
        !          1910:        dec     r7
        !          1911:        brc     tick3
        !          1912: tick4:
        !          1913:        dec     r6
        !          1914:        brc     tick2
        !          1915:        br      tick9
        !          1916: tick5:
        !          1917: /*
        !          1918:  * found this channel (r6<<2 + r7) is timer active (i.e. YTIMACT)
        !          1919:  */
        !          1920:        mov     r6,brg
        !          1921:        mov     brg,r9
        !          1922:        asl     r9
        !          1923:        asl     r9
        !          1924:        asl     r9
        !          1925:        mov     r7,brg
        !          1926:        add     brg,r9          /* r9 is the chan # */
        !          1927:        GLTE(r9)
        !          1928:        mov     C_Y,brg
        !          1929:        add     brg,r10,mar
        !          1930:        mov     mem,r0
        !          1931:        mov     YTIME,brg
        !          1932:        orn     brg,r0,-
        !          1933:        brz     tick7
        !          1934:        br      timeerr
        !          1935: tick7:
        !          1936: /*
        !          1937:  * timer processing is enabled for this chan
        !          1938:  */
        !          1939:        mov     YEXPIRE,brg
        !          1940:        orn     brg,r0,-
        !          1941:        brz     timeerr
        !          1942:        mov     YTIMACT,brg
        !          1943:        orn     brg,r0,-
        !          1944:        brz     1f
        !          1945:        br      timeerr                 /* timer not active */
        !          1946: 1:
        !          1947: /*
        !          1948:  * timer is active, dec ITIME
        !          1949:  */
        !          1950:        mov     C_ITIME,brg
        !          1951:        add     brg,r10,mar
        !          1952:        mov     mem,r0
        !          1953:        dec     r0,mem
        !          1954:        brc     tick3.5         /* not reach zero yet */
        !          1955: /*
        !          1956:  * timer expires: set YEXPIRE
        !          1957:  */
        !          1958:        mov     C_Y,brg
        !          1959:        add     brg,r10,mar
        !          1960:        mov     mem,r0
        !          1961:        mov     YEXPIRE,brg
        !          1962:        or      brg,r0,mem
        !          1963: /*
        !          1964:  * YEXPIRE is set: call 'rcv' 
        !          1965:  */
        !          1966:        mov     %rcvsave,%mar
        !          1967:        mov     rcvsave,mar
        !          1968:        mov     r5,mem|mar++
        !          1969:        mov     r6,mem|mar++
        !          1970:        mov     r7,mem|mar++
        !          1971:        CALL(rcv,s.rcv)
        !          1972:        mov     %rcvsave,%mar
        !          1973:        mov     rcvsave,mar
        !          1974:        mov     mem,r5|mar++
        !          1975:        mov     mem,r6|mar++
        !          1976:        mov     mem,r7|mar++
        !          1977:        CHK(B5_TIME,5)
        !          1978: tick8:
        !          1979: /*
        !          1980:  * reset timemap for this chan
        !          1981:  * the following was done in 'rcv'
        !          1982:        mov     %bitpatt,%mar
        !          1983:        mov     bitpatt,brg
        !          1984:        add     brg,r7,mar
        !          1985:        mov     mem,r0
        !          1986:        mov     %timemap,%mar
        !          1987:        mov     timemap,brg
        !          1988:        add     brg,r6,mar
        !          1989:        xor     mem,r0,mem
        !          1990:  */
        !          1991:        br      tick3.5
        !          1992: timeerr:
        !          1993: /*
        !          1994:  * should never happen: will be removed after being debugged
        !          1995:  */
        !          1996: mov 0222,brg
        !          1997: mov brg,r15
        !          1998: br .
        !          1999: 
        !          2000: tick9:
        !          2001: /*
        !          2002:  * dec 5 sec timer, goto timeout if expires
        !          2003:  * steals this 50-us cycle and 'time' no returns
        !          2004:  */
        !          2005:        mov     clk5s,mar
        !          2006:        mov     %clk5s,%mar
        !          2007:        mov     mem,r0
        !          2008:        dec     r0
        !          2009:        mov     r0,mem|mar++
        !          2010:        mov     mem,r1
        !          2011:        mov     0,brg
        !          2012:        subc    brg,r1,mem
        !          2013:        and     mem,r0,-
        !          2014:        brz     time
        !          2015: tick10:
        !          2016: /*
        !          2017:  * if (outq) goto csrck4;
        !          2018:  * This is the replacement of sending a dummy packet to chan 511
        !          2019:  */
        !          2020:        mov     outq,mar
        !          2021:        mov     %outq,%mar
        !          2022:        mov     mem,r0
        !          2023:        brz     disp2
        !          2024: csrck4:
        !          2025: /*
        !          2026:  * Output data request--jump to output segment
        !          2027:  */
        !          2028:        mov     %out,brg
        !          2029:        mov     brg,pcr
        !          2030:        jmp     out
        !          2031: csrck2:
        !          2032: /*
        !          2033:  * Input data available--jump to input segment
        !          2034:  */
        !          2035:        mov     %in,brg
        !          2036:        mov     brg,pcr
        !          2037:        jmp     in
        !          2038: 
        !          2039: time:
        !          2040: /*
        !          2041:  * timeout routine
        !          2042:  * for each active chan, if (S != R+1) send ENQ
        !          2043:  */
        !          2044: /*
        !          2045:  * reinitialize the clk5s
        !          2046:  */
        !          2047:        mov     clk5s,mar
        !          2048:        mov     %clk5s,%mar
        !          2049:        mov     CLT0,mem|mar++
        !          2050:        mov     CLT1,mem
        !          2051:        mov     CHANMODS,brg
        !          2052:        mov     brg,r9          /* channel # */
        !          2053: time1:
        !          2054:        dec     r9
        !          2055:        brz     disp2
        !          2056:        GLTE(r9)                        /* setup r8/r10 for LTE */
        !          2057:        mov     C_X,brg
        !          2058:        add     brg,r10,mar
        !          2059:        mov     mem,brg
        !          2060:        br0     time1           /* bit 0 indicates un-initialized */
        !          2061:        br1     time2           /* bit 1 indicates initialized */
        !          2062: /*
        !          2063:  * INIT1 was sent and no reply; keep sending INIT1
        !          2064:  */
        !          2065:        mov     I_INIT1,brg
        !          2066:        br      time3
        !          2067: time2:
        !          2068: /*
        !          2069:  * chan is active, if (S!=R+1) send ENQ
        !          2070:  */
        !          2071:        mov     C_S,brg
        !          2072:        add     brg,r10,mar
        !          2073:        mov     mem,r1|mar++
        !          2074:        mov     mem,r0
        !          2075:        inc     r0
        !          2076:        mov     WINDOW,brg
        !          2077:        and     brg,r0,brg
        !          2078:        addn    brg,r1,-
        !          2079:        brz     time1
        !          2080:        mov     C_X1,brg
        !          2081:        add     brg,r10,mar
        !          2082:        mov     mem,r0
        !          2083:        mov     ~(XACK|XREJ),brg
        !          2084:        and     brg,r0                  /* reset XACK and XREJ */
        !          2085:        mov     XENQ,brg
        !          2086:        or      brg,r0,mem              /* set XENQ */
        !          2087:        mov     I_ENQ,brg
        !          2088: time3:
        !          2089:        mov     brg,r1
        !          2090:        CALL(send,s.send)               /* argument in r9, r1 */
        !          2091:        br      time1
        !          2092:  
        !          2093: err_bus:
        !          2094: /*
        !          2095:  * The Unibus transfer fails to complete within 20 usec
        !          2096:  * Clear NEM bit, queue the error, and go to disp
        !          2097:  */
        !          2098:        mov     nprx,r0
        !          2099:        mov     ~(BRQ|ACLO|NEM),brg
        !          2100:        and     brg,r0,nprx
        !          2101:        ERROR(E_BUS)
        !          2102:        br      disp
        !          2103:  
        !          2104: err_dup:
        !          2105: /*
        !          2106:  * Two SEND command
        !          2107:  */
        !          2108:        ERROR(E_DUP)
        !          2109:        br      disp
        !          2110: 
        !          2111: noqb:
        !          2112: /*
        !          2113:  * no queue or buffer
        !          2114:  */
        !          2115:        ERROR(E_NOQB)
        !          2116:        br      disp
        !          2117: 
        !          2118: errlog:
        !          2119: /*
        !          2120:  * r9 - chan#
        !          2121:  * brg - error code
        !          2122:  * after interrupt cpu, go to init and wait for reinitialization
        !          2123:  */
        !          2124:        mov     repinfo,mar
        !          2125:        mov     %repinfo,%mar
        !          2126:        mov     KS_ERR,mem|mar++
        !          2127:        mov     brg,mem
        !          2128:        CALL(report,s.report)
        !          2129:        br      disp2
        !          2130:  
        !          2131: /*
        !          2132:  * End of segment 0
        !          2133:  */
        !          2134: endseg0:
        !          2135: /*
        !          2136:  * Pick up code from other segments
        !          2137:  */
        !          2138: #include       "output.s"
        !          2139: #include       "input.s"
        !          2140: #include       "subr.s"

unix.superglobalmegacorp.com

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