1
0
mirror of https://github.com/hsoft/collapseos.git synced 2024-11-23 19:48:06 +11:00

fs: add private "blk" routines

This way, we can interact with the mounted FS even when we change the
selected blkdev.
This commit is contained in:
Virgil Dupras 2019-04-23 15:50:26 -04:00
parent 3ba0a707e7
commit f00334ec89
3 changed files with 76 additions and 21 deletions

View File

@ -108,9 +108,11 @@ blkGetCW:
; Reads B chars from blkGetC and copy them in (HL).
; Sets Z if successful, unset Z if there was an error.
blkRead:
ld ix, (BLOCKDEV_GETC)
_blkRead:
push hl
.loop:
call blkGetC
call _blkCall
jr nz, .end ; Z already unset
ld (hl), a
inc hl
@ -129,10 +131,12 @@ blkPutC:
; Writes B chars to blkPutC from (HL).
; Sets Z if successful, unset Z if there was an error.
blkWrite:
ld ix, (BLOCKDEV_PUTC)
_blkWrite:
push hl
.loop:
ld a, (hl)
call blkPutC
call _blkCall
jr nz, .end ; Z already unset
inc hl
djnz .loop
@ -149,6 +153,9 @@ blkWrite:
; 4 : Move to the beginning
; Set position of selected device to the value specified in HL
blkSeek:
ld ix, (BLOCKDEV_SEEK)
ld iy, (BLOCKDEV_TELL)
_blkSeek:
push de
cp BLOCKDEV_SEEK_FORWARD
jr z, .forward
@ -162,7 +169,10 @@ blkSeek:
jr .seek ; for absolute mode, HL is already correct
.forward:
ex hl, de ; DE has our offset
call blkTell ; HL has our curpos
; We want to be able to plug our own TELL function, which is why we
; don't call blkTell directly here.
; Calling TELL
call callIY ; HL has our curpos
add hl, de
jr nc, .seek ; no carry? alright!
; we have carry? out of bounds, set to maximum
@ -176,7 +186,6 @@ blkSeek:
ld hl, 0xffff
.seek:
pop de
ld ix, (BLOCKDEV_SEEK)
jr _blkCall
; Returns the current position of the selected device in HL.

View File

@ -71,6 +71,10 @@ callIX:
jp (ix)
ret
callIY:
jp (iy)
ret
; Ensures that Z is unset (more complicated than it sounds...)
unsetZ:
push bc

View File

@ -95,13 +95,16 @@ FS_ERR_NO_FS .equ 0x5
FS_ERR_NOT_FOUND .equ 0x6
; *** VARIABLES ***
; A copy of BLOCKDEV_SEL when the FS was mounted. 0 if no FS is mounted.
FS_BLKSEL .equ FS_RAMSTART
; A copy of BLOCKDEV routines when the FS was mounted. 0 if no FS is mounted.
FS_GETC .equ FS_RAMSTART
FS_PUTC .equ FS_GETC+2
FS_SEEK .equ FS_PUTC+2
FS_TELL .equ FS_SEEK+2
; Offset at which our FS start on mounted device
FS_START .equ FS_BLKSEL+2
FS_START .equ FS_TELL+2
; Offset at which we are currently pointing to with regards to our routines
; below, which all assume this offset as a context. This offset is not relative
; to FS_START. It can be used directly with blkSeek.
; to FS_START. It can be used directly with fsblkSeek.
FS_PTR .equ FS_START+2
; This variable below contain the metadata of the last block FS_PTR was moved
; to. We read this data in memory to avoid constant seek+read operations.
@ -117,8 +120,8 @@ P_FS_MAGIC:
fsInit:
xor a
ld hl, FS_BLKSEL
ld b, FS_RAMEND-FS_BLKSEL
ld hl, FS_GETC
ld b, FS_RAMEND-FS_GETC
call fill
ret
@ -150,10 +153,10 @@ fsNext:
ld a, BLOCKDEV_SEEK_FORWARD
ld hl, FS_BLOCKSIZE
.loop:
call blkSeek
call fsblkSeek
djnz .loop
; Good, were here. We're going to read meta from our current position.
call blkTell ; --> HL
call fsblkTell ; --> HL
ld (FS_PTR), hl
call fsReadMeta
jr nz, .createChainEnd
@ -178,27 +181,27 @@ fsNext:
ret
; Reads metadata at current FS_PTR and place it in FS_META.
; Returns Z according to whether the blkRead operation succeeded.
; Returns Z according to whether the fsblkRead operation succeeded.
fsReadMeta:
call fsPlace
push bc
push hl
ld b, 0x20
ld hl, FS_META
call blkRead ; Sets Z
call fsblkRead ; Sets Z
pop hl
pop bc
ret
; Writes metadata in FS_META at current FS_PTR.
; Returns Z according to whether the blkWrite operation succeeded.
; Returns Z according to whether the fsblkWrite operation succeeded.
fsWriteMeta:
call fsPlace
push bc
push hl
ld b, 0x20
ld hl, FS_META
call blkWrite ; Sets Z
call fsblkWrite ; Sets Z
pop hl
pop bc
ret
@ -228,7 +231,7 @@ fsPlace:
push hl
xor a
ld hl, (FS_PTR)
call blkSeek
call fsblkSeek
pop hl
pop af
ret
@ -279,7 +282,7 @@ fsAlloc:
ldir
; Good, FS_META ready. Now, let's update FS_PTR because it hasn't been
; changed yet.
call blkTell
call fsblkTell
ld (FS_PTR), hl
; Ok, now we can write our metadata
call fsWriteMeta
@ -311,6 +314,28 @@ fsIsDeleted:
cp 0 ; Z flag is our answer
ret
; *** blkdev methods ***
; When "mounting" a FS, we copy the current blkdev's routine privately so that
; we can still access the FS even if blkdev selection changes. These routines
; below mimic blkdev's methods, but for our private mount.
fsblkRead:
ld ix, (FS_GETC)
jp _blkRead
fsblkWrite:
ld ix, (FS_PUTC)
jp _blkWrite
fsblkSeek:
ld ix, (FS_SEEK)
ld iy, (FS_TELL)
jp _blkSeek
fsblkTell:
ld ix, (FS_TELL)
jp _blkCall
; *** Handling ***
; Open file at current position into handle at (HL)
@ -341,23 +366,40 @@ fsSeek:
; *** SHELL COMMANDS ***
; Mount the fs subsystem upon the currently selected blockdev at current offset.
; Verify is block is valid and error out if its not, mounting nothing.
; Upon mounting, copy currently selected device in FS_BLKSEL.
; Upon mounting, copy currently selected device in FS_GETC/PUTC/SEEK/TELL.
fsOnCmd:
.db "fson", 0, 0, 0
push hl
call blkTell
push de
push bc
; We have to set blkdev routines early before knowing whether the
; mounting succeeds because methods like fsReadMeta uses fsblk* methods.
ld hl, BLOCKDEV_GETC
ld de, FS_GETC
ld bc, 8 ; we have 8 bytes to copy
ldir ; copy!
call fsblkTell
ld (FS_START), hl
ld (FS_PTR), hl
call fsReadMeta
jr nz, .error
call fsIsValid
jr nz, .error
; success
ld (FS_START), hl
xor a
jr .end
.error:
; couldn't mount. Let's reset our variables.
xor a
ld b, 10 ; blkdev routines + FS_START which is just
; after.
ld hl, FS_GETC
call fill
ld a, FS_ERR_NO_FS
.end:
pop bc
pop de
pop hl
ret