|
|
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.