Newer
Older
uBix-Retro / dump / oa-2.0.9 / sysapps / fs / fsibm / buffer.a65
/****************************************************************************
   
    OS/A65 Version 2.1.0
    Multitasking Operating System for 6502 Computers

    Copyright (C) 1989-1998 Andre Fachat 

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

****************************************************************************/

/*
 *
 * FIXME: this is horribly complicated
 *
 * Buffer handling
 * Buffer allocation is done elsewhere
 *
 * Exports:
 *  CLBUF	Write buffer if dirty, set it to 0 and free it
 *  DWBUF	Write buffer=YR back if buffer is dirty (Write Dirty)
 *  IDBUF	Invalidate all buffers with drive=XR, without writing
 *  RDBUF	Read sector ar2(24 bit) on drive `drive` into buffer=YR,
 *    		saving dirty buffer if necessary
 *  W1BUF	Flush buffer=YR to sector ar2, invalidate/free it on write error
 *  WABUF	Write buffer=YR back (Write Always)
 *  W2BUF	Flush buffer=YR back, and set buffer to sector ar2.
 *		Set buffer to dirty (no further disk activity)
 *		(handle FAT blocks as well)
 *  INBUF	Set all buffers to free (Init)
 *  FRBUF	Free buffer=YR (no disk activity)
 *  MDBUF	Set buffer=YR to dirty (no disk activity)
 *
 * Imports (calls):
 *  setpadr	XR=buffer-# => AC/XR=buffer address
 *  drive	current drive ...
 *  dzei	... and current Drive Parameter Block (DPB) address 
 *  RWSEC	Drive routine for reading/writing blocks
 *  ar1
 *  div
 *
 */

          .(
	.data
p         .byt 0

abspar    .dsb ABS_SLEN

rwpar     .dsb RW_SLEN

#if B_SLEN=8		/* to much code depends on that */
bpb       .dsb B_SLEN*ANZBUF
#endif

	.zero
bzei      .word 0
	.text

&CLBUF    .(
          sty p
          jsr DWBUF
          bcc clr
          cmp #E_NOTIMP
          beq clr
          sec
          rts
clr       lda p
          asl
          asl
          asl
          tay
          lda #BD_FRE
          sta bpb+B_DIRT,y          
          ldx p
          jsr setpadr
          sta bzei
          stx bzei+1
          lda #0
          tay
          ldx #BUFLEN/256
ccl       sta (bzei),y
          iny
          bne ccl
          inc bzei+1
          dex
          bne ccl
          ldx p
          jsr setpadr
          clc
          rts
          .)

&IDBUF    .(        ; free't alle Puffer mit Drive = xr
	.data
errfl     .byt 0
	.text

          ldy #0
          sty errfl
idl       sty p
          tya
          asl
          asl
          asl
          tay
          txa
          cmp bpb+B_DRV,y
          bne next
          lda bpb+B_DIRT,y
          bmi next
          beq fre
          inc errfl
          lda #BD_IFRE
          .byt $2c
fre       lda #BD_FRE
          sta bpb+B_DIRT,y
next      ldy p
          iny
          cpy #ANZBUF
          bcc idl
          lda errfl
          bne err
          lda #E_OK
          .byt $2c
err       lda #E_FINTERNAL
          cmp #1
          rts
          .)
          
&RDBUF    .(
          sty p
          cpy #ANZBUF
          bcc l1
lserr     
#ifdef DEBUGFS
lda #"x":jsr SEROUT
#endif
	  lda #E_ILLPAR
          sec
          rts
l1        lda ar2
	  sta abspar+ABS_SEC
	  lda ar2+1
          sta abspar+ABS_SEC+1
	  lda ar2+2
          sta abspar+ABS_SEC+2
	  lda ar2+3
          sta abspar+ABS_SEC+3

#if 0 /*def DEBUGFS*/
.(
lda #"r"
jsr SEROUT
lda abspar+ABS_SEC+1
jsr HEXOUT
lda abspar+ABS_SEC
jsr HEXOUT
.)
#endif
          lda drive
          sta abspar+ABS_DRV
          tya
          asl
          asl
          asl
          tay
          lda bpb+B_DIRT,y
          bmi lsx             ; falls frei sofort laden

          lda abspar+ABS_SEC
          cmp bpb+B_SECTOR,y
          bne lsx1
          lda abspar+ABS_SEC+1
          cmp bpb+B_SECTOR+1,y
          bne lsx1
	  lda abspar+ABS_SEC+2
	  cmp bpb+B_SECTOR+2,y
	  bne lsx1
	  lda abspar+ABS_SEC+3
	  cmp bpb+B_SECTOR+3,y
	  bne lsx1
          lda abspar+ABS_DRV
          cmp bpb+B_DRV,y
          beq lsend           ; falls alles gleich ende
          
lsx1      lda bpb+B_DIRT,y
          beq lsx             ; falls nicht dirty laden
          ldy p
          jsr DWBUF           ; sonst Puffer speichern
          bcs lerr 
          lda p
          asl
          asl
          asl
          tay
          
lsx       lda #BD_FRE
          sta bpb+B_DIRT,y
          lda abspar+ABS_DRV
          sta bpb+B_DRV,y
          sta rwpar+RW_DRV
          lda abspar+ABS_SEC+3
          sta bpb+B_SECTOR+3,y
	  sta rwpar+RW_SECTOR+3
          lda abspar+ABS_SEC+2
          sta bpb+B_SECTOR+2,y
	  sta rwpar+RW_SECTOR+2
          lda abspar+ABS_SEC+1
          sta bpb+B_SECTOR+1,y
	  sta rwpar+RW_SECTOR+1
          lda abspar+ABS_SEC
          sta bpb+B_SECTOR,y
	  sta rwpar+RW_SECTOR
          ;jsr sec2rw
          ;bcs lserr
          ldx p
          jsr setpadr
          sta rwpar+RW_ADR
          stx rwpar+RW_ADR+1
          lda #<rwpar
          ldy #>rwpar
          clc                 ; load
          jsr RWSEC
          bcs lerr
          lda p
          asl
          asl
          asl
          tay
          lda #BD_OK
          sta bpb+B_DIRT,y
          lda #E_OK
lsend     clc
lerr      rts
          .)
          
&W1BUF    .(
          sty p
          cpy #ANZBUF
          bcc l1
lserr     lda #E_ILLPAR
          sec
          rts
l1        
          tya
          asl
          asl
          asl
          tay
          lda #BD_FRE
          sta bpb+B_DIRT,y
          lda drive
          sta bpb+B_DRV,y
          sta rwpar+RW_DRV
	  lda ar2
          sta bpb+B_SECTOR,y
	  sta rwpar+RW_SECTOR
	  lda ar2+1
          sta bpb+B_SECTOR+1,y
	  sta rwpar+RW_SECTOR+1
	  lda ar2+2
          sta bpb+B_SECTOR+2,y
	  sta rwpar+RW_SECTOR+2
	  lda ar2+3
          sta bpb+B_SECTOR+3,y
	  sta rwpar+RW_SECTOR+3
          ;jsr sec2rw
          ;bcs lserr
          ldx p
          jsr setpadr
          sta rwpar+RW_ADR
          stx rwpar+RW_ADR+1
          lda #<rwpar
          ldy #>rwpar
          sec            ; write
          jsr RWSEC
          bcs lerr
          lda p
          asl
          asl
          asl
          tay
          lda #BD_OK
          sta bpb+B_DIRT,y
          lda #E_OK
          clc
lerr      rts
          .)

&WABUF    .(
	.data
sector    .word 0,0
xfl       .byt 0
	.text

          ldx #0
          sty p                    ; write always (auch falls nur valid)
          cpy #ANZBUF
          bcs serr2x
          tya
          asl
          asl
          asl
          tay
          lda bpb+B_DIRT,y
          bmi serr1x                ; falls nicht belegt dann ende
          jmp l1
          
&&DWBUF   ldx #0
          .byt $2c
&DxBUF    ldx #1
          sty p
          cpy #ANZBUF
          bcs serr2x
          tya
          asl
          asl
          asl
          tay
          lda bpb+B_DIRT,y         ; falls frei dann fehler
serr1x    bpl xx
          jmp serr1
xx        bne l1
	  jmp serr0                ; falls valid dann nicht schreiben
          
l1        stx xfl
          lda #BD_FRE
          sta bpb+B_DIRT,y
          lda bpb+B_DRV,y          ; hier ist dirty
          sta rwpar+RW_DRV
          ldx p
          jsr setpadr
          sta rwpar+RW_ADR
          stx rwpar+RW_ADR+1
          lda bpb+B_SECTOR,y
	  sta sector
          lda bpb+B_SECTOR+1,y
	  sta sector+1
          lda bpb+B_SECTOR+2,y
	  sta sector+2
          lda bpb+B_SECTOR+3,y
	  sta sector+3
wrloop    lda sector
	  sta rwpar+RW_SECTOR
	  lda sector+1
	  sta rwpar+RW_SECTOR+1
	  lda sector+2
	  sta rwpar+RW_SECTOR+2
	  lda sector+3
	  sta rwpar+RW_SECTOR+3
	  ; sta sector
          ; stx sector+1
          ;jsr sec2rw
	  clc
serr2x    bcs serr2
          sec
          lda #<rwpar
          ldy #>rwpar
          jsr RWSEC
          bcs serr
          
          lda sector
          ora sector+1
	  ora sector+2
	  ora sector+3
          beq wre
          lda xfl
          bne wre
          
          ldy #D_SPF          ; zu Sektor Sekt/FAT addieren 
          lda (dzei),y
          clc
          adc sector
          sta sector
          iny
          lda (dzei),y
          adc sector+1
          sta sector+1
          tax
	  bcc foo1
	  inc sector+2
	  bne foo1
	  inc sector+3
foo1
	  lda sector+2	      ; compare sector with start of main dir
	  ora sector+3	      ; if less, write again.
	  bne wre

	  lda sector+1
          ldy #D_STD+1        ; mit Start Main-Dir vergleichen
          cmp (dzei),y        ; gr��er dann ende
          bcc wrl
          bne wre
          dey
          lda sector
          cmp (dzei),y
          bcs wre
wrl    
          jmp wrloop          ; sonst nochmal schreiben 
          
wre       lda p
          asl
          asl
          asl
          tay
          lda #BD_OK
          sta bpb+B_DIRT,y
serr0     lda #E_OK
          clc
          rts
serr1     lda #E_NOTIMP
          .byt $2c
serr2     lda #E_ILLPAR
serr      sec
          rts
          .)

&W2BUF    .(
          sty p
	  lda ar2
          sta abspar+ABS_SEC
	  lda ar2+1
	  sta abspar+ABS_SEC+1
	  lda ar2+2
	  sta abspar+ABS_SEC+2
	  lda ar2+3
	  sta abspar+ABS_SEC+3
          cpy #ANZBUF
          bcs werr
          tya
          asl
          asl
          asl
          tay
          lda bpb+B_DIRT,y
          bmi w2              ; Daten ung�ltig
          beq w2              ; Daten nicht dirty
          ldy p
          jsr DxBUF        
          bcs err
         
w2        lda p
          asl
          asl
          asl
          tay
          lda drive
          sta bpb+B_DRV,y
          lda abspar+ABS_SEC+3 
          sta bpb+B_SECTOR+3,y
          lda abspar+ABS_SEC+2 
          sta bpb+B_SECTOR+2,y
          lda abspar+ABS_SEC+1 
          sta bpb+B_SECTOR+1,y
          lda abspar+ABS_SEC
          sta bpb+B_SECTOR,y
          lda #BD_DIRTY  ;lda #BD_OK
          sta bpb+B_DIRT,y
          clc
err       rts
werr      lda #E_ILLPAR
          sec
          rts
          .)
         
&INBUF    .(
          ldy #0
inl       sty p
          jsr FRBUF
          ldy p
          iny
          cpy #ANZBUF
          bcc inl
          clc
          rts
          .)
                    
&FRBUF    ldx #BD_FRE
          .byt $2c
&MDBUF    ldx #BD_DIRTY
          .(
          cpy #ANZBUF
          bcs cerr
          tya
          asl
          asl
          asl
          tay
          txa
          sta bpb+B_DIRT,y
          rts
cerr      lda #E_ILLPAR
          sec
          rts
          .)
/*
sec2rw	.(
	sta rwpar+RW_TRCK
	stx rwpar+RW_TRCK+1
	clc
	rts
	.)
*/
          .)