spinix-hive/pfth/mountos.spin

151 lines
4.5 KiB
Plaintext
Raw Permalink Normal View History

' This code is extracted from FSRW 2.6
con
SECTORSIZE = 512
SECTORSHIFT = 9
DIRSHIFT = 5
'SPI_engine_cog = 0
'SPI_command = 1
'SPI_block_index = 2
'SPI_buffer_address = 3
SD_rootdir = 4
SD_filesystem = 5
SD_clustershift = 6
SD_dataregion = 7
SD_fat1 = 8
SD_sectorsperfat = 9
SD_currdir = 10
ERR_BLOCK_NOT_LONG_ALIGNED = -4
ERR_SPI_ENGINE_NOT_RUNNING = -999
obj
sdspi : "safe_spi"
sys : "sysdefs"
dat
pdate long 0
lastread long 0
dirty long 0
filesystem long 0
clustershift long 0
clustersize long 0
fat1 long 0
sectorsperfat long 0
dataregion long 0
rootdir long 0
rootdirend long 0
endofchain long 0
totclusters long 0
buf byte 0[512]
pri brword(b)
'
' Read a byte-reversed word from a (possibly odd) address.
'
return (byte[b]) + ((byte[b][1]) << 8)
pri brlong(b)
'
' Read a byte-reversed long from a (possibly odd) address.
'
return brword(b) + (brword(b+2) << 16)
pri getfstype : r
if (brlong(@buf+$36) == constant("F" + ("A" << 8) + ("T" << 16) + ("1" << 24)) and buf[$3a]=="6")
return 1
if (brlong(@buf+$52) == constant("F" + ("A" << 8) + ("T" << 16) + ("3" << 24)) and buf[$56]=="2")
return 2
' return r (default return)
pub mount_explicit(spi_vars) : r | start, sectorspercluster, reserved, rootentries, sectors
{{
' Mount a volume. The address passed in is passed along to the block
' layer; see the currently used block layer for documentation. If the
' volume mounts, a 0 is returned, else abort is called.
}}
if (pdate == 0)
pdate := constant(((2009-1980) << 25) + (1 << 21) + (27 << 16) + (7 << 11))
'unmount
'sdspi.start_explicit(spi_vars, DO, CLK, DI, CS)
lastread := -1
dirty := 0
readblock(0, @buf)
if (getfstype > 0)
start := 0
else
start := brlong(@buf+$1c6)
readblock(start, @buf)
filesystem := getfstype
if (filesystem == 0)
abort(-20) ' not a fat16 or fat32 volume
if (brword(@buf+$0b) <> SECTORSIZE)
abort(-21) ' bad bytes per sector
sectorspercluster := buf[$0d]
if (sectorspercluster & (sectorspercluster - 1))
abort(-22) ' bad sectors per cluster
clustershift := 0
repeat while (sectorspercluster > 1)
clustershift++
sectorspercluster >>= 1
sectorspercluster := 1 << clustershift
clustersize := SECTORSIZE << clustershift
reserved := brword(@buf+$0e)
if (buf[$10] <> 2)
abort(-23) ' not two FATs
sectors := brword(@buf+$13)
if (sectors == 0)
sectors := brlong(@buf+$20)
fat1 := start + reserved
if (filesystem == 2)
rootentries := 16 << clustershift
sectorsperfat := brlong(@buf+$24)
dataregion := (fat1 + 2 * sectorsperfat) - 2 * sectorspercluster
rootdir := (dataregion + (brword(@buf+$2c) << clustershift)) << SECTORSHIFT
rootdirend := rootdir + (rootentries << DIRSHIFT)
endofchain := $ffffff0
else
rootentries := brword(@buf+$11)
sectorsperfat := brword(@buf+$16)
rootdir := (fat1 + 2 * sectorsperfat) << SECTORSHIFT
rootdirend := rootdir + (rootentries << DIRSHIFT)
dataregion := 1 + ((rootdirend - 1) >> SECTORSHIFT) - 2 * sectorspercluster
endofchain := $fff0
if (brword(@buf+$1fe) <> $aa55)
abort(-24) ' bad FAT signature
totclusters := ((sectors - dataregion + start) >> clustershift)
long[spi_vars][SD_rootdir] := rootdir >> SECTORSHIFT
long[spi_vars][SD_filesystem] := filesystem
long[spi_vars][SD_clustershift] := clustershift
long[spi_vars][SD_dataregion] := dataregion
long[spi_vars][SD_fat1] := fat1
long[spi_vars][SD_sectorsperfat] := sectorsperfat
long[spi_vars][SD_currdir] := rootdir >> SECTORSHIFT
{
PUB readblock(spi_vars, block_index, buffer_address)
if long[spi_vars][SPI_engine_cog] == 0
abort ERR_SPI_ENGINE_NOT_RUNNING
if (buffer_address & 3)
abort ERR_BLOCK_NOT_LONG_ALIGNED
long[spi_vars][SPI_block_index] := block_index
long[spi_vars][SPI_buffer_address] := buffer_address
long[spi_vars][SPI_command] := "r"
repeat while long[spi_vars][SPI_command] == "r"
if long[spi_vars][SPI_command] < 0
abort SPI_command
}
PUB readblock(block_index, buffer_address)
if long[sys#SPI_engine_cog] == 0
abort ERR_SPI_ENGINE_NOT_RUNNING
if (buffer_address & 3)
abort ERR_BLOCK_NOT_LONG_ALIGNED
long[sys#SPI_block_index] := block_index
long[sys#SPI_buffer_address] := buffer_address
long[sys#SPI_command] := "r"
repeat while long[sys#SPI_command] == "r"
if long[sys#SPI_command] < 0
abort long[sys#SPI_command]