|
|
1.1 root 1:
2: /*
3: * subroutine
4: */
5: .org 3072
6: seg3:
7: r_err_bus:
8: /*
9: * Unibus request fails to complete within 20 usec
10: * currently is not tested
11: */
12: mov %err_bus,brg
13: mov brg,pcr
14: jmp err_bus
15:
16: rcv:
17: /*
18: * copy packets from C_RQ to C_RADDR (from host to host for XBLK)
19: * copy from C_RB to C_RADDR for ~XBLK
20: * input : r9 is the chan #, r8/r10 point to LTE
21: * Registers are used as follows:
22: * r15 - repmode
23: * r13(LSB), r12, r11 - ptr2 (RADDR)
24: * r9 - chan #
25: * r8/r10 - LTE address
26: * r7 - RQ
27: * r6(LSB), r5, r4(MSB) - stage 2 buffer
28: * r3 - plen
29: * r2 - len
30: */
31: CHK(B5_ENT,5)
32: /*
33: mov repsave,mar
34: mov %repsave,%mar
35: mov r12,mem
36: */
37: mov 0,brg
38: mov brg,r15
39: mov repctl,mar
40: mov %repctl,%mar
41: mov 0,mem /* flag to indicate no CNTL rcv yet */
42: /*
43: * set STIME if timer expires
44: */
45: mov r8,%mar
46: mov C_Y,brg
47: add brg,r10,mar
48: mov mem,r0
49: mov YEXPIRE,brg
50: orn brg,r0,-
51: brz 1f
52: br 2f
53: 1: mov STIME,brg
54: or brg,r15
55: 2:
56: /*
57: * put RADDR into r13, r12, r11
58: * put RQ/RB into r7
59: * RQ and RADDR will be restored with the new value after the while loop
60: */
61: mov C_X1,brg
62: add brg,r10,mar
63: mov mem,r0
64: mov XBLK,brg
65: orn brg,r0,-
66: brz 1f
67: mov C_RB,brg
68: br 2f
69: 1: /* block mode */
70: mov C_RQ,brg
71: 2: add brg,r10,mar
72: mov mem,r7
73: brz r_ex2
74: mov C_RADDR,brg
75: add brg,r10,mar
76: mov mem,r13|mar++
77: mov mem,r12|mar++
78: mov mem,r11
79: r_while:
80: /*
81: * while ((C_RLEN>0) && (C_RQ!=NULL))
82: */
83: mov r7,r7
84: brz r_endwhile
85: mov C_RLEN,brg
86: add brg,r10,mar
87: mov mem,r0
88: mov mem,r2|mar++
89: mov mem,r1
90: or mem,r0
91: dec r0,-
92: brz r_endwhile
93: /*
94: * len222 = len = min(plen,C_RLEN);
95: */
96: QA(r7)
97: mov mem,mem|mar++
98: mov mem,r3|mar++ /* plen */
99: mov mem,idl|mar++ /* *pdata */
100: dec r3,- /* test for rej packet */
101: brz r_rq
102: /*
103: * r2,r1 -= len222
104: */
105: mov r8,%mar
106: mov C_RLEN,brg
107: add brg,r10,mar
108: mov r3,brg
109: sub brg,r2
110: mov 0,brg
111: subc brg,r1
112: brc 1f
113: /*
114: * case: plen > C_RLEN
115: * len = C_RLEN (r2)
116: * C_RLEN = 0
117: * plen (r3) = plen - len
118: */
119: mov mem,r2
120: mov 0,mem|mar++
121: mov 0,mem
122: CHK(B5_PLEN,5)
123: mov r2,brg
124: sub brg,r3
125: br 2f
126: 1:
127: /*
128: * case: plen <= C_RLEN
129: * C_RLEN is now in r2, r1
130: * len = plen (r3)
131: * plen = 0;
132: */
133: mov r2,mem|mar++
134: mov r1,mem
135: mov r3,brg
136: mov brg,r2
137: sub brg,r3 /* plen = 0 */
138: 2:
139: /*
140: * idl is the buffer index
141: * let r6-r4 points to pdata
142: */
143: mov idl,brg
144: mov brg,r1
145: BITA(r1,r6,r5,r4)
146: /*
147: * while (len--) *ptr2++ = *ptr1++;
148: * test 'r13' for even or odd first
149: */
150: mov r13,brg
151: br0 r_odd
152: br r_even
153: r_odd:
154: /*
155: * copy one byte
156: */
157: CHK(B5_ODD,5)
158: GETTWO(r6,r5,r4,r_err_bus)
159: dec r2
160: mov idh,brg
161: br0 1f
162: br r_cnt1 /* cntl is rcv */
163: 1:
164: mov idl,brg
165: mov brg,odl
166: mov brg,odh
167: PUTONE(r13,r12,r11,r_err_bus)
168: dec r2,-
169: brz r_done
170: r_even:
171: /*
172: * copy two bytes at a time
173: */
174: mov 2,brg
175: sub brg,r2,- /* len - 2 */
176: brc 1f
177: brz r_odd
178: br r_done
179: 1:
180: GETTWO(r6,r5,r4,r_err_bus)
181: dec r2
182: mov idh,brg
183: br0 1f
184: br r_cnt1 /* cntl is rcv */
185: 1:
186: mov idl,brg
187: mov brg,odl
188: GETTWO(r6,r5,r4,r_err_bus)
189: dec r2
190: mov idh,brg
191: br0 1f
192: br r_cnt0
193: 1:
194: mov idl,brg
195: mov brg,odh
196: PUTTWO(r13,r12,r11,r_err_bus)
197: br r_even
198: r_done:
199: /*
200: * this is the end of copy
201: * if (plen==0) ?
202: */
203: dec r3,-
204: brz r_rq
205: /*
206: * plen != 0, move data to the front of the buffer
207: * while (plen--) *ptr2++ = *ptr1++
208: * ptr2 in r13-11 (pdata[0]), ptr1 in r6-r4 (pdata[plen])
209: */
210: CHK(B5_MOVE,5)
211: mov tmp,mar
212: mov %tmp,%mar
213: mov r13,mem|mar++
214: mov r12,mem|mar++
215: mov r11,mem
216: QA(r7)
217: mov mem,mem|mar++
218: mov r3,mem /* store plen */
219: mov mem,idl|mar++ /* idl = plen */
220: mov mem,r3 /* points to pdata[0] */
221: BITA(r3,r13,r12,r11)
222: mov idl,brg
223: mov brg,r3
224: r_move:
225: /*
226: * while (plen--) ....
227: */
228: dec r3,-
229: brz r_ret
230: GETTWO(r6,r5,r4,r_err_bus)
231: mov idl,brg
232: mov brg,odl
233: mov idh,brg
234: mov brg,odh
235: PUTTWO(r13,r12,r11,r_err_bus)
236: dec r3 /* move 2-bytes: 1 9-bit envelop */
237: br r_move
238: r_ret:
239: /*
240: * restore r13, r12, r11
241: */
242: mov tmp,mar
243: mov %tmp,%mar
244: mov mem,r13|mar++
245: mov mem,r12|mar++
246: mov mem,r11
247: /*
248: * now test if cntl was rcv
249: */
250: mov repctl,mar
251: mov %repctl,%mar
252: mov mem,r0
253: dec r0,-
254: brc r_cnt3 /* rcv cntl flag set */
255: br r_rp2 /* plen>0, then RLEN must be 0 */
256: r_rq:
257: /*
258: * RQ = Pnext;
259: * release buffer and queue
260: * send echo or rej if pseq!=0
261: */
262: mov r7,brg
263: mov brg,r5 /* r5 = old RQ */
264: QA(r5)
265: mov mem,r7|mar++ /* r7 = new RQ */
266: mov 0,mem|mar++ /* plen = 0 */
267: mov mem,r6 /* r6 = buf pointer */
268: mov NIL,mem|mar++
269: mov mem,r1 /* pseq */
270: mov mem,r2
271: mov 0,mem
272: FREEQ(r5)
273: IBEG(r6)
274: dec r1,-
275: brz r_rq2
276: /*
277: * if pseq&0370 == I_SEQ: pseq += I_ECHO - I_SEQ; set SBLOCK
278: */
279: mov ~WINDOW,brg
280: and brg,r2
281: mov I_SEQ,brg
282: xor brg,r2
283: dec r2,-
284: brc r_rq1
285: mov WINDOW,brg
286: and brg,r1
287: mov I_ECHO,brg
288: or brg,r1 /* r1 = ECHO + seq */
289: /*
290: * if YBLOCK is set, set SBLOCK
291: */
292: mov r8,%mar
293: mov C_Y,brg
294: add brg,r10,mar
295: mov mem,r0
296: mov YBLOCK,brg
297: orn brg,r0,-
298: brz 1f
299: br r_rq1
300: 1:
301: mov SBLOCK,brg
302: or brg,r15 /* reach end of a block */
303: r_rq1:
304: CALL(send,s.send)
305: mov r8,%mar
306: mov C_C,brg
307: add brg,r10,mar
308: mov r1,mem
309: r_rq2:
310: mov repctl,mar
311: mov %repctl,%mar
312: mov mem,r0
313: dec r0,-
314: brc r_cnt3
315: r_report:
316: /*
317: * if C_RLEN==0 report(KS_RDB,r9)
318: */
319: mov r8,%mar
320: mov C_RLEN,brg
321: add brg,r10,mar
322: mov mem,r0|mar++
323: or mem,r0
324: dec r0,-
325: brz r_rp2
326: mov SBLOCK,brg
327: orn brg,r15,-
328: brz r_rp3
329: br r_while
330: r_rp2:
331: mov SFULL,brg
332: or brg,r15 /* RLEN reaches 0 */
333: r_rp3:
334: /*
335: * save r7 and r13,r12, r11 here
336: * report READ completion: code in r15.
337: */
338: CHK(B5_REP,5)
339: mov r8,%mar
340: mov C_RLEN,brg
341: add brg,r10,mar
342: mov mem,r2
343: mov 0,mem|mar++
344: mov mem,r3
345: mov 0,mem
346: mov %repinfo,%mar
347: mov repinfo,mar
348: mov KS_RDB,mem|mar++
349: mov r2,mem|mar++
350: mov r3,mem|mar++
351: mov mem,mem|mar++ /* cntl char */
352: mov r15,mem
353: CALL(report,s.report)
354: mov r8,%mar
355: br r_ex0
356: r_endwhile:
357: /*
358: * Restore RADDR from r13, r12, r11
359: * Restore RQ or RB (if ~XBLK) from r7
360: */
361: dec r15,-
362: brc r_rp3
363: mov r8,%mar
364: mov C_RADDR,brg
365: add brg,r10,mar
366: mov r13,mem|mar++
367: mov r12,mem|mar++
368: mov r11,mem
369: r_ex0:
370: mov C_X1,brg
371: add brg,r10,mar
372: mov mem,r0
373: mov XBLK,brg
374: orn brg,r0,-
375: brz 1f
376: mov C_RB,brg
377: br 2f
378: 1: /* block mode */
379: mov C_RQ,brg
380: 2: add brg,r10,mar
381: mov r7,mem
382: r_exit:
383: CHK(B5_EXIT,5)
384: /*
385: mov repsave,mar
386: mov %repsave,%mar
387: mov mem,r12
388: */
389: RETURN(s.rcv)
390: r_ex2:
391: dec r15,-
392: brc r_rp3
393: br r_exit
394: r_cnt0:
395: /*
396: * copy 1 byte to RADDR and report completion for SCNTL
397: */
398: mov odl,brg
399: mov brg,odh
400: PUTONE(r13,r12,r11,r_err_bus)
401: r_cnt1:
402: /*
403: * len (r2) may not be 0
404: * adjust RLEN and plen
405: */
406: mov r2,brg
407: add brg,r3
408: mov 0,r0
409: inc r2
410: mov r8,%mar
411: mov C_RLEN,brg
412: add brg,r10,mar
413: add mem,r2,mem|mar++
414: addc mem,r0,mem
415: mov repctl,mar
416: mov %repctl,%mar
417: mov idl,mem
418: br r_done
419: r_cnt3:
420: /*
421: * prepare for report
422: */
423: mov SCNTL,brg
424: or brg,r15
425: br r_rp3
426:
427: clean:
428: /*
429: * r2 is a queue pointer: release all queues/buffers
430: * using r0, r2, r3, brg, mar, %mar
431: */
432: CHK(B5_AJAX,5)
433: c_1:
434: mov r2,brg
435: brz c_exit
436: mov brg,r0
437: QA(r0)
438: mov mem,r2|mar++ /* pnext */
439: mov 0,mem|mar++ /* plen */
440: mov mem,r3
441: mov NIL,mem|mar++ /* *pdata */
442: mov 0,mem /* pseq */
443: FREEQ(r0)
444: IBEG(r3)
445: br c_1
446: c_exit:
447: RETURN(s.clean)
448:
449: send:
450: /*
451: * This subroutine sends a 1-byte (in r1) meta packet on chan r9
452: */
453: SENDHEAD(r9)
454: D422(4)
455: SENDDATA(D_WCNTL,r1)
456: D422(4)
457: SENDPACK(r1)
458: D422(4)
459: SENDCMD(D_READ)
460: RETURN(s.send)
461:
462:
463: report:
464: mov csr0,brg
465: br0 report /* csr0==3, loop forever */
466: /*
467: * kin is 12 bytes: KS_SEND info 4 bytes ==> INCA(8)
468: * KS_RDB info 8 bytes ==> INCA(4)
469: * KS_EOI, KS_ERR info 6 bytes ==> INCA(6)
470: * r9 - channel #
471: * repinfo: code, lenlo, lenhi, cntl, mode
472: * r1, r12, r13 are saved and restored when exit
473: * this implementation is fast but use 70 more instructions than:
474: * have a loop to put info in repinfo to odl/odh for PUTTWO
475: * Modify HS and sbhead
476: * Interrupt cpu
477: * using r0, r1, r2, r9, r11, r12, r13, npr, mar, %mar, odl, odh, oal, oah, brg
478: */
479: mov repsave,mar
480: mov %repsave,%mar
481: mov r1,mem|mar++
482: mov r12,mem|mar++
483: mov r13,mem|mar++
484: mov sbhead,mar
485: mov %sbhead,%mar
486: mov mem,r13|mar++
487: mov mem,r12|mar++
488: mov mem,r11
489: mov %repinfo,%mar
490: mov repinfo,mar
491: mov mem,odl
492: mov mem,r2 /* r2 = (repinfo) */
493: mov kseq,mar
494: mov %kseq,%mar
495: mov mem,odh /* for debugging */
496: mov mem,r0
497: inc r0,mem
498: PUTTWO(r13,r12,r11,r_err_bus)
499: mov r9,brg
500: mov brg,odl /* chan# */
501: PUTTWO(r13,r12,r11,r_err_bus)
502: mov KS_SEND,brg
503: addn brg,r2,-
504: brz rp2
505: /*
506: * report is KS_RDB and others
507: */
508: mov %replen,%mar
509: mov replen,mar
510: mov mem,odl|mar++ /* lenlo */
511: mov mem,odh /* lenhi */
512: PUTTWO(r13,r12,r11,r_err_bus)
513: mov %repctl,%mar
514: mov repctl,mar
515: mov mem,odl|mar++
516: mov mem,odh
517: PUTTWO(r13,r12,r11,r_err_bus)
518: mov KS_RDB,brg
519: addn brg,r2,-
520: brz rp3
521: br rp4
522: rp2:
523: /*
524: * report is KS_SEND
525: */
526: mov 8,brg
527: br rpy
528: rp2.5:
529: /*
530: * reset bit map for chan# in r9
531: */
532: mov 7,brg
533: and brg,r9,brg
534: mov brg,r0
535: mov %bitpatt,%mar
536: mov bitpatt,brg
537: add brg,r0,mar
538: mov mem,r0
539: mov r9,brg
540: mov 0,brg>>
541: mov 0,brg>>
542: mov 0,brg>>
543: mov brg,r2
544: mov %timemap,%mar
545: mov timemap,brg
546: add brg,r2,mar
547: or mem,r0,mem /* turn bit on */
548: xor mem,r0,mem /* turn bit off */
549: br rp4
550: rp3:
551: /*
552: * report was KS_RDB
553: * reset C_Y and RULEN
554: */
555: mov r8,%mar
556: mov C_Y,brg
557: add brg,r10,mar
558: mov mem,r0
559: mov 0,mem /* reset READ mode */
560: mov C_RULEN,brg
561: add brg,r10,mar
562: mov 0,mem|mar++
563: mov 0,mem
564: /*
565: * if YTIMACT, reset bit in timemap
566: */
567: mov YTIMACT,brg
568: orn brg,r0,-
569: brz rp2.5
570: rp4:
571: mov 4,brg
572: rpy:
573: /*
574: * brg: increment count
575: * Now modify HS and sbhead
576: * If HS==BUFSIZ-1, then HS=0 and sbhead=sbaddr
577: */
578: mov brg,odl
579: mov HS,r0
580: mov BUFSIZ-1,brg
581: sub brg,r0,- /* HS-(BUFSIZ-1) */
582: brc 1f
583: inc r0,HS
584: INCA(r13,r12,r11,odl)
585: br 2f
586: 1: mov 0,brg /* reset HS */
587: mov brg,HS
588: mov sbaddr,mar
589: mov %sbaddr,%mar
590: mov mem,r13|mar++
591: mov mem,r12|mar++
592: mov mem,r11
593: 2:
594: /*
595: * Restore sbhead
596: */
597: mov sbhead,mar
598: mov %sbhead,%mar
599: mov r13,mem|mar++
600: mov r12,mem|mar++
601: mov r11,mem|mar++
602: /*
603: * Send interrupt 2 to the PDP-11
604: */
605: mov 0200,brg
606: mov brg,csr2 /* RDYO to csr2 for kmc.c */
607: mov nprx,brg|r0
608: br7 1f
609: mov BRQ|VEC4,brg
610: mov brg,nprx
611: 1:
612: /*
613: * restore r1, r12, r13
614: */
615: mov repsave,mar
616: mov %repsave,%mar
617: mov mem,r1|mar++
618: mov mem,r12|mar++
619: mov mem,r13|mar++
620: RETURN(s.report)
621:
622: copy1:
623: /*
624: * r13 is set to (1<<0) and bit 6 (block/char mode) unchanged because:
625: * rblen == 0; c_ta0 == 0; rlen>0; raddr will become odd after copy1
626: * r12.0 is 1; reset r12 when exit
627: * copy odl to raddr and restore r1 before return
628: * raddr is in oal, oah, r11
629: * since rlen, raddr, rulen were changed for 2 bytes
630: * adjustments are needed here
631: */
632: mov (1<<6),brg
633: and brg,r13 /* preserve block/char mode bit */
634: mov r1,brg
635: mov brg,idh /* save r1 */
636: mov odl,brg
637: mov brg,odh
638: SPUTONE(r11,r_err_bus)
639: mov r8,%mar
640: mov C_RLEN,brg
641: add brg,r10,mar
642: mov 1,r1|brg
643: or brg,r13 /* set bit 0 (radd odd) */
644: mov 0,r0|brg
645: mov brg,r12 /* reset r12 */
646: add mem,r1,mem|mar++ /* inc rlen */
647: addc mem,r0,mem|mar++
648: mov mem,r11
649: dec r11,mem|mar++ /* dec raddr */
650: mov mem,r11
651: subc brg,r11,mem|mar++
652: mov mem,r11
653: subc brg,r11,mem|mar++
654: mov mem,r11
655: dec r11,mem|mar++ /* dec rulen */
656: mov mem,r11
657: subc brg,r11,mem|mar++
658: /*
659: * restore r1 from idh and return
660: */
661: mov idh,brg
662: mov brg,r1
663: RETURN(s.copy1)
664:
665: cktimer:
666: /*
667: * check timer status: it is called from input routine:
668: * if char mode and channel # is changed or fifo is empty;
669: * if rulen>0 && rlen==0, reset rulen to 0, report SFULL, and return
670: * if (c_rb==nil && c_rulen==0) return;
671: * if (YTIME) set YEXPIRE or turn on timer
672: * call 'rcv'
673: * r1 has to be preserved
674: * r9: channel number
675: * using: r0, ....
676: */
677: mov r8,%mar
678: mov C_RULEN,brg
679: add brg,r10,mar
680: mov mem,r2|mar++
681: or mem,r2
682: dec r2,-
683: brz ct_3
684: /*
685: * if rlen==0, report SFULL
686: */
687: mov C_RLEN,brg
688: add brg,r10,mar
689: mov mem,r0|mar++
690: or mem,r0
691: dec r0,-
692: brc ct_4
693: mov %repinfo,%mar
694: mov repinfo,mar
695: mov KS_RDB,mem|mar++
696: mov 0,mem|mar++ /* residue length */
697: mov 0,mem|mar++
698: mov 0,mem|mar++ /* cntl char */
699: mov SFULL,mem /* mode */
700: CALL(report,s.report)
701: br ct_9
702: ct_3:
703: mov C_RB,brg
704: add brg,r10,mar
705: mov mem,brg
706: brz ct_9
707: ct_4:
708: /*
709: * check if timeout mode
710: */
711: mov C_Y,brg
712: add brg,r10,mar
713: mov mem,r0
714: mov YTIME,brg
715: orn brg,r0,-
716: brz 1f
717: br ct_7
718: 1:
719: mov YEXPIRE,brg
720: orn brg,r0,brg
721: brz ct_7 /* timer already expires */
722: mov YTIMACT,brg
723: orn brg,r0,-
724: brz ct_7 /* timer already active */
725: /*
726: * set timer active and load initial timer value
727: */
728: or brg,r0,mem /* set YTIMACT */
729: mov C_INITIM,brg
730: add brg,r10,mar
731: mov mem,r0
732: mov C_ITIME,brg
733: add brg,r10,mar
734: dec r0,mem
735: brc ct_10
736: /*
737: * timer expires: INITIM is 0
738: */
739: mov 0,mem
740: mov C_Y,brg
741: add brg,r10,mar
742: mov mem,r0
743: mov YEXPIRE,brg
744: or brg,r0
745: mov ~YTIMACT,brg
746: and brg,r0,mem
747: ct_7:
748: /*
749: * timer expires, call rcv
750: * save r1 here before calling 'rcv'
751: */
752: mov %rcvsave,%mar
753: mov rcvsave,mar
754: mov r13,mem|mar++
755: mov r12,mem|mar++
756: mov r1,mem|mar++
757: CALL(rcv,s.rcv)
758: mov %rcvsave,%mar
759: mov rcvsave,mar
760: mov mem,r13|mar++
761: mov mem,r12|mar++
762: mov mem,r1
763: ct_9:
764: RETURN(s.cktimer)
765: ct_10:
766: /*
767: * timer not expire: turn on bitmap and set YTIMACT
768: */
769: mov r9,brg
770: mov 7,r7
771: and brg,r7
772: mov 0,brg>>
773: mov 0,brg>>
774: mov 0,brg>>
775: mov brg,r0
776: mov %bitpatt,%mar
777: mov bitpatt,brg
778: add brg,r7,mar
779: mov mem,r7
780: mov %timemap,%mar
781: mov timemap,brg
782: add brg,r0,mar
783: or mem,r7,mem
784: br ct_7
785:
786: strailer:
787: /*
788: * XNIL is set, send trailer-only on this channel
789: * chan# is not on 'outq'
790: * r9, r8/r10 is set up
791: * using r0, r1, r2, ...
792: */
793: mov r8,%mar
794: mov C_S,brg
795: add brg,r10,mar
796: mov mem,r0
797: mov I_SEQ,brg
798: or brg,r0,brg
799: mov brg,r1
800: inc r0
801: mov WINDOW,brg
802: and brg,r0,mem
803: mov C_X1,brg
804: add brg,r10,mar
805: mov mem,r0
806: mov XBOTM,brg
807: orn brg,r0,-
808: brz 1f
809: mov I_BOT,brg
810: br 2f
811: 1: mov I_BOTM,brg
812: 2: mov brg,r2
813: SENDHEAD(r9)
814: D422(4)
815: SENDDATA(D_WCNTL,r2)
816: D422(4)
817: SENDDATA(D_WDATA,0)
818: D422(4)
819: SENDDATA(D_WDATA,0)
820: D422(4)
821: SENDDATA(D_WCNTL,r1)
822: D422(4)
823: SENDPACK(r0)
824: D422(4)
825: SENDCMD(D_READ)
826: RETURN(s.strailer)
827:
828: /*
829: * end of segment 3
830: */
831: endseg3:
832:
833:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.