commit 90d3e182b405dacf60fb0f3b0752f91d13133742
parent 4881e058a9055b48c039522d8b2a8885e8637643
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Wed, 29 Jun 2022 16:26:04 -0400
sys/drive: add "drvseek"
This helper word will allow us to work more effectively on data ranges. For
example, if you want to be able to read 32 bytes at some offset, there's no
straightforward way to reliably do it without this kind of logic: there are
cases where your 32 bytes might cross block boundaries.
Diffstat:
3 files changed, 20 insertions(+), 9 deletions(-)
diff --git a/fs/init.fs b/fs/init.fs
@@ -8,6 +8,7 @@ f<< sys/scratch.fs
f<< sys/drive.fs
f<< drv/ramdrive.fs
fatfs( to ramdrv(
+RAMDRVSECSZ to drvblksz
' ramdrv@ to (drv@)
' ramdrv! to (drv!)
f<< lib/file.fs
diff --git a/fs/sys/drive.fs b/fs/sys/drive.fs
@@ -13,13 +13,15 @@
\ the data held by the storage device to be an array of contiguous blocks of
\ "drvblksz" bytes in size.
-\ The Drive subsystem holds a temporary buffer and manages it. This buffer can
-\ be larger than "drvblksz" to accommodate the possibility of hot-switching
-\ storage drivers, but it *has* to be at least "drvblksz" in bytes.
+\ The Drive subsystem holds a temporary buffer and manages it. This buffer
+\ should be at least twice as large as the largest drvblksz it's ever going to
+\ handle. Being able to hold 2 blocks in memory is necessary for "drvseek".
-$400 const DRVBUFSZ
+$1000 const DRVBUFSZ
create drvbuf( DRVBUFSZ allot
-DRVBUFSZ value drvblksz
+DRVBUFSZ >> value drvblksz
+\ Block number currently in drvbuf(
+-1 value drvcurblk
( blkno buf -- )
alias abort (drv@)
@@ -27,5 +29,14 @@ alias abort (drv@)
( blkno buf -- )
alias abort (drv!)
-: drv@ ( blkno -- ) drvbuf( (drv@) ;
-: drv! ( blkno -- ) drvbuf( (drv!) ;
+: drv@ ( blkno -- ) dup to drvblksz drvbuf( (drv@) ;
+: ?drv@ ( blkno -- ) dup drvblksz = if drop else drv@ then ;
+
+\ Ensure that the block containing offset "off" (in bytes) is loaded and that
+\ there's at least u bytes following that offset that is present in the buffer.
+\ u cannot be larger than drvblksz.
+: drvseek ( off u -- a )
+ dup drvblksz > if abort" can't ensure that many bytes in drv buffer" then
+ swap drvblksz /mod ( u r q ) ?drv@ ( u r )
+ tuck + drvblksz >= if drvcurblk 1+ drvbuf( drvblksz + (drv@) then ( r )
+ drvbuf( + ( a ) ;
diff --git a/fs/tests/sys/drive.fs b/fs/tests/sys/drive.fs
@@ -1,6 +1,5 @@
?f<< tests/harness.fs
testbegin
\ Tests for sys/ramdrive (already loaded in init.fs)
-0 drv@
-drvbuf( $36 + 8 []>str S" FAT16 " #s=
+$36 8 drvseek ( a ) 8 []>str S" FAT16 " #s=
testend