.TITLE PCPCIO .IDENT /01/ ; ; VERSION 1 ; ; M. PETTENGILL 25-MAY-77 ; ; **-PCPCIO-PROCESSOR TO PROCESSOR DATA TRANSFER SYSTEM ; ; ; SYSTEM MACRO CALLS ; .MCALL DIR$,ENAR$S,DSAR$S,QIO$S,CLEF$S,SETF$S,ASTX$S .MCALL WTSE$S,EXIT$S,QIOW$ .MCALL FDBDF$,FDAT$A,FDOP$A,FINIT$,FSRSZ$,NMBLK$ .MCALL OPEN$W,CLOSE$,PUT$ ; ; LOCAL MACROS ; .MACRO BUFFER LABEL LABEL: .WORD 0 .WORD 10$ .WORD 10$+-2 .WORD 10$ 10$: .BLKW BUFSZ .ENDM BUFFER .MACRO TSTERR BCC .+4 HALT .ENDM TSTERR ; ; LOCAL DEFINITIONS ; PCLUN=1 ; LUN USED FOR I/O TO SECOND PROCESSOR TILUN=2 ; LUN USED FOR I/O TO LOCAL USER LOGLUN=3 ; LUN USED FOR LOGGING PC OUTPUT SYNC=27 ; EVENT FLAG FOR I/O SYNCRONIZATION BUFSZ=400 ; SIZE OF I/O BUFFERS ; ; LOCAL DATA AND BUFFERS ; BUFFER IPCQUE ; INPUT FROM PC QUEUE BUFFER ITIQUE ; INPUT FROM TI QUEUE BUFFER OPCQUE ; OUTPUT TO PC QUEUE BUFFER OTIQUE ; OUTPUT TO TI QUEUE PCSTS: ; I/O STATUS AND CONTROL BLOCK TO PC .WORD 1 ; I/O STATUS BLOCK (MUST BE 'DONE') .WORD 0 ; BYTE COUNT (WHO CARES) .WORD OPCQUE .WORD OPCBUF .WORD PCLUN OPCBUF: .BLKW BUFSZ ; OUTPUT BUFFER TO PC TISTS: ; I/O STATUS AND CONTROL BLOCK TO TI .WORD 1 ; I/O STATUS BLOCK (MUST BE 'DONE') .WORD 0 ; BYTE COUNT (WHO CARES) .WORD OTIQUE .WORD OTIBUF .WORD TILUN OTIBUF: .BLKW BUFSZ ; OUTPUT BUFFER TO TI ECHO: .BYTE 0 ; ECHO TO TI FLAG LOGSW: .BYTE 0 ; LOGGING ON/OFF SWITCH ATTPC: QIOW$ IO.ATA!TF.BIN,PCLUN,PCLUN,,,, ATTTI: QIOW$ IO.ATA!TF.BIN,TILUN,TILUN,,,, LOGFIL: FDBDF$ ; PC OUTPUT LOG FILE FDB FDAT$A R.VAR,FD.CR FDOP$A LOGLUN,,LOGDN LOGDN: NMBLK$ LOGFIL,TXT,0 LBUFR: .BLKB 140. ; LOGFIL I/O BUFFER LBPNTR: .WORD LBUFR ; POINTER INTO LOG BUFFER LBCNTR: .WORD 0 ; COUNT OF CHARACTERS IN BUFFER FFREC: .BYTE 14,0 ; FORM FEED RECORD FSRSZ$ 1 ; ALLOW FOR ONE FILE ; ; INITIALIZATION AND MAIN CONTROL LOOP ; PCPCIO: FINIT$ ; INIT FCS DIR$ #ATTPC ; ATTACH WITH AST TO PC LINK TSTERR ; TRAP ERRORS DIR$ #ATTTI ; ATTACH WITH AST TO TI TERMINAL TSTERR ; TRAP ERRORS OPEN$W #LOGFIL ; OPEN LOG FILE TSTERR ; TRAP ERRORS ; BEGIN MAIN LOOP MAINLP: CLEF$S #SYNC ; CLEAR I/O SYNC FLAG 10$: DSAR$S ; SYNCRONIZE WITH BUFFER MANAGEMENT MOV #IPCQUE,R1 ; GET INPUT, IF ANY, FROM REMOTE PC CALL GETWD ; ANY INPUT? BCS 20$ ; IF CS NO ENAR$S ; RETURN TO NORMAL SYNC SETF$S #SYNC ; INDICATE I/O SYNC MOV R0,-(SP) ; SAVE CHARACTER FOR LATER CALL LOGIT ; LOGIT TO LOG FILE (DISK) MOV (SP)+,R0 ; RESTORE R0 BIC #177600,R0 ; CLEAR PARITY BIT BEQ 10$ ; IGNORE IF NULL CMP #177,R0 ; DELETE CHARACTER? BEQ 10$ ; IF EQ YES TSTB ECHO ; ECHOING (CONTROL O)? BNE 10$ ; IF NE NO CALL OCHRTI ; QUEUE CHARACTER FOR OUTPUT TO TI 20$: DSAR$S ; BUFFER MANAGEMENT SYNC MOV #ITIQUE,R1 ; GET INPUT, IF ANY, FROM TI CALL GETWD ; ANY INPUT? BCS 30$ ; IF CS NO ENAR$S ; RETURN TO NORMAL SYNC SETF$S #SYNC ; INDICATE I/O SYNC CALL CONTRL ; INTERPRET CONTROL CHARACTERS BCS 20$ ; IF CS NO FURTHER PROCESSING CALL OCHRPC ; OUTPUT TO REMOTE PC BR 10$ ; TRY AGAIN FOR BOTH TI AND PC 30$: ENAR$S ; RETURN TO NORMAL SYNC WTSE$S #SYNC ; SYNC WITH I/O BR MAINLP ; DO IT AGAIN ; ; **-LOGIT-OUTPUT CHARACTER TO LOG FILE (CONDITIONALLY) ; ; INPUTS: ; R0=CHARACTER TO LOG ; ; OUTPUTS: ; CHARACTER OUTPUT TO ASCII FILE IF APPROPRIATE ; LOGIT: TSTB LOGSW ; LOGGING ON? BEQ 30$ ; IF EQ NO BIC #177600,R0 ; CLEAR PARITY BIT AND CHECK IF NUL BEQ 30$ ; IF EQ YES, IGNORE NUL CMP #177,R0 ; CHECK FOR DELETE (RUBOUT) BEQ 30$ ; IF EQ YES, IGNORE RUBOUT CMP #12,R0 ; CHECK FOR LINEFEED **NOTE** ; THIS ASSUMES THAT A LINEFEED FOLLOWS ; A CARRIAGE RETURN AND IS REDUNDANT BEQ 30$ ; IF EQ YES, IGNORE LINEFEED CMP #15,R0 ; CHECK FOR CARRIAGE RETURN BEQ 20$ ; IF EQ YES, OUTPUT RECORD CMP #14,R0 ; FORM FEED? BNE 10$ ; IF NE NO TST LBCNTR ; ANY CHARACTERS IN BUFFER? BEQ 5$ ; IF EQ NO CALL 20$ ; OUTPUT THEM 5$: PUT$ #LOGFIL,#FFREC,#1 ; OUTPUT A FF RECORD BR 20$ ; PROCESSING COMPLETE FOR CHARACTER 10$: MOVB R0,@LBPNTR ; PUT CHARACTER IN RECORD INC LBPNTR ; UPDATE POINTER INC LBCNTR ; INCREASE COUNT CMP #135.,LBCNTR ; RECORD BUFFER FULL BGT 30$ ; IF GT NO 20$: PUT$ #LOGFIL,#LBUFR,LBCNTR ; WRITE RECORD CLR LBCNTR ; RESET COUNTER MOV #LBUFR,LBPNTR ; RESET BUFFER POINTER 30$: RETURN ; ; **EXITRQ-EXIT REQUESTED, CLEAN UP AND EXIT ; EXITRQ: CLOSE$ #LOGFIL ; CLOSE LOGFIL EXIT$S ; BYE ; ; **-CONTRL-PROCESS CONTROL CHARACTERS FROM TI ; ; INPUTS: ; R0=CHARACTER ; ; OUTPUTS: ; IF CC R0=CHARACTER ; IF CS NO FURTHER PROCESSING REQUIRED ; CONTRL: MOV R0,-(SP) ; SAVE CHARACTER BIC #177600,R0 ; STRIP PARITY CMP #'W-100,R0 ; TOGGLE ECHO? BNE 10$ ; IF NE NO COMB ECHO ; TOGGLE ECHO BR FLSHCH ; FLUSH CHARACTER 10$: CMP #'Y-100,R0 ; EXIT REQUEST? BNE 20$ ; IF NE NO JMP EXITRQ ; GO DOWN THE TUBES 20$: CMP #'V-100,R0 ; TOGGLE LOG SWITCH? BNE 30$ ; IF NE NO COMB LOGSW ; TOGGLE IT BR FLSHCH ; FLUSH CHARACTER 30$: MOV (SP)+,R0 ; RESTORE CHARACTER CLRB ECHO ; REINSTATE ECHOING CLC ; INDICATE GOOD CHARACTER RETURN ; FLSHCH: TST (SP)+ ; CLEAN STACK SEC ; INDICATE NO CHARACTER TO OUTPUT RETURN ; ; ; **-OCHRTI-OUTPUT CHARACTER TO TI ; **-OCHRPC-OUTPUT CHARACTER TO PC ; ; INPUTS: ; R0=CHARACTER TO OUTPUT ; ; OUTPUTS: ; CHARACTER QUEUED FOR OUTPUT ; .ENABL LSB OCHRTI: MOV #OTIQUE,R1 ; INSERT IN TI OUTPUT QUEUE MOV #TISTS,R2 ; SETUP CONTROL BLOCK ADDRESS BR 10$ ; GO TO COMMON CODE OCHRPC: MOV #OPCQUE,R1 ; INSERT IN PC OUTPUT QUEUE MOV #PCSTS,R2 ; SETUP CONTROL BLOCK ADDRESS 10$: DSAR$S ; BUFFER MANAGEMENT SYNC CALL PUTWD ; PUT WORD IN QUEUE CALL OCHRCM ; MAKE SURE OUTPUT IS IN PROGRESS ENAR$S ; RETURN TO NORMAL SYNC RETURN ; .DSABL LSB OCHRCM: TST (R2) ; I/O IN PROGRESS? BEQ 30$ ; IF EQ YES MOV 6(R2),R3 ; GET ADDRESS OF OUTPUT BUFFER CLR R4 ; RESET CHARACTER COUNT 10$: MOV 4(R2),R1 ; GET ADDRESS OF QUEUE TO GET FROM CALL GETWD ; GET THE NEXT CHARACTER BCS 20$ ; IF CS NONE IN QUEUE MOVB R0,(R3)+ ; FILL THE BUFFER INC R4 ; COUNT THE CHARACTER BR 10$ ; TRY AGAIN 20$: TST R4 ; ANY CHARACTERS IN BUFFER BEQ 30$ ; IF EQ NO QIO$S #IO.WAL,10(R2),,,R2,#IOFIN,<6(R2),R4,#0> 30$: RETURN ; IOFIN: MOV R0,-(SP) ; SAVE SOME REGISTERS MOV R1,-(SP) ; MOV R2,-(SP) ; MOV R3,-(SP) ; MOV R4,-(SP) ; MOV R5,-(SP) ; MOV 14(SP),R2 ; GET ADDRESS OF CONTROL BLOCK CALL OCHRCM ; TRY TO KEEP I/O GOING MOV (SP)+,R5 ; MOV (SP)+,R4 ; MOV (SP)+,R3 ; MOV (SP)+,R2 ; MOV (SP)+,R1 ; MOV (SP)+,R0 ; REGISTERS RESTORED TST (SP)+ ; CLEAN STATUS BLOCK FROM STACK ASTX$S ; EXIT AST .ENABL LSB ICHRTI: MOV R1,-(SP) ; SAVE R1 MOV #ITIQUE,R1 ; GET ADDRESS OF TI INPUT QUEUE BR 10$ ; GO TO COMMON CODE ICHRPC: MOV R1,-(SP) ; SAVE R1 MOV #IPCQUE,R1 ; GET ADDRESS OF PC INPUT QUEUE 10$: MOV R0,-(SP) ; SAVE R0 MOV 4(SP),R0 ; GET INPUT CHARACTER CALL PUTWD ; INSERT IN APPROPRIATE QUEUE MOV (SP)+,R0 ; RESTORE R0 MOV (SP)+,R1 ; RESTORE R1 TST (SP)+ ; CLEAN INPUT CHARACTER FROM STACK SETF$S #SYNC ; WAKE-UP ALL BELOW, SET I/O SYNC ASTX$S ; EXIT AST .DSABL LSB .ENABL LSB PUTWD: CMP (R1),#BUFSZ ; ROOM IN THE INN? BHIS 30$ ; IF HIS NO INC (R1)+ ; INCREASE THE COUNT MOV R0,@(R1)+ ; STUFF THE CHARACTER CMP (R1),-(R1) ; WRAP REQUIRED? BR 10$ ; GO TO COMMON CODE GETWD: TST (R1) ; BUFFER EMPTY? BEQ 30$ ; IF EQ YES DEC (R1)+ ; DECREASE COUNT CMP (R1)+,(R1)+ ; SKIP TO POINTER FIELD MOV @(R1),R0 ; GET THE CHARACTER CMP -2(R1),(R1) ; WRAP REQUIRED? 10$: BHI 20$ ; IF HI NO SUB #BUFSZ*2,(R1) ; UNWRAP 20$: ADD #2,(R1) ; UPDATE POINTER FOR NEXT TRIP CLC ; SUCCESS RETURN ; 30$: SEC ; FAILURE RETURN ; .DSABL LSB .END PCPCIO