        SUBT    > <wini>arm.FileSwitch.OSArgs

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; +                                                                           +
; +                           A R G S   S W I                                 +
; +                                                                           +
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; ArgsEntry. Vectored SWI level entry
; =========
;
; Special and normal OS_Args entry point

; In:  r0 = &00, r1b =      &00: Read FS number to r0
;                      &01..&FF: Read PTR of file to r2

;      r0 = &01, r1b =      &00: Read command tail; not done - use OS_GetEnv
;                      &01..&FF: Set PTR of file from r2
;                                  r2 preserved

;      r0 = &02, r1b =      &00: Read NFS version number; not done
;                      &01..&FF: Read extent of file to r2

;      r0 = &03, r1b = &01..&FF: Set extent of file from r2 (r1b = 0 invalid)
;                                  r2 preserved

;      r0 = &04, r1b = &01..&FF: Read size of file to r2    (r1b = 0 invalid)

;      r0 = &05, r1b = &01..&FF: Check EOF on file          (r1b = 0 invalid)
;                                  r2 = 0 -> ~EOF, r2 = -1 -> EOF

;      r0 = &06, r1b = &01..&FF: Ensure file size from r2   (r1b = 0 invalid)
;                                  r2 := new allocated size (>= r2in)

;      r0 = &FE, r1b = &01..&FF: Read info on file to r0,r2 (r1b = 0 invalid)
;                                  r0 := scb status, r2 := fscb info

;      r0 = &FF, r1b =      &00: Flush all files on temp fs call
;                      &01..&FF: Flush file call

ArgsEntry ROUT

 [ debugosargs
 DREG r0,"OS_Args ",cc
 DREG r1,", handle/parm ",cc
 DREG r2,", data "
 ]
        AND     r14, r0, #&FF           ; r0b = &FF -> Flushing op
        TEQ     r14, #&FF
        BEQ     FlushingArgsEntry

        TST     r1, #&FF                ; Is it ReadFS number (r0b=0, r1b=0) ?
        TEQEQ   r14, #&00
        BEQ     ReadFSArgsEntry

; .............................................................................
; Bash the given file

; In    r0  = OS_Args action
;       r1b = FileSwitch handle
;       r2  = data

; Out   VC: ok, r0 updated / preserved according to r0in
;               r1 preserved
;               r2 updated / preserved according to r0in
;       VS: fail, handle appended to error

FileArgsEntry NewSwiEntry "r0-r1, scb, $streaminfo"

        AND     r1, r1, #&FF            ; r1b is file handle
        ADR     r14, streamtable
        LDR     scb, [r14, r1, LSL #2]  ; Get scb^

        ReadStreamInfo

10 ; Reentry point for below

        TEQ     r0, #OSArgs_ReadInfo    ; Common to buffered/unbuffered files
        BEQ     %FT27                   ; >>>a186<<< harder than I thought

        CMP     r0, #OSArgs_EnsureSize  ; Largest low one we know about
        BHI     %FA99                   ; [duff rc]

        TEQ     r0, #OSArgs_SetPTR      ; Reset EOF state if writing these
        TEQNE   r0, #OSArgs_SetEXT
        BICEQ   status, status, #scb_EOF_pending

        TST     status, #scb_unbuffered :OR: scb_directory :OR: scb_unallocated
        TSTEQ   status, #scb_datalost :OR: scb_critical
        BNE     %FT80                   ; [strange bits set]

; *************************** Buffered stream *********************************

        TEQ     r0, #OSArgs_ReadPTR     ; Read PTR of buffered file
        MOVEQ   r2, fileptr
        BEQ     %FA25 ; SwiExit

        TEQ     r0, #OSArgs_ReadEXT     ; Read EXT of buffered file
        MOVEQ   r2, extent
        BEQ     %FA25 ; SwiExit

        TEQ     r0, #OSArgs_ReadSize    ; Read allocated size of buffered file
        LDREQ   r2, scb_allocsize
        BEQ     %FA25 ; SwiExit

        TEQ     r0, #OSArgs_EOFCheck    ; Check EOF on buffered file
        BNE     %FT30
        TEQ     fileptr, extent
        MOV     r2, #0                  ;  0 -> ~EOF
        MOVEQ   r2, #-1                 ; -1 -> EOF

 [ :LNOT: appendhandle
95
 ]

25
 [ debugosargs
 DREG r2,"OS_Args returns "
 ]
        SwiExit


27      STR     status, [fp, #4*0]      ; Resultis r0 and r2
        TST     status, #scb_unallocated ; >>>a186<<< stop causing exceptions
        MOVNE   r2, #0
        LDREQ   r14, scb_fscb
        LDREQ   r2, [r14, #fscb_info]
        B       %BA25 ; SwiExit



30 ; Write fileptr of buffered file ?

        CMP     r0, #OSArgs_SetPTR
        BNE     %FT60

 [ debugosargs
 DREG r2,"Setting PTR to "
 ]
        EOR     r14, r2, extent         ; Moving PTR to same buffer as EOF ?
        BICS    r14, r14, bufmask
        BLEQ    InvalidateBGetCache     ; Ensures we don't read off EOF

        CMP     r2, extent              ; Trying to move off EOF ?
        MOVLS   fileptr, r2             ; Merely update fileptr, status
        BLS     %FT50

        TST     status, #scb_write      ; Can we write to the file ?
        BEQ     %FA98                   ; 'Outside file' if not

        BL      ExtendFileWithZeroes    ; No longer updates extent as well
        MOVVC   extent, r2
        MOVVC   fileptr, extent


50      STMVCIA scb, {status, fileptr, extent} ; Update info exit
 assert :INDEX: scb_status = 0


 [ appendhandle
95      BLVS    AppendHandleToError     ; For all errors in OSArgs
 ]
        B       %BA25 ; SwiExit


60 ; Write extent of buffered file ?

        TEQ     r0, #OSArgs_SetEXT
        BNE     %FT70

        TST     status, #scb_write      ; Can't write if no permission
        BEQ     %FT96                   ; Even if doing EXT#h = EXT#h

        BL      InvalidateBGetCache     ; May be shrinking file so PTR in the
                                        ; same buffer as EOF

        CMP     r2, extent
        BLO     %FT65                   ; [shrinking file]

        BLNE    ExtendFileWithZeroes    ; [growing file, or staying same]
        MOVVC   extent, r2
        B       %BA50                   ; Update info exit


65      CMP     r2, fileptr             ; Dragging eof over old fileptr ?
        MOVLO   fileptr, r2             ; fileptr := extent if so

        MOV     r0, extent              ; Start point in file
        MOV     r1, #&FFFFFFFF          ; End point in file
        BL      DiscardBuffersBetween   ; Discard all info fully spanned by
        MOVVC   extent, r2              ; old extent and something big
        B       %BA50                   ; Update info exit



70 ; Ensure file space allocation ok ?

        TEQ     r0, #OSArgs_EnsureSize
        BNE     %FA99

        BL      EnsureFileSize
        B       %BA25 ; SwiExit



80 ; Complicated OSArgs - some flags set

        TST     status, #scb_unallocated        ; Not a stream ?
        BNE     %FT92

        TST     status, #scb_critical           ; Return - done nothing to file
        EXIT    NE

        TST     status, #scb_datalost           ; Can't do anything to the dead
        BNE     %FT93

        TST     status, #scb_directory          ; Can't do anything to a dir.
        BNE     %FT94

; *************************** Unbuffered stream *******************************

        TEQ     r0, #OSArgs_EnsureSize  ; Convert to low level op
        MOVEQ   r0, #fsargs_EnsureSize

        Push    r2                      ; Preserve r2 for some ops
        BL      CallFSArgs
        Pull    r14
        BVS     %BT95

        TEQ     r0, #OSArgs_SetPTR      ; Only these two ops preserve r2
        TEQNE   r0, #OSArgs_SetEXT
        MOVEQ   r2, r14                 ; Preserve r2 if not result from call
        STREQ   status, scb_status      ; Only thing that needs updating
                                        ; as we don't keep local fileptr,extent
 [ debugosargs
 DREG r2,"OS_Args (ub) returns "
 ]
        B       %BA25 ; SwiExit


92      BL      SetErrorChannel
        B       %BT95

93      BL      SetErrorDataLost
        B       %BT95

94      BL      SetErrorStreamIsDirectory
        B       %BT95

96      BL      SetErrorNotOpenForUpdate
        B       %BT95

98      addr    r0, ErrorBlock_OutsideFile
        BL      CopyError
        B       %BT95


; Unknown rc for OS_Args

99      CMP     r0, #&FF                ; Silly bits set ?
        ANDHI   r0, r0, #&FF            ; r0b is reason code
        BHI     %BT10                   ; Reenter

        addr    r14, ErrorBlock_BadOSArgsReason
        B       %BA9999 ; SwiExit with r14 -> error

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; ReadFSArgsEntry
; ===============
;
; Entry for the wally part of OS_Args (r0b=0, r1b=0)

; Return Filing System number that is being used at the moment; ie. tempfs

; Out   r0 = temp fs number

ReadFSArgsEntry ROUT ; NB. No local frame, just dealing with global state

        LDR     r0, tempfs              ; Where we think we're at, man ...
        CMP     r0, #Nowt
        MOVEQ   r0, #0
        LDRNEB  r0, [r0, #fscb_info]    ; Just the filing system number
 [ debugosargs
 DREG r0,"OS_Args (ReadFS) returns "
 ]
        Pull    pc,,^                   ; Claim vector. Assumes VClear in lr

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; FlushingArgsEntry
; =================
;
; Flush file(s) on the current Filing System to media

; In    r0b = &FF
;       r1b =            0 : Flush all files on the temp Filing System
;             1..MaxHandle : Flush file of given handle

; Out   VC: ok, all regs preserved
;       VS: fail

FlushingArgsEntry NewSwiEntry "r0-r1, scb, fscb, $streaminfo"

        ANDS    r1, r1, #&FF            ; r1b is handle
        BEQ     %FT30

; Flush a single file. Allow flushing of directories to not yield errors

        BL      FindValidStream
        BVS     %FT15

        ReadStreamInfo
        BL      FlushStream
15
 [ appendhandle
        BLVS    AppendHandleToError
 ]

20      SwiExit



30 ; Flush all files on temp Filing System. NB. There is no 'flush everywhere'

        LDR     fscb, tempfs
        MOV     r1, #MaxHandle          ; Loop over handles in stream table

50      BL      FindStream              ; Get scb^ for this handle, VClear
        BEQ     %FT90

        LDR     r14, scb_fscb           ; Is handle on this Filing System ?
        TEQ     r14, fscb
        BNE     %FT90

        ReadStreamInfo
        BL      FlushStream
 [ appendhandle
        BLVS    AppendHandleToError     ; globalerror picked up at SwiExit
 ]

90      SUBS    r1, r1, #1              ; Last valid handle = 1
        BNE     %BT50                   ; VClear from SUBS

        B       %BA20 ; SwiExit

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

        LTORG

        LNK     $fileprefix.LowLevel
