|
|
1.1 ! root 1: ! 2: /* ! 3: * Output segment ! 4: */ ! 5: .org 1024 ! 6: seg1: ! 7: charsw: ! 8: /* br o_isbs /* 010 - BS */ ! 9: /* br o_isht /* 011 - HT */ ! 10: /* br o_isnl /* 012 - NL */ ! 11: /* br o_isvt /* 013 - VT */ ! 12: /* br o_isff /* 014 - FF */ ! 13: /* br o_iscr /* 015 - CR */ ! 14: /* br o_sendit /* 016 - SO */ ! 15: /* br o_sendit /* 017 - SI */ ! 16: ! 17: out: ! 18: /* ! 19: * This is equivalent to xmit routine ! 20: */ ! 21: CHK(B1_ENT,1) /* check point */ ! 22: /* ! 23: * Registers are used as follows: ! 24: * r15 - flag ! 25: * r14 - free queue pointer ! 26: * r13 - bit 7-0 of XADDR ! 27: * r12 - bit 15-8 of XADDR ! 28: * r11 - bit 17-16 of XADDR ! 29: * r9 - chan# ! 30: * r8/r10 - LTE address ! 31: * r7 - blklen, pklen ! 32: * r6,r5 - XLEN ! 33: * r4 - C_S ! 34: * r3 - C_R ! 35: * r2 - blklen ! 36: * ! 37: */ ! 38: ! 39: /* ! 40: * outq is a linked list for all output active channels ! 41: */ ! 42: CHK(B1_ERO,1) /* check point */ ! 43: mov outq,mar ! 44: mov %outq,%mar ! 45: mov mem,r2|mar++ /* outq1 = outq */ ! 46: mov r2,mem ! 47: o_robin: ! 48: /* ! 49: * while (outq1) (pointer in r2) ! 50: */ ! 51: brz o_bye ! 52: QA(r2) ! 53: mov mem,r2|mar++ ! 54: mov mem,r9 ! 55: mov outq1,mar ! 56: mov %outq1,%mar ! 57: mov r2,mem ! 58: GLTE(r9) /* set up r8/r10 */ ! 59: /* ! 60: * if (C_S ^ C_R)&DKBMASK), then the chan is blocked ! 61: */ ! 62: mov C_S,brg ! 63: add brg,r10,mar ! 64: mov mem,r4|mar++ ! 65: xor mem,r4,brg ! 66: mov brg,r0 ! 67: mov DKBMASK,brg ! 68: and brg,r0 ! 69: dec r0,- ! 70: brz o_endrobin ! 71: mov mem,r3|mar++ ! 72: mov mem,r2 /* r2 = C_A */ ! 73: /* ! 74: * r15 is a flag: ! 75: * bit 0 - C_S == C_R ! 76: * bit 1 - mlen == 0 ! 77: * bit 4 - send XCNTL ! 78: */ ! 79: mov C_XCNTL,brg ! 80: add brg,r10,mar ! 81: mov mem,r0 ! 82: dec r0,- ! 83: brz 1f ! 84: mov (1<<4),brg ! 85: br 2f ! 86: 1: mov 0,brg ! 87: 2: mov brg,r15 ! 88: /* ! 89: * mlen' (in r1/r2) = (S-A-1)&07 * DKBLOCK ! 90: */ ! 91: mov r2,brg ! 92: addn brg,r4,brg /* brg=C_S-C_A-1 */ ! 93: mov brg,r5 ! 94: mov WINDOW,brg ! 95: and brg,r5 ! 96: mov DKBLOCK,brg ! 97: mov brg,r6 ! 98: TIMES(r5,r6,r2,r1) ! 99: /* ! 100: * if (mlen'<XLEN) {mlen=XLEN-mlen'; goto o_while;} ! 101: * else if (mlen'>XLEN) { goto o_endrobin; } ! 102: * else if (mlen'=XLEN) { goto o_cntl; } ! 103: * ! 104: * mlen (r6/5) = XLEN (r6/5) - mlen' (r1/r2) ! 105: */ ! 106: mov C_XLEN,brg ! 107: add brg,r10,mar ! 108: mov mem,r6|mar++ ! 109: mov mem,r5|mar++ ! 110: mov r1,brg ! 111: sub brg,r6 ! 112: mov r2,brg ! 113: subc brg,r5,r5|brg ! 114: brc 1f ! 115: /* ! 116: * XLEN < mlen': no data to go out ! 117: */ ! 118: br o_endrobin ! 119: 1: ! 120: /* ! 121: * see if mlen==0 ! 122: */ ! 123: or brg,r6,brg ! 124: mov brg,r0 ! 125: dec r0,- ! 126: brz o_cntl /* send XCNTL, if any */ ! 127: /* ! 128: * ptr = C_XADDR+mlen' ! 129: */ ! 130: add mem,r1,brg|mar++ ! 131: mov brg,r13 ! 132: addc mem,r2,brg|mar++ ! 133: mov brg,r12 ! 134: mov mem,r11 ! 135: adc r11 ! 136: o_while: ! 137: /* ! 138: * blklen (in r2) = min{mlen, DKBLOCK} ! 139: * mlen -= blklen ! 140: */ ! 141: mov DKBLOCK+1,brg ! 142: sub brg,r6 ! 143: mov 0,brg ! 144: subc brg,r5 ! 145: brc o_chunk ! 146: /* ! 147: * mlen <= DKBLOCK: blklen = mlen; mlen = 0; ! 148: */ ! 149: mov DKBLOCK+1,brg ! 150: add brg,r6,brg ! 151: mov brg,r2 ! 152: mov brg,r7 ! 153: mov 0,brg ! 154: mov brg,r6 ! 155: mov brg,r5 ! 156: mov (1<<1),brg ! 157: or brg,r15 ! 158: br o_blk ! 159: o_chunk: ! 160: /* ! 161: * mlen > DKBLOCK: blklen = DKBLOCK; mlen -= DKBLOCK; ! 162: */ ! 163: inc r6 ! 164: adc r5 ! 165: mov DKBLOCK,brg ! 166: mov brg,r2 ! 167: mov brg,r7 ! 168: o_blk: ! 169: /* ! 170: * now wants to send a block with len in r2 ! 171: * pklen (r1) = min{r2, DKCHUNK} ! 172: * blklen -= pklen ! 173: */ ! 174: mov DKCHUNK,brg ! 175: sub brg,r2 ! 176: brc 1f ! 177: /* ! 178: * r2 < DKCHUNK: r1 = r2; r2 = 0; ! 179: */ ! 180: add brg,r2,brg ! 181: mov brg,r1 ! 182: dec r1,- ! 183: brz o_tail /* go send trailer */ ! 184: mov 0,brg ! 185: mov brg,r2 ! 186: br 2f ! 187: 1: ! 188: /* ! 189: * r2 >= DKCHUNK: r1 = DKCHUNK; r2 -= DKCHUNK; ! 190: */ ! 191: mov brg,r1 ! 192: 2: ! 193: o_mark: ! 194: /* ! 195: * Now send the DKMARK with chan# ! 196: */ ! 197: SENDHEAD(r9) ! 198: /* ! 199: * output the rest of the data ! 200: * if r13 is odd, get one byte first ! 201: */ ! 202: mov r13,brg ! 203: br0 o_getone ! 204: o_gettwo: ! 205: /* ! 206: * Get another two bytes of data for this channel ! 207: */ ! 208: SGETTWO(r13,r12,r11,o_err_bus) ! 209: /* ! 210: * Send two bytes out to CIM ! 211: * if pklen is zero, then issue send-packet command ! 212: * otherwise, go back to get another two bytes ! 213: * Now odh was set to DKDATA ! 214: */ ! 215: dec r1 ! 216: BUSWAIT ! 217: SENDDATA(D_WDATA,idl) ! 218: dec r1 /* pklen-- */ ! 219: brz o_sodd ! 220: o_sendhi: ! 221: D422(3) ! 222: SENDDATA(D_WDATA,idh) /* send the hi byte */ ! 223: dec r1,- /* pklen-- */ ! 224: brz o_sendpack ! 225: br o_gettwo ! 226: o_getone: ! 227: /* ! 228: * get 2 bytes, throw away the low byte ! 229: * send the hi byte ! 230: */ ! 231: dec r13 ! 232: mov 0,brg ! 233: subc brg,r12 ! 234: subc brg,r11 /* back up to even address */ ! 235: dec r1 ! 236: GETTWO(r13,r12,r11,o_err_bus) ! 237: br o_sendhi ! 238: o_sodd: ! 239: /* ! 240: * hi byte has not been sent yet: dec addr by 1 ! 241: */ ! 242: mov 0,brg ! 243: dec r13 ! 244: subc brg,r12 ! 245: subc brg,r11 ! 246: o_sendpack: ! 247: /* ! 248: * if r2 (running blklen) > 0, issue XPACK and goto o_blk ! 249: */ ! 250: dec r2,- ! 251: brz o_pack2 ! 252: /* ! 253: * Having loaded a whole packet, now issue the ! 254: * transmit-packet command, i.e. dkcsr=D_XPACK ! 255: */ ! 256: CHK(B1_SPK,1) /* check point */ ! 257: D422(2) ! 258: SENDPACK(r1) ! 259: br o_blk /* go back to send another packet */ ! 260: o_pack2: ! 261: /* ! 262: * if r7-1 (fixed blklen) & 014 == 014, issue XPACK and send trailer ! 263: * in the next packet ! 264: * else don't issue XPACK and send trailer in this packet ! 265: */ ! 266: dec r7,brg ! 267: mov brg,r0 ! 268: mov 014,brg ! 269: orn brg,r0 ! 270: brz 1f ! 271: br o_ta1 ! 272: 1: ! 273: SENDPACK(r1) ! 274: D422(4) ! 275: o_tail: ! 276: /* ! 277: * just sent a block, now send the trailer ! 278: * MARK+chan# BOT blklen 0 SEQ+C_S ! 279: */ ! 280: SENDHEAD(r9) ! 281: o_ta1: ! 282: D422(2) ! 283: mov r15,brg ! 284: br1 o_ta3 ! 285: o_ta1.5: ! 286: mov I_BOTM,brg ! 287: o_ta2: ! 288: mov brg,r0 ! 289: SENDDATA(D_WCNTL,r0) ! 290: D422(4) ! 291: SENDDATA(D_WDATA,r7) ! 292: o_ta2.5: ! 293: D422(4) ! 294: SENDDATA(D_WDATA,ZERO) ! 295: D422(3) ! 296: mov I_SEQ,brg ! 297: or brg,r4,brg ! 298: mov brg,r0 ! 299: SENDDATA(D_WCNTL,r0) ! 300: D422(4) ! 301: SENDPACK(r1) ! 302: /* ! 303: * C_S++ and set XACK ! 304: */ ! 305: inc r4 /* C_S + 1 */ ! 306: mov WINDOW,brg ! 307: and brg,r4 ! 308: mov r8,%mar ! 309: mov C_X1,brg ! 310: add brg,r10,mar ! 311: mov mem,r0 ! 312: mov XACK,brg ! 313: or brg,r0,mem ! 314: /* ! 315: * r2 - pklen ! 316: * Now r6/r5 is the real mlen ! 317: * while (mlen && C_S != C_R) { ! 318: */ ! 319: mov r3,brg ! 320: xor brg,r4,brg ! 321: mov brg,r0 ! 322: mov DKBMASK,brg ! 323: and brg,r0 ! 324: dec r0,- ! 325: brz o_end1 ! 326: mov r15,brg ! 327: br1 o_ta5 ! 328: br o_while ! 329: o_ta3: ! 330: /* ! 331: * reach end of this xmit buffer ! 332: */ ! 333: mov r15,brg ! 334: br4 o_ta5 ! 335: o_ta4: ! 336: mov r8,%mar ! 337: mov C_X1,brg ! 338: add brg,r10,mar ! 339: mov mem,r0 ! 340: mov ~XBOTM,brg ! 341: or brg,r0,- ! 342: brz 1f ! 343: mov I_BOT,brg ! 344: br o_ta2 ! 345: 1: ! 346: mov I_BOTM,brg ! 347: br o_ta2 ! 348: o_ta5: ! 349: /* ! 350: * check if XCNTL to be sent ! 351: */ ! 352: mov r15,brg ! 353: br4 1f ! 354: br o_end1 /* no XCNTL */ ! 355: 1: ! 356: /* ! 357: * reset bit 4 so that next time around we will not duplicate ! 358: */ ! 359: mov ~(1<<4),brg ! 360: and brg,r15 ! 361: /* ! 362: * check if blklen<DKBLOCK: send XCNTL in this block ! 363: */ ! 364: mov DKBLOCK,brg ! 365: addn brg,r7,- ! 366: brz o_ta1.5 /* send XCNTL in next block */ ! 367: /* ! 368: * send XCNT in this block: see if in the same chunk ! 369: * if the last chunk size was 12-16, then start a new chunk ! 370: */ ! 371: dec r7,brg ! 372: mov brg,r0 ! 373: mov ~014,brg ! 374: or brg,r0,- ! 375: brz o_ta6 /* r7 was 16, 15, 14, or 13 */ ! 376: or brg,r7,- ! 377: brz o_ta6 /* r7 was 12 */ ! 378: br o_ta8 ! 379: o_ta6: ! 380: /* ! 381: * finish the old chunk, restart with a new chunk ! 382: */ ! 383: SENDPACK(r1) ! 384: D422(4) ! 385: o_ta7: ! 386: SENDHEAD(r9) ! 387: D422(2) ! 388: o_ta8: ! 389: CHK(B1_CNTL,1) ! 390: mov r8,%mar ! 391: mov C_XCNTL,brg ! 392: add brg,r10,mar ! 393: SENDDATA(D_WCNTL,mem) /* send cntl */ ! 394: inc r7 ! 395: br o_ta4 ! 396: o_cntl: ! 397: /* ! 398: * send XCNTL, if any ! 399: */ ! 400: mov r15,brg ! 401: br4 1f ! 402: br o_endrobin ! 403: 1: ! 404: /* ! 405: * now send the single XCNTL in a block by itself ! 406: * code should look like: ! 407: * SENDHEAD(r9) ! 408: * SENDDATA(D_WCNTL,r1) ! 409: * mov I_BOT,brg ! 410: * mov brg,r1 ! 411: * SENDDATA(D_WCNTL,r1) ! 412: * mov 1,r1 ! 413: * SENDDATA(D_WDATA,r1) ! 414: * br o_ta2.5 ! 415: * ! 416: * the reason we goto o_tail is to save text space and slightly slower ! 417: */ ! 418: mov (1<<1),brg /* indicate mlen == 0 */ ! 419: or brg,r15 ! 420: mov 0,brg /* is 0, will be 1 later */ ! 421: mov brg,r7 ! 422: br o_ta7 ! 423: o_done: ! 424: /* ! 425: * mlen is 0: we can send CHECK here or do nothing ! 426: mov I_CHECK,brg ! 427: mov brg,r1 ! 428: CALL(send,s.send) ! 429: */ ! 430: ! 431: o_end1: ! 432: /* ! 433: * save r4 in C_S ! 434: */ ! 435: mov r8,%mar ! 436: mov C_S,brg ! 437: add brg,r10,mar ! 438: mov r4,mem /* restore C_S */ ! 439: o_endrobin: ! 440: /* ! 441: * BEWARE issue D_WRITE in the while loop, instead of robin loop. ! 442: * inc r9 and go to robin loop. ! 443: */ ! 444: CHK(B1_ENRO,1) /* check point */ ! 445: mov outq1,mar ! 446: mov %outq1,%mar ! 447: mov mem,r2 ! 448: br o_robin ! 449: o_bye: ! 450: o_disp: ! 451: /* ! 452: * return to main dispatch loop ! 453: */ ! 454: CHK(B1_EXIT,1) /* check point */ ! 455: mov %disp2,brg ! 456: mov brg,pcr ! 457: jmp disp2 ! 458: o_err_bus: ! 459: /* ! 460: * Unibus request fails to complete within 20 usec ! 461: */ ! 462: mov %err_bus,brg ! 463: mov brg,pcr ! 464: jmp err_bus ! 465: ! 466: ii_init: ! 467: /* ! 468: * send(r9, I_AINIT); ! 469: */ ! 470: mov I_AINIT,brg ! 471: mov brg,r1 ! 472: CALL(send,s.send) /* argument in r9, r1 */ ! 473: mov r5,brg /* r5=0 for init0, r5=1 for init1 */ ! 474: br0 i_init1 ! 475: br i_init0 ! 476: i_init1: ! 477: /* ! 478: * set block mode ! 479: * reset TA0-TA3, RSEQ, RBLEN, RULEN ! 480: * release all queues and buffers from C_RB, C_RQ ! 481: */ ! 482: CHK(B4_IN1,4) ! 483: mov r8,%mar ! 484: mov C_X1,brg ! 485: add brg,r10,mar ! 486: mov XBLK,brg ! 487: mov brg,r0 ! 488: or mem,r0,mem /* set block mode */ ! 489: mov C_TA0,brg ! 490: add brg,r10,mar ! 491: mov 0,mem|mar++ ! 492: mov 0,mem|mar++ ! 493: mov 0,mem|mar++ ! 494: mov 0,mem|mar++ ! 495: mov C_RSEQ,brg ! 496: add brg,r10,mar ! 497: mov 0,mem ! 498: mov C_RULEN,brg ! 499: add brg,r10,mar ! 500: mov 0,mem|mar++ ! 501: mov 0,mem|mar++ /* RULEN = 0 */ ! 502: mov C_RBLEN,brg ! 503: add brg,r10,mar ! 504: mov 0,mem|mar++ ! 505: mov 0,mem|mar++ /* RBLEN = 0 */ ! 506: mov mem,r2 /* r2 = C_RB */ ! 507: brz i_11 ! 508: mov NIL,mem ! 509: CALL(clean,s.clean) ! 510: i_11: ! 511: mov r8,%mar ! 512: mov C_RQ,brg ! 513: add brg,r10,mar ! 514: mov mem,r2 /* r2 = C_RQ */ ! 515: brz ii_loop ! 516: mov NIL,mem ! 517: CALL(clean,s.clean) ! 518: br ii_loop ! 519: ! 520: i_init0: ! 521: /* ! 522: * set char mode ! 523: */ ! 524: CHK(B4_IN0,4) ! 525: mov r8,%mar ! 526: mov C_X1,brg ! 527: add brg,r10,mar ! 528: mov ~XBLK,brg ! 529: mov brg,r0 ! 530: and mem,r0,mem /* set char mode */ ! 531: br ii_loop ! 532: ! 533: ii_ainit: ! 534: /* ! 535: * S = 1, R = 0, A = 0; ! 536: * X = XACT; ! 537: */ ! 538: CHK(B4_AIN,4) ! 539: mov r8,%mar ! 540: mov C_S,brg ! 541: add brg,r10,mar ! 542: mov 1,mem|mar++ /* S = 1 */ ! 543: mov 0,mem|mar++ /* R = 0 */ ! 544: mov 0,mem /* A = 0 */ ! 545: mov C_X,brg ! 546: add brg,r10,mar ! 547: mov XACT,mem|mar++ ! 548: mov mem,r0 /* C_X1 */ ! 549: mov XNIL,brg ! 550: orn brg,r0,- ! 551: brz i_ai5 /* send trailer only */ ! 552: mov C_XLEN,brg ! 553: add brg,r10,mar ! 554: mov mem,r0|mar++ ! 555: or mem,r0 ! 556: mov C_XCNTL,brg ! 557: add brg,r10,mar ! 558: or mem,r0 ! 559: dec r0,- ! 560: brz ii_loop ! 561: /* ! 562: * this channel is output active: put it in 'outq' ! 563: */ ! 564: GETQ(r1,o_noqb) ! 565: mov NIL,mem|mar++ ! 566: mov r9,mem ! 567: mov %outq,%mar ! 568: mov outq,mar ! 569: i_ai2: ! 570: mov mem,r2 ! 571: brz i_ai3 ! 572: QA(r2) ! 573: br i_ai2 ! 574: i_ai3: ! 575: mov r1,mem ! 576: br ii_loop ! 577: i_ai5: ! 578: /* ! 579: * send trailer-only mode ! 580: */ ! 581: CALL(strailer,s.strailer) ! 582: br ii_loop ! 583: ! 584: ii_req: ! 585: /* ! 586: * send I_INIT1 ! 587: * X = XINIT; ! 588: */ ! 589: CHK(B4_IREQ,4) ! 590: mov I_INIT1,brg ! 591: mov brg,r1 ! 592: CALL(send,s.send) ! 593: mov r8,%mar ! 594: mov C_X,brg ! 595: add brg,r10,mar ! 596: mov XINIT,mem ! 597: br ii_loop ! 598: ! 599: ii_enq: ! 600: /* ! 601: * send C_C ! 602: */ ! 603: CHK(B3_ENQ,3) ! 604: mov r8,%mar ! 605: mov C_C,brg ! 606: add brg,r10,mar ! 607: mov mem,r1 ! 608: CALL(send,s.send) ! 609: ii_check: ! 610: /* ! 611: * send ACK+C_RSEQ ! 612: * release C_RB ! 613: */ ! 614: CHK(B3_CHK,3) ! 615: mov r8,%mar ! 616: mov C_RSEQ,brg ! 617: add brg,r10,mar ! 618: mov mem,r1 ! 619: mov I_ACK,brg ! 620: or brg,r1 ! 621: CALL(send,s.send) ! 622: mov r8,%mar ! 623: mov C_RB,brg ! 624: add brg,r10,mar ! 625: mov mem,r2 ! 626: brz ii_loop ! 627: mov NIL,mem ! 628: CALL(clean,s.clean) ! 629: mov %i_ebmode,brg ! 630: mov brg,pcr ! 631: jmp i_ebmode ! 632: ! 633: ii_eoi: ! 634: /* ! 635: * if TA0==SOI and TA1==2, then report KS_EOI ! 636: * TA0,TA1 = 0; ! 637: */ ! 638: CHK(B4_EOI,4) ! 639: mov r8,%mar ! 640: mov C_TA0,brg ! 641: add brg,r10,mar ! 642: mov mem,r7 ! 643: mov 0,mem|mar++ ! 644: mov mem,r6 ! 645: mov 0,mem|mar++ ! 646: mov I_SOI,brg ! 647: addn brg,r7,- ! 648: brz 1f ! 649: br ii_loop ! 650: 1: ! 651: mov 2,brg ! 652: addn brg,r6,- ! 653: brz 1f ! 654: br ii_loop ! 655: 1: ! 656: /* ! 657: * report 2 bytes in TA2, TA3 ! 658: */ ! 659: mov mem,r7|mar++ /* TA2 */ ! 660: mov mem,r6 /* TA3 */ ! 661: mov %repinfo,%mar ! 662: mov repinfo,mar ! 663: mov KS_EOI,mem|mar++ ! 664: mov r7,mem|mar++ /* lo byte */ ! 665: mov r6,mem|mar++ /* hi byte */ ! 666: br ii_rpt /* goto CALL(report,s.report) */ ! 667: ! 668: ii_tdkcl: ! 669: /* ! 670: * rcv a tdk control char, report tdk cntl ! 671: */ ! 672: mov repinfo,mar ! 673: mov %repinfo,%mar ! 674: mov KS_CNTL,mem|mar++ ! 675: mov 0,mem|mar++ ! 676: mov 0,mem|mar++ ! 677: mov r1,mem|mar++ ! 678: ii_rpt: ! 679: CALL(report,s.report) ! 680: ii_loop: ! 681: /* ! 682: * return to i_loop ! 683: */ ! 684: mov %i_loop,brg ! 685: mov brg,pcr ! 686: jmp i_loop ! 687: o_noqb: ! 688: /* ! 689: * run out of queues and buffers ! 690: */ ! 691: mov %noqb,brg ! 692: mov brg,pcr ! 693: jmp noqb ! 694: ! 695: endseg1: ! 696: ! 697:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.