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,@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,@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,@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$,@-(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,@TICSRA ;SET THE INPUT INTERRUPT
        BR      INPRTN          ;GO RETURN

OUTCHR: MOV     R5,@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,@TIVECA      ;CLEAR ANY CARRY BITS SET IN
        BIC     #1,@TOVECA      ;THE INTERRUPT PSW
        .MTPS   #340            ;RAISE PRIORITY TO PREVENT INTERRUPTS
        BIC     #CS$INT,@TICSRA ;NO INPUT INTERRUPTS FOR NOW
        BIS     #CS$INT,@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,@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,@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,@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,@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,@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,@TICSRA ;ZAP INTERRUPT ENABLE
        BIC     #CS$INT,@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,@TOCSRA ;SET UP KNOWN STATE
        BIC     #CS$INT,@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,@TOBFRA ;;;SEND ONES FOR TIMING
        BIS     #<CS$INT!CS$BRK>,@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,@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,@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,@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,@TOBFRA  ;;;OUTPUT FIRST BYTE (FLAG)
        BIS     #CS$INT,@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,@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,@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,@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,@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,@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,@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,@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,@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,@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,@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,@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,@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,@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,@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
--------------------------------------------------


Reply via email to