.TITLE PD DATACOMMUNICATION HANDLER WITH RSP PROTOCOL. ; Multiprocessor V5 ; file PD50.MAC, this is the standard interrupt handler for ; DR(V)-11(C/00), and WB(V)-11 HARDWARE ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++; ; COPYRIGHT (c) 1981,82,83 by ; ; H.H. Klin. Neuro. AZG ; ; ; ; This software is furnished under a LICENSE and may be USED ONLY IN ; ; ACCORDANCE WITH THE TERMS OF SUCH LICENSE. This software or ; ; any other copies thereof may not be provided or otherwise made ; ; available to any other person. NO TITLE TO AND OWNERSHIP OF THE ; ; SOFTWARE IS HEREBY TRANSFERRED. ; ; ; ; The information in this software is subject to change without notice. ; ; ; ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++; WB = 1 ;0= DR-11(V)/(C), 1= WB-11(V) HARDWARE PD$PRI = 4 ;INTERRUPT PRIORITY( WB(V) = 4, DR-11C = 5, DRV-11 =4) CKS = 1 ;1=Enable checksum calculation, 0=minimal checking. TIMOUT = 200. ;.NE. = Enable time-out initial setting, 0.1*TIMOUT sec. UNIT0 = 0 ;RSP unit start number UNITS = 8. ;No. of device units CH = 0 ;1= Insert cache macro FAST = 1 ;1=Fast interrupt processing. QLEN = 5 ;Nr. of (pseudo)devices which can simultaneous generate a ;request for datacommunication I/O.(=Queuelength) CHECK = 125252 .IIF NE,TIMOUT TIM$IT=1 ;System time-out support required. ;*** ATTENTION: 1. IO-page address and vector to be set in .DRDEF macro!! ; 2. If PD is NOT the name of the bootable driver on disk, then ; set B$DNAM=XX, where XX.SYS is the name on disk. B$DNAM is ; located after the .DRBOT macro. .IDENT /V 5.0/ ; ; * Extra protection data outside buffer, when receiving DATA. ; * Implementation of internal device queue for queueing (pseudo)- ; device requests. Queue contains pointers to handler blocks with ; the following format: ; ----------------------------------------- ; HDBLK: ! SPFUN CODE 0-377 ! UNIT NR. 0-377 ! ; ----------------------------------------- ; ! Q-ELEMENT POINTER ! ; ----------------------------------------- ; ! RETURN ADRES ! ; ----------------------------------------- ; ! SPFUN DATA ! ; ----------------------------------------- QLEN=QLEN+QLEN ;Make byte length of handler queue. ; Q-Input !------! /----------\ No !-------! !--------------! ; --------->! QIN !---< IO going? >------! QOUT !-->! Handler code !-- ; !------! \----------/ !-------! !--------------! ; ! Yes ^ ; RETURN ! ; ! ; /---------\ no !------------! ! ; --------< Q empty? >----! CALL HDRET !-----/ ; \---------/ !------------! ; ! yes ; JMP HDRET ;----------------------------------------------------------------------- .ENABL LC .SBTTL MACROS AND DEFINITIONS ;----------------------------- .MCALL .DRDEF, .MTPS, .PRINT, .INTEN, .TIMIO, .CTIMIO ; Define device: minimal size = 16. blocks .IF EQ,WB .DRDEF PD,276,FILST$!SPFUN$!VARSZ$,16.,167770,310 ;Parallel line CS$INI = 40 ;Input interrupt enable bit in status. .IFF ;;; .DRDEF PD,275,FILST$!SPFUN$!VARSZ$,16.,175610,270 ;Serial WB-11 .DRDEF PD,274,FILST$!SPFUN$!VARSZ$,16.,175620,170 ;Serial " 2nd CS$INI = 100 .ENDC ; CS$INO = 100 ;Output interrupt enable bit in status. ; Level 2 codes (OPCODE byte) R$$NOP = 0 ;NOP R$$INT = 1 ;Initialize R$$RED = 2 ;Read function R$$WRT = 3 ;Write function R$$END = 100 ;End packet ; Level 1 codes (FLAG byte) R$CONT = 20 ;Continue R$CDAT = 40 ;Continue with data R$INIT = 4 ;Init R$DATA = 1 ;Data packet R$MSG = 2 ;Message/Command packet R$MSIZ = 5. ; " / " " size in words. R$DSIZ = 256. ;Max. data-packet size in words. R$ASIZ = 2*R$DSIZ ; Adress offset size for DATA-packet. ; .SBTTL SET OPTION PARAMETER TABLE ;--------------------------------- .DRSET SHOW,-1,S.SHOW ;;SHOW .DRSET UNITS,8.,S.UNITS, ;;Set No. Device Units. .IF NE,TIMOUT SETTIM = TIMOUT .DRSET TIME,-1,S.TIME, ;;TIME-OUT .IFF SETTIM = -1 .ENDC ; TIMOUT ; .SBTTL SET OPTION PROCESSING ROUTINES ;------------------------------------- NR=7 S.SHOW: MOV R4,-(SP) MOV R5,-(SP) MOV PC,R4 ADD #NUMBER-.,R4 MOV PC,R5 ADD #TEXT-.,R5 MOV #NR,R2 MOV PC,R1 ADD #OUTP-.,R1 LOOP: MOV (R4)+,R0 MOV R1,R3 ;+ CALL CNV8 ; Routine converts bits to octal ASCII string. ; R0; Contains bits to be converted ; R3; Points to output area ; Size of area should be nr. digits plus two ; On return R3 points to string terminator ; Note: Contens of R0, R3 is changed!! CNV8:: MOV R1,-(SP) CALL CONVRT MOVB #' ,(R3)+ MOVB #200,@R3 MOV (SP)+,R1 ;- End CNV8 .PRINT R5 .PRINT R1 ADD #8.,R5 SOB R2,LOOP MOV PC,R0 ADD #CRLF-.,R0 .PRINT MOV (SP)+,R5 MOV (SP)+,R4 CLC RETURN S.UNIT: CMP R0,R3 BHI 2$ ;Not too high! MOV R0,SUNITS ;Copy DEVICE UNITs for SHOW BLE 2$ MOV R0,NUNITS ;Set No DEVICE UNITs. RETURN 2$: SEC RETURN .IF NE,TIMOUT S.TIME: MOV R0,TIMDAT ; On entry Carry = clear ASL R0 ;*2 ASL R0 ;*4, sets Carry! ADD TIMDAT,R0 ;*5 = *5 ticks = *0.1 sec.,sets Carry! MOV R0,TIMVAL ;New timout value! Carry unaffected! RETURN .ENDC ; TIMOUT NUMBER: .WORD PDSTS .WORD PD$CSR .WORD PD$VEC .WORD PD$PRI .WORD UNIT0 SUNITS: .WORD UNITS TIMDAT: .WORD SETTIM TEXT: .ASCII /Status=/<200> .IIF EQ,WB .ASCII /DRCCSR=/<200> .IIF NE,WB .ASCII /WB-CSR=/<200> .ASCII /Vector=/<200> .ASCII <15><12>/Prio=/<200> .ASCII /Unit0 =/<200> .ASCII /Units =/<200> .iif EQ,CKS .ASCII/No / .ASCII /CKS Time=/<200> OUTP: .BLKB 10. CRLF: .BYTE 0 .EVEN ;+ CONVRT CONVRT: MOV R0,R1 CLR R0 DIV #8.,R0 MOV R1,-(SP) TST R0 BEQ DONE CALL CONVRT DONE: MOVB (SP)+,@R3 BISB #'0,(R3)+ RETURN ;- End CONVRT .IIF GT <.-1000>, .ERROR .-1000 ;SET code too big! .SBTTL START I/O ENTRY ;---------------------- ;========================================================= .DRBEG PD .IIF NE,CH CACHE ;Caching Link!! MOV PDCQE,R4 ;COPY Q-pointer MOVB Q$UNIT(R4),R1 ;Get device unit nr. BIC #^C<7>,R1 ;strip to 0-7 CMP NUNITS,R1 ;Valid nr.? BLOS PDERR ADD #UNIT0,R1 ;Make RSP unitnr. CLR SPDATA ;Clear SPFUN data word in HDBLK. CLR R0 BISB Q$FUNC(R4),R0 BEQ RDWT ;Read/write only. ;-----------------------------------------------------------------------; SPFUN: CMP R0,#373 ;Size request? BNE PDERR ; ; Variable size support; setup for remote spfun 373 request: ; SWAB R0 BIS R0,R1 MOV #1,Q$WCNT(R4) ;Read 1 word (=size) from remote dev. MOV #1,SPDATA ;Read 1 word SPFUN ; Standard read/write: RDWT: ;------------Set up HDBLK for this handler---------------- ; MOV PC,R2 ;PIC ADD #HDBLK-.,R2 ; of Handler block MOV R2,R0 ;R0 must point to HDBLK MOV R1,(R2)+ ;copy unitnr. in HDBLK MOV R4,(R2)+ ; " Q-pointer " " MOV PC,R1 ADD #PDFIN-.,R1 MOV R1,(R2)+ ;copy return adress in HDBLK ;-----------Put IO request in handler queue---------------- QIN: ;R0 points to HDBLK .MTPS #340 ;Do not disturb us while MOV PC,R1 ; we are queueing. ADD #HDQB-.,R1 ADD INQP,R1 MOV R0,(R1) ;Store HDBLK pointer in Q CMP #QLEN,INQP ;End of Queue? BNE 1$ CLR INQP ;Reset to begin. BR 2$ 1$: ADD #2,INQP ;To next free slot 2$: TST IOFLAG ;IO going? BEQ QOUT RETURN PDERR: BIS #1,@-(R4) ;SET HARD-ERROR BIT in CSW PDFIN: .DRFIN PD ;exit to completion I/O NUNITS: .WORD UNITS ;No. of device units HDBLK: .WORD 0 ;Handler block of PD .WORD 0 ;Q-POINTER .WORD 0 ;Return address SPDATA: .WORD 0 ;Saved SPFUN word count HDBLKP: .WORD 0 ;Pointer to current HDBLK HLPCQE: .WORD 0 ;Help Q-pointer IOFLAG: .WORD 0 INQP: .WORD 0 ;Pointer to next free slot in Q. OUTQP: .WORD 0 ;Pointer to next available HDBLK. HDQB: .WORD 0 ;Begin of handler queue .=HDQB+QLEN+2 ;Set end of queue ;-----------Get IO request from handler queue---------------- QOUT: MOV PC,R4 ADD #HDQB-.,R4 ADD OUTQP,R4 MOV (R4),HDBLKP ;Points to current HDBLK CMP #QLEN,OUTQP ;End of Q? BNE 3$ CLR OUTQP BR 4$ 3$: ADD #2,OUTQP 4$: BIS #1,IOFLAG ;-----------Start with datacommunication IO.------------------ IOGO: .MTPS #0 BR STARIO ;Startup RSP IO. VECTAB: .DRVTB PD,PD$VEC,PDINT .DRVTB ,PD$VEC+4,PDINT ; ; .SBTTL PD VECTOR AND CSR ADDRESS LIST ;------------------------------------- .IF EQ,WB TICSRA: .WORD PD$CSR TIBFRA: .WORD PD$CSR+4 TOCSRA: .WORD PD$CSR TOBFRA: .WORD PD$CSR+2 TIVECA: .WORD PD$VEC+6 ;VECTOR+2= PSW value!!, used for TOVECA: .WORD PD$VEC+2 ; carry bit setting!. .IFF TICSRA: .WORD PD$CSR TIBFRA: .WORD PD$CSR+2 TOCSRA: .WORD PD$CSR+4 TOBFRA: .WORD PD$CSR+6 TIVECA: .WORD PD$VEC+2 ;VECTOR+2= PSW value!!, used for TOVECA: .WORD PD$VEC+6 ; carry bit setting!. .ENDC ; .SBTTL INTERRUPT ENTRY ;---------------------- PDABRT::TST PK$FLG ;Interrupt IO going? BEQ 1$ ;If not dispatch Q-element RETURN ;Else wait until IO complete. 1$: JMP FORKF ;-----------------------------------------------------------------------; BR QIN ;Entry point for Pseudo-H's BR PDABRT ;-----------------------------------------------------------------------; PDINT:: .IIF NE,FAST BCS 1$ ;Don't do .INTEN if C=1 for speed. JSR R5,@$INPTR ;.DRAST PD,PD$PRI,PDABRT .WORD ^C&^O340 ; JMP @I$INTR ;goto interrupt service, R4+R5 free to use .IF NE,FAST ; High speed interrupt entry 1$: MOV R4,-(SP) ; goto to interrupt CALL @I$INTR ; service, R4 free to use. MOV (SP)+,R4 RTI .ENDC .SBTTL INTERRUPT EXIT ;--------------------- INIRTN: BIS #CS$INI,@TICSRA ;enable input interrupts OUTRTN: INTRTN: MOV (SP)+,I$INTR ;save return for the interrupt RETURN ; service routine!! ; ; ; .SBTTL COMPLETION EXIT ;---------------------- ERROR: MOV HLPCQE,R4 BIS #1,@Q$CSW(R4) ;SET HARD-ERROR BIT in CSW CMPB I$MSUC,#-2 ;EOF? BNE PDEXIT BIS #20000,@Q$CSW(R4);Set EOF bit also! PDEXIT: MOV #177777,@TOBFRA ;RESET INTERRUPT LOGIC DRV-11 00 TST @TIBFRA ; " ;------------Check if there's still IO to be done------------ ;------------Again an IO done, examine HANDLER Q ------------ IODONE: .MTPS #340 MOV HDBLKP,R4 ADD #6,R4 ;Point to SPDATA MOV PC,@R4 ;Get adres for ADD #I$SPFE-.,@R4 ; error-return block. Fill it. CMP INQP,OUTQP ;Q empty? BNE 5$ BIC #1,IOFLAG ;Set all IO done. JMP @-(R4) ;Q empty--> do not return 5$: CALL @-(R4) ;Link out Q-element, and return here. BR QOUT ;Examine Handler queue. .SBTTL STARIO - START I/O CODE ;------------------------------- ; R0-R5 available ; On exit interrupts enabled, all set up to start transfer(TX) .IIF NE,TIMOUT TIMVAL: .WORD 5*TIMOUT STARIO::TST @TIBFRA ;Dump input buffer. MOV HDBLKP,R0 MOV (R0)+,PK$UNT ;Store unit nr.+SPFUN in packet MOV (R0)+,R3 MOV R3,HLPCQE ;R3 -> to Queue-element TST (R0)+ MOV (R0)+,PK$SSQ ;SPFUN DATA CLR PK$OPC ;Set wordcount=0 MOV Q$WCNT(R3),R1 ;R1 -> word count. BEQ 9$ BPL 8$ ;+ means read MOVB #R$$WRT,PK$OPC ;make write NEG R1 ;and make + word count BR 9$ ;normal I/O 8$: MOVB #R$$RED,PK$OPC ;assume read, clear modifier 9$: MOV Q$BUFF(R3),I$ADRS ;address for TX MOV R1,I$WRDC ;save word count MOV R1,PK$BCT ;copy word count into packet .IF NE,TIMOUT CLR TICMPL MOV TIMVAL,R1 TSTB PK$SPF ;SPF/SPDIR Request? BEQ TIMEGO MOV #-1,R1 ;Max. time-out= 20 min. due to ; long lasting SPF/SPDIR requests as MAGTAPE searches ; Fastest transmission = 56 blks/s.(Memory to virtual memory via link) ; To RK05 : 19 blks/s. ---> 50 ms./block. (PDP 11/34, WB/DR-11) ; Max. time interval = 16. Kw. = 64 blocks = 3.2 sec. TIMEGO: MOV R1,TIMDNE-2 ;Time-low , store in timer block CLR TIMDNE-4 ;Time-high, store in timer block MOV PC,R1 ;Construct ADD #TIMRTN-.,R1 ; completion MOV R1,TICMPL ; adres. MOVB Q$JNUM(R3),R1 ; id. JOB nr. ASH #-3,R1 ;Shift right 3* BIC #^C<16>,R1 ;Isolate. MOV R1,TIJNUM ;JOB nr. for TIMIO .TIMIO TIMBLK,0,0 TIMDNE: ;End .TIMIO .ENDC ;TIMOUT CLR PK$FLG ;Indicate no interrupt occured yet. MOV @R3,PK$RCD ;block nr. into packet MOV PC,R1 ;make ADD #TXGO-.,R1 ; PIC address TX start MOV R1,I$INTR ;interrupt starts it MOV #177777,@TOBFRA ;RESET INTERRUPT LOGIC DRV-11 00 BIS #CS$INO,@TOCSRA ;Enabl. outp. interr. RETURN .SBTTL TXGO - START TRANSFER FROM INTERRUPT LEVEL ;---------------------------------------------------- TXGO: MOV #R$MSG,PK$FLG ;flagbyte= command type MOVB #R$MSIZ,PK$MWC ;set packet size MOV #R$MSIZ,WCNT ;Set locally counter. MOV PC,R4 ;PIC-address ADD #PK$OPC-.,R4 MOV R4,I$MADR ; of message OPCODE CALL SNDPKT ;send packet to start I/O ; speeding up by receive CONTINUE in SNDPKT in case of write. 2$: MOV I$ADRS,I$MADR ;get the DATA address MOV I$WRDC,R4 ; and the wordcount BEQ TXEND ;No bytes -> position get END-packet CMPB PK$OPC,#R$$WRT ;write? BNE 4$ MOV R4,WCNT ;Set locally counter. CMP R4,#R$DSIZ ;too large for one packet? BLOS 3$ ;nope, use this count MOV #R$DSIZ,WCNT ;set counter CLR R4 ;full packet TX 3$: MOVB R4,PK$MWC ;Set pack size. MOVB #R$DATA,PK$FLG ;Set data-flag. CALL SNDPKT ;send data-packet BR 5$ ;go, send next data packet 4$: MOV #R$DATA,I$EFLG ;Set flag expected CALL RCVPKT ;read, receive data-packet 5$: ADD #R$ASIZ,I$ADRS ;adjust the address, use nr. BYTES! SUB #R$DSIZ,I$WRDC ;count one packet from the wordcount BHI 2$ ;still more to go CLR I$WRDC ;all has been TX'erred ; ; .SBTTL TXEND - READ THE END PACKET AFTER A TRANSFER ;----------------------------------------------------- TXEND: MOV PC,R4 ;point to message packet ADD #I$MBFR-.,R4 MOV R4,I$MADR ; by PIC method MOV #R$MSG,I$EFLG ;Set flag expexted. CALL RCVPKT ;get a packet ; .SBTTL Analyze the END PACKET ;----------------------------- ENDANA: BIC #CS$INO,@TOCSRA ;ZAP interrupt enable on BIC #CS$INI,@TICSRA ;both sides .FORK PDFBLK ;R0-R3 available, R4+R5 as before .IF NE,TIMOUT TST TICMPL ;Is there outstanding timout request? BEQ 1$ ;EQ --> no! .CTIMIO TIMBLK BCC 1$ RETURN ;Let Time-out routine do the work!! 1$: .ENDC ; TIMOUT CMPB PK$FLG,#R$MSG ;message packet? BNE ABORT ;no, protocol screwup, try reinitializing CMPB I$MOPC,#R$$END ;End-packet? BNE ABORT ;no -> error TSTB I$MSUC ;check for succes via succes byte in mess. BPL CPLRTN ;OK, so complete without error FATAL: JMP ERROR ;completion ERROR exit CPLRTN: JMP PDEXIT ;completion exit PDFBLK: .BLKW 4. .SBTTL ABORT - COMMUNICATIONS ERROR ;------------------------------------- ABORT: ; Initialize the device ; if a checksum error occurs, a unexpected packet type is ; received, or something else happens which indicates the ; transmission line or protocol is out of sync, we send RSP-init ; 7 attempts are made to signal the device/JOB after transfer, then ; we quit and return hard error. TXINIT: .MTPS #340 ;raise priority to prevent interrupt TST @TIBFRA ;dump input to clear ready flag BIC #CS$INI,@TICSRA ;Stop inp. interr. BIS #CS$INO,@TOCSRA ;Enabl. interr. MOV #-1,COUNT INITS: MOV #R$INIT,@TOBFRA ;send INIT CALL OUTRTN ;OUTPUT WAIT .IF EQ,WB 3$: TST @TICSRA .IFF 3$: TSTB @TICSRA .ENDC BMI 2$ ;now wait for answer DEC COUNT BNE 3$ BR INITS 2$: MOV @TIBFRA,R4 ;get the flag 8$: CMPB R4,#R$CONT ;is it correct? BNE INITS ;try again, wait until we have ;synchronized! FORKF: BIC #CS$INO,@TOCSRA ;ZAP interrupt enable on BIC #CS$INI,@TICSRA ;both sides .FORK PDFBLK ;R0-R3 available, R4+R5 as before .IF NE,TIMOUT TST TICMPL ;Is there outstanding timout request? BEQ 2$ ;EQ --> no! .CTIMIO TIMBLK ;Cancel current timer. BCC 2$ RETURN ;Let Time-out routine do the work!! 2$: .ENDC ;TIMOUT BR FATAL ;return here is fatal .IF NE,TIMOUT TIMRTN: BIC #CS$INO,@TOCSRA ;ZAP interrupt enable on BIC #CS$INI,@TICSRA ;both sides MOV PC,R0 ADD #TIMMSG-.,R0 ;Message time-out .PRINT MOV @SP,-(SP) ;Copy return adres. CLR 2(SP) ;Make interrupt return. .MTPS #340 ;Prio -> 7 .INTEN 0,PIC ;Enter system state. BR FORKF ;Exit from interr. level, do FORK ;and finish with error. TIMBLK: .WORD 0,0,0 ;High+low order time, Link to next Q ;;TIJNUM: .WORD 0,177000+PD$COD,0 ;Job no, Seq no V5.1, Used by monitor(-1) TIJNUM: .WORD 0,177400,0 ;Job nr., Seq. nr., Used by monitor(-1) TICMPL: .WORD 0 ;Completion routine adres. TIMMSG: .ASCIZ /?RSP-F-Timeout error/ .EVEN .ENDC ;TIMOUT COUNT: .WORD 0 ;Local wait counter. .SBTTL SNDPKT - SEND RADIAL SERIAL PACKET ;------------------------------------------ ; CALL SNDPKT ; R4+R5 for use, packet sent, outp interr. disabled ; .INTEN state/level SNDPKT: MOV (SP)+,I$SUBR ;save subr. return .if NE,CKS MOV PK$FLG,PK$CKS ;init checksum .iff MOV #CHECK,PK$CKS ;Set CHECK pattern .endc MOV PK$FLG,@TOBFRA ;output 1st word. BIS #CS$INO,@TOCSRA ;Enabl. outp. interr. .iif NE,FAST BIS #1,@TOVECA ;set carry -> no .INTEN CALL OUTRTN ;wait for outp. interr. 2$: MOV @I$MADR,@TOBFRA ;outp. data byte .if NE,CKS ADD @I$MADR,PK$CKS ;add it to the checksum ADC PK$CKS ;end around carry .endc ADD #2,I$MADR ;next address DEC WCNT ;are we done? BEQ 3$ ;yes, time to clear the carry RTS PC ;no, keep on sending those ; characters fast. 3$: .IIF NE,FAST BIC #1,@TOVECA ;CC, do .INTEN ADD #4$-2$,I$INTR ;set up the return address RTS PC ;go back the way you came 4$: MOV PK$CKS,@TOBFRA ;output checksum c.q. CHECK CALL OUTRTN ;til out BIC #CS$INO,@TOCSRA ;Stop outp. interr. ; ; speeding up: ; CMPB PK$OPC,#R$$WRT ;is it a write? BNE PKTRTN ;No, then to PacKeTReTurN CMPB PK$FLG,#R$MSG ;Command? BEQ 5$ ;Yes then go. No, next check. CMP I$WRDC,#R$DSIZ ;Last packet for write? BLOS GTXEND ;Then don't expect a CONTINUE 5$: CALL INIRTN ;Wait for input RCVCNT: MOV @TIBFRA,R4 ;Get it CMPB R4,#R$CDAT ;Is it CONTINUE WITH DATA? BEQ PKTRTN ;Yes normal return MOV R4,PK$FLG ;Set flag for RCVPKT CLR I$EFLG ;This flag is never expected ADD #RCVDAT-RCVCNT,I$INTR ;New interrupt pointer BR GETEND ;Get ?END?-packet GTXEND: JMP TXEND ; packet routine return PKTRTN: BIC #CS$INI,@TICSRA JMP @I$SUBR ;and return from subroutine ; ; .SBTTL RCVPKT - RECEIVE A RADIAL SERIAL PACKET ;----------------------------------------------- ; I$EFLG expected flagbyte, entered in .INTEN state ; CALL RCVPKT ; I$MBFR = packet if not expected type, unless data packet in which ; case abort is entered. RCVPKT: MOV (SP)+,I$SUBR ;save subr. return CALL INIRTN ;and come back here RCVGO: MOV @TIBFRA,R4 ;save word. MOV R4,PK$FLG ;save the char for a flag ADD #RCVDAT-RCVGO,I$INTR ;set up new return CMPB R4,I$EFLG ;flag expected? BEQ OKEY ;yes OK. GETEND: CMPB R4,#R$MSG ;message packet? BNE ABORCV ;No, then unexpected error MOV PC,-(SP) ;PIC ADD #I$MBFR-.,@SP ; address of MOV (SP)+,I$MADR ; message buffer OKEY: MOV #R$DSIZ,WCNT ;Set counter for full pkt. TSTB PK$MWC ;O.K.? BEQ 6$ ;Yes, go. CLR WCNT ;No BISB PK$MWC,WCNT ; then set correctly. 6$: CMPB #R$DATA,PK$FLG ;Going to receive DATA? BNE 1$ MOV I$WRDC,R4 ;See if we are going SUB WCNT,R4 ; outside mem. buffer. BLT ABORCV ;If so do'not do it. 1$: .if NE,CKS MOV PK$FLG,PK$CKS ;init. checksum .iff MOV #CHECK,PK$CKS ;init. with CHECK .endc .IIF NE,FAST BIS #1,@TIVECA ;CS -> no .INTEN now RLOOP: RTS PC ;return from interrupt RCVDAT: MOV @TIBFRA,R4 ;get char MOV R4,@I$MADR ;store the data in buffer ADD #2,I$MADR ;next address .if NE,CKS ADD R4,PK$CKS ;add in current checksum ADC PK$CKS ;add in end around carry .endc DEC WCNT ;any more words? BNE RLOOP ;yes, go get 'em .IIF NE,FAST BIC #1,@TIVECA ;do .INTEN next interrupt ADD #7$-RCVDAT,I$INTR ;set up new return point RTS PC ;go back the way you entered interrupt 7$: MOV @TIBFRA,R4 ;save char CMP R4,PK$CKS ;is it correct? BNE 5$ ;checksum error CMPB PK$FLG,I$EFLG ;flag we expected? BEQ PKTRTN ;yes, OK goto common return JMP ENDANA ;no signal(INIT?) error, i.e. END-packet 5$: ABORCV: JMP ABORT ;Nope- fatal error .SBTTL DATA AREA ; WCNT: .WORD 0 ;Locally counter for nr. packet words. I$ADRS: .WORD 0 I$WRDC: .WORD 0 I$INTR: .WORD 0 I$MADR: .WORD 0 I$SUBR: .WORD 0 I$EFLG: .WORD 0 I$MBFR: I$MOPC: .BYTE 0 I$MSUC: .BYTE 0 I$SPFE: .WORD 0,0,0,0 ;SPFUN/SPDIR error return block! PK$FLG: .BYTE 0 PK$MWC: .BYTE 0 PK$OPC: .BYTE 0 PK$MOD: .BYTE 0 PK$UNT: .BYTE 0 PK$SPF: .BYTE 0 PK$SSQ: .BYTE 0,0 PK$BCT: .BYTE 0,0 PK$RCD: .BYTE 0,0 PK$CKS: .BYTE 0,0 ; .SBTTL BOOTSTRAP READ ROUTINE ;----------------------------- .DRBOT PD,BOOT1,READ PDCNT = 7 ; ATTENTION: Omit the next assignment if the name of the bootable Handler ; on disk is PD.SYS!! .IF EQ,WB B$DNAM=^RDR ;DR is the name of the bootable driver on disk .IFF B$DNAM=^RWB ;WB is the name of the bootable driver on disk .ENDC ;WB . = PDBOOT+40 BOOT1: JMP @#BOOT-PDBOOT . = PDBOOT+210 READ: MOV #PDCNT,RTRCNT MOV @#B$DEVU,PDUNIT ADD #UNIT0,PDUNIT MOV R0,PDBLK ;Contains blocknr. to read MOV R1,PDBTCT ; " nr. words to read BRESTR: MOV R2,-(SP) ;Mem. buff. adres, save. MOV (PC)+,R0 .IF EQ,WB BOOCSR: .WORD PD$CSR ;Output status reg. .IFF BOOCSR: .WORD PD$CSR+4 ;Output status reg. .ENDC WAIT: TSTB @R0 ;Output ready? BPL WAIT .IF EQ,WB TST 4(R0) ;clear input reg. .IFF TST -2(R0) ;clear input reg. .ENDC ; ; Send command packet. ; MOV #B$CHK-PDBOOT,R4;Point to checksum. .if NE,CKS CLR @R4 ;Init=clear checksum. .iff MOV #CHECK,@R4 ;Init=CHECK .endc MOV #B$PKT-PDBOOT,R5;Point to packet. 1$: MOV (R5)+,R3 ;Get packet word. .if NE,CKS ADD R3,@R4 ;update ADC @R4 ; checksum. .endc CALL BCHROS ;send word CMP R5,R4 ;End of packet BLOS 1$ ;no ; ; Receive bootstrap data and store them. ; BRDPKT: CALL BICHR ;R1 contains receiv. word. MOV #R$DSIZ,R4 ;Set to full packet count. TSTB R3 ;O.K. BEQ 3$ ;Yes, then go. CLR R4 ;No. BISB R3,R4 ;R3 " swapped R1, packetwordcnt. 3$: .if NE,CKS MOV R1,-(SP) ;init checksum .iff MOV #CHECK,-(SP) ;init with CHECK .endc CMPB R1,#R$DATA ;data packet? BNE BEND ;no, then must be endpacket. 2$: CALL BICHR ;input next. MOV R1,(R2)+ ;store data in memory buff. .if NE,CKS ADD R1,@SP ;Update ADC @SP ; checksum .endc SOB R4,2$ CALL BICHR ;checksum! CMP R1,(SP)+ ;O.K.? BNE BFATAL ;no, then branch. BR BRDPKT ;and again. BEND: CALL BICHR ;Receive Endpacket MOVB R3,R5 ;Save succescode. 1$: .if NE,CKS ADD R1,@SP ;and ADC @SP ; receive .endc CALL BICHR ; rest SOB R4,1$ ; of END CMP R1,(SP)+ ; packet. BNE BFATAL ;checksum O.K.? TSTB R5 ;check BMI BFATAL ;Succes or error? MOV (SP)+,R2 CLC ;make sure carry clear upon RETURN ;return. BFATAL: MOV (SP)+,R2 DEC RTRCNT BNE BRESTR BR BIOERR ; BICHR: .IF EQ,WB TST (R0) ;Input ready bit = highest bit! BPL BICHR MOV 4(R0),R1 ;R0 points to status reg.: .IFF TSTB -4(R0) ;Input ready bit = highest bit! BPL BICHR MOV -2(R0),R1 ;R0 points to status reg.: .ENDC MOV R1,R3 ;COPY, lowbyte R3=packet word cnt. SWAB R3 ; 2 = PD$CSR+2 = output buffer RETURN ; 4 = PD$CSR+4 = input buffer BCHROS: MOV R3,2(R0) 1$: TSTB (R0) ;Output ready bit = No. 7 !! BPL 1$ RETURN B$PKT: .BYTE R$MSG,R$MSIZ,R$$RED,0 PDUNIT: .WORD 0 .BYTE 0,0 PDBTCT: .WORD 0 PDBLK: .WORD 0 B$CHK: .WORD 0 RTRCNT: .WORD 0 ; ; ; . = PDBOOT+606 BOOT: MOV #10000,SP MOV R0,@#B$DEVU ;001 MOV R0,-(SP) ;**-1 MOV #2,R0 MOV #<4*400>,R1 MOV #1000,R2 JSR PC,READ MOV #READ-PDBOOT,@#B$READ MOV #B$DNAM,@#B$DEVN MOV (SP)+,@#B$DEVU JMP @#B$BOOT .DREND PD .END