|
|
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"
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.