commit 2ccd6bf24511e13887e3fd70a6811ae65c09c126
parent 79f180c3e50925f3cf8dcb2c335ca01e7622c0a9
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Sat, 20 Aug 2022 07:18:08 -0400
drv/pc/ata: implement ata!
Also, add FAT :remove.
Diffstat:
4 files changed, 23 insertions(+), 15 deletions(-)
diff --git a/fs/drv/pc/ata.fs b/fs/drv/pc/ata.fs
@@ -44,9 +44,12 @@ $ec const IDENTIFY
: ata@ ( sec dst drv -- )
drop swap _locate $20 ( read sectors ) _cmd pc! _wait ( dst )
- A>r ( dst ) >A $100 >r begin _data pw@ A> w! A+ A+ next r>A ;
+ A>r >A $100 >r begin _data pw@ A> w! A+ A+ next r>A ;
-: ata! abort" ATA driver doesn't support writing" ;
+: ata! ( sec src drv -- )
+ drop swap _locate $30 ( write sectors ) _cmd pc! _wait ( src )
+ A>r >A $100 >r begin A> w@ _data pw! A+ A+ next r>A
+ $e7 ( flush cache ) _cmd pc! _wait ;
: .ata ( -- ) atabus . ':' emit atadrive . spc> ataidentify .x1 ;
: .ataall ( -- )
diff --git a/fs/fs/fat.fs b/fs/fs/fat.fs
@@ -18,7 +18,6 @@
\ File and directory IDs in FAT are the offset, on disk, of their corresponding
\ DirEntry.
-\ TODO: in my big FAT refactoring, I broke this section. Fix it.
?f<< /fs/fatlo.fs
?f<< /lib/str.fs
@@ -60,8 +59,8 @@ $ffff const EOC
r@ FATLO :)buf 1+ c@ r@ FATLO :buf( c!
r@ FATLO bufsec 1+ r@ FATLO :drv :sec! then rdrop ;
: FAT16! ( entry cluster self -- ) FATLO :FAT16' w! ;
-: FAT! ( entry cluster self -- )
- dup FATLO :FAT12? if dup FAT12! else dup FAT16! then writecursector ;
+: FAT! ( entry cluster self -- ) >r
+ r@ FATLO :FAT12? if r@ FAT12! else r@ FAT16! then r> writecursector ;
: zerocluster ( cluster self -- )
dup FATLO :buf( over FATLO secsz 0 fill ( cluster self )
@@ -73,6 +72,9 @@ $ffff const EOC
: findfreecluster ( self -- cluster )
1 begin ( self cl ) 1+ 2dup swap FATLO :FAT@ not until ( self cl ) nip ;
+: allocatecluster ( self -- cluster )
+ dup findfreecluster ( self cl ) tuck EOC swap rot FAT! ( cl ) ;
+
\ Get next FAT entry and if it's EOC, allocate a new one
: FAT@+ ( cluster self -- entry ) >r
dup r@ FATLO :FAT@ ( cl ncl ) dup r@ FATLO :EOC? if
@@ -132,7 +134,7 @@ $ffff const EOC
to self size self :cluster0 ( cluster0 )
\ special case: if :cluster0 is zero, we have an empty file. We need to
\ update its direntry to record the file's first cluster.
- ?dup not if self fat findfreecluster then ( cluster0 )
+ ?dup not if self fat allocatecluster then ( cluster0 )
self :dirent 2dup DirEntry cluster! ( custer0 dirent )
self size swap to DirEntry filesize self fat writecursector ( cluster0 )
self size self fat FATLO :ClusterSize / ?dup if
@@ -152,8 +154,13 @@ $ffff const EOC
: fatinfo ( id self -- info ) FATInfo :read ;
+\ TODO: deallocate the chain before clearing the entry
+: fatremove ( id self -- ) >r
+ r@ FATLO :getdirentry ( dirent ) DirEntry SZ 0 fill r> writecursector ;
+
: _patchFS ( fs -- )
- ['] fatinfo over 8 + ! ['] fatopen over 12 + ! ['] fatnewfile swap 16 + ! ;
+ ['] fatinfo over 8 + ! ['] fatopen over 12 + ! ['] fatnewfile over 16 + !
+ ['] fatremove swap 28 + ! ;
: :mountvolume ( drv -- fs ) FATLO :mountvolume dup _patchFS ;
bootfs 8 + @ ' abort = [if] bootfs _patchFS [then]
diff --git a/fs/fs/fatlo.fs b/fs/fs/fatlo.fs
@@ -80,10 +80,12 @@ r@ reservedseccnt + r> :RootDirSectors + - ;
: :CountOfClusters dup :DataSec swap secpercluster / ;
: :FAT12? :CountOfClusters 4085 < ;
+\ Read specified sector into buffer if it's not already there.
\ "cnt" is the number of sectors ahead of "sec" that are available for a
-\ seqential read.
+\ sequential read.
: :readsector ( sec cnt self -- ) >r
-to r@ bufseccnt dup to r@ bufsec ( sec )
+to r@ bufseccnt dup r@ bufsec = if rdrop drop exit then
+dup to r@ bufsec ( sec )
r@ :buf( r> Filesystem :drv :sec@ ;
: :FAT12' ( cluster self -- 'entry ) >r
diff --git a/fs/tests/sys/file.fs b/fs/tests/sys/file.fs
@@ -26,12 +26,8 @@ myinfo FSInfo dir? not #
S" /lib" curpath :find Path :info value myinfo
myinfo FSInfo dir? #
\ test write, copy remove
-S" atabus" sysdict find [if]
- \ The ATA driver doesn't support writing yet and it breaks tests below.
- \ TODO: add writing support to ATA drivers
- testend \s [then]
-S" foo.fs" curpath :newfile dup # dup Path id .x
-( path ) Path :open value myfile myfile .x
+S" foo.fs" curpath :newfile dup #
+( path ) Path :open value myfile
S" 42" c@+ myfile File :write myfile File :close
S" /foo.fs" curpath :find# Path :fload 42 #eq
\ let's copy that file