~vdupras/duskos

ea87055dff072d7d3bab004ad7570eba6642c058 — Virgil Dupras 21 days ago 37a2f72
fs/fatlo: consolidate
1 files changed, 33 insertions(+), 44 deletions(-)

M fs/fs/fatlo.fs
M fs/fs/fatlo.fs => fs/fs/fatlo.fs +33 -44
@@ 42,9 42,8 @@ here const )fnbuf
    c@+ ( a len ) fnbuf( swap move exit then
  c@+ swap >r fnbuf( swap for ( dst ) \ V1=a
    8b to@+ V1 dup '.' = if
      2drop fnbuf( DirEntry EXTIDX + else
      upcase swap c!+ then ( dst+1 )
    dup )fnbuf = if 1 to i then next drop rdrop ;
      2drop fnbuf( DirEntry EXTIDX + else upcase swap c!+ then ( dst+1 )
    dup )fnbuf = if break then next then drop rdrop ;

\ The FAT struct in this unit is split in 2. The first part contains code needed
\ by FATFile, and the second part contains the rest of the code for FAT. This


@@ 62,28 61,26 @@ 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 bytes
SZ $16 + &+w@ FATsz          \ in sectors
$18 const HDRSZ
\ buffer for reading FAT tables and dir entries. one sector in length.
SZ HDRSZ + &+ :buf(
: :)buf bi :buf( | secsz + ;

: :RootDirSectors ( self -- n )
bi rootentcnt 32 * | secsz /mod ( r q ) swap bool + ;
: :FirstDataSector ( self -- n ) >r
r@ reservedseccnt r@ FATcnt r@ FATsz * + r> :RootDirSectors + ;
: :FirstSectorOfCluster ( n self -- sec ) >r
dup << r@ secsz r@ FATsz * >= if abort" cluster out of range" then
1- 1- r@ secpercluster * r> :FirstDataSector + ;
: :FirstRootDirSecNum ( self -- n ) >r
r@ reservedseccnt r@ FATcnt r> FATsz * + ;
: :ClusterSize bi secpercluster | secsz * ;
: :DataSec ( self -- n ) >r
r@ seccnt r@ FATsz r@ FATcnt *
r@ reservedseccnt + r> :RootDirSectors + - ;
\ These words have the same sig: fat -- n
: :RootDirSectors bi rootentcnt 32 * | secsz /mod ( r q ) swap bool + ;
: :totsec bi FATcnt | FATsz * ;
: :FirstRootDirSecNum bi reservedseccnt | :totsec + ;
: :FirstDataSector bi :FirstRootDirSecNum | :RootDirSectors + ;
: :DataSec bi seccnt | :FirstDataSector - ;
: :CountOfClusters bi :DataSec | secpercluster / ;
: :ClusterSize bi secpercluster | secsz * ;
: :FAT12? :CountOfClusters 4085 < ;

: :FirstSectorOfCluster ( n self -- sec ) >r
  dup << r@ secsz r@ FATsz * >= if abort" cluster out of range" then
  1- 1- r@ secpercluster * r> :FirstDataSector + ;

\ Read specified sector into buffer if it's not already there.
\ "cnt" is the total number of sectors ahead of "sec" that are available for a
\ sequential read, *including this sector*. For example, "2" means that we're


@@ 92,36 89,30 @@ r@ reservedseccnt + r> :RootDirSectors + - ;
  1 max 1- to r@ bufseccnt dup r@ bufsec = if rdrop drop else
    dup to r@ bufsec ( sec ) r@ :buf( r> :drv :sec@ then ;

: :sec+( ( off sec self -- a ) tuck 1 swap :readsector :buf( + ;
: :FAT12' ( cluster self -- 'entry ) >r
  dup >> + ( cl offset ) r@ secsz /mod ( cl secoff sec )
  r@ reservedseccnt +
  dup >> + ( offset ) r@ secsz /mod r@ reservedseccnt + ( secoff sec )
  over 1+ r@ secsz = if \ end-of-sector cross-over!
    dup 1+ 0 r@ :readsector r@ :buf( c@ r@ :)buf c! then
  0 r@ :readsector ( cl secoff )
  r> :buf( + ;
    dup 1+ 1 r@ :readsector r@ :buf( c@ r@ :)buf c! then
  r> :sec+( ;
: :FAT12@ ( cluster self -- entry )
  over swap :FAT12' w@ swap 1 and if 4 rshift else $fff and then ;
: :FAT16' ( cluster self -- 'entry ) >r
  << ( offset ) r@ secsz /mod ( secoff sec )
  r@ reservedseccnt + 0 r@ :readsector ( secoff )
  r> :buf( + ;
  << ( offset ) r@ secsz /mod r@ reservedseccnt + ( secoff sec ) r> :sec+( ;
: :FAT16@ ( cluster self -- entry ) :FAT16' w@ ;
: :FAT@ ( cluster self -- entry )
  over 2 < if 2drop EOC else
    dup :FAT12? if :FAT12@ else :FAT16@ then then ;
  over 2 < if 2drop EOC else dup :FAT12? if :FAT12@ else :FAT16@ then then ;

: :EOC? ( cluster self -- f )
  :FAT12? if $ff8 else $fff8 then tuck and = ;
: :EOC? ( cluster self -- f ) :FAT12? if $ff8 else $fff8 then tuck and = ;

\ Read next sector if a sequential read is available, else return false.
: :nextsector? ( self -- f ) >r
  r@ bufseccnt if \ still on a sector streak
    r@ bufsec 1+ r@ bufseccnt 1- r> :readsector 1
: :nextsector? ( self -- f )
  dup bufseccnt if \ still on a sector streak
    bi+ bufsec 1+ | bufseccnt 1- rot :readsector 1
  else \ out of sector, try next cluster
    r@ bufcluster r@ :FAT@ dup r@ :EOC? if rdrop drop 0 else
      dup to r@ bufcluster r@ :FirstSectorOfCluster
      r@ secpercluster r> :readsector 1 then
  then ;
    bi+ bufcluster | :FAT@ swap 2dup :EOC? if 2drop 0 else ( cl self )
      2dup to bufcluster tuck :FirstSectorOfCluster ( self sec )
      over secpercluster rot :readsector 1 then then ;

\ Find current fnbuf( in current dir buffer and return a dir entry.
: :findindir ( self -- direntry-or-0 ) >r


@@ 143,12 134,11 @@ r@ reservedseccnt + r> :RootDirSectors + - ;
\ Get DirEntry address from FS ID "id"
: :getdirentry ( id self -- direntry )
  over if
    dup >r secsz /mod ( offset sec ) 1 r@ :readsector ( off ) r> :buf( +
    r! secsz /mod ( offset sec ) 1 r@ :readsector ( off ) r> :buf( +
  else 2drop rootdirentry( then ;

\ Get ID for direntry
: :getid ( direntry self -- id )
  dup >r :buf( - r@ bufsec r> secsz * + ;
: :getid ( direntry self -- id ) r! :buf( - r@ bufsec r> secsz * + ;

\ read multiple sectors in buf
: :readsectors ( sec u buf self -- ) >r \ V1=self


@@ 222,8 212,8 @@ extends File struct[ FATFile
    0 align4 dup to' FAT lastcursor lladd ( fat newll )
    swap :cursorsize allot ( newll ) CELLSZ + ( hdl ) dup :release ;

  : :findfreecursor ( fat -- hdl ) >r \ V1=fat
    r@ FAT lastcursor begin ( ll )
  : :findfreecursor ( fat -- hdl )
    r! FAT lastcursor begin ( ll ) \ V1=fat
      ?dup while dup CELLSZ + :free? not while llnext repeat
      CELLSZ + else r@ :createcursor then
    EmptyCursor over SZ move ( hdl )


@@ 236,10 226,9 @@ struct+[ FAT
  \ This is the "low" part. Complete open is finalized in fs/fat
  : :fatopen ( id self -- hdl ) >r \ V1=self
    V1 :getdirentry
    V1 FATFile :findfreecursor >r ( dirent ) r@ FATFile :hold \ V2=hdl
    V1 FATFile :findfreecursor ( dirent hdl ) r! FATFile :hold \ V2=hdl
    \ write the rest
    dup V1 :buf( -
    V1 bufsec V1 secsz * + ( dirent doffset )
    dup V1 :buf( - V1 bufsec V1 secsz * + ( dirent doffset )
    r@ to FATFile entryoff DirEntry filesize r@ to FATFile size ( ) r> rdrop ;

  : :mountvolume ( drv -- fs )