136 lines
4.1 KiB
Plaintext
136 lines
4.1 KiB
Plaintext
' 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"
|
|
|
|
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, DO, CLK, DI, CS) : 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(spi_vars, 0, @buf)
|
|
if (getfstype > 0)
|
|
start := 0
|
|
else
|
|
start := brlong(@buf+$1c6)
|
|
readblock(spi_vars, 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 |