; > DiscBash2   Reads/writes a sector using the RXV11 or F311-L11 controller, 
;               to/from an address given by the user from the console.
;
;               Prompts user for track/sector (IN DECIMAL), address required (IN OCTAL).
;
        ORG     1024            ; Octal 2000
;
        BR      START
STOP:   HALT
START:  MOV     #1024,R6        ; initialise stack
MLOOP:  NOP                     ; patch space
        NOP
        NOP
        JSR     R7,@#CRLF
        JSR     R7,@#CRLF
        JSR     R5,@#MSSG
        DEFS    "  (Decimal) Track ?"
        DEFB    &A0
        ALIGN
        JSR     R7,@#GETV
        MOV     R5,R0           ; R0=track
        JSR     R5,@#MSSG
        DEFS    " (Decimal) Sector ?"
        DEFB    &A0
        ALIGN
        JSR     R7,@#GETV
        MOV     R5,R1           ; R1=sector
        JSR     R5,@#MSSG
        DEFS    "  (Octal) Address ?"
        DEFB    &A0
        ALIGN
        JSR     R7,@#GETO
        MOV     R5,R2           ; R2=address
COMMND: JSR     R5,@#MSSG
        DEFS    "R(ead) or W(rite) ?"
        DEFB    &A0
        ALIGN
        JSR     R7,@#GETA
        CMPB    R5,#33
        BLO     STOP            ; any CTRL-char ends program
        BIC     #&FFA0,R5       ; ensure upper case
        JSR     R7,@#PRTA
        MOV     #7,R3           ; make for read
        CMP     R5,#ASC"R"
        BEQ     DISCOP
        MOV     #5,R3           ; nope, maybe write
        CMP     R5,#ASC"W"
        BNE     COMMND
WRITE:  MOV     #1,@#O177170    ; load FILL BUFFER command and GO bit
WRLOOP: TSTB    @#O177170       ; look for DONE bit (O40) or TR bit (O200)
        BEQ     WRLOOP          ; if it was TST not TSTB you'd be checking for error
        BPL     DISCOP
WRTBYT: MOVB    (R2)+,@#O177172 ; put a byte
        BR      WRLOOP
DISCOP: MOV     R3,@#O177170    ; load READ/WRITE SECTOR command and GO bit
        JSR     R7,@#TREQ
        MOV     R1,@#O177172    ; load sector number
        JSR     R7,@#TREQ
        MOV     R0,@#O177172    ; load track number
        JSR     R7,@#DONE
        CMP     #7,R3           ; check command
        BNE     MLOOP           ; if not reading, we just finished the task
READ:   MOV     #3,@#O177170    ; load EMPTY BUFFER command and GO bit
RDLOOP: TSTB    @#O177170       ; look for DONE bit (O40) or TReq bit (O200)
        BEQ     RDLOOP
        BPL     MLOOP           ; finished if DONE set
RDBYTE: NOP                     ; a small delay, necessary on LSI-11/23 for F311 to catch up
        MOVB    @#O177172,(R2)+ ; get a byte
        BR      RDLOOP
;
;
DONE:   BIT     #O40,@#O177170  ; look for DONE bit
        BEQ     DONE
        RTS     R7
;
TREQ:   BIT     #O200,@#O177170 ; look for TRANSFER REQUEST bit
        BEQ     TREQ
        RTS     R7
;
; > Print_Lib   Library of console print subroutines
;
;               Includes PRTH - prints R5 (16 bits) in hex
;                        PRTO - prints R5 (16 bits) in octal
;                        PRTA - prints R5 (8 bits) in ASCII
;                        MSSG - prints the string following the JSR
;                               (terminate with top-bit-set character/byte)
;                        CRLF - prints carriage-return/linefeed
;
;       All subroutines link with R7 except MSSG (link with R5)
;
;
CRLF:   MOV     #13,R5          ; print <CR> and <LF> on console
        JSR     R7,@#PRTA
        MOV     #10,R5
        JSR     R7,@#PRTA
        RTS     R7
;
PRTH:   MOV     R5,-(R6)        ; print R5 in hex
        ASR     R5
        ASR     R5
        ASR     R5
        ASR     R5
        JSR     R7,@#HEX1
        MOV     (R6)+,R5
        BIC     #&F0,R5
HEX1:   BIS     #ASC"0",R5      ; make hex into ASCII and print it
        CMPB    #ASC"9",R5
        BPL     PRTA
        ADD     #7,R5
;
PRTA:   TSTB    @#O177564       ; wait for console XBUFF to be ready
        BPL     PRTA
        MOV     R5,@#O177566
        RTS     R7
;
PRTO:   MOV     R0,-(R6)        ; save R0,R4 on stack
        MOV     R4,-(R6)
        MOV     R5,R4
        MOV     #O30,R5         ; R4 will be 6x after shifts
        ROL     R4              ; rotate 1 bit from R4 to R5
        ROL     R5
        JSR     R7,@#PRTA       ; print - as ASCII since it's 6x
        MOV     #5,R0           ; set to do five octets
CLOOP:  MOV     #6,R5           ; 6>>3 becomes octal 60, ie "0"
        ROL     R4              ; rotate R4>R5: 3 bits of octal number
        ROL     R5              ; could use ASHC R4,#3 if we have EIS
        ROL     R4
        ROL     R5
        ROL     R4
        ROL     R5
        JSR     R7,@#PRTA       ; print a digit
        DEC     R0              ; one less digit to do
        BNE     CLOOP
        MOV     (R6)+,R4        ; restore caller's R4,R0
        MOV     (R6)+,R0
        RTS     R7
;
MSSG:   TSTB    @#O177564       ; prints message at word following call
        BPL     MSSG
        MOVB    (R5),@#O177566  ; print char just past where we were
        TSTB    (R5)+           ; see if it was last, and point to next
        BPL     MSSG            ; top bit set = finished
        INC     R5              ; in case it's not on a word boundary
        BIC     #1,R5           ; in case it was
        RTS     R5
;
; > Input_Lib   Library of subroutines to call console for input.
;
;               Includes GETA - gets a single ASCII character in R5
;                        GETV - gets a 16-bit decimal value in R5.
;                        GETO - gets a 16-bit octal value in R5
;                        GETH - gets a 16-bit hex value in R5
;                        GETS - gets a string to the buffer located by R5
;                               Size of buffer must be in R4.
;
;   All routines linked to by R7.
;
GETA:   TSTB    @#O177560       ; wait for character
        BPL     GETA
        MOV     @#O177562,R5
        RTS     R7
;
GETV:   CLR     -(R6)           ; clear a word on the stack
GETV1:  JSR     R7,@#GETA       ; get a character
        CMP     #33,R5
        BMI     DECIN           ; terminate on any control char or space
        JSR     R7,@#CRLF       ; ***** remove if not required *****
        MOV     (R6)+,R5
        RTS     R7
DECIN:  CMP     R5,#ASC"0"      ; check character>="0"
        BMI     GETV1
        CMP     #ASC"9",R5      ; check character<="9"
        BMI     GETV1
        JSR     R7,@#PRTA       ; ***** remove if not required *****
        BIC     #ASC"0",R5      ; ascii-to-decimal
        ASL     (R6)            ; times 2
        ADD     (R6),R5         ; add to the new value
        ASL     (R6)            ; times 4
        ASL     (R6)            ; times 8
        ADD     R5,(R6)         ; times 10, plus new value
        BR      GETV1
;
GETO:   CLR     -(R6)           ; stack space for value
GETO1:  JSR     R7,@#GETA
        CMP     #33,R5          ; terminate on any control char or space
        BMI     OCTIN
        JSR     R7,@#CRLF       ; ***** remove if not required *****
        MOV     (R6)+,R5
        RTS     R7
OCTIN:  CMP     R5,#ASC"0"      ; if not CR, test for numeric
        BMI     GETO1
        CMP     R5,#ASC"8"
        BPL     GETO1
        JSR     R7,@#PRTA       ; ***** remove if not required *****
        BIC     #&F8,R5         ; mask off to make octal
        ASL     (R6)            ; move one octet
        ASL     (R6)
        ASL     (R6)
        ADD     R5,(R6)         ; add this octet
        BR      GETO1
;
GETH:   CLR     -(R6)           ; clear a word on the stack
GETH1:  JSR     R7,@#GETA
        CMP     #33,R5          ; terminate on any control char or space
        BMI     HEXIN
        JSR     R7,@#CRLF       ; ***** remove if not required *****
        MOV     (R6)+,R5
        RTS     R7
HEXIN:  CMP     R5,#ASC"0"
        BMI     GETH1
        CMP     #ASC"F",R5
        BMI     GETH1
        CMP     #ASC"9",R5
        BPL     OKVAL
        CMP     R5,#ASC"A"
        BMI     GETH1
OKVAL:  JSR     R7,@#PRTA       ; ***** remove if not required *****
        CMP     #ASC"9",R5
        BPL     $+6
        SUB     #ASC"A"-ASC"9",R5
        BIC     #ASC"0",R5
        ASL     (R6)
        ASL     (R6)
        ASL     (R6)
        ASL     (R6)
        ADD     R5,(R6)
        BR      GETH1
;
