 lib environment
 sttl Read Write Routines
 pag
 name rdwr
 global filrd,nulrd,chrrd,clcpos,filwr,chrwr
 global flsha,flshd

*
* All routines in this file deal with reading
* or writing data to and from files.  The routines
* to do file mapping are also in here.
*

 pag

*
* filrd
*
* Read the file associated with the fdn pointed
* at by Y.  If the fdn represents a character type
* device, then call 'chrrd', otherwise, read the
* requested data into memory.
*

filrd pshs y save fdn pointer
 ldd uicnt get byte count for read
 beq filrd9 if 0, exit now
 lda fmode,y get fdn modes
 bita #FSCHR is it character device?
 lbne chrrd do char read if so
filrd2 lbsr clcpos calculate file position
 pshs x,y,u,d save all info about pos
 ldy 8,s point to fdn
 lda fmode,y get fdn modes
 bita #FSBLK is this a block device?
 bne filrd5
 ldd fsize,y get file size
 subd uipos see if byte position
 bmi filr95 requested is beyond the
 bne filrd3 end of the file
 ldd fsize+2,y if not, see if byte count
 subd uipos2 is > bytes left to end
 bcs filr95 of the file
 cmpd 0,s if bytes left < count
 bhs filrd3 then only read in
 std 0,s the number of bytes left
 beq filr95 zero count?
filrd3 ldu 8,s point to fdn
 ldx 2,s get requested block no.
 ldy 4,s
 clr umaprw set for read
 lbsr mapfil find physical block number
 beq nulrd 'eq' if block not found
filrd4 ldd fdevic,u get device no. from fdn
 bra filrd6
filrd5 ldd 2,s compute read-ahead block #
 addd #1
 std unxtbl+1
 lda 5,s
 adca #0
 sta unxtbl
 ldd ffmap,y get block device number
 ldy 4,s set up block number
filrd6 lbsr rabuf read in the block
filrd7 tfr y,x save buffer pointer
 ldu 6,s get buffer offset
 ldd 0,s get byte count
 leas 8,s clean up stack
 pshs y save pointer
 lbsr indata transfer data into memory
 puls y point to buffer
 lbsr freebf free up the buffer
 ldd uiocnt bump block counter
 addd #1
 std uiocnt
 ldd uicnt see if count=0
 beq filrd9 if so, all done!
 lda uerror check for errors
 beq filrd2 if none, go read some more
filrd9 puls y,pc return
filr95 leas 8,s clean up stack
 puls y,pc return


*
* nulrd
*
* Set up a buffer of zeroes for null read.
*

nulrd ldd #NODEV set no device
 lbsr alocbf allocate a buffer
 lbsr clrbfr clear out buffer
 bra filrd7 go finish read


 pag

*
* chrrd
*
* Do a read from the character device represented
* by the fdn pointed at by Y.
*

chrrd ldd ffmap,y get device number from fdn
 pshs d save it
 ldb #DEVSIZ
 mul calc device table entry
 ldx #chrtab
 leax d,x point to entry
 puls d reset device number
 jsr [devrd,x] go do read
 puls y,pc return


*
* clcpos
*
* Calculate position information for reads and
* writes.  Return logical block number in Y.X,
* buffer offset in U, and transfer count in D.
*

clcpos leas -2,s save space on stack
 clra
 ldb uipos get position
 lsrb calc block number by
 pshs d position>>9
 ldd uipos+1 get rest of pos
 rora
 rorb
 pshs d save block no on stack
 ldd uipos2 calculate buffer offset
 anda #1 from low part of uipos
 std 4,s save on stack
 coma calculate tfr count
 comb
 anda #1 actually doing 512-offset
 addd #1
 cmpd uicnt cnt>remaining in buffer?
 bls clcpo4
 ldd uicnt set up count
clcpo4 puls x,y,u,pc return values


 pag

*
* filwr
*
* Write the file associated with the fdn pointed
* at by Y.  If the fdn represents a character
* type device, call 'chrwr', else write the block
* of memory specified out to the file.
*

filwr pshs y save fdn
 ldd uicnt check data count
 lbeq filw95 if zero, exit
 lda fmode,y check fdn mode
 bita #FSCHR is it character device?
 lbne chrwr do character write
filwr2 bsr clcpos calculate file position
 pshs x,y,u,d save data
 ldy 8,s point to fdn
 lda fmode,y get fdn mode
 bita #FSBLK is it block device?
 bne filwr4
 lda #1 set mode to write
 sta umaprw for mapfil
 ldu 8,s get fdn
 ldx 2,s get block number
 ldy 4,s
 lbsr mapfil map block in file
 beq filw97 disk full?
 ldd fdevic,u get device number
 bra filwr5
filwr4 ldd ffmap,y get device number
 ldy 4,s get block number
filwr5 ldu 0,s get data count
 cmpu #512 full buffer?
 beq filwr6
 lbsr rdbuf read in block
 bra filwr7
filwr6 lbsr alocbf alocate a buffer
filwr7 tfr y,x save buffer ptr
 ldu 6,s get buffer offset
 ldd 0,s get count
 leas 8,s clean up stack
 pshs y save buffer
 lbsr otdata output data to buffer
 puls y reset buffer
 ldd uipos2 get file position
 tstb check for full buffer
 bne filw75
 bita #1 check rest
 bne filw75 if not full, do later write
 lbsr wbfnow do no wait write
 bra filwr8
filw75 lbsr wbflat write out the buffer
filwr8 ldy 0,s get fdn pointer
 if 0
 ldd fdevic,y get device #
 bsr prt_dbl print device buffer list
 endif
 ldd fsize,y get file size
 cmpd uipos see if file has grown
 bne filw85
 ldd fsize+2,y
 cmpd uipos2
filw85 bhs filwr9
 lda fmode,y get fdn modes
 bita #FSBLK is it block device
 bne filwr9 if so - no size update
 ldd uipos reset file size
 std fsize,y to current file position
 ldd uipos2
 std fsize+2,y
filwr9 lda fstat,y get fdn status
 ora #FMOD set mod flag
 sta fstat,y save new status
 ldd uiocnt bump io counter
 addd #1
 std uiocnt
 ldd uicnt is count zero?
 beq filw95 exit if so
 tst uerror errors?
 lbeq filwr2 if none, repeat
filw95 puls y,pc return
filw97 leas 8,s reset stack
 lda #EDFUL set full error
 sta uerror
 puls y,pc return

 if 0
prt_dbl pshs d,x,y,u save registers
 tst 0,s negative device #?
 bmi 99f yes - don't try to print anything
 ldx #blktab print device buffer list
 ldb #BLKSIZ
 lda 0,s
 mul
 leax d,x
 ldu blktpt,x device table address
 ldy dtdfl,u first buffer
 ldx #02f
 jsr Pdata
0 pshs y end of list?
 cmpu ,s++
 beq 99f
 ldx #10f
 jsr Pdata
 ldd bfdvn,y
 bsr phex2
 ldx #11f
 jsr Pdata
 lda bfflag,y
 jsr Phex
 ldx #12f
 jsr Pdata
 lda bfblch,y
 jsr Phex
 ldd bfblck,y
 bsr phex2
 ldy bfdfl,y
 bra 0b
99 puls d,x,y,u,pc return
*
phex2 pshs d
 lda 0,s
 jsr Phex
 lda 1,s
 jsr Phex
 puls d,pc
02 fcc $d,'Device Buffer List:',0
10 fcc $d,'  Device = ',0
11 fcc ', Flags = ',0
12 fcc ', Block = ',0
 endif

*
* chrwr
*
* Do a write to the character device represented
* by the fdn pointed at by Y.
*

chrwr ldd ffmap,y get device number
 pshs d save it
 ldb #DEVSIZ get device size
 mul calculate which device
 ldx #chrtab point to char table
 leax d,x point to entry
 puls d get device number
 jsr [devwr,x] go write data
 puls y,pc return


 pag

*
* flsha
*
* Flush all device buffers.
*

flsha ldy #buflst point to buffer list
flsha1 ldy bfffl,y get fwd link
flsha2 cmpy #buflst end of list?
 beq flsha4
 lda bfflag,y get flags
 bita #BFLAT set for later write?
 beq flsha1
 bsr flshx do actual flush
 bra flsha2 repeat
flsha4 rts return

*
* flshd
*
* Flush all buffers associated with the device in D.
*

flshd ldy #buflst point to buffer list
 pshs d save device number
flshd1 ldy bfffl,y get fwd link
flshd2 cmpy #buflst end of list?
 beq flshd4
 ldd bfdvn,y get device number
 cmpd 0,s is it the one?
 bne flshd1
 lda bfflag,y get flags
 bita #BFLAT set for later write?
 beq flshd1
 bsr flshx do actual flush
 bra flshd2 repeat
flshd4 puls d,pc return

*
* flshx
*

flshx lda #BFNOW set for no wait write
 sta bfflag,y set flags
 ldx bfffl,y point to next in list
 pshs x save it
 lbsr eatbuf eat the buffer
 lbsr wrbuf write the buffer
 puls y,pc return
