RT-11 5.x install tapes?
Jörg Hoppe
j_hoppe at t-online.de
Fri Mar 10 13:56:34 CST 2017
Alan,
thanks!
- I saw that neither 5.5 nor 5.6 has no DD, but 5.0 -5.4G and 5.7 has.
Didn't understand the reason.
- Also DD.MAC in the 5.0 - 5.4 and 5.7 changes often.
I tested tu58fs with oversized TU58 tape for 5.3 and 5.7, the number of
blocks is always patched into into offset 0x2c, 0x2d in DD.SYS
- I made a working DD.SYS with
.macro DD,
.link DD,
.rename DD.SAV DD.SYS
Do you know how to make DDX.SYS? Must be a conditional MACRO symbol.
Joerg
>
>> for work on TU58 emulator "tu58fs" I'd like to experiment with
>> oversized tape images under RT-11 5.5, 5.6 and 5.7. The images I
>> know about are the classiccmp collections, Earl Evans pointed me
>> to the RT11DV50.ISO archive.
>> However, in these images the TU58 driver files
>> DD.MAC/DD.SYS/DDX.SYS are mostly missing. Strange, because they
>> claim to be pristine.
>> Somebody knows about original RT-11 V5 installation tape images?
> Here is the DD.MAC file you are looking for. It was part of
> the RT-11 v5.6 sources that Mentec supplied to the Y2K update
> team to make v5.7. Since the last modification was in 1979,
> it is safe to assume that it applies to all recent versions.
>
> Have fun!
>
> Alan
>
> --------------------------------------------------
> .MCALL .MODULE
> .MODULE DD,VERSION=21,COMMENT=<DECtape II Handler>,AUDIT=YES
>
> ; COPYRIGHT (c) 1989 BY
> ; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
> ; ALL RIGHTS RESERVED
> ;
> ;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
> ;ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH THE
> ;INCLUSION OF THE ABOVE COPYRIGHT NOTICE. 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
> ;AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT
> ;CORPORATION.
> ;
> ;DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS
> ;SOFTWARE ON EQUIPMENT THAT IS NOT SUPPLIED BY DIGITAL.
>
> .SBTTL CONDITIONAL ASSEMBLY SUMMARY
> ;+
> ;COND
> ; DD$PRI (4) Interrupt Priority
> ; 4-7 possible interrupt priorities
> ;
> ; DDT$O (0) two controller support
> ; 0 1 controller
> ; 1 2 controllers
> ;
> ; DD$CSR (176500) 1st controller CSR
> ; DD$VEC (300) 1st controller VECTOR
> ;
> ; DD$CS2 (176510) 2nd controller CSR
> ; DD$VC2 (310) 2nd controller VECTOR
> ;
> ; EIS$I (MMG$T) Use SOB instruction (no code effects!)
> ; 0 simulate SOB
> ; 1 use SOB
> ;
> ; MMG$T std conditional
> ; TIM$IT std conditional (no code effects)
> ; ERL$G std conditional
> ;-
>
> .SBTTL GENERAL COMMENTS
>
> .ENABL LC
>
> ;+
> ; ABSTRACT FOR CODE FROM WHICH THIS WAS TAKEN:
> ;
> ; THIS MODULE MAY BE ASSEMBLED TO YIELD EITHER THE RAM PORTION OF A PDT
> ; DRIVER WITH PRIMITIVES IN ROM OR A MODULE TO BE LINKED WITH ANOTHER
> ; MODULE TO MAKE AN RT11 DRIVER FROM THE ROM PRIMITIVES.
> ;
> ; AUTHOR:
> ;
> ; BILL CLOGHER VERSION 1
> ; DARRELL DUFFY VERSION 2 27-APR-78
> ;
> ; MODIFIED BY:
> ; BARBARA DOERRE
> ; 23-AUG-78 SINGLE MODULE RT11 DRIVER
> ; DENISE LANGLAIS
> ; 29-JUN-79 REMOVE 'DEVICE DRIVER LIST' (R5) AND IMPURE AREA (R4)
> ; 1-AUG-79 ADD DUAL CONTROLLER CODE AND SET OPTIONS
> ;-
>
> .SBTTL MACROS AND DEFINITIONS
>
> .MCALL .DRDEF, .MTPS, .ASSUME .ADDR
>
> ; DD IS CONTROLLED VIA A SERIAL LINE OF DL TYPE
> ; CONTROL REGISTERS ARE THEREFORE A DL
>
> .IIF NDF DD$PRI DD$PRI = 4 ;STANDARD PRIORITY FOR DL
>
> .IIF NDF DDT$O DDT$O = 0 ;DEFAULT TO SINGLE CONTROLLER
>
> .IIF NDF DD$CS2 DD$CS2 = 176510 ;DEFAULT CSR FOR SECOND CONTROLLER
> .IIF NDF DD$VC2 DD$VC2 = 310 ;DEFAULT VECTOR
>
> .DRDEF DD,34,FILST$,512.,176500,300
> .IIF EQ MMG$T .DRPTR
> .IIF NE MMG$T .DRPTR FETCH=*NO*
> .DREST CLASS=DVC.DK
>
> .IIF NDF EIS$I EIS$I = MMG$T
> .IIF EQ EIS$I .MCALL SOB ; USE SOB INSTRUCTION UNDER XM
>
> ;THE FOLLOWING LIST OF SYMBOLICS WERE DELETED SINCE ACCESS TO THE CSR'S
> ;IS THROUGH A LIST OF THEIR ADDRESSES (@TICSRA AS OPPOSED TO @#TI$CSR)
> ;TI$CSR =: DD$CSR ;INPUT CONTROL AND STATUS
> ;TI$BFR =: TI$CSR+2 ;INPUT BUFFER
> ;TO$CSR =: TI$CSR+4 ;OUTPUT CONTROL
> ;TO$BFR =: TI$CSR+6 ;OUTPUT BUFFER
> ;TI$VEC =: DD$VEC ;INPUT VECTOR
> ;TO$VEC =: TI$VEC+4 ;OUTPUT VECTOR
>
> CS$INT =: 100 ;CONTROL INTERRUPT ENABLE
> CS$BRK =: 1 ;CONTROL BREAK ENABLE
>
> ; ERROR LOG VALUES
>
> DDCNT =: 8. ;RETRY COUNT
> DDNREG =: 10. ;COUNT OF REGISTERS REPORT TO EL
>
> ; RADIAL SERIAL CODES
>
> ; LEVEL 2 CODES (OPCODE BYTE)
>
> R$$NOP =: 0 ;NO OPERATION
> R$$INT =: 1 ;INITIALIZE
> R$$RED =: 2 ;READ FUNCTION
> R$$WRT =: 3 ;WRITE OPERATION
> R$$POS =: 5 ;POSITION
> R$$END =: 100 ;END PACKET FROM PERIPHERAL
>
> ; LEVEL 1 CODES (FLAG BYTE)
>
> R$CONT =: 20 ;CONTINUE
> R$INIT =: 4 ;INIT PROTOCOL
> R$DATA =: 1 ;DATA PACKET
> R$MSG =: 2 ;MESSAGE PACKET
> R$MSIZ =: 10. ;MESSAGE PACKET SIZE
> R$DSIZ =: 128. ;MAX DATA PACKET SIZE FOR DD
>
> ; MMU REGISTERS
>
> KISAR1 =: 172342 ;KERNEL PAR1
>
> ; RMON REFERENCES
>
> SYSPTR =: 54 ; SYSCOM pointer to RMON
> CONFG2 =: 370 ; second configuration word
> BUS$ =: 000100 ;
> PROS$ =: 020000 ;
> BUS$M =: BUS$!PROS$ ;Mask for type bits
> BUS$X =: BUS$!PROS$ ;Strange (busless) KXJ
> BUS$C =: PROS$ ;CTI bus
> BUS$Q =: BUS$ ;QBUS
> BUS$U =: 0 ;UNIBUS
>
> SYSCHN =: 17 ; system channel number
> .READ =: 375 ; EMT code for .READ/.WRITE
> .WRITE =: 375 ; EMT CODE FOR .READ/.WRITE
> ..READ =: 010 ; Subcode for .READ
> ..WRIT =: 011 ; Subcode for .WRITE
>
> .SBTTL INSTALLATION CODE
>
> .ASECT
> .IF NE DDT$O
> .DRINS DD,<DD$CS2>
> .IFF
> .DRINS DD
> .ENDC
> BR 1$ ;Data device installation check
> .ASSUME . EQ INSSYS
> BR 15$ ;System device installation check (none)
> 1$: MOV @#SYSPTR,R0 ; get address of RMON
> MOV CONFG2(R0),R0 ;Get configuration word for BUS check
> BIC #^C<BUS$M>,R0 ;Isolate bus bits
> CMP #<BUS$X>,R0 ;Running on KXJ?
> BNE 15$ ;Yes, go ahead and install
> CMP #<BUS$C>,R0 ;CTI bus?
> BEQ 2$ ; yes, don't install
> 15$: TST (PC)+ ; clear carry, skip setting carry
> 2$: SEC ; set carry
> RETURN
>
> ; The EMT area for reading/writing the bootstrap is placed here
> ; to leave room for set option code.
>
> BAREA: .BYTE SYSCHN,..READ ;CHANNEL 17, READ
> .BLKW ;BLOCK NUMBER
> .BLKW ;BUFFER ADDRESS
> .WORD 256. ;WORD COUNT
> .WORD 0 ;COMPLETION (WAIT)
>
>
> O.RTR1: CMP R0,R3 ;ASKING FOR TOO MANY RETRIES?
> BHI O.BAD ;USER IS BEING UNREASONABLE...
> TST R0 ;WERE NON-ZERO RETRIES SPECIFIED?
> BEQ O.BAD ;CAN'T ASK FOR NO RETRIES
> MOV R0,DRETRY ;OKAY, SET IT
> BR O.GOOD
>
> O.SYWL:
> MOV @SP,R0 ; copy return address
> INC R0 ; point to opcode at return
> CMPB #BR/400,(R0)+ ; is it a BR xxx?
> BNE O.BAD ; NO, old style SET
> MOV R0, at SP ; use alternate return (RET+2)
> BR O.BAD ; with carry set
>
> .ASSUME . LE 400,MESSAGE=<;Install area too big>
>
> .SBTTL SET OPTIONS
>
> .DRSET CSR, 160000, O.CSR, OCT
> .DRSET VECTOR, 500, O.VEC, OCT
>
> .IF NE DDT$O
> .DRSET CSR2, 160000, O.CSR2, OCT
> .DRSET VEC2, 500, O.VEC2, OCT
> .ENDC ;NE DDT$O
>
> .DRSET RETRY, 127., O.RTRY, NUM
>
> .IF NE ERL$G
> .DRSET SUCCES, -1, O.SUCC, NO
> .ENDC ;NE ERL$G
>
> BTCSR = <DDEND-DDSTRT> + <BOTCSR-DDBOOT> + 1000
>
> O.RTRY: BR O.RTR1 ; MOVED TO INSTALL AREA
>
> O.CSR: CMP R0,R3 ;CSR IN RANGE? (>160000)
> BLO O.BAD ;NOPE...
> MOV R0,INSCSR ;YES, INSTALLATION CODE NEEDS IT
> MOV R0,DISCSR ;AND SO DOES RESORC
>
> ; When the CSR for units 0 and 1 is changed, the bootstrap must
> ; be altered such that it will use the correct controller.
>
> ;R1->EMT AREA
> .ADDR #BAREA+4,R1 ; (BUFFER ADDRESS WORD)
> ;R2->READ/WRITE BUFFER
> .ADDR #1000,R2 ; (OVERWRITES CORE COPY OF BLOCK 1)
> MOV R2,(R1) ;SET THE BUFFER ADDRESS
> MOV #BTCSR/1000,-(R1) ; AND THE BOOT BLOCK TO READ/WRITE
> TST -(R1) ;R1->EMT AREA
> MOV R0,R3 ;SAVE CSR ELSEWHERE, EMT NEEDS R0
> MOV R1,R0 ;R0->EMT AREA FOR READ
> EMT .READ ; *** (.READW) ***
> BCS O.BAD
> MOV R3,<BTCSR&777>(R2) ;SET THE NEW CSR
> ADD #4,<BTCSR&777>(R2) ; (+4)
> MOV R1,R0 ;R0->EMT AREA AGAIN
> .ASSUME ..READ+1 EQ ..WRIT
> INCB 1(R0) ;CHANGE FROM 'READ' TO 'WRITE'
> EMT .WRITE ; *** (.WRITW) ***
> BCS O.SYWL
> MOV R1,R0 ;R0->EMT AREA (LAST TIME, HONEST)
> .ASSUME ..WRIT-1 EQ ..READ
> DECB 1(R0) ;CHANGE BACK TO A 'READ'
> MOV #1,2(R0) ; OF BLOCK 1 OF HANDLER
> EMT .READ ; ** (.READW) ***
> BCS O.BAD
>
> .IF NE DDT$O
> MOV R3,SET$L1+2 ;SET NEW CSR FOR CREATING ADDR LIST
> .ENDC ;NE DDT$O
>
> ;GET ADDR OF CSR ADDRESS TABLE
> .ADDR #TICSRA,R1 ; IN A PIC FASHION
> MOV #2,R0
> MOV R3,(R1)+ ;SAVE RCSR,
> ADD R0,R3
> MOV R3,(R1)+ ; RBUF,
> ADD R0,R3
> MOV R3,(R1)+ ; XCSR,
> ADD R0,R3
> MOV R3, at R1 ; AND XBUF
> O.GOOD: TST (PC)+ ;GOOD RETURN (CARRY CLEAR)
> O.BAD: SEC ;BAD RETURN (CARRY SET)
> RETURN
>
> O.VEC: CMP R0,R3 ;VECTOR IN RANGE? (<500)
> BHIS O.BAD ;NOPE...
> BIT #3,R0 ;YES, BUT ON A VECTOR BOUNDRY?
> BNE O.BAD ;NOPE...
> MOV R0,VECTAB ;VECTOR ADDR TO DRIVER TABLE
> TST (R0)+ ;+2 FOR PSW
>
> .IF NE DDT$O
> MOV R0,SET$L2+2 ;SET VECTOR USED TO CREATE ADDR LIST
> .ENDC ;NE DDT$O
>
> ;GET POINTER TO TIVECA
> .ADDR #TIVECA,R1 ; IN A PIC FASHION
> MOV R0,(R1)+ ;STORE ADDR OF INPUT PSW
> TST (R0)+ ;+2 FOR OUTPUT VECTOR
> MOV R0,VECTAB+6 ;VECTOR ADDR TO DRIVER TABLE
> TST (R0)+ ;+2 FOR PSW
> MOV R0, at R1 ;STORE ADDR OF OUTPUT PSW
> RETURN
>
> .IF NE DDT$O
> O.CSR2: CMP R0,R3 ;CSR IN RANGE? (>160000)
> BLO O.BAD ;NOPE...
> MOV R0,SET$L3+2 ;CHANGE CSR USED TO CREATE ADDR LIST
> MOV R0,DISCS2 ;AND FOR RESORC
> RETURN
>
> O.VEC2: CMP R0,R3 ;VECTOR IN RANGE? (<500)
> BHIS O.BAD ;NOPE...
> BIT #3,R0 ;YES, BUT ON A VECTOR BOUNDRY?
> BNE O.BAD ;NOPE...
> MOV R0,VECTAB+14 ;VECTOR ADDR TO DRIVER TABLE
> TST (R0)+ ;+2 FOR PSW
> MOV R0,SET$L4+2 ;SET VECTOR USED TO CREATE ADDR LIST
> TST (R0)+ ; +2 FOR OUTPUT VECTOR
> MOV R0,VECTAB+22 ;VECTOR ADDR TO DRIVER TABLE
> BR O.GOOD
> .ENDC ;NE DDT$O
>
> .IF NE ERL$G
> O.SUCC: MOV #0,R3 ;'SUCCESS' ENTRY POINT
> ; (MUST TAKE UP TWO WORDS)
> N.SUCC: MOV R3,SCSFLG ;'NOSUCCESS' ENTRY POINT
> .ASSUME O.SUCC+4 EQ N.SUCC
> BR O.GOOD
> .ENDC ;NE ERL$G
>
> .Assume . LE 1000,MESSAGE=<;SET area too big>
>
> .SBTTL START I/O ENTRY
>
> .DRBEG DD
>
> CALL STARIO ;CALL START I/O - ONLY RETNS IF ERROR
> ERR1: MOV DDCQE,R4 ;ERROR, R4 -> CURRENT QUEUE ELEMENT
> .ASSUME Q$BLKN-2 EQ Q$CSW
> BIS #HDERR$, at -(R4) ;SET HARD ERROR BIT IN CSW
> BR PDEXIT ;EXIT ON HARD ERROR
>
> ; FOR SET OPTIONS TO ALLOW VECTORS TO BE CHANGED
> ; KEEP .DRVTB MACRO CALLS IN THIS ORDER
>
> VECTAB: .DRVTB DD,DD$VEC,DDINT
> .DRVTB ,DD$VEC+4,DDINT
> .ASSUME .-DDSTRT LE 1000
> .IF NE DDT$O
> .DRVTB ,DD$VC2,DDINT
> .DRVTB ,DD$VC2+4,DDINT
> .ASSUME .-DDSTRT LE 1000
> .ENDC ;NE DDT$O
>
> .IF NE ERL$G
> SCSFLG: .WORD 0 ; :SUCCESSFUL LOGGING FLAG (DEFAULT=YES)
> .ASSUME .-DDSTRT LE 1000
> ; =0 - LOG SUCCESSES,
> ; <>0 - DON'T LOG SUCCESSES
> .ENDC ;NE ERL$G
>
> .SBTTL DD VECTOR AND CSR ADDRESS LIST
>
> ; NOTE:
> ; THIS LIST WAS CREATED TO IMPLEMENT THE DUAL CONTROLLER CODE, HOWEVER
> ; THE LIST DEFAULTS TO THE CORRECT ADDRESSES FOR A SINGLE CONTROLLER
> ; SINCE ALL REFERENCES TO THE CSR'S AND VECTORS ARE THROUGH THIS LIST.
> ; NOT ONLY IS THE ORDER CRITICAL BUT ALSO THE FACT THAT THIS LIST MUST
> ; BE LOCATED IN THE FIRST BLOCK OF THE HANDLER IN ORDER FOR THE SET
> ; OPTIONS TO WORK (I.E. KMON READS ONLY THE FIRST 2 BLOCKS FOR A SET
> ; COMMAND)
>
> ; *ORDER*
>
> TICSRA: .WORD DD$CSR
> TIBFRA: .WORD DD$CSR+2
> TOCSRA: .WORD DD$CSR+4
> TOBFRA: .WORD DD$CSR+6
> TIVECA: .WORD DD$VEC+2
> TOVECA: .WORD DD$VEC+6
>
> ; *END ORDER*
> .ASSUME .-DDSTRT LE 1000
>
> .SBTTL INTERRUPT ENTRY
>
> .ENABL LSB
>
> BR DDABRT
> DDINT:: BCS 1$ ;DON'T DO .INTEN IF C=1 ON INTERRUPT (SPEED)
> JSR R5,@$INPTR ;JUST LIKE THE .DRAST MACRO WOULD DO
> .WORD ^C<DD$PRI*^O40>&^O340 ;.DRAST DD,DD$PRI,DDABRT
> CLR (PC)+ ;CLEAR FORK FLAG - NEEDED FOR ERROR LOGGER
> FKFLG: .WORD 0 ;FLAG=0 UNTIL .FORK IS DONE
> JMP @I$INTR ;GO TO INTERRUPT SERVICE
>
> ; HIGH SPEED INTERRUPT ENTRY
>
> 1$: MOV R4,-(SP) ;SAVE R4
> CALL @I$INTR ;CALL WHERE WE LEFT OFF
> MOV (SP)+,R4 ;RESTORE
> RTI ;RETURN FROM INTERRUPT
>
> .DSABL LSB
>
> .SBTTL INTERRUPT EXIT
>
> ;+
> ; INIRTN - ENABLES THE INPUT INTERRUPT AND BRANCHES TO INPRTN
> ; SAME INPUT AND OUTPUT AS INPRTN
> ;
> ; OUTCHR - OUTPUTS THE CHARACTER PASSED IN R5 AND FALLS INTO OUTRTN
> ; SAME INPUT AND OUTPUT AS OUTRTN EXCEPT R5 ON ENTRY
> ; CONTAINS THE CHARACTER TO OUTPUT
> ;
> ; NOTE: TWO ENTRIES (OUTRTN, INPRTN) ARE IDENTICAL
> ;
> ; JSR PC,XXXRTN
> ;
> ; RETURN SAVED IN I$INTR
> ; RETURN FROM INTERRUPT
> ;-
>
> INIRTN: BIS #CS$INT, at TICSRA ;SET THE INPUT INTERRUPT
> BR INPRTN ;GO RETURN
>
> OUTCHR: MOV R5, at TOBFRA ;OUTPUT A CHARACTER
> OUTRTN:
> INPRTN: MOV (SP)+,I$INTR ;SAVE RETURN
> INTRTN: RETURN
>
> .SBTTL COMPLETION EXIT
>
> COMPLT: BCS ERR1 ;IF CS, ERROR
>
> .IF NE ERL$G
> TST FKFLG ;WAS A FORK DONE
> BNE 1$ ;IF NE, YES, OK TO GO TO ERROR LOGGER THEN
> CALL FORK ;NO, MUST BE AT FORK LEVEL FOR ERROR LOGGING
> 1$: TST SCSFLG ;LOGGING SUCCESSES?
> BNE PDEXIT ;NOPE...
> MOV #DD$COD*400+377,R4 ;SUCCESSFUL I/O - CALL ERROR LOGGER
> MOV DDCQE,R5 ;CALL ERROR LOGGER FOR SUCCESS
> CALL @$ELPTR
> .ENDC ;NE ERL$G
>
> PDEXIT: .DRFIN DD ;EXIT TO COMPLETION
>
> .SBTTL FORK ROUTINE
>
> ;+
> ; FORK - DO A .FORK
> ;
> ; R0 - R3 = SAME AS WHEN INTERRUPT SERVICE ENTERED
> ; SP -> THE RETURN PC
> ; FKFLG = 0 (NO .FORK DONE YET)
> ;
> ; JSR PC,FORK
> ;
> ; R0 - R3 = AVAILABLE FOR USE
> ; R4, R5 = SAME AS WHEN FORK WAS CALLED
> ; STACK = UNSPECIFIED. GUARANTEED NOT TO BE SAME
> ; PRIORITY = 0 (FORK LEVEL)
> ; FKFLG <> 0 TO INDICATE A .FORK HAS BEEN DONE
> ;-
>
> FORK: MOV (SP)+,FKFLG ;SAVE RETURN, POPPING STACK, AND SET FORK FLAG
> MOV R0,-(SP) ;SAVE REGISTERS 0-3
> MOV R1,-(SP)
> MOV R2,-(SP)
> MOV R3,-(SP)
> MOV FKFLG,-(SP) ;GET THE RETURN ADDRESS
> JSR PC,@(SP)+ ;CO-ROUTINE BACK TO IT
> MOV (SP)+,R3 ;RESTORE THE REGISTERS
> MOV (SP)+,R2
> MOV (SP)+,R1
> MOV (SP)+,R0
> RTS PC ;COMPLETE THE UN-WINDING
>
> .SBTTL DDABRT - ABORT ENTRY
>
> DDABRT::BIC #1, at TIVECA ;CLEAR ANY CARRY BITS SET IN
> BIC #1, at TOVECA ;THE INTERRUPT PSW
> .MTPS #340 ;RAISE PRIORITY TO PREVENT INTERRUPTS
> BIC #CS$INT, at TICSRA ;NO INPUT INTERRUPTS FOR NOW
> BIS #CS$INT, at TOCSRA ;SET UP OUTPUT INTERRUPT
> CLR (PC)+ ;CLEAR THE COUNT-DOWN WORD
> 5$: .BLKW
> 10$: MOV #R$INIT,R5 ;SEND INIT
> CALL OUTCHR ;OUTPUT IT
> DECB 5$ ;WAIT A REASONABLE AMOUNT OF TIME
> BEQ 15$ ; AND IF NO RESPONSE, GIVE UP TRYING
> ; TO LEAVE IN A KNOWN STATE (AS PER
> ; REPLY TO SPR #47883)
> TSTB @TICSRA ;INPUT CHAR READY YET?
> BPL 10$ ;NO,KEEP SENDING INITS
> CALL TXINIT ;LEAVE IN A KNOWN STATE
> 15$: BR PDEXIT ;EXIT NOW - DRFIN
>
> .SBTTL STARIO - START I/O CODE
>
> ;+
> ; STARIO - START I/O CODE
> ;
> ; R0-R4 AVAILABLE
> ;
> ; JSR PC,STARIO
> ;
> ; INTERRUPTS ENABLED, ALL SETUP TO START TRANSFER
> ;
> ; RETURN TO CALLER ON COMMAND ERROR
> ; ELSE RETURN TO CALLER'S CALLER
> ;-
>
> .ENABL LSB
>
> STARIO::CLR PK$UNT ;ASSUME FIRST UNIT
> MOV DDCQE,R3 ;R3 -> QUEUE ELEMENT
> MOVB Q$UNIT(R3),R0 ;GET THE UNIT BYTE
> BIC #^C<7>,R0 ;CLEAR ALL BUT THE UNIT
> ASR R0 ;SHIFT IT TO CHECK FOR ODD UNIT
>
> .IF EQ DDT$O
> BNE 10$ ;IF UNIT > 1 ERROR
> .ENDC ;EQ DDT$O
>
> BCC 1$ ;OK IF EVEN UNIT
> INC PK$UNT ;SELECT ODD UNIT FOR TRANSFER
> 1$:
> .IF NE DDT$O
> SET$L1: MOV #DD$CSR,R3 ;ASSUME FIRST DD CONTROLLER
> SET$L2: MOV #DD$VEC+2,R2 ;CSR AND VECTOR
> .ASSUME .-DDSTRT LE 1000
> ASR R0 ;SHIFT UNIT TO CHECK FOR SECOND CONTROLLER
> BNE 10$ ;IF UNIT WAS 4 TO 7 ERROR
> BCC 2$ ;FIRST CONTROLLER WAS RIGHT
> SET$L3: MOV #DD$CS2,R3 ;IT'S THE SECOND CONTROLLER
> SET$L4: MOV #DD$VC2+2,R2 ;CSR AND VECTOR
> .ASSUME .-DDSTRT LE 1000
> 2$:
> .ADDR #TICSRA,R1 ;POINT TO ADDRESS LIST
> CMP R3, at R1 ;IS THE LIST OF ADDRESSES OK AS IS?
> BEQ 4$ ;YES, DON'T BOTHER TO CHANGE AGAIN
> MOV #4,R0 ;NO, THERE ARE FOUR TO CHANGE
> 3$: MOV R3,(R1)+ ;STORE THE ADDRESSES IN THE TABLE
> TST (R3)+ ;THEY ARE LOCATED TOGETHER SO +2
> SOB R0,3$ ;MORE?
> MOV R2,(R1)+ ;NOW STORE THE VECTOR PSW LOCATIONS
> CMP (R2)+,(R2)+ ;ADD FOR THE OUTPUT VECTOR PSW ADDR
> MOV R2, at R1
> 4$:
> .ENDC ;NE DDT$O
>
> DRETRY = .+2
> MOV #DDCNT,I$ERCT ;COMM RETRY COUNT
> .ASSUME .-DDSTRT LE 1000
> CLR RETIO ;CLEAR THE RETRY I/O FLAG
> TST I$ABRT ;DO WE NEED TO ABORT THE TX?
> BNE RETRY ;NO OK ITS DONE
> INC I$ERCT ;1 RETRY REQUIRED TO INIT
> .ADDR #ABORT,R1 ;POINT TO ABORT
> BR GO ;AND START THE BALL ROLLING
>
> RETRY: MOV DDCQE,R3 ;R3 -> QUEUE ELEMENT
> TST RETIO ;IS I/O BEING RETRIED ?
> BEQ 7$ ;NO, CONTINUE
> ADD #Q$WCNT,R3 ;POINT AT THE WORD COUNT
> MOV @R3,R1 ;PICK UP THE WORD COUNT
> BPL 5$ ;BRANCH IF IT'S READ
> NEG R1 ;MAKE WORD COUNT POSITIVE
> 5$: ASL R1 ;MAKE IT A BYTE COUNT
> SUB I$BYTC,R1 ;COMPUTE NUMBER OF BYTES TRANSFERED
> ROR R1 ;MAKE IT WORD COUNT
> CLRB R1 ;ROUND DOWN TO A BLOCK MULTIPLE
> MOV R1,R2 ;COPY IT
> TST @R3 ;IS WORD COUNT POSITIVE?
> BPL 6$ ;YES, SUBTRACT #WORDS TRANSFERRED
> NEG R1 ;NO, ADD #WORDS TRANSFERRED
> 6$: SUB R1, at R3 ;UPDATE THE WORD COUNT
>
> .IF EQ MMG$T
> .ASSUME Q$WCNT-2 EQ Q$BUFF
> ADD R2,-(R3) ;UPDATE THE BUFFER ADDRESS
> ADD R2, at R3 ;TWICE FOR CORRECT ADDRESS
> .ASSUME Q$BUFF-2 EQ Q$FUNC
> TST -(R3) ;POINT AT THE Q$FUNC
> .IFF
> MOV R2,R1 ;COPY THE WORD COUNT
> ASHC #-5,R1 ;SHIFT IT RIGHT TO GET 32W UNIT COUNT
> ADD R1,Q$PAR-Q$WCNT(R3) ;UPDATE THE BUFFER ADDRESS
> .ASSUME Q$WCNT-4 EQ Q$FUNC
> CMP -(R3),-(R3) ;BACK OFF THE QUEUE ELEMENT POINTER
> .ENDC ;EQ MMG$T
>
> SWAB R2 ;GET THE NUMBER BLOCKS TRANSFERRED
> .ASSUME Q$FUNC-2 EQ Q$BLKN
> ADD R2,-(R3) ;UPDATE THE BLOCK NUMBER
> 7$: MOV #R$$RED,PK$OPC ;GUESS READ OP, CLEAR MODIFIER BYTE
> CLRB PK$SSQ ;CLEAR UP UNUSED STUFF
> CLR PK$SSQ+1 ;SINCE TX DOES NOT USE IT
> MOV Q$WCNT(R3),R1 ;GET WORD COUNT
> BPL 8$ ;POSITIVE MEANS READ
> MOVB #R$$WRT,PK$OPC ;MAKE IT WRITE
> NEG R1 ; AND MAKE A POSITIVE WORD COUNT
> 8$: ASL R1 ;MAKE BYTE COUNT
> BNE 9$ ;NORMAL I/O
> MOVB #R$$POS,PK$OPC ;COUNT=0 => SEEK, FUNCTION IS POSITION
> 9$: MOV Q$BUFF(R3),I$ADRS ;ADDRESS FOR TRANSFER
>
> .IF NE MMG$T
> MOV Q$PAR(R3),I$PAR ;SAVE PAR VALUE, TOO
> .ENDC ;NE MMG$T
>
> MOV R1,I$BYTC ;SAVE BYTE COUNT
> MOV R1,PK$BCT ;COPY BYTE COUNT INTO PACKET
> MOV @R3,PK$RCD ;STORE BLOCK NUMBER IN COMMAND PACKET
> .ADDR #TXGO,R1 ;MAKE THE ADDRESS OF THE TRANSFER START
> GO: MOV R1,I$INTR ;OUTPUT SIDE STARTS US
> BIS #CS$INT, at TOCSRA ;OUTPUT INTERRUPTS
> TST (SP)+ ;RETURN DIRECT TO MONITOR
> 10$: RETURN ;ERROR RETURN TO SKELETON
>
> .DSABL LSB
>
> .SBTTL TXGO - START TRANSFER FROM INTERRUPT LEVEL
>
> ;+
> ; TXGO - START TRANSFER
> ;
> ; JMP TXGO
> ;
> ; TRANSFER TO COMPLETION OR ERROR ENTRY
> ;-
>
> TXGO: CALL FORK ;ENTER FORK STATE
> MOV #R$MSG,PK$FLG ;MESSAGE TYPE TO FLAG BYTE
> MOV #R$MSIZ,R2 ;MESSAGE SIZE FOR PACKET
> ;GET ADDRESS OF MESSAGE
> .ADDR #PK$OPC,R1 ;OPCODE IS FIRST BYTE
> CALL SNDPKT ;SEND A PACKET TO START IO
> 1$: CMPB PK$OPC,#R$$WRT ;IS IT A WRITE?
> BNE 2$ ;NO
> JSR R5,RCVPKT ;IF WRITE, RECEIVE THE CONTINUE PACKET
> .WORD R$CONT ;EXPECTED A CONTINUE
> 2$: MOV I$ADRS,R1 ;GET THE DATA ADDRESS
> MOV I$BYTC,R2 ; AND THE BYTE COUNT
> BEQ TXEND ;NO BYTES => POSITION (GET END PACKET)
> CMP R2,#R$DSIZ ;TOO LARGE FOR ONE PACKET?
> BLOS 3$ ;NOPE, USE THIS COUNT
> MOV #R$DSIZ,R2 ;REDUCE TO A SINGLE PACKET TRANSFER
> 3$: CMPB PK$OPC,#R$$WRT ;WRITE?
> BNE 4$ ;NO
> MOVB #R$DATA,PK$FLG ;YES, SET UP DATA FLAG
> CALL SNDPKT ;SEND DATA PACKET
> CMP I$BYTC,#R$DSIZ ;MORE LEFT TO DO?
> BLOS TXEND ;NO, FINISH UP
> JSR R5,RCVPKT ;YES, RECEIVE THE NEXT CONTINUE PACKET
> .WORD R$CONT ;EXPECT A CONTINUE
> BR 5$ ;GO SEND THE NEXT DATA PACKET
>
> 4$: JSR R5,RCVPKT ;READ, RECEIVE A DATA PACKET
> .WORD R$DATA ;EXPECT A DATA FLAG
> 5$:
> .IF EQ MMG$T
> ADD #R$DSIZ,I$ADRS ;ADJUST THE ADDRESS
> .IFF
> ADD #2,I$PAR ;ADJUST THE PAR BIAS TO UPDATE THE ADDR
> .ENDC ;EQ MMG$T
>
> SUB #R$DSIZ,I$BYTC ;COUNT ONE PACKET FROM THE WORD COUNT
> BHI 2$ ;STILL MORE TO GO
> CLR I$BYTC ;ALL HAS BEEN TRANSFERRED
>
> .SBTTL TXEND - READ THE END PACKET AFTER A TRANSFER
>
> TXEND: ;POINT TO THE MESSAGE PACKET
> .ADDR #I$MBFR,R1 ; BY THE PIC METHOD
> MOV #R$MSIZ,R2 ;THE SIZE OF A MESSAGE
> JSR R5,RCVPKT ;GET A PACKET
> .WORD R$MSG ;EXPECT A MESSAGE PACKET
>
> .SBTTL ERROR - ANALYZE AN END PACKET
>
> ERROR: CMPB PK$FLG,#R$MSG ;MESSAGE PACKET?
> BNE ABORTR ;NO, PROTOCOL SCREWUP, TRY REINITIALIZING
> CMPB I$MOPC,#R$$END ;END PACKET?
> BNE ABORTR ;NO, ERROR
> TSTB I$MSUC ;CHECK FOR SUCCESS
>
> .IF EQ ERL$G
> BPL CPLRTN ;OK, SO COMPLETE WITHOUT ERROR
> .IFF
> BEQ CPLRTN ;OK, SO COMPLETE WITHOUT ERROR
> BLT FATAL ;FATAL ERROR
> MOV I$ERCT,R2 ;DATA IS OK, BUT LOG CONTROLLER RETRIES
> CALL LOGERR ;LOG THE RETRY ATTEMPT
> BR CPLRTN ;NOW YOU CAN RETURN
> .ENDC ;EQ ERL$G
>
> FATAL: TST FKFLG ;FORK DONE?
> BNE 1$ ;YES, COMPLETE WITH AN ERROR
> CALL FORK ;ELSE GO TO FORK LEVEL
>
> .IF NE ERL$G
> CLR R2 ;INDICATE FATAL I/O ERROR
> CALL LOGERR ;LOG THE HARD ERROR
> .ENDC ;NE ERL$G
>
> 1$: SEC ;SET C FOR FATAL ERROR
> CPLRTN: BIC R4,R4 ;ZERO R4
> BIC #CS$INT, at TICSRA ;ZAP INTERRUPT ENABLE
> BIC #CS$INT, at TOCSRA ;ON BOTH SIDES
> JMP COMPLT ;*C* GO TO COMPLETION EXIT
>
> .SBTTL ABORT - COMMUNICATIONS ERROR
>
> ABORTR: MOV SP,(PC)+ ;INDICATE I/O RETRY IN PROGRESS
> RETIO: .WORD 0 ;RETRY I/O INDICATOR
> ABORT: CALL TXINIT ;ABORT THE TRANSFER
> CLR I$ABRT ;ABORT IS NEEDED (ASSUME)
> TST I$ERCT ;TRIED ALL WE CAN?
> BLE FATAL ;YES- NO MORE TRIES
> INC I$ABRT ;NO IT WORKED THIS TIME
> MOV R3,-(SP) ;SAVE
> MOV R2,-(SP) ; ALL
> MOV R1,-(SP) ; IMPORTANT
> MOV R0,-(SP) ; REGISTERS
> CALL 9$ ;CALL SIMULATES MONITOR CALL TO STARTIO
> MOV (SP)+,R0 ;RESTORE
> MOV (SP)+,R1 ; ALL
> MOV (SP)+,R2 ; IMPORTANT
> MOV (SP)+,R3 ; REGISTERS
> RETURN ;RETURN FROM INTERRUPT
>
> 9$: CALL RETRY ;RETRY ENTRY IN MAIN START CODE
> TST (SP)+ ;DUMP NEXT RETURN TO CLEAN STACK
> MOV (SP)+,R0 ;RESTORE
> MOV (SP)+,R1 ; ALL
> MOV (SP)+,R2 ; IMPORTANT
> MOV (SP)+,R3 ; REGISTERS
> BR FATAL ;RETURN HERE IS FATAL
>
> .IF NE ERL$G
>
> .SBTTL LOGERR - SET UP AND CALL ERROR LOGGER
>
> ;+
> ; R2 > 0 => RETRY ATTEMPT (SOFT ERROR)
> ; = 0 => HARD ERROR
> ;
> ; JSR PC,LOGERR
> ;
> ; ALL REGISTERS RESTORED
> ;-
>
> LOGERR: MOV R2,R4 ;R4 LOB = CURRENT RETRY COUNT
> BIS #DD$COD*400,R4 ;R4 HOB = DEVICE ID CODE
> MOV DRETRY,R3
> SWAB R3
> ADD #DDNREG,R3 ;R3=MAX RETRIES/NUMBER OF REGISTERS
> ;FORM THE ADDRESS OF THE REGISTER
> .ADDR #I$LCHR,R2 ;BUFFER IN R2
> MOV DDCQE,R5 ;LOG THE ERRORS
> CALL @$ELPTR
> CLR I$LCHR ;CLEAR FOR NEXT TIME
> RETURN ;NO NEED TO RESTORE REGISTRS
>
> .ENDC ;NE ERL$G
>
> .SBTTL TXINIT - INIT THE TU58
>
> ; TXINIT - INITILIZE THE TU58
> ;
> ; IF A CHECKSUM ERROR OCCURS, AN UNEXPECTED PACKET TYPE IS RECEIVED,
> ; OR SOMETHING ELSE HAPPENS WHICH INDICATES THE TRANSMISSION LINE
> ; OR PROTOCOL IS OUT OF SYNC, WE SEND RADIAL SERIAL 'SIGNAL' TO THE DD
> ; ('SIGNAL' IS BREAK STATE ON THE COMM LINE).
> ; WE TIME BREAK WITH TWO NULL CHARS, THEN SEND TWO INIT CHARS
> ; AND WAIT FOR A CONT FLAG TO SAY WE ARE IN SYNC.
> ; IF THINGS ARE REALLY SCREWED UP, THIS COULD OCCUR FOREVER.
> ; TO AVOID THIS, IF 8 ATTEMPTS ARE MADE TO SIGNAL THE DD
> ; DURING ONE TRANSFER, WE QUIT AND RETURN A HARD ERROR.
> ;-
>
> TXINIT: BIC #CS$INT, at TOCSRA ;SET UP KNOWN STATE
> BIC #CS$INT, at TICSRA
> MOV (SP)+,I$SUBR ;SAVE SUBROUTINE RETURN
> 1$:
> .IF NE ERL$G
> TST I$ABRT ;FORCED ABORT ?
> BEQ 2$ ;YES, DON'T LOG AN ERROR
> TST FKFLG ;AT FORK LEVEL FOR ERROR LOGGING ?
> BNE 3$ ;YES, DON'T FORK AGAIN
> CALL FORK ;FORK
> 3$: MOV I$ERCT,R2 ;SET UP THE RETRY COUNT
> CALL LOGERR ;LOG THE RETRY ATTEMPT
> 2$:
> .ENDC ;NE ERL$G
>
> .MTPS #340 ;RAISE PRIORITY TO PREVENT INTERRUPT
> MOV #177777, at TOBFRA ;;;SEND ONES FOR TIMING
> BIS #<CS$INT!CS$BRK>, at TOCSRA ;;;SET BREAK AND INTERRUPT ENABLE
> CALL OUTRTN ;;;OUTPUT WAIT
> MOV #177777,R5 ;SEND RUBOUT FOR TIMING
> CALL OUTCHR ; AND WAIT ON IT
> BIC #CS$BRK, at TOCSRA ;SHUT OFF BREAK
> MOV #R$INIT,R5 ;SEND AN INIT
> CALL OUTCHR ; AND WAIT ON IT
> MOV #R$INIT,R5 ;TRY TWO JUST IN CASE
> CALL OUTCHR ; AND WAIT ON THE SECOND
> BIC #CS$INT, at TOCSRA ;TURN OFF OUTPUT INTERRUPTS
> TST @TIBFRA ;DUMP THE INPUT CHARACTER TO CLEAR READY
> CALL INIRTN ;NOW WAIT FOR THE ANSWER
> MOV @TIBFRA,PK$FLG ;GET THE FLAG
> BIC #CS$INT, at TICSRA ;NO MORE INPUT INTERRUPTS
> DEC I$ERCT ;TOO MANY TIMES?
> BLE 9$ ;YES, BAD LINE OR BAD DEVICE
> CMPB PK$FLG,#R$CONT ;IS IT CORRECT?
> BNE 1$ ;TRY AGAIN
> 9$: CALLR @I$SUBR ;RETURN FROM THIS SUBROUTINE
>
> .SBTTL SNDPKT - SEND RADIAL SERIAL PACKET
>
> ;+
> ; SNDPKT - SEND RADIAL SERIAL PACKET
> ;
> ; R1 -> DATA
> ; R2 = BYTE COUNT
> ; PK$FLG = FLAG BYTE
> ; ENTRY IN FORK STATE
> ;
> ; JSR PC,SNDPKT
> ;
> ; R0,R3 = UNDEFINED
> ; PACKET SENT
> ; OUTPUT INTERRUPT DISABLED
> ; EXIT IN FORK STATE
> ;-
>
> SNDPKT: MOV (SP)+,I$SUBR ;SAVE SUBROUTINE RETURN
> MOV R1,I$MADR ;SAVE ADDRESS
> MOVB R2,PK$MBC ;SAVE BYTE COUNT IN PACKET
> MOV PK$FLG,PK$CKS ;INITILIZE CHECKSUM
> .MTPS #340 ;NO INTERRUPTS
> MOVB PK$FLG, at TOBFRA ;;;OUTPUT FIRST BYTE (FLAG)
> BIS #CS$INT, at TOCSRA ;;;ENABLE INTERRUPTS
> CALL OUTRTN ;;;WAIT FOR OUTPUT INTERRUPT
> MOVB PK$MBC,R5 ;OUTPUT MESSAGE BYTE COUNT
> CLRB I$TDAT+1 ;CLEAR THE HIGH BYTE OF TEMP WORD
> BIS #1, at TOVECA ;SET CARRY => NO .INTEN
> CALL OUTCHR ;AND WAIT FOR INTERRUPT
> 2$:
> .IF NE MMG$T
> MOV @#KISAR1,-(SP) ;SAVE OLD PAR1
> MOV I$PAR,@#KISAR1 ;USE OUR OWN VALUE
> .ENDC ;NE MMG$T
>
> MOVB @I$MADR, at TOBFRA ;OUTPUT DATA BYTE
> MOVB @I$MADR,I$TDAT ;STORE THE BYTE JUST OUTPUT
>
> .IF NE MMG$T
> MOV (SP)+,@#KISAR1 ;RESTORE SAVED PAR1
> .ENDC ;NE MMG$T
>
> INC I$MADR ;NEXT ADDRESS
> ADD I$TDAT,PK$CKS ;ADD IT TO THE CHECKSUM
> ADC PK$CKS ;END AROUND CARRY
> SWAB PK$CKS ;SWAP CKECKSUM FOR ODD BYTE
> DECB PK$MBC ;ARE WE DONE?
> BEQ 3$ ;YES, TIME TO CLEAR THE CARRY
> RETURN ;NO, KEEP ON SENDING THOSE CHARACTERS FAST
>
> 3$: BIC #1, at TOVECA ;CC => DO INTEN
> ADD #4$-2$,I$INTR ;SET UP THE RETURN ADDRESS
> RETURN ;GO BACK THE WAY YOU CAME
>
> 4$: MOVB PK$CKS,R5 ;OUTPUT CHECKSUM
> CALL OUTCHR ;TIL OUT
> MOVB PK$CKS+1,R5 ;HO HUM
> CALL OUTCHR ;TIL GONE
> BIC #CS$INT, at TOCSRA ;CLEAR INTERRUPTS, FALL THROUGH TO RETURN PKT
>
> ; PACKET ROUTINE RETURN
>
> PKTRTN: CALL FORK ;USING SKELETON DRIVER
> CALLR @I$SUBR ;AND RETURN FROM SUBROUTINE
>
> .SBTTL RCVPKT - RECEIVE A RADIAL SERIAL PACKET
>
> ;+
> ; RCVPKT - RECEIVE A RADIAL SERIAL PACKET
> ;
> ; R1 -> DATA AREA
> ; R2 = BYTE COUNT
> ; I$EFLG EXPECTED FLAG BYTE
> ; ENTERED IN FORK STATE
> ;
> ; JSR PC,RCVPKT
> ;
> ; R0-R3 = UNDEFINED
> ; PK$FLG = FLAG RECEIVED
> ; I$MBFR = PACKET IF NOT EXPECTED TYPE UNLESS
> ; DATA PACKET IN WHICH CASE ABORT IS ENTERED
> ; EXIT IN FORK STATE
> ;-
>
> RCVPKT: MOV (R5)+,I$EFLG ;SAVE THE EXPECTED FLAG
> MOV R5,I$SUBR ;SAVE SUBROUTINE RETURN
> MOV (SP)+,R5 ;RESTORE R5
> MOV R1,I$MADR ;PACKET ADDRESS SPACE
> .MTPS #340 ;LOCK OUT INTERRUPTS
> CALL INIRTN ;;;AND COME BACK HERE
> MOV @TIBFRA,R4 ; SAVE THE CHAR AND THE OVERRUN ERROR
> BMI 6$ ; ERROR ABORT THE TRANSFER
> MOVB R4,PK$FLG ; SAVE THE CHAR FOR A FLAG
> CMPB R4,I$EFLG ;FLAG EXPECTED?
> BEQ 2$ ;YES- OK
> CMPB R4,#R$MSG ;MESSAGE PACKET ?
> BNE 6$ ;NO, THEN UNEXPECTED ERROR
> .ADDR #I$MBFR,-(SP) ;MAKE ADDRESS OF MESSAGE BUFFER
> MOV (SP)+,I$MADR ;TO MESSAGE ADDRESS
> 2$: CMPB R4,#R$CONT ;CONTINUE FLAG?
> BEQ PKTRTN ;YES - NO MORE DATA NOW
> BIS #1, at TIVECA ;CS => NO .INTEN
> CALL INPRTN ;WAIT ON A CHAR
> 1$: MOV @TIBFRA,R4 ; SAVE THE CHAR AND THE OVERRUN ERROR
> BMI 8$ ; ERROR ABORT THE TRANSFER
> MOVB R4,PK$MBC ;IT'S THE MESSAGE COUNT
> MOV PK$FLG,PK$CKS ;INITIALIZE THE CHECKSUM
> ADD #4$-1$,I$INTR ;SET UP NEW RETURN
> 3$: RETURN ;RETURN FROM INTERRUPT
>
> 4$: MOV @TIBFRA,R4 ;SAVE THE CHAR AND OVERRUN ERROR
> BMI 8$ ;ERROR ABORT THE TRANSFER
>
> .IF NE MMG$T
> MOV @#KISAR1,-(SP) ;SAVE CURRENT PAR1
> MOV I$PAR,@#KISAR1 ;USE OUR OWN VALUE
> .ENDC ;NE MMG$T
>
> MOVB R4, at I$MADR ;STORE THE DATA IN BUFFER
>
> .IF NE MMG$T
> MOV (SP)+,@#KISAR1 ;RESTORE PREVIOUS PAR1
> .ENDC ;NE MMG$T
>
> INC I$MADR ;NEXT ADDRESS
> BIC #^C<377>,R4 ;INTERESTED ONLY IN BYTE
> ADD PK$CKS,R4 ;ADD IN THE CURRENT CHECKSUM
> ADC R4 ;ADD IN END AROUND CARRY
> SWAB R4 ;SWAP CHECKSUM BYTES FOR NEXT CHAR
> MOV R4,PK$CKS ;SAVE CHECKSUM
> DECB PK$MBC ;ANY MORE BYTES?
> BNE 3$ ;YES, GO GET 'EM
> BIC #1, at TIVECA ;DO .INTEN NEXT INTERRUPT
> ADD #7$-4$,I$INTR ;SET UP NEW RETURN POINT
> RETURN ;GO BACK THE WAY YOU ENTERED INTERRUPT
>
> 7$: MOV @TIBFRA,R4 ; SAVE THE CHAR AND THE OVERRUN ERROR
> BMI 6$ ; ERROR ABORT THE TRANSFER
> MOVB R4,I$TDAT ; GET THE LOW BYTE FIRST
> CALL INPRTN ;HIGH BYTE NEXT
> MOV @TIBFRA,R4 ; SAVE THE CHAR AND THE OVERRUN ERROR
> BMI 6$ ; ERROR ABORT THE TRANSFER
> MOVB R4,I$TDAT+1 ; SAVE IT
> BIC #CS$INT, at TICSRA ;NO MORE INTERRUPTS
> CMP I$TDAT,PK$CKS ;IS IT CORRECT?
> BNE 5$ ;CHECKSUM ERROR
> CMPB PK$FLG,I$EFLG ;FLAG WE EXPECTED?
> BEQ PKTRTN ;YES OK GO TO COMMON RETURN
> JMP ERROR ;NO SIGNAL ERROR
>
> 6$:
> .IF NE ERL$G
> MOV R4,I$LCHR ;STORE THAT LAST CHAR IN ERROR
> .ENDC ;NE ERL$G
>
> 5$: JMP ABORTR ;NOPE- FATAL ERROR
>
> 8$:
> .IF NE ERL$G
> MOV R4,I$LCHR ;SAVE THE CHAR IN ERROR
> .ENDC ;NE ERL$G
>
> ; GET OUT FROM INTERRUPT LEVEL
>
> BIC #1, at TIVECA ;CLEAR CARRY
> .ADDR #ABORTR,-(SP) ;TO ABORT
> MOV (SP)+,I$INTR ;AS RETURN
> RETURN
>
> .SBTTL DATA AREA
>
> ; *ORDER* SOME CODE DEPENDS ON THE CURRENT ORDERING OF THIS DATA
>
> I$ABRT: .WORD 0 ;ZERO FOR ABORT REQUIRED ON STARTUP
> I$ADRS: .WORD 0 ;ADDRESS OF DATA
> I$BYTC: .WORD 0 ;BYTE COUNT FOR DATA
> I$INTR: .WORD 0 ;INPUT INTERRUPT RETURN
> I$ERCT: .WORD 0 ;ERROR RETRY COUNT (COMMUNICATIONS)
> I$MADR: .WORD 0 ;MESSAGE ADDRESS
> I$TDAT: .WORD 0 ;MESSAGE TEMP DATA
> I$SUBR: .WORD 0 ;SUBROUTINE RETURN ADDRESS
>
> .IF NE ERL$G
> I$LCHR: .WORD 0 ;LAST CHARACTER INPUT
> .ENDC ;NE ERL$G
>
> I$EFLG: .WORD 0 ;EXPECTED FLAG BYTE
> I$MBFR: ;*ORDER* MESSAGE PACKET BUFFER
> I$MOPC: .BYTE 0 ;* MESSAGE OPCODE
> I$MSUC: .BYTE 0 ;* SUCCESS CODE FOR END PACKET
> .BYTE 0,0,0,0,0,0,0,0 ;*END* REMAINDER OF PACKET
>
> .IF NE MMG$T
> I$PAR: .WORD 0 ;PAR VALUE TO MAP USER BUFFER
> .ENDC ;NE MMG$T
>
> ; PACKET BUFFER FOR MESSAGE
>
> ; *ORDER*
>
> PK$FLG: .BYTE 0 ;FLAG BYTE
> PK$MBC: .BYTE 0 ;BYTE COUNT FOR PACKET
> PK$OPC: .BYTE 0 ;OPCODE
> PK$MOD: .BYTE 0 ;MODIFIER BYTE
> PK$UNT: .BYTE 0 ;UNIT
> PK$SSQ: .BYTE 0,0,0 ;SWITCH AND SEQUENCE
> PK$BCT: .BYTE 0,0 ;BYTE COUNT FOR DATA
> PK$RCD: .BYTE 0,0 ;RECORD NUMBER OF START
> PK$CKS: .BYTE 0,0 ;CHECKSUM FOR PACKET
>
> ; *END ORDER*
>
> .SBTTL BOOTSTRAP READ ROUTINE
>
> .DRBOT DD,BOOT1,READ
>
> . = DDBOOT+40 ;PUT THE JUMP BOOT INTO SYSCOM AREA
> BOOT1: JMP @#BOOT-DDBOOT ;START THE BOOTSTRAP
>
> . = DDBOOT+210
> READ: MOV #DDCNT,RTRCNT ;INIT THE RETRY COUNT
> MOV @#B$DEVU,DDUNIT ;STORE THE UNIT NUMBER
> ASL R1 ;MAKE BYTE COUNT OF WORD COUNT
> MOV R0,DDBLK ;MOVE IN THE BLOCK (RECORD) NUMBER
> MOV R1,DDBTCT ;MOVE THE BYTE COUNT INTO PACKET
>
> ; INITIALIZE THE TX CONTROLLER IN CASE
>
> BRESTR: MOV R2,-(SP) ;SAVE THE START OF BUFFER ON STACK
> MOV (PC)+,R0 ;GET THE CSR ADDRESS+4
> BOTCSR: .WORD DD$CSR+4 ;PATCH THIS WORD IF CSR CHANGED (SET)
> BIS #CS$BRK, at R0 ;SET BREAK FOR SIGNAL
> MOV (PC)+,R3 ;SEND ONES FOR TIMING
> .WORD 177777
> CALL BCHROS ;OUTPUT THEM
> CONRD1: TSTB @R0 ;READY YET ?
> BPL CONRD1 ;NOT YET
> BIC #CS$BRK, at R0 ;CLEAR THE BREAK
> MOV (PC)+,R3 ;GET TWO INITS
> .BYTE R$INIT,R$INIT ;TWO INITS FOR TX
> CALL BCHROS ;OUTPUT BOTH INITS
> TST -2(R0) ;DUMP OLD CHAR
> CALL BICHR ;GET A CHAR FOR INPUT
> CMPB R3,#R$CONT ;IS IT A CONTINUE?
> BNE BFATAL ;NO
> MOV #B$CHK-DDBOOT,R4 ;POINT TO THE CHECKSUM WORD IN PACKET
> CLR @R4 ;INITIALIZE IT CHECKSUM
> MOV #B$PKT-DDBOOT,R5 ;COMMAND PACKET PATTERN
> 1$: MOV (R5)+,R3 ;GET NEXT TWO BYTES TO OUTPUT
> ADD R3, at R4 ;ADD INTO THE CHECKSUM
> ADC @R4 ;END AROUND
> CALL BCHROS ;OUTPUT THE TWO BYTES
> CMP R5,R4 ;ALL THE PACKET OUT ?
> BLOS 1$ ;NO, KEEP OUTPUTTING
>
> ; PACKET IS OUT, NOW WAIT FOR DATA PACKET FROM TX
>
> BRDPKT: CALL BICHP2 ;READ TWO CHARACTERS
> MOVB R3,R4 ;BYTE COUNT TO R4
> ;NOTE THE C BIT IS ALREADY CLEARED
> RORB R4 ;MAKE IT A WORD COUNT
> MOV R1,-(SP) ;INIT THE CHECKSUM
> CMPB R1,#R$DATA ;DATA PACKET ?
> BNE BEND ;NOPE, END PACKET ?
> 2$: CALL @R5 ;INPUT 2 BYTES
> MOV R1,(R2)+ ;STORE IN THE BUFFER
> ADD R1, at SP ;BUILD THE CHECKSUM
> ADC @SP ;END AROUND CARRY
> DECB R4 ;DONE ?
> BGT 2$ ;IF GT - NO
> CALL (R5) ;GET 2 CHECKSUM BYTES
> CMP R1,(SP)+ ;CHECKSUM OK ?
> BNE BFATAL ;NO
> BR BRDPKT ;YES, CONTINUE
>
> ; IF WE ARE GETTING INIT,INIT,INIT,... ITS OK SINCE THE CODE
> ; WILL WORK AND FAIL TO FIND A GOOD SUCCESS CODE OR CHECKSUM
>
> BEND: CALL (R5) ;TWO CHARS IN
> TSTB R3 ;CHECK SUCCESS CODE
> BMI BOTH ;NO - DO RETRY OR GIVE ERROR
> 1$: ADD R1, at SP ;COMPUTE CHECKSUM
> ADC @SP ;END AROUND
> CALL (R5) ;INPUT CHECKSUM
> SOB R4,1$ ;DONE ?
> CMP R1,(SP)+ ;CHECKSUM OK
> BNE BFATAL ;WE BLEW AN END PACKET!!
> MOV (SP)+,R2 ;RESTORE START OF BUFFER
> CLC ;MAKE SURE C-BIT CLEAR UPON RETURN
> RETURN ;EXIT
>
> BOTH: TST (SP)+ ;DUMP THE CHECKSUM WORD
> BFATAL: MOV (SP)+,R2 ;RESTORE THE BUFFER ADDRESS
> DEC RTRCNT ;ANY RETRIES LEFT ?
> BNE BRESTR ;YES, TRY AGAIN
> BR BIOERR ;HARD ERROR - PRINT MESSAGE
>
> .SBTTL BYTE INPUT ROUTINES (BOOT)
>
> ;+
> ; INPUT BYTE ROUTINES
> ;
> ; BICHP2 - INPUT BYTE IN R1 AND SWAP THE BYTES. CALLS BICHR TWICE
> ;
> ; BICHR - INPUT ONE BYTE IN R1
> ;
> ; R0 -> TRANSMIT CSR
> ; R1 = PARTIAL WORD INPUT, LOW BYTE=0 [BICHR]
> ;
> ; JSR PC,BICHP2/BICHR
> ;
> ; R1 = OLD HIGH BYTE (LOW) / NEW BYTE (HIGH)
> ; R3 = DATA BYTE
> ; R5 = UNDEFINED
> ;-
>
> BICHP2: MOV PC,R5 ;STORE THE ENTRY POINT TO THE
> CLR R1 ; FOLLOWING ROUTINE
> CALL @PC ;ENTRY FOR TWO BYTES WITHOUT STORE
> BICHR: TSTB -4(R0) ;WAIT ON READY
> BPL BICHR ;TIL SET
> MOVB -2(R0),R3 ;GET BYTE
> BISB R3,R1 ;MAKE PARTIAL WORD
> SWAB R1 ;AND SET TO MAKE NEXT PART
> RETURN
>
> .SBTTL BYTE OUTPUT ROUTINES (BOOT)
>
> ;+
> ; OUTPUT BYTE ROUTINES
> ;
> ; BCHROS - OUTPUT 2 BYTES
> ;
> ; R0 -> TRANSMIT CSR
> ; R3 = BYTES TO OUTPUT (LOW BYTE FIRST)
> ;
> ; JSR PC,BCHROS
> ;-
>
> BCHROS: CALL @PC ;OUTPUT LOW BYTE
> 1$: TSTB @R0 ;WAIT TIL DONE
> BPL 1$
> MOVB R3,2(R0) ;AND OUTPUT LOW BYTE
> SWAB R3 ;AND SWAP THE WORD
> RETURN
>
> ; COMMAND PACKET PATTERN:
> ; ***** THIS PACKET MUST REMAIN IN ORDER *****
>
> B$PKT: .BYTE R$MSG,R$MSIZ,R$$RED,0
> DDUNIT: .WORD 0 ;UNIT BOOTED FROM
> .BYTE 0,0
> DDBTCT: .WORD 0 ;BYTE COUNT
> DDBLK: .WORD 0 ;RECORD NUMBER
> B$CHK: .WORD 0 ;CHECKSUM
>
> RTRCNT: .WORD 0 ;RETRY COUNT
>
> . = DDBOOT+606
> BOOT: MOV #10000,SP ;SET STACK POINTER
> MOV R0,@#B$DEVU ;SAVE THE UNIT NUMBER
> MOV R0,-(SP) ;SAVE ON THE STACK TOO
> MOV #2,R0 ;READ IN SECOND PART OF BOOT
> MOV #<4*400>,R1 ;EVERY BLOCK BUT THE ONE WE ARE IN
> MOV #1000,R2 ;INTO LOCATION 1000
> CALL READ ;GO READ IT IN
> MOV #READ-DDBOOT,@#B$READ ;STORE START LOCATION FOR READ ROUTINE
> MOV #B$DNAM,@#B$DEVN ;STORE RAD50 DEVICE NAME
> MOV (SP)+,@#B$DEVU ;STORE THE UNIT NUMBER
> JMP @#B$BOOT ;START SECONDARY BOOT
>
> .DREND DD
>
> .END
> --------------------------------------------------
More information about the cctalk
mailing list