M fs/doc/lib/drive.txt => fs/doc/lib/drive.txt +3 -0
@@ 62,6 62,9 @@ Words:
Move window to "fsec" with "cnt" sectors. This doesn't change or flush the
current buffer.
+:fulldrv ( self -- )
+ Move the window so that it spans the whole drive.
+
:load ( sec self -- )
Load sector "sec" in the buffer. Aborts if outside the window.
M fs/fs/fat.fs => fs/fs/fat.fs +29 -35
@@ 100,8 100,8 @@ $e5 const DIRFREE
else nip then rdrop ;
\ try to find in current buffer
-: _findinsec ( self -- a-or-0 ) >r
- r@ :dirwin :buf( begin ( a )
+: _findinsec ( self -- a-or-0 )
+ r! :dirwin :buf( begin ( a ) \ V1=self
dup c@ dup DIRFREE = swap not or if ( free! ) rdrop exit then
DirEntry SZ + dup r@ :dirwin :)buf >= until rdrop drop 0 ;
@@ 126,26 126,24 @@ $e5 const DIRFREE
: _makedir ( dirent -- dirent ) $10 over to DirEntry attr ;
-0 value _self 0 value _cluster 0 value _parentcl
-: fatnewdir ( dirid name self -- id ) to _self
- _self allocatecluster0 to _cluster ( dirid name )
- _self _newentry ( dirent ) _makedir ( dirent )
- _cluster over to DirEntry cluster _self writecursector ( dirent )
- _self :getid ( id ) _self bufcluster to _parentcl
+: fatnewdir ( dirid name self -- id )
+ r! allocatecluster0 >r ( dirid name ) \ V1=self V2=cluster
+ V1 _newentry ( dirent ) _makedir ( dirent )
+ V2 over to DirEntry cluster V1 writecursector ( dirent )
+ V1 :getid ( id ) V1 bufcluster >r \ V3=parentcl
\ Cluster allocated, now let's initialize it with "." and ".."
- _cluster _self :FirstSectorOfCluster 1 _self :readsector
- _self :dirwin :buf( dup DirEntry NAMESZ SPC fill '.' over c! _makedir ( id buf )
- _cluster over to DirEntry cluster ( id buf ) DirEntry SZ +
+ V2 V1 :FirstSectorOfCluster 1 V1 :readsector
+ V1 :dirwin :buf( dup DirEntry NAMESZ SPC fill '.' over c! _makedir ( id buf )
+ V2 over to DirEntry cluster ( id buf ) DirEntry SZ +
dup DirEntry NAMESZ SPC fill '.' over c!+ '.' swap c! ( id buf )
- _makedir ( id buf ) _parentcl swap to DirEntry cluster
- _self writecursector ( id ) ;
+ _makedir ( id buf ) V3 swap to DirEntry cluster
+ 2rdrop r> writecursector ( id ) ;
-0 value self
\ write multiple sectors from buf
-: writesectors ( sec u buf self -- ) to self
- rot >r swap for ( buf ) \ V1=sec
- V1 over self :drv :sec! to1+ V1 self :drv secsz + next ( buf )
- drop rdrop ;
+: writesectors ( sec u buf self -- ) >r \ V1=self
+ rot >r swap for ( buf ) \ V2=sec
+ V2 over V1 :drv :sec! to1+ V2 V1 :drv secsz + next ( buf )
+ drop 2rdrop ;
: writecluster ( cluster src self -- ) >r
over 2 - $fff6 > if abort" cluster out of range!" then
@@ 196,8 194,8 @@ $e5 const DIRFREE
: fatinfo ( id self -- info ) FATInfo :read ;
\ TODO: deallocate the chain before clearing the entry
-: fatremove ( id self -- ) >r
- r@ :getdirentry ( dirent ) DIRFREE swap c! r> writecursector ;
+: fatremove ( id self -- )
+ tuck :getdirentry ( dirent ) DIRFREE swap c! writecursector ;
\ This approach to iteration is inefficient, but simple. I keep it as-is for now
: _next ( entry self -- entry-or-0 ) >r \ V1=self
@@ 211,7 209,7 @@ $e5 const DIRFREE
V1 _next dup while dup V1 :getid V2 <> while repeat then then ( entry-or-0 )
dup if V1 _next dup if V1 :getid then then 2rdrop ;
-: _patchFS ( fs -- ) >r \ V1=fs
+: :patchlo ( fs -- ) >r \ V1=fs
['] fatinfo r@ 12 + ! ['] fatiter r@ 20 + !
['] fatnewfile r@ 24 + ! ['] fatnewdir r@ 28 + ! ['] fatremove r@ 32 + !
['] fatwritebuf FATFile EmptyCursor 8 + !
@@ 219,9 217,7 @@ $e5 const DIRFREE
['] fatflush FATFile EmptyCursor 12 + !
['] fattruncate FATFile EmptyCursor 40 + !
1 r> to flags ;
-: :mountvolume ( drv -- fs ) FAT :mountvolume dup _patchFS ;
-
-bootfs 12 + @ ' abort = [if] bootfs _patchFS [then]
+: :mountvolume ( drv -- fs ) FAT :mountvolume dup :patchlo ;
create _FATTemplate
( jmp ) $eb c, $3c c, $90 c, ( OEMName ) ," DuskFAT " ( BytsPerSec ) 0 c, 0 c,
@@ 232,14 228,12 @@ create _FATTemplate
( BootSig ) $29 c, ( VolID ) 0 , ( VolLabel ) ," NONAME "
( FilSysType ) ," FAT12 "
-0 value fatseccnt
-0 value secsz
: newFAT12 ( drv -- )
- fatopts clustercnt 341 / 1+ to fatseccnt
- ( drv ) dup Drive secsz to secsz ( drv )
- here secsz 0 fill
+ fatopts clustercnt 341 / 1+ >r \ V1=fatseccnt
+ ( drv ) dup Drive secsz >r ( drv ) \ V2=secsz
+ here V2 0 fill
_FATTemplate here $3e move ( drv )
- secsz here $0b + w!
+ V2 here $0b + w!
fatopts secpertrk here $18 + w!
fatopts numheads here $1a + w!
fatopts drvnum here $24 + c!
@@ 247,16 241,16 @@ create _FATTemplate
fatopts rsvdsec here $0e + w!
fatopts rootentsec DirEntry SZ * here $11 + w!
fatopts clustercnt fatopts secperclus * fatopts rootentsec +
- fatopts rsvdsec + fatseccnt + dup here $13 + w!
+ fatopts rsvdsec + V1 + dup here $13 + w!
." TotSec " . nl>
- fatseccnt here $16 + w!
+ V1 here $16 + w!
$aa55 here $1fe + w!
( drv ) dup 0 here rot Drive :sec! ( drv )
\ header done. Now, zero-out all FAT and root dir entries
- here secsz 0 fill
- fatopts rootentsec fatseccnt + 1- fatopts rsvdsec 1+ swap for ( drv sec )
+ here V2 0 fill
+ fatopts rootentsec V1 + 1- fatopts rsvdsec 1+ swap for ( drv sec )
2dup here rot Drive :sec! next ( drv sec ) drop
\ finally, initialize the first FAT sector
$fffff0 here !
- ( drv ) fatopts rsvdsec here rot Drive :sec! ;
+ ( drv ) fatopts rsvdsec here rot Drive :sec! 2rdrop ;
]struct
M fs/fs/fatlo.fs => fs/fs/fatlo.fs +17 -18
@@ 54,15 54,16 @@ sfield bufcluster \ cluster number of current buf
sfield lastcursor
sfield fatwin \ FAT secwin
sfield dirwin \ DirEntry secwin
-
-SZ &+ :hdr(
-SZ $0b + &+w@ secsz \ in bytes
-SZ $0d + &+c@ secpercluster
-SZ $0e + &+w@ reservedseccnt \ number of sectors reserved before FAT starts
-SZ $10 + &+c@ FATcnt \ >1 means backup FATs
-SZ $11 + &+w@ rootentcnt \ count of 32b entries
-SZ $13 + &+w@ seccnt
-SZ $16 + &+w@ FATsz \ in sectors
+\ FAT header now
+$0b sallot
+sfieldw secsz \ in bytes
+sfieldb secpercluster
+sfieldw reservedseccnt
+sfieldb FATcnt
+sfieldw rootentcnt
+sfieldw seccnt
+1 sallot
+sfieldw FATsz \ in sectors
$18 const HDRSZ
: :fatwin [compile] fatwin [compile] SectorWindow ; immediate
: :dirwin [compile] dirwin [compile] SectorWindow ; immediate
@@ 77,13 78,13 @@ $18 const HDRSZ
: :ClusterSize bi secpercluster | secsz * ;
: :FAT12? :CountOfClusters 4085 < ;
+: cl# ( n -- ) not if abort" cluster out of range" then ;
: :FirstSectorOfCluster ( n self -- sec ) >r
- dup << r@ secsz r@ FATsz * >= if abort" cluster out of range" then
- 1- 1- r@ secpercluster * r> :FirstDataSector + ;
+ dup << r@ secsz r@ FATsz * < cl#
+ 2 - r@ secpercluster * r> :FirstDataSector + ;
: :readsector ( sec cnt self -- ) r! :dirwin :move 0 r> :dirwin :seek 2drop ;
-: cl# ( n -- ) not if abort" cluster out of range" then ;
: :FAT12@ ( cluster self -- entry ) >r
dup dup >> + ( cl offset ) dup r@ :fatwin :seek cl# c@ ( cl off lsb )
swap 1+ r> :fatwin :seek cl# c@ 8 lshift or ( cl entry )
@@ 121,9 122,7 @@ $18 const HDRSZ
\ Get DirEntry address from FS ID "id"
: :getdirentry ( id self -- direntry )
- over if
- r! secsz /mod ( offset sec ) 1 r@ :readsector ( off ) r> :dirwin :buf( +
- else 2drop rootdirentry( then ;
+ over if dup :dirwin :fulldrv :dirwin :seek cl# else 2drop rootdirentry( then ;
\ Get ID for direntry
: :getid ( direntry self -- id )
@@ 185,7 184,7 @@ extends File struct[ FATFile
r@ :ptr r@ :)buf over - ( n a nmax )
rot min ( a n ) dup r> to+ pos ( a n ) ;
- : :fatclose ( self -- ) dup IO :flush :release ;
+ : :fatclose ( self -- ) dup :flush :release ;
\ these words below are "static" words not called with "self" as an argument,
\ but "fat".
@@ 223,8 222,8 @@ struct+[ FAT
: :mountvolume ( drv -- fs )
dup SectorWindow :new over SectorWindow :new rot
here >r ( fatwin dirwin rot ) \ V1=fs
- dup , 0 ( flags ) , ['] :child , ['] abort , ['] :fatopen , ['] abort ,
- ['] abort , ['] abort , ['] abort ,
+ dup , 0 ( flags ) , ['] :child , ['] abort , ['] :fatopen ,
+ ['] abort dup , dup , dup , ,
0 ( bufcluster ) , 0 ( lastcursor ) , rot ( fatwin ) , swap ( dirwin ) ,
\ At this point, "here" points to the FAT-header-to-be. Read the first sector
\ directly in "here": we'll have the header right here!
M fs/lib/drivelo.fs => fs/lib/drivelo.fs +1 -0
@@ 15,6 15,7 @@ struct[ SectorWindow
2dup tuck fsec - swap cnt >= if abort" secwin oor" then ( sec self )
dup :flush 2dup to sec tuck :buf( rot :drv :sec@ else 2drop then ;
: :move ( fsec cnt self -- ) swap 1 max over to cnt to fsec ;
+ : :fulldrv ( self -- ) 0 over :drv seccnt rot :move ;
: :seek ( pos self -- a? n-or-0 )
r! :drv secsz /mod ( off relsec ) \ V1=self
dup r@ cnt < if ( off relsec )
M fs/xcomp/i386/pc/init.fs => fs/xcomp/i386/pc/init.fs +1 -0
@@ 31,6 31,7 @@ f<< /drv/pc/pic.fs
pic$ idt$
f<< /fs/fat.fs
+bootfs FAT :patchlo
f<< /sys/kbd.fs
f<< /sys/mouse.fs