Annotation of researchv8dc/sys/kdi/main.s, revision 1.1.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.