From 2cc2cc2e394382597cb37ada2627758b4c39db49 Mon Sep 17 00:00:00 2001 From: Michael Chisholm Date: Thu, 20 Nov 2008 05:22:28 +0000 Subject: [PATCH] Moved disc interfaces to appropriate libraries (DLDI to libnds, SD/USB to libogc). Changed read/write functions to use size_t and seek function to use off_t -- will help on 64 bit platforms. Partitions no longer specified by fat1:/, fat2:/, etc. Use "nice" device names. On GBA/NDS the default partition is still fat:/; however on Wii and GC sd:/, usb:/, etc. are used instead. Added fsync and ftruncate functions. Mount and unmount no longer startup/shutdown the device, this is the job of the host app. Mount now accepts a partition start parameter. Used standard types, eg uint32_t instead of u32. Archive bit is set when closing/synchronizing a modified file. Various minor bug fixes. --- gba/Makefile | 2 +- gba/include/fat.h | 51 ++- include/fat.h | 72 ++-- libogc/Makefile | 2 +- libogc/include/fat.h | 55 ++- nds/Makefile | 2 +- nds/include/fat.h | 53 ++- nds/source/nitrofs.c | 21 +- source/bit_ops.h | 27 +- source/cache.c | 47 ++- source/cache.h | 41 ++- source/common.h | 42 ++- source/directory.c | 140 +++----- source/directory.h | 26 +- source/disc.h | 95 ++---- source/disc_io/disc.c | 210 ------------ source/disc_io/io_cf_common.c | 322 ------------------ source/disc_io/io_cf_common.h | 78 ----- source/disc_io/io_dldi.h | 44 --- source/disc_io/io_dldi.s | 73 ---- source/disc_io/io_efa2.c | 307 ----------------- source/disc_io/io_efa2.h | 23 -- source/disc_io/io_fcsr.c | 334 ------------------ source/disc_io/io_fcsr.h | 44 --- source/disc_io/io_m3_common.c | 60 ---- source/disc_io/io_m3_common.h | 48 --- source/disc_io/io_m3cf.c | 96 ------ source/disc_io/io_m3cf.h | 45 --- source/disc_io/io_m3sd.c | 518 ---------------------------- source/disc_io/io_m3sd.h | 48 --- source/disc_io/io_mpcf.c | 100 ------ source/disc_io/io_mpcf.h | 45 --- source/disc_io/io_njsd.c | 595 --------------------------------- source/disc_io/io_njsd.h | 50 --- source/disc_io/io_nmmc.c | 348 ------------------- source/disc_io/io_nmmc.h | 53 --- source/disc_io/io_sc_common.c | 47 --- source/disc_io/io_sc_common.h | 49 --- source/disc_io/io_sccf.c | 83 ----- source/disc_io/io_sccf.h | 45 --- source/disc_io/io_scsd.c | 399 ---------------------- source/disc_io/io_scsd.h | 48 --- source/disc_io/io_scsd_s.s | 139 -------- source/disc_io/io_sd_common.c | 210 ------------ source/disc_io/io_sd_common.h | 117 ------- source/fatdir.c | 159 ++++----- source/fatdir.h | 21 +- source/fatfile.c | 409 ++++++++++++++-------- source/fatfile.h | 75 +++-- source/file_allocation_table.c | 106 +++--- source/file_allocation_table.h | 34 +- source/filetime.c | 27 +- source/filetime.h | 12 +- source/libfat.c | 179 +++++----- source/lock.c | 35 -- source/lock.h | 37 +- source/mem_allocate.h | 5 +- source/ogc_io/disc.c | 169 ---------- source/ogc_io/gcsd.h | 43 --- source/ogc_io/wiisd.h | 41 --- source/partition.c | 274 +++------------ source/partition.h | 85 ++--- 62 files changed, 908 insertions(+), 6057 deletions(-) delete mode 100644 source/disc_io/disc.c delete mode 100644 source/disc_io/io_cf_common.c delete mode 100644 source/disc_io/io_cf_common.h delete mode 100644 source/disc_io/io_dldi.h delete mode 100644 source/disc_io/io_dldi.s delete mode 100644 source/disc_io/io_efa2.c delete mode 100644 source/disc_io/io_efa2.h delete mode 100644 source/disc_io/io_fcsr.c delete mode 100644 source/disc_io/io_fcsr.h delete mode 100644 source/disc_io/io_m3_common.c delete mode 100644 source/disc_io/io_m3_common.h delete mode 100644 source/disc_io/io_m3cf.c delete mode 100644 source/disc_io/io_m3cf.h delete mode 100644 source/disc_io/io_m3sd.c delete mode 100644 source/disc_io/io_m3sd.h delete mode 100644 source/disc_io/io_mpcf.c delete mode 100644 source/disc_io/io_mpcf.h delete mode 100644 source/disc_io/io_njsd.c delete mode 100644 source/disc_io/io_njsd.h delete mode 100644 source/disc_io/io_nmmc.c delete mode 100644 source/disc_io/io_nmmc.h delete mode 100644 source/disc_io/io_sc_common.c delete mode 100644 source/disc_io/io_sc_common.h delete mode 100644 source/disc_io/io_sccf.c delete mode 100644 source/disc_io/io_sccf.h delete mode 100644 source/disc_io/io_scsd.c delete mode 100644 source/disc_io/io_scsd.h delete mode 100644 source/disc_io/io_scsd_s.s delete mode 100644 source/disc_io/io_sd_common.c delete mode 100644 source/disc_io/io_sd_common.h delete mode 100644 source/lock.c delete mode 100644 source/ogc_io/disc.c delete mode 100644 source/ogc_io/gcsd.h delete mode 100644 source/ogc_io/wiisd.h diff --git a/gba/Makefile b/gba/Makefile index 648f64e..52c34dc 100644 --- a/gba/Makefile +++ b/gba/Makefile @@ -17,7 +17,7 @@ include $(DEVKITARM)/gba_rules # all directories are relative to this makefile #--------------------------------------------------------------------------------- BUILD ?= release -SOURCES := ../source ../source/disc_io +SOURCES := ../source INCLUDES := ../include DATA := LIB := $(TOPDIR)/gba/lib diff --git a/gba/include/fat.h b/gba/include/fat.h index d445b6b..f3b1f63 100644 --- a/gba/include/fat.h +++ b/gba/include/fat.h @@ -24,7 +24,6 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ @@ -35,11 +34,8 @@ extern "C" { #endif -#include "gba_types.h" - -typedef enum {PI_CART_SLOT} PARTITION_INTERFACE; - -struct IO_INTERFACE_STRUCT ; +#include +#include "disc_io.h" /* Initialise any inserted block-devices. @@ -47,45 +43,36 @@ Add the fat device driver to the devoptab, making it available for standard file cacheSize: The number of pages to allocate for each inserted block-device setAsDefaultDevice: if true, make this the default device driver for file operations */ -bool fatInit (u32 cacheSize, bool setAsDefaultDevice); +extern bool fatInit (uint32_t cacheSize, bool setAsDefaultDevice); /* Calls fatInit with setAsDefaultDevice = true and cacheSize optimised for the host system. */ -bool fatInitDefault (void); +extern bool fatInitDefault (void); /* -Mount the device specified by partitionNumber -PD_DEFAULT is not allowed, use _FAT_partition_setDefaultDevice -PD_CUSTOM is not allowed, use _FAT_partition_mountCustomDevice +Mount the device pointed to by interface, and set up a devoptab entry for it as "name:". +You can then access the filesystem using "name:/". +This will mount the active partition or the first valid partition on the disc, +and will use a cache size optimized for the host system. */ -bool fatMountNormalInterface (PARTITION_INTERFACE partitionNumber, u32 cacheSize); +extern bool fatMountSimple (const char* name, const DISC_INTERFACE* interface); /* -Mount a partition on a custom device +Mount the device pointed to by interface, and set up a devoptab entry for it as "name:". +You can then access the filesystem using "name:/". +If startSector = 0, it will mount the active partition of the first valid partition on +the disc. Otherwise it will try to mount the partition starting at startSector. +cacheSize specifies the number of pages to allocate for the cache. +This will not startup the disc, so you need to call interface->startup(); first. */ -bool fatMountCustomInterface (struct IO_INTERFACE_STRUCT* device, u32 cacheSize); +extern bool fatMount (const char* name, const DISC_INTERFACE* interface, sec_t startSector, uint32_t cacheSize); /* -Unmount the partition specified by partitionNumber -If there are open files, it will fail +Unmount the partition specified by name. +If there are open files, it will attempt to synchronise them to disc. */ -bool fatUnmount (PARTITION_INTERFACE partitionNumber); - - -/* -Forcibly unmount the partition specified by partitionNumber -Any open files on the partition will become invalid -The cache will be invalidated, and any unflushed writes will be lost -*/ -bool fatUnsafeUnmount (PARTITION_INTERFACE partitionNumber); - -/* -Set the default device for access by fat: and fat0: -PD_DEFAULT is unallowed. -Doesn't do anything useful on GBA, since there is only one device -*/ -bool fatSetDefaultInterface (PARTITION_INTERFACE partitionNumber); +extern void fatUnmount (const char* name); #ifdef __cplusplus } diff --git a/include/fat.h b/include/fat.h index 26e111c..2ccf604 100644 --- a/include/fat.h +++ b/include/fat.h @@ -24,15 +24,6 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release - - 2006-07-14 - * fatInitialise renamed to fatInit - - 2006-07-16 - Chishm - * Added fatInitDefault */ @@ -50,73 +41,54 @@ extern "C" { #endif #endif +#include + #if defined(__gamecube__) || defined (__wii__) -# include +# include #else # ifdef NDS -# include +# include "nds/disc_io.h" # else -# include "gba_types.h" +# include "disc_io.h" # endif #endif -#if defined( __wii__ ) -typedef enum {PI_DEFAULT, PI_SDGECKO_A, PI_SDGECKO_B, PI_INTERNAL_SD, PI_CUSTOM, PI_MAX_PARTITIONS } PARTITION_INTERFACE; -#elif defined(__gamecube__) -typedef enum {PI_DEFAULT, PI_SDGECKO_A, PI_SDGECKO_B, PI_CUSTOM, PI_MAX_PARTITIONS } PARTITION_INTERFACE; -#elif defined(NDS) -typedef enum {PI_DEFAULT, PI_SLOT_1, PI_SLOT_2, PI_CUSTOM, PI_MAX_PARTITIONS} PARTITION_INTERFACE; -#elif defined(GBA) -typedef enum {PI_CART_SLOT, PI_MAX_PARTITIONS} PARTITION_INTERFACE; -#endif - -struct IO_INTERFACE_STRUCT ; - /* Initialise any inserted block-devices. Add the fat device driver to the devoptab, making it available for standard file functions. cacheSize: The number of pages to allocate for each inserted block-device setAsDefaultDevice: if true, make this the default device driver for file operations */ -bool fatInit (u32 cacheSize, bool setAsDefaultDevice); +extern bool fatInit (uint32_t cacheSize, bool setAsDefaultDevice); /* Calls fatInit with setAsDefaultDevice = true and cacheSize optimised for the host system. */ -bool fatInitDefault (void); +extern bool fatInitDefault (void); /* -Mount the device specified by partitionNumber -PD_DEFAULT is not allowed, use _FAT_partition_setDefaultDevice -PD_CUSTOM is not allowed, use _FAT_partition_mountCustomDevice +Mount the device pointed to by interface, and set up a devoptab entry for it as "name:". +You can then access the filesystem using "name:/". +This will mount the active partition or the first valid partition on the disc, +and will use a cache size optimized for the host system. */ -bool fatMountNormalInterface (PARTITION_INTERFACE partitionNumber, u32 cacheSize); +extern bool fatMountSimple (const char* name, const DISC_INTERFACE* interface); /* -Mount a partition on a custom device +Mount the device pointed to by interface, and set up a devoptab entry for it as "name:". +You can then access the filesystem using "name:/". +If startSector = 0, it will mount the active partition of the first valid partition on +the disc. Otherwise it will try to mount the partition starting at startSector. +cacheSize specifies the number of pages to allocate for the cache. +This will not startup the disc, so you need to call interface->startup(); first. */ -bool fatMountCustomInterface (const struct IO_INTERFACE_STRUCT* device, u32 cacheSize); +extern bool fatMount (const char* name, const DISC_INTERFACE* interface, sec_t startSector, uint32_t cacheSize); /* -Unmount the partition specified by partitionNumber -If there are open files, it will fail +Unmount the partition specified by name. +If there are open files, it will attempt to synchronise them to disc. */ -bool fatUnmount (PARTITION_INTERFACE partitionNumber); - - -/* -Forcibly unmount the partition specified by partitionNumber -Any open files on the partition will become invalid -The cache will be invalidated, and any unflushed writes will be lost -*/ -bool fatUnsafeUnmount (PARTITION_INTERFACE partitionNumber); - -/* -Set the default device for access by fat: and fat0: -PD_DEFAULT is unallowed. -Doesn't do anything useful on GBA, since there is only one device -*/ -bool fatSetDefaultInterface (PARTITION_INTERFACE partitionNumber); +extern void fatUnmount (const char* name); #ifdef __cplusplus } diff --git a/libogc/Makefile b/libogc/Makefile index 8929ff1..cd83f34 100644 --- a/libogc/Makefile +++ b/libogc/Makefile @@ -22,7 +22,7 @@ endif # all directories are relative to this makefile #--------------------------------------------------------------------------------- BUILD ?= wii_release -SOURCES := ../source ../source/ogc_io +SOURCES := ../source INCLUDES := ../include DATA := LIBDIR := $(TOPDIR)/libogc/lib diff --git a/libogc/include/fat.h b/libogc/include/fat.h index 6667838..8457593 100644 --- a/libogc/include/fat.h +++ b/libogc/include/fat.h @@ -24,7 +24,6 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ @@ -35,15 +34,8 @@ extern "C" { #endif -#include - -#if defined(__wii__) -typedef enum {PI_DEFAULT, PI_SDGECKO_A, PI_SDGECKO_B, PI_INTERNAL_SD, PI_CUSTOM } PARTITION_INTERFACE; -#else -typedef enum {PI_DEFAULT, PI_SDGECKO_A, PI_SDGECKO_B, PI_CUSTOM } PARTITION_INTERFACE; -#endif - -struct IO_INTERFACE_STRUCT ; +#include +#include /* Initialise any inserted block-devices. @@ -51,45 +43,36 @@ Add the fat device driver to the devoptab, making it available for standard file cacheSize: The number of pages to allocate for each inserted block-device setAsDefaultDevice: if true, make this the default device driver for file operations */ -bool fatInit (u32 cacheSize, bool setAsDefaultDevice); +extern bool fatInit (uint32_t cacheSize, bool setAsDefaultDevice); /* Calls fatInit with setAsDefaultDevice = true and cacheSize optimised for the host system. */ -bool fatInitDefault (void); +extern bool fatInitDefault (void); /* -Mount the device specified by partitionNumber -PD_DEFAULT is not allowed, use _FAT_partition_setDefaultDevice -PD_CUSTOM is not allowed, use _FAT_partition_mountCustomDevice +Mount the device pointed to by interface, and set up a devoptab entry for it as "name:". +You can then access the filesystem using "name:/". +This will mount the active partition or the first valid partition on the disc, +and will use a cache size optimized for the host system. */ -bool fatMountNormalInterface (PARTITION_INTERFACE partitionNumber, u32 cacheSize); +extern bool fatMountSimple (const char* name, const DISC_INTERFACE* interface); /* -Mount a partition on a custom device +Mount the device pointed to by interface, and set up a devoptab entry for it as "name:". +You can then access the filesystem using "name:/". +If startSector = 0, it will mount the active partition of the first valid partition on +the disc. Otherwise it will try to mount the partition starting at startSector. +cacheSize specifies the number of pages to allocate for the cache. +This will not startup the disc, so you need to call interface->startup(); first. */ -bool fatMountCustomInterface (struct IO_INTERFACE_STRUCT* device, u32 cacheSize); +extern bool fatMount (const char* name, const DISC_INTERFACE* interface, sec_t startSector, uint32_t cacheSize); /* -Unmount the partition specified by partitionNumber -If there are open files, it will fail +Unmount the partition specified by name. +If there are open files, it will attempt to synchronise them to disc. */ -bool fatUnmount (PARTITION_INTERFACE partitionNumber); - - -/* -Forcibly unmount the partition specified by partitionNumber -Any open files on the partition will become invalid -The cache will be invalidated, and any unflushed writes will be lost -*/ -bool fatUnsafeUnmount (PARTITION_INTERFACE partitionNumber); - -/* -Set the default device for access by fat: and fat0: -PD_DEFAULT is unallowed. -Doesn't do anything useful on GBA, since there is only one device -*/ -bool fatSetDefaultInterface (PARTITION_INTERFACE partitionNumber); +extern void fatUnmount (const char* name); #ifdef __cplusplus } diff --git a/nds/Makefile b/nds/Makefile index c39b56c..cc7afe9 100644 --- a/nds/Makefile +++ b/nds/Makefile @@ -16,7 +16,7 @@ include $(DEVKITARM)/ds_rules # all directories are relative to this makefile #--------------------------------------------------------------------------------- BUILD ?= release -SOURCES := ../source ../source/disc_io source +SOURCES := ../source source INCLUDES := ../include DATA := LIB := $(TOPDIR)/nds/lib diff --git a/nds/include/fat.h b/nds/include/fat.h index 807ffdf..67c927d 100644 --- a/nds/include/fat.h +++ b/nds/include/fat.h @@ -24,7 +24,6 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ @@ -37,14 +36,11 @@ extern "C" { // When compiling for NDS, make sure NDS is defined #ifndef NDS - #define NDS +#define NDS #endif -#include - -typedef enum {PI_DEFAULT, PI_SLOT_1, PI_SLOT_2, PI_CUSTOM} PARTITION_INTERFACE; - -struct IO_INTERFACE_STRUCT ; +#include +#include "nds/disc_io.h" /* Initialise any inserted block-devices. @@ -52,45 +48,36 @@ Add the fat device driver to the devoptab, making it available for standard file cacheSize: The number of pages to allocate for each inserted block-device setAsDefaultDevice: if true, make this the default device driver for file operations */ -bool fatInit (u32 cacheSize, bool setAsDefaultDevice); +extern bool fatInit (uint32_t cacheSize, bool setAsDefaultDevice); /* Calls fatInit with setAsDefaultDevice = true and cacheSize optimised for the host system. */ -bool fatInitDefault (void); +extern bool fatInitDefault (void); /* -Mount the device specified by partitionNumber -PD_DEFAULT is not allowed, use _FAT_partition_setDefaultDevice -PD_CUSTOM is not allowed, use _FAT_partition_mountCustomDevice +Mount the device pointed to by interface, and set up a devoptab entry for it as "name:". +You can then access the filesystem using "name:/". +This will mount the active partition or the first valid partition on the disc, +and will use a cache size optimized for the host system. */ -bool fatMountNormalInterface (PARTITION_INTERFACE partitionNumber, u32 cacheSize); +extern bool fatMountSimple (const char* name, const DISC_INTERFACE* interface); /* -Mount a partition on a custom device +Mount the device pointed to by interface, and set up a devoptab entry for it as "name:". +You can then access the filesystem using "name:/". +If startSector = 0, it will mount the active partition of the first valid partition on +the disc. Otherwise it will try to mount the partition starting at startSector. +cacheSize specifies the number of pages to allocate for the cache. +This will not startup the disc, so you need to call interface->startup(); first. */ -bool fatMountCustomInterface (struct IO_INTERFACE_STRUCT* device, u32 cacheSize); +extern bool fatMount (const char* name, const DISC_INTERFACE* interface, sec_t startSector, uint32_t cacheSize); /* -Unmount the partition specified by partitionNumber -If there are open files, it will fail +Unmount the partition specified by name. +If there are open files, it will attempt to synchronise them to disc. */ -bool fatUnmount (PARTITION_INTERFACE partitionNumber); - - -/* -Forcibly unmount the partition specified by partitionNumber -Any open files on the partition will become invalid -The cache will be invalidated, and any unflushed writes will be lost -*/ -bool fatUnsafeUnmount (PARTITION_INTERFACE partitionNumber); - -/* -Set the default device for access by fat: and fat0: -PD_DEFAULT is unallowed. -Doesn't do anything useful on GBA, since there is only one device -*/ -bool fatSetDefaultInterface (PARTITION_INTERFACE partitionNumber); +extern void fatUnmount (const char* name); #ifdef __cplusplus } diff --git a/nds/source/nitrofs.c b/nds/source/nitrofs.c index 00b58d0..1eb2ef2 100644 --- a/nds/source/nitrofs.c +++ b/nds/source/nitrofs.c @@ -17,8 +17,8 @@ int nitroFSDirNext(struct _reent *r, DIR_ITER *dirState, char *filename, struct int nitroFSDirClose(struct _reent *r, DIR_ITER *dirState); int nitroFSOpen(struct _reent *r, void *fileStruct, const char *path,int flags,int mode); int nitroFSClose(struct _reent *r,int fd); -int nitroFSRead(struct _reent *r,int fd,char *ptr,int len); -int nitroFSSeek(struct _reent *r,int fd,int pos,int dir); +ssize_t nitroFSRead(struct _reent *r,int fd,char *ptr,size_t len); +off_t nitroFSSeek(struct _reent *r,int fd,off_t pos,int dir); int nitroFSFstat(struct _reent *r,int fd,struct stat *st); #define LOADERSTR "PASS" //look for this @@ -81,9 +81,9 @@ devoptab_t nitroFSdevoptab={ sizeof(struct nitroFSStruct), // int structSize; &nitroFSOpen, // int (*open_r)(struct _reent *r, void *fileStruct, const char *path,int flags,int mode); &nitroFSClose, // int (*close_r)(struct _reent *r,int fd); - NULL, // int (*write_r)(struct _reent *r,int fd,const char *ptr,int len); - &nitroFSRead, // int (*read_r)(struct _reent *r,int fd,char *ptr,int len); - &nitroFSSeek, // int (*seek_r)(struct _reent *r,int fd,int pos,int dir); + NULL, // ssize_t (*write_r)(struct _reent *r,int fd,const char *ptr,size_t len); + &nitroFSRead, // ssize_t (*read_r)(struct _reent *r,int fd,char *ptr,size_t len); + &nitroFSSeek, // off_t (*seek_r)(struct _reent *r,int fd,off_t pos,int dir); &nitroFSFstat, // int (*fstat_r)(struct _reent *r,int fd,struct stat *st); NULL, // int (*stat_r)(struct _reent *r,const char *file,struct stat *st); NULL, // int (*link_r)(struct _reent *r,const char *existing, const char *newLink); @@ -97,8 +97,11 @@ devoptab_t nitroFSdevoptab={ &nitroFSDirOpen, // DIR_ITER* (*diropen_r)(struct _reent *r, DIR_ITER *dirState, const char *path); &nitroDirReset, // int (*dirreset_r)(struct _reent *r, DIR_ITER *dirState); &nitroFSDirNext, // int (*dirnext_r)(struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *filestat); - &nitroFSDirClose // int (*dirclose_r)(struct _reent *r, DIR_ITER *dirState); - + &nitroFSDirClose, // int (*dirclose_r)(struct _reent *r, DIR_ITER *dirState); + NULL, // int (*statvfs_r)(struct _reent *r, const char *path, struct statvfs *buf); + NULL, // int (*ftruncate_r)(struct _reent *r, int fd, off_t len); + NULL, // int (*fsync_r)(struct _reent *r, int fd); + NULL, // void *deviceData; }; //inline these mebbe? these 4 'sub' functions deal with actually reading from either gba rom or .nds file :) @@ -340,7 +343,7 @@ int nitroFSClose(struct _reent *r,int fd) { return(nitroSubClose(&((struct nitroFSStruct *)fd)->nrs)); } -int nitroFSRead(struct _reent *r,int fd,char *ptr,int len) { +ssize_t nitroFSRead(struct _reent *r,int fd,char *ptr,size_t len) { struct nitroFSStruct *fatStruct=(struct nitroFSStruct *)fd; struct nitroRawStruct *nrs=&((struct nitroFSStruct *)fd)->nrs; if(nrs->pos+len > fatStruct->end) @@ -350,7 +353,7 @@ int nitroFSRead(struct _reent *r,int fd,char *ptr,int len) { return(nitroSubRead(nrs,ptr,len)); } -int nitroFSSeek(struct _reent *r,int fd,int pos,int dir) { +off_t nitroFSSeek(struct _reent *r,int fd ,off_t pos,int dir) { //need check for eof here... struct nitroFSStruct *fatStruct=(struct nitroFSStruct *)fd; struct nitroRawStruct *nrs=&((struct nitroFSStruct *)fd)->nrs; diff --git a/source/bit_ops.h b/source/bit_ops.h index f823db7..762be0b 100644 --- a/source/bit_ops.h +++ b/source/bit_ops.h @@ -24,35 +24,34 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release */ #ifndef _BIT_OPS_H #define _BIT_OPS_H +#include + /*----------------------------------------------------------------- -Functions to deal with little endian values stored in u8 arrays +Functions to deal with little endian values stored in uint8_t arrays -----------------------------------------------------------------*/ -static inline u16 u8array_to_u16 (const u8* item, int offset) { +static inline uint16_t u8array_to_u16 (const uint8_t* item, int offset) { return ( item[offset] | (item[offset + 1] << 8)); } -static inline u32 u8array_to_u32 (const u8* item, int offset) { +static inline uint32_t u8array_to_u32 (const uint8_t* item, int offset) { return ( item[offset] | (item[offset + 1] << 8) | (item[offset + 2] << 16) | (item[offset + 3] << 24)); } -static inline void u16_to_u8array (u8* item, int offset, u16 value) { - item[offset] = (u8)value; - item[offset + 1] = (u8)(value >> 8); +static inline void u16_to_u8array (uint8_t* item, int offset, uint16_t value) { + item[offset] = (uint8_t) value; + item[offset + 1] = (uint8_t)(value >> 8); } -static inline void u32_to_u8array (u8* item, int offset, u32 value) { - item[offset] = (u8)value; - item[offset + 1] = (u8)(value >> 8); - item[offset + 2] = (u8)(value >> 16); - item[offset + 3] = (u8)(value >> 24); +static inline void u32_to_u8array (uint8_t* item, int offset, uint32_t value) { + item[offset] = (uint8_t) value; + item[offset + 1] = (uint8_t)(value >> 8); + item[offset + 2] = (uint8_t)(value >> 16); + item[offset + 3] = (uint8_t)(value >> 24); } #endif // _BIT_OPS_H diff --git a/source/cache.c b/source/cache.c index dfd759c..3d62bb8 100644 --- a/source/cache.c +++ b/source/cache.c @@ -31,13 +31,10 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2007-11-14 - Chishm - * Fixed _FAT_cache_constructor to return NULL on error, not false - * Fixed _FAT_cache_flush to return false on error. With thanks to xorloser */ #include +#include #include "common.h" #include "cache.h" @@ -46,11 +43,11 @@ #include "mem_allocate.h" #include "bit_ops.h" -#define CACHE_FREE 0xFFFFFFFF +#define CACHE_FREE UINT_MAX -CACHE* _FAT_cache_constructor (u32 numberOfPages, const IO_INTERFACE* discInterface) { +CACHE* _FAT_cache_constructor (unsigned int numberOfPages, const DISC_INTERFACE* discInterface) { CACHE* cache; - u32 i; + unsigned int i; CACHE_ENTRY* cacheEntries; if (numberOfPages < 2) { @@ -80,7 +77,7 @@ CACHE* _FAT_cache_constructor (u32 numberOfPages, const IO_INTERFACE* discInterf cache->cacheEntries = cacheEntries; - cache->pages = (u8*) _FAT_mem_allocate ( CACHE_PAGE_SIZE * numberOfPages); + cache->pages = (uint8_t*) _FAT_mem_allocate ( CACHE_PAGE_SIZE * numberOfPages); if (cache->pages == NULL) { _FAT_mem_free (cache->cacheEntries); _FAT_mem_free (cache); @@ -107,13 +104,13 @@ Retrieve a sector's page from the cache. If it is not found in the cache, load it into the cache and return the page it was loaded to. Return CACHE_FREE on error. */ -static u32 _FAT_cache_getSector (CACHE* cache, u32 sector) { - u32 i; +static unsigned int _FAT_cache_getSector (CACHE* cache, sec_t sector) { + unsigned int i; CACHE_ENTRY* cacheEntries = cache->cacheEntries; - u32 numberOfPages = cache->numberOfPages; + unsigned int numberOfPages = cache->numberOfPages; - u32 leastUsed = 0; - u32 lowestCount = 0xFFFFFFFF; + unsigned int leastUsed = 0; + unsigned int lowestCount = UINT_MAX; for (i = 0; (i < numberOfPages) && (cacheEntries[i].sector != sector); i++) { // While searching for the desired sector, also search for the leased used page @@ -153,8 +150,8 @@ static u32 _FAT_cache_getSector (CACHE* cache, u32 sector) { /* Reads some data from a cache page, determined by the sector number */ -bool _FAT_cache_readPartialSector (CACHE* cache, void* buffer, u32 sector, u32 offset, u32 size) { - u32 page; +bool _FAT_cache_readPartialSector (CACHE* cache, void* buffer, sec_t sector, unsigned int offset, size_t size) { + unsigned int page; if (offset + size > BYTES_PER_READ) { return false; @@ -168,8 +165,8 @@ bool _FAT_cache_readPartialSector (CACHE* cache, void* buffer, u32 sector, u32 o return true; } -bool _FAT_cache_readLittleEndianValue (CACHE* cache, u32 *value, u32 sector, u32 offset, u32 num_bytes) { - u8 buf[4]; +bool _FAT_cache_readLittleEndianValue (CACHE* cache, uint32_t *value, sec_t sector, unsigned int offset, int num_bytes) { + uint8_t buf[4]; if (!_FAT_cache_readPartialSector(cache, buf, sector, offset, num_bytes)) return false; switch(num_bytes) { @@ -184,8 +181,8 @@ bool _FAT_cache_readLittleEndianValue (CACHE* cache, u32 *value, u32 sector, u32 /* Writes some data to a cache page, making sure it is loaded into memory first. */ -bool _FAT_cache_writePartialSector (CACHE* cache, const void* buffer, u32 sector, u32 offset, u32 size) { - u32 page; +bool _FAT_cache_writePartialSector (CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size) { + unsigned int page; if (offset + size > BYTES_PER_READ) { return false; @@ -202,8 +199,8 @@ bool _FAT_cache_writePartialSector (CACHE* cache, const void* buffer, u32 sector return true; } -bool _FAT_cache_writeLittleEndianValue (CACHE* cache, const u32 value, u32 sector, u32 offset, u32 size) { - u8 buf[4] = {0, 0, 0, 0}; +bool _FAT_cache_writeLittleEndianValue (CACHE* cache, const uint32_t value, sec_t sector, unsigned int offset, int size) { + uint8_t buf[4] = {0, 0, 0, 0}; switch(size) { case 1: buf[0] = value; break; @@ -218,8 +215,8 @@ bool _FAT_cache_writeLittleEndianValue (CACHE* cache, const u32 value, u32 secto /* Writes some data to a cache page, zeroing out the page first */ -bool _FAT_cache_eraseWritePartialSector (CACHE* cache, const void* buffer, u32 sector, u32 offset, u32 size) { - u32 page; +bool _FAT_cache_eraseWritePartialSector (CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size) { + unsigned int page; if (offset + size > BYTES_PER_READ) { return false; @@ -243,7 +240,7 @@ Flushes all dirty pages to disc, clearing the dirty flag. Also resets all pages' page count to 0. */ bool _FAT_cache_flush (CACHE* cache) { - u32 i; + unsigned int i; for (i = 0; i < cache->numberOfPages; i++) { if (cache->cacheEntries[i].dirty) { @@ -259,7 +256,7 @@ bool _FAT_cache_flush (CACHE* cache) { } void _FAT_cache_invalidate (CACHE* cache) { - int i; + unsigned int i; for (i = 0; i < cache->numberOfPages; i++) { cache->cacheEntries[i].sector = CACHE_FREE; cache->cacheEntries[i].count = 0; diff --git a/source/cache.h b/source/cache.h index 1e6c277..de4866a 100644 --- a/source/cache.h +++ b/source/cache.h @@ -31,9 +31,6 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release */ #ifndef _CACHE_H @@ -45,16 +42,16 @@ #define CACHE_PAGE_SIZE BYTES_PER_READ typedef struct { - u32 sector; - u32 count; - bool dirty; + sec_t sector; + unsigned int count; + bool dirty; } CACHE_ENTRY; typedef struct { - const IO_INTERFACE* disc; - u32 numberOfPages; - CACHE_ENTRY* cacheEntries; - u8* pages; + const DISC_INTERFACE* disc; + unsigned int numberOfPages; + CACHE_ENTRY* cacheEntries; + uint8_t* pages; } CACHE; @@ -65,43 +62,43 @@ offset is the position to start reading from size is the amount of data to read Precondition: offset + size <= BYTES_PER_READ */ -bool _FAT_cache_readPartialSector (CACHE* cache, void* buffer, u32 sector, u32 offset, u32 size); +bool _FAT_cache_readPartialSector (CACHE* cache, void* buffer, sec_t sector, unsigned int offset, size_t size); -bool _FAT_cache_readLittleEndianValue (CACHE* cache, u32 *value, u32 sector, u32 offset, u32 num_bytes); +bool _FAT_cache_readLittleEndianValue (CACHE* cache, uint32_t *value, sec_t sector, unsigned int offset, int num_bytes); /* Write data to a sector in the cache If the sector is not in the cache, it will be swapped in. When the sector is swapped out, the data will be written to the disc -offset is the position to start reading from -size is the amount of data to read +offset is the position to start writing to +size is the amount of data to write Precondition: offset + size <= BYTES_PER_READ */ -bool _FAT_cache_writePartialSector (CACHE* cache, const void* buffer, u32 sector, u32 offset, u32 size); +bool _FAT_cache_writePartialSector (CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size); -bool _FAT_cache_writeLittleEndianValue (CACHE* cache, const u32 value, u32 sector, u32 offset, u32 num_bytes); +bool _FAT_cache_writeLittleEndianValue (CACHE* cache, const uint32_t value, sec_t sector, unsigned int offset, int num_bytes); /* Write data to a sector in the cache, zeroing the sector first If the sector is not in the cache, it will be swapped in. When the sector is swapped out, the data will be written to the disc -offset is the position to start reading from -size is the amount of data to read +offset is the position to start writing to +size is the amount of data to write Precondition: offset + size <= BYTES_PER_READ */ -bool _FAT_cache_eraseWritePartialSector (CACHE* cache, const void* buffer, u32 sector, u32 offset, u32 size); +bool _FAT_cache_eraseWritePartialSector (CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size); /* Read a full sector from the cache */ -static inline bool _FAT_cache_readSector (CACHE* cache, void* buffer, u32 sector) { +static inline bool _FAT_cache_readSector (CACHE* cache, void* buffer, sec_t sector) { return _FAT_cache_readPartialSector (cache, buffer, sector, 0, BYTES_PER_READ); } /* Write a full sector to the cache */ -static inline bool _FAT_cache_writeSector (CACHE* cache, const void* buffer, u32 sector) { +static inline bool _FAT_cache_writeSector (CACHE* cache, const void* buffer, sec_t sector) { return _FAT_cache_writePartialSector (cache, buffer, sector, 0, BYTES_PER_READ); } @@ -115,7 +112,7 @@ Clear out the contents of the cache without writing any dirty sectors first */ void _FAT_cache_invalidate (CACHE* cache); -CACHE* _FAT_cache_constructor (u32 numberOfPages, const IO_INTERFACE* discInterface); +CACHE* _FAT_cache_constructor (unsigned int numberOfPages, const DISC_INTERFACE* discInterface); void _FAT_cache_destructor (CACHE* cache); diff --git a/source/common.h b/source/common.h index 80b75ae..354c689 100644 --- a/source/common.h +++ b/source/common.h @@ -24,14 +24,16 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release */ #ifndef _COMMON_H #define _COMMON_H +#define BYTES_PER_READ 512 +#include +#include +#include + // When compiling for NDS, make sure NDS is defined #ifndef NDS #if defined ARM9 || defined ARM7 @@ -39,24 +41,34 @@ #endif #endif +// Platform specific includes #if defined(__gamecube__) || defined (__wii__) #include -#else -# ifdef NDS + #include + #include +#elif defined(NDS) #include #include - -# else - #include "gba_types.h" -# endif + #include +#elif defined(GBA) + #include + #include #endif -#define BYTES_PER_READ 512 - -#ifndef NULL - #define NULL 0 +// Platform specific options +#if defined (__wii__) + #define DEFAULT_CACHE_PAGES 8 + #define USE_LWP_LOCK + #define USE_RTC_TIME +#elif defined (__gamecube__) + #define DEFAULT_CACHE_PAGES 8 + #define USE_LWP_LOCK + #define USE_RTC_TIME +#elif defined (NDS) + #define DEFAULT_CACHE_PAGES 8 + #define USE_RTC_TIME +#elif defined (GBA) + #define DEFAULT_CACHE_PAGES 2 #endif -#include - #endif // _COMMON_H diff --git a/source/directory.c b/source/directory.c index 4d6e008..18ebe36 100644 --- a/source/directory.c +++ b/source/directory.c @@ -25,47 +25,6 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-08-14 - Chishm - * entryFromPath correctly finds "" and "." now - - 2006-08-17 - Chishm - * entryFromPath doesn't look for "" anymore - use "." to refer to the current directory - - 2006-08-19 - Chishm - * Fixed entryFromPath bug when looking for "." in root directory - - 2006-10-01 - Chishm - * Now clears the whole new cluster when linking in more clusters for a directory - - 2006-10-28 - Chishm - * stat returns the hostType for the st_dev value - - 2007-03-14 - Chishm - * Check long file names for buffer overflow - - 2007-04-22 - Chishm - * Added space to list of illegal alias characters - fixes filename creation bug when filename contained a space - - 2007-09-01 - Chishm - * Use CLUSTER_ERROR when an error occurs with the FAT, not CLUSTER_FREE - - 2007-11-01 - Chishm - * Added unicode support - - 2007-11-04 - Chishm - * Fixed alias creation bugs - - 2007-11-16 - Chishm - * Fixed LFN creation with character codes > 0x7F - - 2008-08-02 - Chishm - * Correct cluster given on FAT32 when .. entry is included in path to subdirectory - * Fixed creation of long filename entry for all-caps filenames longer than 8 characters - - 2008-09-07 - Chishm - * Don't read high 16 bits of start cluster from a directory entry on non-FAT32 partititions, in case it contains non-zero data - * Thanks to Chris Liu */ #include @@ -73,6 +32,7 @@ #include #include #include +#include #include "directory.h" #include "common.h" @@ -125,8 +85,8 @@ Returns -1 if it is an invalid LFN */ #define ABOVE_UCS_RANGE 0xF0 static int _FAT_directory_lfnLength (const char* name) { - u32 i; - u32 nameLength; + unsigned int i; + size_t nameLength; int ucsLength; const char* tempName = name; @@ -185,7 +145,7 @@ static size_t _FAT_directory_mbstoucs2 (ucs2_t* dst, const char* src, size_t len /* Convert a UCS-2 string into a NUL-terminated multibyte string, storing at most len chars -return number of chars stored +return number of chars stored, or (size_t)-1 on error */ static size_t _FAT_directory_ucs2tombs (char* dst, const ucs2_t* src, size_t len) { mbstate_t ps = {0}; @@ -194,7 +154,7 @@ static size_t _FAT_directory_ucs2tombs (char* dst, const ucs2_t* src, size_t len char buff[MB_CUR_MAX]; int i; - while (count < len - 1 && src != '\0') { + while (count < len - 1 && *src != '\0') { bytes = wcrtomb (buff, *src, &ps); if (bytes < 0) { return -1; @@ -233,7 +193,7 @@ static int _FAT_directory_mbsncasecmp (const char* s1, const char* s2, size_t le s2 += b2; b1 = mbrtowc(&wc1, s1, MB_CUR_MAX, &ps1); b2 = mbrtowc(&wc2, s2, MB_CUR_MAX, &ps2); - if (b1 < 0 || b2 < 0) { + if ((int)b1 < 0 || (int)b2 < 0) { break; } len1 -= b1; @@ -276,7 +236,7 @@ static bool _FAT_directory_entryGetAlias (const u8* entryData, char* destName) { return (destName[0] != '\0'); } -u32 _FAT_directory_entryGetCluster (PARTITION* partition, const u8* entryData) { +uint32_t _FAT_directory_entryGetCluster (PARTITION* partition, const uint8_t* entryData) { if (partition->filesysType == FS_FAT32) { // Only use high 16 bits of start cluster when we are certain they are correctly defined return u8array_to_u16(entryData,DIR_ENTRY_cluster) | (u8array_to_u16(entryData, DIR_ENTRY_clusterHigh) << 16); @@ -286,9 +246,8 @@ u32 _FAT_directory_entryGetCluster (PARTITION* partition, const u8* entryData) { } static bool _FAT_directory_incrementDirEntryPosition (PARTITION* partition, DIR_ENTRY_POSITION* entryPosition, bool extendDirectory) { - DIR_ENTRY_POSITION position; - position = *entryPosition; - u32 tempCluster; + DIR_ENTRY_POSITION position = *entryPosition; + uint32_t tempCluster; // Increment offset, wrapping at the end of a sector ++ position.offset; @@ -323,17 +282,12 @@ static bool _FAT_directory_incrementDirEntryPosition (PARTITION* partition, DIR_ bool _FAT_directory_getNextEntry (PARTITION* partition, DIR_ENTRY* entry) { DIR_ENTRY_POSITION entryStart; DIR_ENTRY_POSITION entryEnd; - - u8 entryData[0x20]; - + uint8_t entryData[0x20]; ucs2_t lfn[MAX_LFN_LENGTH]; - bool notFound, found; - u32 maxSectors; int lfnPos; - u8 lfnChkSum, chkSum; + uint8_t lfnChkSum, chkSum; bool lfnExists; - int i; lfnChkSum = 0; @@ -347,13 +301,6 @@ bool _FAT_directory_getNextEntry (PARTITION* partition, DIR_ENTRY* entry) { entryEnd = entryStart; - // Can only be FAT16_ROOT_DIR_CLUSTER if it is the root directory on a FAT12 or FAT16 partition - if (entryStart.cluster == FAT16_ROOT_DIR_CLUSTER) { - maxSectors = partition->dataStart - partition->rootDirStart; - } else { - maxSectors = partition->sectorsPerCluster; - } - lfnExists = false; found = false; @@ -364,7 +311,9 @@ bool _FAT_directory_getNextEntry (PARTITION* partition, DIR_ENTRY* entry) { notFound = true; } - _FAT_cache_readPartialSector (partition->cache, entryData, _FAT_fat_clusterToSector(partition, entryEnd.cluster) + entryEnd.sector, entryEnd.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); + _FAT_cache_readPartialSector (partition->cache, entryData, + _FAT_fat_clusterToSector(partition, entryEnd.cluster) + entryEnd.sector, + entryEnd.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); if (entryData[DIR_ENTRY_attributes] == ATTRIB_LFN) { // It's an LFN @@ -412,7 +361,7 @@ bool _FAT_directory_getNextEntry (PARTITION* partition, DIR_ENTRY* entry) { } if (lfnExists) { - if (_FAT_directory_ucs2tombs (entry->filename, lfn, MAX_FILENAME_LENGTH) < 0) { + if (_FAT_directory_ucs2tombs (entry->filename, lfn, MAX_FILENAME_LENGTH) == (size_t)-1) { // Failed to convert the file name to UTF-8. Maybe the wrong locale is set? return false; } @@ -436,7 +385,7 @@ bool _FAT_directory_getNextEntry (PARTITION* partition, DIR_ENTRY* entry) { } } -bool _FAT_directory_getFirstEntry (PARTITION* partition, DIR_ENTRY* entry, u32 dirCluster) { +bool _FAT_directory_getFirstEntry (PARTITION* partition, DIR_ENTRY* entry, uint32_t dirCluster) { entry->dataStart.cluster = dirCluster; entry->dataStart.sector = 0; entry->dataStart.offset = -1; // Start before the beginning of the directory @@ -469,19 +418,14 @@ bool _FAT_directory_getRootEntry (PARTITION* partition, DIR_ENTRY* entry) { } bool _FAT_directory_entryFromPosition (PARTITION* partition, DIR_ENTRY* entry) { - DIR_ENTRY_POSITION entryStart; - DIR_ENTRY_POSITION entryEnd; - entryStart = entry->dataStart; - entryEnd = entry->dataEnd; + DIR_ENTRY_POSITION entryStart = entry->dataStart; + DIR_ENTRY_POSITION entryEnd = entry->dataEnd; bool entryStillValid; bool finished; - ucs2_t lfn[MAX_LFN_LENGTH]; - int i; int lfnPos; - - u8 entryData[DIR_ENTRY_DATA_SIZE]; + uint8_t entryData[DIR_ENTRY_DATA_SIZE]; memset (entry->filename, '\0', MAX_FILENAME_LENGTH); @@ -525,7 +469,7 @@ bool _FAT_directory_entryFromPosition (PARTITION* partition, DIR_ENTRY* entry) { } } else { // Encode the long file name into a multibyte string - if (_FAT_directory_ucs2tombs (entry->filename, lfn, MAX_FILENAME_LENGTH) < 0) { + if (_FAT_directory_ucs2tombs (entry->filename, lfn, MAX_FILENAME_LENGTH) == (size_t)-1) { return false; } } @@ -539,11 +483,9 @@ bool _FAT_directory_entryFromPath (PARTITION* partition, DIR_ENTRY* entry, const size_t dirnameLength; const char* pathPosition; const char* nextPathPosition; - u32 dirCluster; + uint32_t dirCluster; bool foundFile; - char alias[MAX_ALIAS_LENGTH]; - bool found, notFound; pathPosition = path; @@ -659,14 +601,11 @@ bool _FAT_directory_entryFromPath (PARTITION* partition, DIR_ENTRY* entry, const } bool _FAT_directory_removeEntry (PARTITION* partition, DIR_ENTRY* entry) { - DIR_ENTRY_POSITION entryStart; - DIR_ENTRY_POSITION entryEnd; - entryStart = entry->dataStart; - entryEnd = entry->dataEnd; + DIR_ENTRY_POSITION entryStart = entry->dataStart; + DIR_ENTRY_POSITION entryEnd = entry->dataEnd; bool entryStillValid; bool finished; - - u8 entryData[DIR_ENTRY_DATA_SIZE]; + uint8_t entryData[DIR_ENTRY_DATA_SIZE]; // Create an empty directory entry to overwrite the old ones with for ( entryStillValid = true, finished = false; @@ -688,14 +627,11 @@ bool _FAT_directory_removeEntry (PARTITION* partition, DIR_ENTRY* entry) { return true; } -static bool _FAT_directory_findEntryGap (PARTITION* partition, DIR_ENTRY* entry, u32 dirCluster, u32 size) { +static bool _FAT_directory_findEntryGap (PARTITION* partition, DIR_ENTRY* entry, uint32_t dirCluster, size_t size) { DIR_ENTRY_POSITION gapStart; DIR_ENTRY_POSITION gapEnd; - - u8 entryData[DIR_ENTRY_DATA_SIZE]; - - u32 dirEntryRemain; - + uint8_t entryData[DIR_ENTRY_DATA_SIZE]; + size_t dirEntryRemain; bool endOfDirectory, entryStillValid; // Scan Dir for free entry @@ -763,11 +699,11 @@ static bool _FAT_directory_findEntryGap (PARTITION* partition, DIR_ENTRY* entry, return true; } -static bool _FAT_directory_entryExists (PARTITION* partition, const char* name, u32 dirCluster) { +static bool _FAT_directory_entryExists (PARTITION* partition, const char* name, uint32_t dirCluster) { DIR_ENTRY tempEntry; bool foundFile; char alias[MAX_ALIAS_LENGTH]; - u32 dirnameLength; + size_t dirnameLength; dirnameLength = strnlen(name, MAX_FILENAME_LENGTH); @@ -835,7 +771,7 @@ static int _FAT_directory_createAlias (char* alias, const char* lfn) { lfnPos += bytesUsed; continue; } - if (oemChar == WEOF) { + if (oemChar == EOF) { oemChar = '_'; // Replace unconvertable characters with underscores lossyConversion = true; } @@ -882,7 +818,7 @@ static int _FAT_directory_createAlias (char* alias, const char* lfn) { lfnExt += bytesUsed; continue; } - if (oemChar == WEOF) { + if (oemChar == EOF) { oemChar = '_'; // Replace unconvertable characters with underscores lossyConversion = true; } @@ -910,14 +846,14 @@ static int _FAT_directory_createAlias (char* alias, const char* lfn) { } } -bool _FAT_directory_addEntry (PARTITION* partition, DIR_ENTRY* entry, u32 dirCluster) { - u32 entrySize; - u8 lfnEntry[DIR_ENTRY_DATA_SIZE]; - s32 i,j; // Must be signed for use when decrementing in for loop +bool _FAT_directory_addEntry (PARTITION* partition, DIR_ENTRY* entry, uint32_t dirCluster) { + size_t entrySize; + uint8_t lfnEntry[DIR_ENTRY_DATA_SIZE]; + int i,j; // Must be signed for use when decrementing in for loop char *tmpCharPtr; DIR_ENTRY_POSITION curEntryPos; bool entryStillValid; - u8 aliasCheckSum = 0; + uint8_t aliasCheckSum = 0; char alias [MAX_ALIAS_LENGTH]; int aliasLen; int lfnLen; @@ -938,7 +874,7 @@ bool _FAT_directory_addEntry (PARTITION* partition, DIR_ENTRY* entry, u32 dirClu entry->filename[i] = '\0'; } // Remove leading spaces - for (i = 0; (i < strlen (entry->filename)) && (entry->filename[i] == ' '); ++i) ; + for (i = 0; (i < (int)strlen (entry->filename)) && (entry->filename[i] == ' '); ++i) ; if (i > 0) { memmove (entry->filename, entry->filename + i, strlen (entry->filename + i)); } @@ -1060,7 +996,7 @@ bool _FAT_directory_addEntry (PARTITION* partition, DIR_ENTRY* entry, u32 dirClu { if (i > 1) { // Long filename entry - lfnEntry[LFN_offset_ordinal] = (i - 1) | (i == entrySize ? LFN_END : 0); + lfnEntry[LFN_offset_ordinal] = (i - 1) | ((size_t)i == entrySize ? LFN_END : 0); for (j = 0; j < 13; j++) { if (lfn [(i - 2) * 13 + j] == '\0') { if ((j > 1) && (lfn [(i - 2) * 13 + (j-1)] == '\0')) { diff --git a/source/directory.h b/source/directory.h index 5e34e8d..7ad5306 100644 --- a/source/directory.h +++ b/source/directory.h @@ -25,16 +25,6 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release - - 2007-11-01 - Chishm - * Added unicode support - - 2008-09-07 - Chishm - * Don't read high 16 bits of start cluster from a directory entry on non-FAT32 partititions, in case it contains non-zero data - * Thanks to Chris Liu */ #ifndef _DIRECTORY_H @@ -70,16 +60,16 @@ typedef enum {FT_DIRECTORY, FT_FILE} FILE_TYPE; typedef struct { - u32 cluster; - u32 sector; - s32 offset; + uint32_t cluster; + sec_t sector; + int32_t offset; } DIR_ENTRY_POSITION; typedef struct { - u8 entryData[DIR_ENTRY_DATA_SIZE]; + uint8_t entryData[DIR_ENTRY_DATA_SIZE]; DIR_ENTRY_POSITION dataStart; // Points to the start of the LFN entries of a file, or the alias for no LFN DIR_ENTRY_POSITION dataEnd; // Always points to the file/directory's alias entry - char filename[MAX_FILENAME_LENGTH]; + char filename[MAX_FILENAME_LENGTH]; } DIR_ENTRY; // Directory entry offsets @@ -121,7 +111,7 @@ Places result in entry entry will be destroyed even if no directory entry is found Returns true on success, false on failure */ -bool _FAT_directory_getFirstEntry (PARTITION* partition, DIR_ENTRY* entry, u32 dirCluster); +bool _FAT_directory_getFirstEntry (PARTITION* partition, DIR_ENTRY* entry, uint32_t dirCluster); /* Reads the next directory entry after the one already pointed to by entry @@ -161,12 +151,12 @@ The fileData, dataStart and dataEnd elements of the DIR_ENTRY struct are updated with the new directory entry position and alias. Returns true on success, false on failure */ -bool _FAT_directory_addEntry (PARTITION* partition, DIR_ENTRY* entry, u32 dirCluster); +bool _FAT_directory_addEntry (PARTITION* partition, DIR_ENTRY* entry, uint32_t dirCluster); /* Get the start cluster of a file from it's entry data */ -u32 _FAT_directory_entryGetCluster (PARTITION* partition, const u8* entryData); +uint32_t _FAT_directory_entryGetCluster (PARTITION* partition, const uint8_t* entryData); /* Fill in the file name and entry data of DIR_ENTRY* entry. diff --git a/source/disc.h b/source/disc.h index 9ec9fc0..d9f3c04 100644 --- a/source/disc.h +++ b/source/disc.h @@ -25,81 +25,28 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release - */ #ifndef _DISC_H #define _DISC_H #include "common.h" -//---------------------------------------------------------------------- -// Customisable features - -// Use DMA to read the card, remove this line to use normal reads/writes -// #define _IO_USE_DMA - -// Allow buffers not alligned to 16 bits when reading files. -// Note that this will slow down access speed, so only use if you have to. -// It is also incompatible with DMA -#define _IO_ALLOW_UNALIGNED - -#if defined _IO_USE_DMA && defined _IO_ALLOW_UNALIGNED - #error "You can't use both DMA and unaligned memory" -#endif - -#define DEVICE_TYPE_WII 0 -#define DEVICE_TYPE_GC 1 - -#define FEATURE_MEDIUM_CANREAD 0x00000001 -#define FEATURE_MEDIUM_CANWRITE 0x00000002 -#define FEATURE_SLOT_GBA 0x00000010 -#define FEATURE_SLOT_NDS 0x00000020 -#define FEATURE_GAMECUBE_SLOTA 0x00000010 -#define FEATURE_GAMECUBE_SLOTB 0x00000020 - -typedef bool (* FN_MEDIUM_STARTUP)(void) ; -typedef bool (* FN_MEDIUM_ISINSERTED)(void) ; -typedef bool (* FN_MEDIUM_READSECTORS)(u32 sector, u32 numSectors, void* buffer) ; -typedef bool (* FN_MEDIUM_WRITESECTORS)(u32 sector, u32 numSectors, const void* buffer) ; -typedef bool (* FN_MEDIUM_CLEARSTATUS)(void) ; -typedef bool (* FN_MEDIUM_SHUTDOWN)(void) ; - -struct IO_INTERFACE_STRUCT { - unsigned long ioType ; - unsigned long features ; - FN_MEDIUM_STARTUP fn_startup ; - FN_MEDIUM_ISINSERTED fn_isInserted ; - FN_MEDIUM_READSECTORS fn_readSectors ; - FN_MEDIUM_WRITESECTORS fn_writeSectors ; - FN_MEDIUM_CLEARSTATUS fn_clearStatus ; - FN_MEDIUM_SHUTDOWN fn_shutdown ; -} ; - -typedef struct IO_INTERFACE_STRUCT IO_INTERFACE ; - /* -Search for a block based device in all available slots. -Return a pointer to a usable interface if one is found, -NULL if not. +A list of all default devices to try at startup, +terminated by a {NULL,NULL} entry. */ -extern const IO_INTERFACE* _FAT_disc_findInterface (void); - -/* -Search for a block based device in a specific slot. -Return a pointer to a usable interface if one is found, -NULL if not. -*/ -extern const IO_INTERFACE* _FAT_disc_findInterfaceSlot (PARTITION_INTERFACE partitionNumber); +typedef struct { + const char* name; + const DISC_INTERFACE* (*getInterface)(void); +} INTERFACE_ID; +extern const INTERFACE_ID _FAT_disc_interfaces[]; /* Check if a disc is inserted Return true if a disc is inserted and ready, false otherwise */ -static inline bool _FAT_disc_isInserted (const IO_INTERFACE* disc) { - return disc->fn_isInserted(); +static inline bool _FAT_disc_isInserted (const DISC_INTERFACE* disc) { + return disc->isInserted(); } /* @@ -108,8 +55,8 @@ numSectors is between 1 and 256 sector is from 0 to 2^28 buffer is a pointer to the memory to fill */ -static inline bool _FAT_disc_readSectors (const IO_INTERFACE* disc, u32 sector, u32 numSectors, void* buffer) { - return disc->fn_readSectors (sector, numSectors, buffer); +static inline bool _FAT_disc_readSectors (const DISC_INTERFACE* disc, sec_t sector, sec_t numSectors, void* buffer) { + return disc->readSectors (sector, numSectors, buffer); } /* @@ -118,43 +65,43 @@ numSectors is between 1 and 256 sector is from 0 to 2^28 buffer is a pointer to the memory to read from */ -static inline bool _FAT_disc_writeSectors (const IO_INTERFACE* disc, u32 sector, u32 numSectors, const void* buffer) { - return disc->fn_writeSectors (sector, numSectors, buffer); +static inline bool _FAT_disc_writeSectors (const DISC_INTERFACE* disc, sec_t sector, sec_t numSectors, const void* buffer) { + return disc->writeSectors (sector, numSectors, buffer); } /* Reset the card back to a ready state */ -static inline bool _FAT_disc_clearStatus (const IO_INTERFACE* disc) { - return disc->fn_clearStatus(); +static inline bool _FAT_disc_clearStatus (const DISC_INTERFACE* disc) { + return disc->clearStatus(); } /* Initialise the disc to a state ready for data reading or writing */ -static inline bool _FAT_disc_startup (const IO_INTERFACE* disc) { - return disc->fn_startup(); +static inline bool _FAT_disc_startup (const DISC_INTERFACE* disc) { + return disc->startup(); } /* Put the disc in a state ready for power down. Complete any pending writes and disable the disc if necessary */ -static inline bool _FAT_disc_shutdown (const IO_INTERFACE* disc) { - return disc->fn_shutdown(); +static inline bool _FAT_disc_shutdown (const DISC_INTERFACE* disc) { + return disc->shutdown(); } /* Return a 32 bit value unique to each type of interface */ -static inline u32 _FAT_disc_hostType (const IO_INTERFACE* disc) { +static inline uint32_t _FAT_disc_hostType (const DISC_INTERFACE* disc) { return disc->ioType; } /* Return a 32 bit value that specifies the capabilities of the disc */ -static inline u32 _FAT_disc_features (const IO_INTERFACE* disc) { +static inline uint32_t _FAT_disc_features (const DISC_INTERFACE* disc) { return disc->features; } diff --git a/source/disc_io/disc.c b/source/disc_io/disc.c deleted file mode 100644 index 9684057..0000000 --- a/source/disc_io/disc.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - - disc.c - - uniformed io-interface to work with Chishm's FAT library - - Written by MightyMax - - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2005-11-06 - Chishm - * Added WAIT_CR modifications for NDS - - 2006-02-03 www.neoflash.com - * Added SUPPORT_* defines, comment out any of the SUPPORT_* defines in disc_io.h to remove support - for the given interface and stop code being linked to the binary - - * Added support for MK2 MMC interface - - * Added disc_Cache* functions - - 2006-02-05 - Chishm - * Added Supercard SD support - - 2006-02-26 - Cytex - * Added EFA2 support - - 2006-05-18 - Chishm - * Rewritten for FATlib disc.c - - 2006-06-19 - Chishm - * Changed read and write interface to accept a u32 instead of a u8 for the number of sectors - - 2006-07-11 - Chishm - * Removed disc_Cache* functions, since there is now a proper unified cache - * Removed SUPPORT_* defines - * Rewrote device detection functions - * First libfat release - - 2006-07-25 - Chishm - * Changed IO_INTERFACEs to const - - 2006-08-02 - Chishm - * Added NinjaDS - - 2006-12-25 - Chishm - * Added DLDI - * Removed experimental interfaces - - 2007-05-01 - Chishm - * Removed FCSR -*/ - -#include "../disc.h" - -#ifdef NDS - #include -#endif - -#include - -// Include known io-interfaces: -#include "io_dldi.h" -#include "io_njsd.h" -#include "io_nmmc.h" -#include "io_mpcf.h" -#include "io_m3cf.h" -#include "io_sccf.h" -#include "io_scsd.h" -#include "io_m3sd.h" - -const IO_INTERFACE* ioInterfaces[] = { - &_io_dldi, // Reserved for new interfaces -#ifdef NDS - // Place Slot 1 (DS Card) interfaces here - &_io_njsd, &_io_nmmc, -#endif - // Place Slot 2 (GBA Cart) interfaces here - &_io_mpcf, &_io_m3cf, &_io_sccf, &_io_scsd, &_io_m3sd -}; - -/* - - Hardware level disc funtions - -*/ - -const IO_INTERFACE* _FAT_disc_gbaSlotFindInterface (void) -{ - // If running on an NDS, make sure the correct CPU can access - // the GBA cart. First implemented by SaTa. -#ifdef NDS - #ifdef ARM9 - sysSetCartOwner(BUS_OWNER_ARM9); - #endif -#endif - - int i; - - for (i = 0; i < (sizeof(ioInterfaces) / sizeof(IO_INTERFACE*)); i++) { - if ((ioInterfaces[i]->features & FEATURE_SLOT_GBA) && (ioInterfaces[i]->fn_startup())) { - return ioInterfaces[i]; - } - } - return NULL; -} - -#ifdef NDS -/* - * Check the DS card slot for a valid memory card interface - * If an interface is found, it is set as the default interace - * and it returns true. Otherwise the default interface is left - * untouched and it returns false. - */ -const IO_INTERFACE* _FAT_disc_dsSlotFindInterface (void) -{ -#ifdef ARM9 - sysSetCardOwner(BUS_OWNER_ARM9); -#endif - int i; - - for (i = 0; i < (sizeof(ioInterfaces) / sizeof(IO_INTERFACE*)); i++) { - if ((ioInterfaces[i]->features & FEATURE_SLOT_NDS) && (ioInterfaces[i]->fn_startup())) { - return ioInterfaces[i]; - } - } - - return NULL; -} -#endif - -/* - * When running on an NDS, check the either slot for a valid memory - * card interface. - * When running on a GBA, call _FAT_disc_gbaSlotFindInterface - * If an interface is found, it is set as the default interace - * and it returns true. Otherwise the default interface is left - * untouched and it returns false. - */ -#ifdef NDS -const IO_INTERFACE* _FAT_disc_findInterface (void) -{ -#ifdef ARM9 - sysSetBusOwners(BUS_OWNER_ARM9, BUS_OWNER_ARM9); -#endif - - int i; - - for (i = 0; i < (sizeof(ioInterfaces) / sizeof(IO_INTERFACE*)); i++) { - if (ioInterfaces[i]->fn_startup()) { - return ioInterfaces[i]; - } - } - - return NULL; -} -#else -const IO_INTERFACE* _FAT_disc_findInterface (void) -{ - return _FAT_disc_gbaSlotFindInterface(); -} -#endif - -const IO_INTERFACE* _FAT_disc_findInterfaceSlot (PARTITION_INTERFACE partitionNumber) -{ - -#ifdef NDS - switch (partitionNumber) { - case PI_SLOT_1: - // Mount the disc in slot 1 - return _FAT_disc_dsSlotFindInterface (); - break; - case PI_SLOT_2: - // Mount the disc in slot 2 - return _FAT_disc_gbaSlotFindInterface (); - break; - case PI_DEFAULT: - case PI_CUSTOM: - default: - // Anything else has to be handled specially - return NULL; - break; - } -#else - return _FAT_disc_gbaSlotFindInterface (); -#endif - -} diff --git a/source/disc_io/io_cf_common.c b/source/disc_io/io_cf_common.c deleted file mode 100644 index f405d85..0000000 --- a/source/disc_io/io_cf_common.c +++ /dev/null @@ -1,322 +0,0 @@ -/* - io_cf_common.c based on - - compact_flash.c - By chishm (Michael Chisholm) - - Common hardware routines for using a compact flash card. This is not reentrant - and does not do range checking on the supplied addresses. This is designed to - be as fast as possible. - - CF routines modified with help from Darkfader - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include "io_cf_common.h" - -//--------------------------------------------------------------- -// DMA -#ifdef _IO_USE_DMA - #ifndef NDS - #include "gba_dma.h" - #else - #include - #ifdef ARM9 - #include - #endif - #endif -#endif - -//--------------------------------------------------------------- -// CF Addresses & Commands - -CF_REGISTERS cfRegisters = {0}; - - -/*----------------------------------------------------------------- -_CF_isInserted -Is a compact flash card inserted? -bool return OUT: true if a CF card is inserted ------------------------------------------------------------------*/ -bool _CF_isInserted (void) { - // Change register, then check if value did change - *(cfRegisters.status) = CF_STS_INSERTED; - return ((*(cfRegisters.status) & 0xff) == CF_STS_INSERTED); -} - - -/*----------------------------------------------------------------- -_CF_clearStatus -Tries to make the CF card go back to idle mode -bool return OUT: true if a CF card is idle ------------------------------------------------------------------*/ -bool _CF_clearStatus (void) { - int i; - - // Wait until CF card is finished previous commands - i=0; - while ((*(cfRegisters.command) & CF_STS_BUSY) && (i < CF_CARD_TIMEOUT)) { - i++; - } - - // Wait until card is ready for commands - i = 0; - while ((!(*(cfRegisters.status) & CF_STS_INSERTED)) && (i < CF_CARD_TIMEOUT)) { - i++; - } - if (i >= CF_CARD_TIMEOUT) - return false; - - return true; -} - - -/*----------------------------------------------------------------- -_CF_readSectors -Read 512 byte sector numbered "sector" into "buffer" -u32 sector IN: address of first 512 byte sector on CF card to read -u32 numSectors IN: number of 512 byte sectors to read, - 1 to 256 sectors can be read -void* buffer OUT: pointer to 512 byte buffer to store data in -bool return OUT: true if successful ------------------------------------------------------------------*/ -bool _CF_readSectors (u32 sector, u32 numSectors, void* buffer) { - int i; - - u16 *buff = (u16*)buffer; -#ifdef _IO_ALLOW_UNALIGNED - u8 *buff_u8 = (u8*)buffer; - int temp; -#endif - -#if (defined _IO_USE_DMA) && (defined NDS) && (defined ARM9) - DC_FlushRange( buffer, j * BYTES_PER_READ); -#endif - - // Wait until CF card is finished previous commands - i=0; - while ((*(cfRegisters.command) & CF_STS_BUSY) && (i < CF_CARD_TIMEOUT)) { - i++; - } - - // Wait until card is ready for commands - i = 0; - while ((!(*(cfRegisters.status) & CF_STS_INSERTED)) && (i < CF_CARD_TIMEOUT)) { - i++; - } - if (i >= CF_CARD_TIMEOUT) - return false; - - // Set number of sectors to read - *(cfRegisters.sectorCount) = (numSectors < 256 ? numSectors : 0); // Read a maximum of 256 sectors, 0 means 256 - - // Set read sector - *(cfRegisters.lba1) = sector & 0xFF; // 1st byte of sector number - *(cfRegisters.lba2) = (sector >> 8) & 0xFF; // 2nd byte of sector number - *(cfRegisters.lba3) = (sector >> 16) & 0xFF; // 3rd byte of sector number - *(cfRegisters.lba4) = ((sector >> 24) & 0x0F )| CF_CMD_LBA; // last nibble of sector number - - // Set command to read - *(cfRegisters.command) = CF_CMD_READ; - - - while (numSectors--) - { - // Wait until card is ready for reading - i = 0; - while (((*(cfRegisters.status) & 0xff)!= CF_STS_READY) && (i < CF_CARD_TIMEOUT)) - { - i++; - } - if (i >= CF_CARD_TIMEOUT) - return false; - - // Read data -#ifdef _IO_USE_DMA - #ifdef NDS - DMA3_SRC = (u32)(cfRegisters.data); - DMA3_DEST = (u32)buff; - DMA3_CR = 256 | DMA_COPY_HALFWORDS | DMA_SRC_FIX; - #else - DMA3COPY ( (cfRegisters.data), buff, 256 | DMA16 | DMA_ENABLE | DMA_SRC_FIXED); - #endif - buff += BYTES_PER_READ / 2; -#elif defined _IO_ALLOW_UNALIGNED - i=256; - if ((u32)buff_u8 & 0x01) { - while(i--) - { - temp = *(cfRegisters.data); - *buff_u8++ = temp & 0xFF; - *buff_u8++ = temp >> 8; - } - } else { - while(i--) - *buff++ = *(cfRegisters.data); - } -#else - i=256; - while(i--) - *buff++ = *(cfRegisters.data); -#endif - } -#if (defined _IO_USE_DMA) && (defined NDS) - // Wait for end of transfer before returning - while(DMA3_CR & DMA_BUSY); -#endif - return true; -} - - - -/*----------------------------------------------------------------- -_CF_writeSectors -Write 512 byte sector numbered "sector" from "buffer" -u32 sector IN: address of 512 byte sector on CF card to read -u32 numSectors IN: number of 512 byte sectors to read, - 1 to 256 sectors can be read -void* buffer IN: pointer to 512 byte buffer to read data from -bool return OUT: true if successful ------------------------------------------------------------------*/ -bool _CF_writeSectors (u32 sector, u32 numSectors, void* buffer) { - int i; - - u16 *buff = (u16*)buffer; -#ifdef _IO_ALLOW_UNALIGNED - u8 *buff_u8 = (u8*)buffer; - int temp; -#endif - -#if defined _IO_USE_DMA && defined NDS && defined ARM9 - DC_FlushRange( buffer, j * BYTES_PER_READ); -#endif - - // Wait until CF card is finished previous commands - i=0; - while ((*(cfRegisters.command) & CF_STS_BUSY) && (i < CF_CARD_TIMEOUT)) - { - i++; - } - - // Wait until card is ready for commands - i = 0; - while ((!(*(cfRegisters.status) & CF_STS_INSERTED)) && (i < CF_CARD_TIMEOUT)) - { - i++; - } - if (i >= CF_CARD_TIMEOUT) - return false; - - // Set number of sectors to write - *(cfRegisters.sectorCount) = (numSectors < 256 ? numSectors : 0); // Write a maximum of 256 sectors, 0 means 256 - - // Set write sector - *(cfRegisters.lba1) = sector & 0xFF; // 1st byte of sector number - *(cfRegisters.lba2) = (sector >> 8) & 0xFF; // 2nd byte of sector number - *(cfRegisters.lba3) = (sector >> 16) & 0xFF; // 3rd byte of sector number - *(cfRegisters.lba4) = ((sector >> 24) & 0x0F )| CF_CMD_LBA; // last nibble of sector number - - // Set command to write - *(cfRegisters.command) = CF_CMD_WRITE; - - while (numSectors--) - { - // Wait until card is ready for writing - i = 0; - while (((*(cfRegisters.status) & 0xff) != CF_STS_READY) && (i < CF_CARD_TIMEOUT)) - { - i++; - } - if (i >= CF_CARD_TIMEOUT) - return false; - - // Write data -#ifdef _IO_USE_DMA - #ifdef NDS - DMA3_SRC = (u32)buff; - DMA3_DEST = (u32)(cfRegisters.data); - DMA3_CR = 256 | DMA_COPY_HALFWORDS | DMA_DST_FIX; - #else - DMA3COPY( buff, (cfRegisters.data), 256 | DMA16 | DMA_ENABLE | DMA_DST_FIXED); - #endif - buff += BYTES_PER_READ / 2; -#elif defined _IO_ALLOW_UNALIGNED - i=256; - if ((u32)buff_u8 & 0x01) { - while(i--) - { - temp = *buff_u8++; - temp |= *buff_u8++ << 8; - *(cfRegisters.data) = temp; - } - } else { - while(i--) - *(cfRegisters.data) = *buff++; - } -#else - i=256; - while(i--) - *(cfRegisters.data) = *buff++; -#endif - } -#if defined _IO_USE_DMA && defined NDS - // Wait for end of transfer before returning - while(DMA3_CR & DMA_BUSY); -#endif - - return true; -} - -/*----------------------------------------------------------------- -_CF_shutdown -shutdown the CF interface ------------------------------------------------------------------*/ -bool _CF_shutdown(void) { - return _CF_clearStatus() ; -} - -/*----------------------------------------------------------------- -_CF_startUp -Initializes the CF interface using the supplied registers -returns true if successful, otherwise returns false ------------------------------------------------------------------*/ -bool _CF_startup(const CF_REGISTERS *usableCfRegs) { - cfRegisters = *usableCfRegs; - // See if there is a read/write register - u16 temp = *(cfRegisters.lba1); - *(cfRegisters.lba1) = (~temp & 0xFF); - temp = (~temp & 0xFF); - if (!(*(cfRegisters.lba1) == temp)) { - return false; - } - // Make sure it is 8 bit - *(cfRegisters.lba1) = 0xAA55; - if (*(cfRegisters.lba1) == 0xAA55) { - return false; - } - return true; -} - diff --git a/source/disc_io/io_cf_common.h b/source/disc_io/io_cf_common.h deleted file mode 100644 index 5164164..0000000 --- a/source/disc_io/io_cf_common.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - io_cf_common.h - - By chishm (Michael Chisholm) - - Common Compact Flash card values - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release - - 2006-07-16 - Chishm - * Combined all CF interfaces into one common set of routines -*/ - -#ifndef IO_CF_COMMON_H -#define IO_CF_COMMON_H - -#include "../disc.h" - -typedef struct { - vu16* data; - vu16* status; - vu16* command; - vu16* error; - vu16* sectorCount; - vu16* lba1; - vu16* lba2; - vu16* lba3; - vu16* lba4; -} CF_REGISTERS; - - -// CF Card status -#define CF_STS_INSERTED 0x50 -#define CF_STS_REMOVED 0x00 -#define CF_STS_READY 0x58 - -#define CF_STS_DRQ 0x08 -#define CF_STS_BUSY 0x80 - -// CF Card commands -#define CF_CMD_LBA 0xE0 -#define CF_CMD_READ 0x20 -#define CF_CMD_WRITE 0x30 - -#define CF_CARD_TIMEOUT 10000000 - -bool _CF_isInserted (void); -bool _CF_clearStatus (void); -bool _CF_readSectors (u32 sector, u32 numSectors, void* buffer); -bool _CF_writeSectors (u32 sector, u32 numSectors, void* buffer); -bool _CF_shutdown(void); -bool _CF_startup(const CF_REGISTERS *usableCfRegs); - -#endif // define IO_CF_COMMON_H diff --git a/source/disc_io/io_dldi.h b/source/disc_io/io_dldi.h deleted file mode 100644 index a3dca2f..0000000 --- a/source/disc_io/io_dldi.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - io_dldi.h - - Reserved space for post-compilation adding of an extra driver - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-12-22 - Chishm - * Original release -*/ - -#ifndef IO_DLDI_H -#define IO_DLDI_H - -// 'DLDI' -#define DEVICE_TYPE_DLDI 0x49444C44 - -#include "../disc.h" - -// export interface -extern const IO_INTERFACE _io_dldi ; - -#endif // define IO_DLDI_H diff --git a/source/disc_io/io_dldi.s b/source/disc_io/io_dldi.s deleted file mode 100644 index 1f1e5ed..0000000 --- a/source/disc_io/io_dldi.s +++ /dev/null @@ -1,73 +0,0 @@ -@--------------------------------------------------------------------------------- - .align 4 - .arm - .global _io_dldi -@--------------------------------------------------------------------------------- -.equ FEATURE_MEDIUM_CANREAD, 0x00000001 -.equ FEATURE_MEDIUM_CANWRITE, 0x00000002 -.equ FEATURE_SLOT_GBA, 0x00000010 -.equ FEATURE_SLOT_NDS, 0x00000020 - - -_dldi_start: - -@--------------------------------------------------------------------------------- -@ Driver patch file standard header -- 16 bytes - .word 0xBF8DA5ED @ Magic number to identify this region - .asciz " Chishm" @ Identifying Magic string (8 bytes with null terminator) - .byte 0x01 @ Version number - .byte 0x0F @32KiB @ Log [base-2] of the size of this driver in bytes. - .byte 0x00 @ Sections to fix - .byte 0x0F @32KiB @ Log [base-2] of the allocated space in bytes. - -@--------------------------------------------------------------------------------- -@ Text identifier - can be anything up to 47 chars + terminating null -- 16 bytes - .align 4 - .asciz "Default (No interface)" - -@--------------------------------------------------------------------------------- -@ Offsets to important sections within the data -- 32 bytes - .align 6 - .word _dldi_start @ data start - .word _dldi_end @ data end - .word 0x00000000 @ Interworking glue start -- Needs address fixing - .word 0x00000000 @ Interworking glue end - .word 0x00000000 @ GOT start -- Needs address fixing - .word 0x00000000 @ GOT end - .word 0x00000000 @ bss start -- Needs setting to zero - .word 0x00000000 @ bss end - -@--------------------------------------------------------------------------------- -@ IO_INTERFACE data -- 32 bytes -_io_dldi: - .ascii "DLDI" @ ioType - .word 0x00000000 @ Features - .word _DLDI_startup @ - .word _DLDI_isInserted @ - .word _DLDI_readSectors @ Function pointers to standard device driver functions - .word _DLDI_writeSectors @ - .word _DLDI_clearStatus @ - .word _DLDI_shutdown @ - -@--------------------------------------------------------------------------------- - -_DLDI_startup: -_DLDI_isInserted: -_DLDI_readSectors: -_DLDI_writeSectors: -_DLDI_clearStatus: -_DLDI_shutdown: - mov r0, #0x00 @ Return false for every function - bx lr - - - -@--------------------------------------------------------------------------------- - .align - .pool - -.space (_dldi_start + 32768) - . @ Fill to 32KiB - -_dldi_end: - .end -@--------------------------------------------------------------------------------- diff --git a/source/disc_io/io_efa2.c b/source/disc_io/io_efa2.c deleted file mode 100644 index b3c313a..0000000 --- a/source/disc_io/io_efa2.c +++ /dev/null @@ -1,307 +0,0 @@ -/* -io_efa2.c by CyteX - -Based on io_mpfc.c by chishm (Michael Chisholm) - -Hardware Routines for reading the NAND flash located on -EFA2 flash carts - -This software is completely free. No warranty is provided. -If you use it, please give me credit and email me about your -project at cytex gmx de and do not forget to also -drop chishm hotmail com a line - - Use with permission by Michael "Chishm" Chisholm -*/ - -#include "io_efa2.h" - -// -// EFA2 register addresses -// - -// RTC registers -#define REG_RTC_CLK (*(vu16*)0x080000c4) -#define REG_RTC_EN (*(vu16*)0x080000c8) - -// "Magic" registers used for unlock/lock sequences -#define REG_EFA2_MAGIC_A (*(vu16*)0x09fe0000) -#define REG_EFA2_MAGIC_B (*(vu16*)0x08000000) -#define REG_EFA2_MAGIC_C (*(vu16*)0x08020000) -#define REG_EFA2_MAGIC_D (*(vu16*)0x08040000) -#define REG_EFA2_MAGIC_E (*(vu16*)0x09fc0000) - -// NAND flash lock/unlock register -#define REG_EFA2_NAND_LOCK (*(vu16*)0x09c40000) -// NAND flash enable register -#define REG_EFA2_NAND_EN (*(vu16*)0x09400000) -// NAND flash command write register -#define REG_EFA2_NAND_CMD (*(vu8*)0x09ffffe2) -// NAND flash address/data write register -#define REG_EFA2_NAND_WR (*(vu8*)0x09ffffe0) -// NAND flash data read register -#define REG_EFA2_NAND_RD (*(vu8*)0x09ffc000) - -// ID of Samsung K9K1G NAND flash chip -#define EFA2_NAND_ID 0xEC79A5C0 - -// first sector of udisk -#define EFA2_UDSK_START 0x40 - -// -// EFA2 access functions -// - -// deactivate RTC ports -static inline void _EFA2_rtc_deactivate(void) { - REG_RTC_EN = 0; -} - -// unlock register access -static void _EFA2_reg_unlock(void) { - REG_EFA2_MAGIC_A = 0x0d200; - REG_EFA2_MAGIC_B = 0x01500; - REG_EFA2_MAGIC_C = 0x0d200; - REG_EFA2_MAGIC_D = 0x01500; -} - -// finish/lock register access -static inline void _EFA2_reg_lock(void) { - REG_EFA2_MAGIC_E = 0x1500; -} - -// global reset/init/enable/unlock ? -static void _EFA2_global_unlock(void) { - _EFA2_reg_unlock(); - *(vu16*)0x09880000 = 0x08000; - _EFA2_reg_lock(); -} - -// global lock, stealth mode -/*static void _EFA2_global_lock(void) { - // quite sure there is such a sequence, but haven't had - // a look for it upto now -}*/ - -// unlock NAND Flash -static void _EFA2_nand_unlock(void) { - _EFA2_reg_unlock(); - REG_EFA2_NAND_LOCK = 0x01500; - _EFA2_reg_lock(); -} - -// lock NAND Flash -static void _EFA2_nand_lock(void) { - _EFA2_reg_unlock(); - REG_EFA2_NAND_LOCK = 0x0d200; - _EFA2_reg_lock(); -} - -// -// Set NAND Flash chip enable and write protection bits ? -// -// val | ~CE | ~WP | -// -----+-----+-----+ -// 0 | 0 | 0 | -// 1 | 1 | 0 | -// 3 | 1 | 1 | -// -----+-----+-----+ -// -static void _EFA2_nand_enable(u16 val) { - _EFA2_reg_unlock(); - REG_EFA2_NAND_EN = val; - _EFA2_reg_lock(); -} - -// -// Perform NAND reset -// NAND has to be unlocked and enabled when called -// -static inline void _EFA2_nand_reset(void) { - REG_EFA2_NAND_CMD = 0xff; // write reset command -} - -// -// Read out NAND ID information, could be used for card detection -// -// | EFA2 1GBit | -// ------------------+------------+ -// maker code | 0xEC | -// device code | 0x79 | -// don't care | 0xA5 | -// multi plane code | 0xC0 | -// ------------------+------------+ -// -static u32 _EFA2_nand_id(void) { - u8 byte; - u32 id; - - _EFA2_nand_unlock(); - _EFA2_nand_enable(1); - - REG_EFA2_NAND_CMD = 0x90; // write id command - REG_EFA2_NAND_WR = 0x00; // (dummy) address cycle - byte = REG_EFA2_NAND_RD; // read maker code - id = byte; - byte = REG_EFA2_NAND_RD; // read device code - id = (id << 8) | byte; - byte = REG_EFA2_NAND_RD; // read don't care - id = (id << 8) | byte; - byte = REG_EFA2_NAND_RD; // read multi plane code - id = (id << 8) | byte; - - _EFA2_nand_enable(0); - _EFA2_nand_lock(); - return (id); -} - -// -// Start of gba_nds_fat block device description -// - -/*----------------------------------------------------------------- -EFA2_clearStatus -Reads and checks NAND status information -bool return OUT: true if NAND is idle ------------------------------------------------------------------*/ -bool _EFA2_clearStatus (void) -{ - // tbd: currently there is no write support, so always return - // true, there is no possibility for pending operations - return true; -} - -/*----------------------------------------------------------------- -EFA2_isInserted -Checks to see if the NAND chip used by the EFA2 is present -bool return OUT: true if the correct NAND chip is found ------------------------------------------------------------------*/ -bool _EFA2_isInserted (void) -{ - _EFA2_clearStatus(); - return (_EFA2_nand_id() == EFA2_NAND_ID); -} - -/*----------------------------------------------------------------- -EFA2_readSectors -Read "numSecs" 512 byte sectors starting from "sector" into "buffer" -No error correction, no use of spare cells, no use of R/~B signal -u32 sector IN: number of first 512 byte sector to be read -u32 numSecs IN: number of 512 byte sectors to read, -void* buffer OUT: pointer to 512 byte buffer to store data in -bool return OUT: true if successful ------------------------------------------------------------------*/ -bool _EFA2_readSectors (u32 sector, u32 numSecs, void* buffer) -{ - int i; - -#ifndef _IO_ALLOW_UNALIGNED - u8 byte; - u16 word; -#endif - - // NAND page 0x40 (EFA2_UDSK_START) contains the MBR of the - // udisk and thus is sector 0. The original EFA2 firmware - // does never look at this, it only watches page 0x60, which - // contains the boot block of the FAT16 partition. That is - // fixed, so the EFA2 udisk must not be reformated, else - // the ARK Octopus and also the original Firmware won't be - // able to access the udisk anymore and I have to write a - // recovery tool. - u32 page = EFA2_UDSK_START + sector; - - // future enhancement: wait for possible write operations to - // be finisched - if (!_EFA2_clearStatus()) return false; - - _EFA2_nand_unlock(); - _EFA2_nand_enable(1); - _EFA2_nand_reset(); - - // set NAND to READ1 operation mode and transfer page address - REG_EFA2_NAND_CMD = 0x00; // write READ1 command - REG_EFA2_NAND_WR = 0x00; // write address [7:0] - REG_EFA2_NAND_WR = (page ) & 0xff; // write address [15:8] - REG_EFA2_NAND_WR = (page >> 8 ) & 0xff; // write address[23:16] - REG_EFA2_NAND_WR = (page >> 16) & 0xff; // write address[26:24] - - // Due to a bug in EFA2 design there is need to waste some cycles - // "by hand" instead the possibility to check the R/~B port of - // the NAND flash via a register. The RTC deactivation is only - // there to make sure the loop won't be optimized by the compiler - for (i=0 ; i < 3 ; i++) _EFA2_rtc_deactivate(); - - while (numSecs--) - { - // read page data -#ifdef _IO_ALLOW_UNALIGNED - // slow byte access to RAM, but works in principle - for (i=0 ; i < 512 ; i++) - ((u8*)buffer)[i] = REG_EFA2_NAND_RD; -#else - // a bit faster, but DMA is not possible - for (i=0 ; i < 256 ; i++) { - byte = REG_EFA2_NAND_RD; // read lo-byte - word = byte; - byte = REG_EFA2_NAND_RD; // read hi-byte - word = word | (byte << 8); - ((u16*)buffer)[i] = word; - } -#endif - } - - _EFA2_nand_enable(0); - _EFA2_nand_lock(); - return true; -} - - -/*----------------------------------------------------------------- -EFA2_writeSectors -Write "numSecs" 512 byte sectors starting at "sector" from "buffer" -u32 sector IN: address of 512 byte sector on card to write -u32 numSecs IN: number of 512 byte sectors to write -1 to 256 sectors can be written, 0 = 256 -void* buffer IN: pointer to 512 byte buffer to read data from -bool return OUT: true if successful ------------------------------------------------------------------*/ -bool _EFA2_writeSectors (u32 sector, u8 numSecs, void* buffer) -{ - // Upto now I focused on reading NAND, write operations - // will follow - return false; -} - -/*----------------------------------------------------------------- -EFA2_shutdown -unload the EFA2 interface ------------------------------------------------------------------*/ -bool _EFA2_shutdown(void) -{ - return _EFA2_clearStatus(); -} - -/*----------------------------------------------------------------- -EFA2_startUp -initializes the EFA2 card, returns true if successful, -otherwise returns false ------------------------------------------------------------------*/ -bool _EFA2_startUp(void) -{ - _EFA2_global_unlock(); - return (_EFA2_nand_id() == EFA2_NAND_ID); -} - -/*----------------------------------------------------------------- -the actual interface structure ------------------------------------------------------------------*/ -const IO_INTERFACE _io_efa2 = { - DEVICE_TYPE_EFA2, - FEATURE_MEDIUM_CANREAD | FEATURE_SLOT_GBA, - (FN_MEDIUM_STARTUP)&_EFA2_startUp, - (FN_MEDIUM_ISINSERTED)&_EFA2_isInserted, - (FN_MEDIUM_READSECTORS)&_EFA2_readSectors, - (FN_MEDIUM_WRITESECTORS)&_EFA2_writeSectors, - (FN_MEDIUM_CLEARSTATUS)&_EFA2_clearStatus, - (FN_MEDIUM_SHUTDOWN)&_EFA2_shutdown -}; diff --git a/source/disc_io/io_efa2.h b/source/disc_io/io_efa2.h deleted file mode 100644 index 47e084f..0000000 --- a/source/disc_io/io_efa2.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - io_efa2.h by CyteX - - Based on io_mpfc.h by chishm (Michael Chisholm) - - Hardware Routines for reading the NAND flash located on - EFA2 flash carts - - Used with permission from Cytex. -*/ - -#ifndef IO_EFA2_H -#define IO_EFA2_H - -// 'EFA2' -#define DEVICE_TYPE_EFA2 0x32414645 - -#include "../disc.h" - -// export interface -extern const IO_INTERFACE _io_efa2; - -#endif // define IO_EFA2_H diff --git a/source/disc_io/io_fcsr.c b/source/disc_io/io_fcsr.c deleted file mode 100644 index 3a4b25e..0000000 --- a/source/disc_io/io_fcsr.c +++ /dev/null @@ -1,334 +0,0 @@ -/* - io_fcsr.c based on - - compact_flash.c - By chishm (Michael Chisholm) - - Hardware Routines for using a GBA Flash Cart and SRAM as a - block device. - - The file system must be 512 byte aligned, in cart address space. - SRAM is supported. - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include "io_fcsr.h" - -#include - -//--------------------------------------------------------------- -// DMA -#ifdef _IO_USE_DMA - #ifndef NDS - #include "gba_dma.h" - #else - #include - #ifdef ARM9 - #include - #endif - #endif -#endif - -#ifdef NDS - #define SRAM_START 0x0A000000 -#else - #define SRAM_START 0x0E000000 -#endif - -#define NO_SRAM 0xFFFFFFFF - -#define FCSR 0x52534346 -const char _FCSR_LabelString[] = " Chishm FAT"; - -u8* _FCSR_FileSysPointer = 0; -u8* _FCSR_SramSectorPointer[4] = {0,0,0,0}; -u32 _FCSR_SramSectorStart[4] = {0,0,0,0}; -u32 _FCSR_SramSectorEnd[4] = {0,0,0,0}; - -/*----------------------------------------------------------------- -_FCSR_isInserted -Is a GBA Flash Cart with a valid file system inserted? -bool return OUT: true if a GBA FC card is inserted ------------------------------------------------------------------*/ -bool _FCSR_isInserted (void) -{ - bool flagFoundFileSys = false; - - u32* fileSysPointer = (u32*)0x08000100; // Start at beginning of cart address space, offset by expected location of string - - // Search for file system - while ((fileSysPointer < (u32*)0x0A000000) && !flagFoundFileSys) // Only search while not at end of cart address space - { - while ((*fileSysPointer != FCSR) && (fileSysPointer < (u32*)0x0A000000)) - fileSysPointer += 0x40; - if ((strncmp(_FCSR_LabelString, (char*)(fileSysPointer + 1), 12) == 0) && (fileSysPointer < (u32*)0x0A000000)) - { - flagFoundFileSys = true; - } else { - fileSysPointer += 0x80; - } - } - - return flagFoundFileSys; -} - - -/*----------------------------------------------------------------- -_FCSR_clearStatus -Finish any pending operations -bool return OUT: always true for GBA FC ------------------------------------------------------------------*/ -bool _FCSR_clearStatus (void) -{ - return true; -} - - -/*----------------------------------------------------------------- -_FCSR_readSectors -Read 512 byte sector numbered "sector" into "buffer" -u32 sector IN: address of first 512 byte sector on Flash Cart to read -u32 numSectors IN: number of 512 byte sectors to read, - 1 to 256 sectors can be read -void* buffer OUT: pointer to 512 byte buffer to store data in -bool return OUT: true if successful ------------------------------------------------------------------*/ -bool _FCSR_readSectors (u32 sector, u32 numSectors, void* buffer) -{ - int i; - bool flagSramSector = false; - int readLength = numSectors * BYTES_PER_READ; - u8* src;; - u8* dst; - - // Find which region this read is in - for (i = 0; (i < 4) && !flagSramSector; i++) - { - if ((sector >= _FCSR_SramSectorStart[i]) && (sector < _FCSR_SramSectorEnd[i])) - { - flagSramSector = true; - break; - } - } - - // Make sure read will be completely in SRAM range if it is partially there - if ( flagSramSector && ((sector + numSectors) > _FCSR_SramSectorEnd[i])) - return false; - - // Copy data to buffer - if (flagSramSector) - { - src = _FCSR_SramSectorPointer[i] + (sector - _FCSR_SramSectorStart[i]) * BYTES_PER_READ; - } else { - src = _FCSR_FileSysPointer + sector * BYTES_PER_READ; - } - dst = (u8*)buffer; - - if (flagSramSector) - { - while (readLength--) - { - *dst++ = *src++; - } - } else { // Reading from Cart ROM - -#ifdef _IO_USE_DMA - #ifdef NDS - #ifdef ARM9 - DC_FlushRange( buffer, readLength); - #endif // ARM9 - DMA3_SRC = (u32)src; - DMA3_DEST = (u32)buffer; - DMA3_CR = (readLength >> 1) | DMA_COPY_HALFWORDS; - #else // ! NDS - DMA3COPY ( src, buffer, (readLength >> 1) | DMA16 | DMA_ENABLE); - #endif // NDS -#else // !_IO_USE_DMA - memcpy (buffer, src, readLength); -#endif // _IO_USE_DMA - - } // if (flagSramSector) - - return true; -} - -/*----------------------------------------------------------------- -_FCSR_writeSectors -Write 512 byte sector numbered "sector" from "buffer" -u32 sector IN: address of 512 byte sector on Flash Cart to read -u32 numSectors IN: number of 512 byte sectors to read, - 1 to 256 sectors can be read -void* buffer IN: pointer to 512 byte buffer to read data from -bool return OUT: true if successful ------------------------------------------------------------------*/ -bool _FCSR_writeSectors (u32 sector, u8 numSectors, void* buffer) -{ - int i; - bool flagSramSector = false; - u32 writeLength = numSectors * BYTES_PER_READ; - u8* src = (u8*) buffer; - u8* dst; - - // Find which region this sector belongs in - for (i = 0; (i < 4) && !flagSramSector; i++) - { - if ((sector >= _FCSR_SramSectorStart[i]) && (sector < _FCSR_SramSectorEnd[i])) - { - flagSramSector = true; - break; - } - } - - if (!flagSramSector) - return false; - - // Entire write must be within an SRAM region - if ((sector + numSectors) > _FCSR_SramSectorEnd[i]) - return false; - - // Copy data to SRAM - dst = _FCSR_SramSectorPointer[i] + (sector - _FCSR_SramSectorStart[i]) * BYTES_PER_READ; - while (writeLength--) - { - *dst++ = *src++; - } - - return true; -} - -/*----------------------------------------------------------------- -_FCSR_shutdown -unload the Flash Cart interface ------------------------------------------------------------------*/ -bool _FCSR_shutdown(void) -{ - int i; - if (_FCSR_clearStatus() == false) - return false; - - _FCSR_FileSysPointer = 0; - - for (i=0; i < 4; i++) - { - _FCSR_SramSectorPointer[i] = 0; - _FCSR_SramSectorStart[i] = 0; - _FCSR_SramSectorEnd[i] = 0; - } - return true; -} - -/*----------------------------------------------------------------- -_FCSR_startUp -initializes the Flash Cart interface, returns true if successful, -otherwise returns false ------------------------------------------------------------------*/ -bool _FCSR_startUp(void) -{ - bool flagFoundFileSys = false; - int i; - int SramRegionSize[4]; - u8* srcByte; - u8* destByte; - - u32* fileSysPointer = (u32*)0x08000100; // Start at beginning of cart address space, offset by expected location of string - - // Search for file system - while ((fileSysPointer < (u32*)0x0A000000) && !flagFoundFileSys) // Only search while not at end of cart address space - { - while ((*fileSysPointer != FCSR) && (fileSysPointer < (u32*)0x0A000000)) - fileSysPointer += 0x40; - if ((strncmp(_FCSR_LabelString, (char*)(fileSysPointer + 1), 12) == 0) && (fileSysPointer < (u32*)0x0A000000)) - { - flagFoundFileSys = true; - } else { - fileSysPointer += 0x80; - } - } - - if (!flagFoundFileSys) - return false; - - // Flash cart file system pointer has been found - _FCSR_FileSysPointer = (u8*)(fileSysPointer - 0x40); - - // Get SRAM sector regions from header block - for (i = 0; i < 4; i++) - { - _FCSR_SramSectorStart[i] = fileSysPointer[i+4]; - SramRegionSize[i] = fileSysPointer[i+8]; - _FCSR_SramSectorEnd[i] = _FCSR_SramSectorStart[i] + SramRegionSize[i]; - } - - // Calculate SRAM region pointers - _FCSR_SramSectorPointer[0] = (u8*)(SRAM_START + 4); - for (i = 1; i < 4; i++) - { - _FCSR_SramSectorPointer[i] = _FCSR_SramSectorPointer[i-1] + (SramRegionSize[i-1] * BYTES_PER_READ); - } - - // Initialise SRAM with overlay if it hasn't been done so - if ( (*((u8*)SRAM_START) != 'F') || (*((u8*)(SRAM_START+1)) != 'C') || (*((u8*)(SRAM_START+2)) != 'S') || (*((u8*)(SRAM_START+3)) != 'R') ) - { - *((u8*)SRAM_START) = 'F'; - *((u8*)(SRAM_START+1)) = 'C'; - *((u8*)(SRAM_START+2)) = 'S'; - *((u8*)(SRAM_START+3)) = 'R'; - - for (i = 0; i < 4; i++) - { - srcByte = _FCSR_FileSysPointer + (_FCSR_SramSectorStart[i] * BYTES_PER_READ); - destByte = _FCSR_SramSectorPointer[i]; - while (srcByte < _FCSR_FileSysPointer + (_FCSR_SramSectorEnd[i] * BYTES_PER_READ) ) - *destByte++ = *srcByte++; - } - } - - // Get SRAM sector regions from header block - for (i = 0; i < 4; i++) - { - if (SramRegionSize[i] == 0) - { - _FCSR_SramSectorStart[i] = NO_SRAM; - _FCSR_SramSectorEnd[i] = NO_SRAM; - } - } - - return true; -} - -/*----------------------------------------------------------------- -the actual interface structure ------------------------------------------------------------------*/ -const IO_INTERFACE _io_fcsr = { - DEVICE_TYPE_FCSR, // 'FCSR' - FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_SLOT_GBA, - (FN_MEDIUM_STARTUP)&_FCSR_startUp, - (FN_MEDIUM_ISINSERTED)&_FCSR_isInserted, - (FN_MEDIUM_READSECTORS)&_FCSR_readSectors, - (FN_MEDIUM_WRITESECTORS)&_FCSR_writeSectors, - (FN_MEDIUM_CLEARSTATUS)&_FCSR_clearStatus, - (FN_MEDIUM_SHUTDOWN)&_FCSR_shutdown -} ; diff --git a/source/disc_io/io_fcsr.h b/source/disc_io/io_fcsr.h deleted file mode 100644 index 737cca6..0000000 --- a/source/disc_io/io_fcsr.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - io_fcsr.h - - Hardware Routines for using a GBA Flash Cart with SRAM - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release -*/ - -#ifndef IO_FCSR_H -#define IO_FCSR_H - -// 'FCSR' -#define DEVICE_TYPE_FCSR 0x52534346 - -#include "../disc.h" - -// export interface -extern const IO_INTERFACE _io_fcsr ; - -#endif // define IO_FCSR_H diff --git a/source/disc_io/io_m3_common.c b/source/disc_io/io_m3_common.c deleted file mode 100644 index ab2c143..0000000 --- a/source/disc_io/io_m3_common.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - io_m3_common.c - - Routines common to all version of the M3 - - Some code based on M3 SD drivers supplied by M3Adapter. - Some code written by SaTa may have been unknowingly used. - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "io_m3_common.h" - -static u16 _M3_readHalfword (u32 addr) { - return *((vu16*)addr); -} - -void _M3_changeMode (u32 mode) { - _M3_readHalfword (0x08e00002); - _M3_readHalfword (0x0800000e); - _M3_readHalfword (0x08801ffc); - _M3_readHalfword (0x0800104a); - _M3_readHalfword (0x08800612); - _M3_readHalfword (0x08000000); - _M3_readHalfword (0x08801b66); - _M3_readHalfword (0x08000000 + (mode << 1)); - _M3_readHalfword (0x0800080e); - _M3_readHalfword (0x08000000); - - if ((mode & 0x0f) != 4) { - _M3_readHalfword (0x09000000); - } else { - _M3_readHalfword (0x080001e4); - _M3_readHalfword (0x080001e4); - _M3_readHalfword (0x08000188); - _M3_readHalfword (0x08000188); - } -} - diff --git a/source/disc_io/io_m3_common.h b/source/disc_io/io_m3_common.h deleted file mode 100644 index 56a18eb..0000000 --- a/source/disc_io/io_m3_common.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - io_m3_common.h - - Routines common to all version of the M3 - - Some code based on M3 SD drivers supplied by M3Adapter. - Some code written by SaTa may have been unknowingly used. - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release -*/ - -#ifndef IO_M3_COMMON_H -#define IO_M3_COMMON_H - -#include "../disc.h" - -// Values for changing mode -#define M3_MODE_ROM 0x00400004 -#define M3_MODE_MEDIA 0x00400003 - -extern void _M3_changeMode (u32 mode); - -#endif // IO_M3_COMMON_H - diff --git a/source/disc_io/io_m3cf.c b/source/disc_io/io_m3cf.c deleted file mode 100644 index d416a4b..0000000 --- a/source/disc_io/io_m3cf.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - io_m3cf.c based on - - compact_flash.c - By chishm (Michael Chisholm) - - Hardware Routines for reading a compact flash card - using the M3 Perfect CF Adapter - - CF routines modified with help from Darkfader - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include "io_m3cf.h" -#include "io_m3_common.h" -#include "io_cf_common.h" - -//--------------------------------------------------------------- -// DMA -#ifdef _IO_USE_DMA - #ifndef NDS - #include "gba_dma.h" - #else - #include - #ifdef ARM9 - #include - #endif - #endif -#endif - -//--------------------------------------------------------------- -// M3 CF Addresses -#define REG_M3CF_STS ((vu16*)0x080C0000) // Status of the CF Card / Device control -#define REG_M3CF_CMD ((vu16*)0x088E0000) // Commands sent to control chip and status return -#define REG_M3CF_ERR ((vu16*)0x08820000) // Errors / Features - -#define REG_M3CF_SEC ((vu16*)0x08840000) // Number of sector to transfer -#define REG_M3CF_LBA1 ((vu16*)0x08860000) // 1st byte of sector address -#define REG_M3CF_LBA2 ((vu16*)0x08880000) // 2nd byte of sector address -#define REG_M3CF_LBA3 ((vu16*)0x088A0000) // 3rd byte of sector address -#define REG_M3CF_LBA4 ((vu16*)0x088C0000) // last nibble of sector address | 0xE0 - -#define REG_M3CF_DATA ((vu16*)0x08800000) // Pointer to buffer of CF data transered from card - -static const CF_REGISTERS _M3CF_Registers = { - REG_M3CF_DATA, - REG_M3CF_STS, - REG_M3CF_CMD, - REG_M3CF_ERR, - REG_M3CF_SEC, - REG_M3CF_LBA1, - REG_M3CF_LBA2, - REG_M3CF_LBA3, - REG_M3CF_LBA4 -}; - - -bool _M3CF_startup(void) { - _M3_changeMode (M3_MODE_MEDIA); - return _CF_startup (&_M3CF_Registers); -} - - -const IO_INTERFACE _io_m3cf = { - DEVICE_TYPE_M3CF, - FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_SLOT_GBA, - (FN_MEDIUM_STARTUP)&_M3CF_startup, - (FN_MEDIUM_ISINSERTED)&_CF_isInserted, - (FN_MEDIUM_READSECTORS)&_CF_readSectors, - (FN_MEDIUM_WRITESECTORS)&_CF_writeSectors, - (FN_MEDIUM_CLEARSTATUS)&_CF_clearStatus, - (FN_MEDIUM_SHUTDOWN)&_CF_shutdown -} ; diff --git a/source/disc_io/io_m3cf.h b/source/disc_io/io_m3cf.h deleted file mode 100644 index 6c762c3..0000000 --- a/source/disc_io/io_m3cf.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - io_m3cf.h - - Hardware Routines for reading a compact flash card - using the M3 CF - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release -*/ - -#ifndef IO_M3CF_H -#define IO_M3CF_H - -// 'M3CF' -#define DEVICE_TYPE_M3CF 0x4643334D - -#include "../disc.h" - -// export interface -extern const IO_INTERFACE _io_m3cf ; - -#endif // define IO_M3CF_H diff --git a/source/disc_io/io_m3sd.c b/source/disc_io/io_m3sd.c deleted file mode 100644 index 322ad00..0000000 --- a/source/disc_io/io_m3sd.c +++ /dev/null @@ -1,518 +0,0 @@ -/* - io_m3sd.c - - Hardware Routines for reading a Secure Digital card - using the M3 SD - - Some code based on M3 SD drivers supplied by M3Adapter. - Some code written by SaTa may have been unknowingly used. - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-25 - Chishm - * Improved startup function that doesn't delay hundreds of seconds - before reporting no card inserted. - * Fixed writeData function to timeout on error - * writeSectors function now wait until the card is ready before continuing with a transfer - - 2006-08-05 - Chishm - * Tries multiple times to get a Relative Card Address at startup - - 2006-08-07 - Chishm - * Moved the SD initialization to a common function -*/ - -#include "io_m3sd.h" -#include "io_sd_common.h" -#include "io_m3_common.h" - -//--------------------------------------------------------------- -// M3SD register addresses - -#define REG_M3SD_DIR (*(vu16*)0x08800000) // direction control register -#define REG_M3SD_DAT (*(vu16*)0x09000000) // SD data line, 8 bits at a time -#define REG_M3SD_CMD (*(vu16*)0x09200000) // SD command byte -#define REG_M3SD_ARGH (*(vu16*)0x09400000) // SD command argument, high halfword -#define REG_M3SD_ARGL (*(vu16*)0x09600000) // SD command argument, low halfword -#define REG_M3SD_STS (*(vu16*)0x09800000) // command and status register - -//--------------------------------------------------------------- -// Send / receive timeouts, to stop infinite wait loops -#define NUM_STARTUP_CLOCKS 100 // Number of empty (0xFF when sending) bytes to send/receive to/from the card -#define TRANSMIT_TIMEOUT 20000 // Time to wait for the M3 to respond to transmit or receive requests -#define RESPONSE_TIMEOUT 256 // Number of clocks sent to the SD card before giving up -#define WRITE_TIMEOUT 3000 // Time to wait for the card to finish writing - -//--------------------------------------------------------------- -// Variables required for tracking SD state -static u32 _M3SD_relativeCardAddress = 0; // Preshifted Relative Card Address - -//--------------------------------------------------------------- -// Internal M3 SD functions - -static inline void _M3SD_unlock (void) { - _M3_changeMode (M3_MODE_MEDIA); -} - -static inline bool _M3SD_waitOnBusy (void) { - int i = 0; - while ( (REG_M3SD_STS & 0x01) == 0x00) { - i++; - if (i >= TRANSMIT_TIMEOUT) { - return false; - } - } - return true; -} - -static inline bool _M3SD_waitForDataReady (void) { - int i = 0; - while ( (REG_M3SD_STS & 0x40) == 0x00) { - i++; - if (i >= TRANSMIT_TIMEOUT) { - return false; - } - } - return true; -} - - -static bool _M3SD_sendCommand (u16 command, u32 argument) { - REG_M3SD_STS = 0x8; - REG_M3SD_CMD = 0x40 + command; // Include the start bit - REG_M3SD_ARGH = argument >> 16; - REG_M3SD_ARGL = argument; - // The CRC7 of the command is calculated by the M3 - - REG_M3SD_DIR=0x29; - if (!_M3SD_waitOnBusy()) { - REG_M3SD_DIR=0x09; - return false; - } - REG_M3SD_DIR=0x09; - return true; -} - -static bool _M3SD_sendByte (u8 byte) { - int i = 0; - REG_M3SD_DAT = byte; - REG_M3SD_DIR = 0x03; - REG_M3SD_STS = 0x01; - while ((REG_M3SD_STS & 0x04) == 0) { - i++; - if (i >= TRANSMIT_TIMEOUT) { - return false; - } - } - return true; -} - -static u8 _M3SD_getByte (void) { - int i; - // Request 8 bits of data from the SD's CMD pin - REG_M3SD_DIR = 0x02; - REG_M3SD_STS = 0x02; - // Wait for the data to be ready - i = 0; - while ((REG_M3SD_STS & 0x08) == 0) { - i++; - if (i >= TRANSMIT_TIMEOUT) { - // Return an empty byte if a timeout occurs - return 0xFF; - } - } - i = 0; - while ((REG_M3SD_STS & 0x08) != 0) { - i++; - if (i >= TRANSMIT_TIMEOUT) { - // Return an empty byte if a timeout occurs - return 0xFF; - } - } - // Return the data - return (REG_M3SD_DAT & 0xff); -} - -// Returns the response from the SD card to a previous command. -static bool _M3SD_getResponse (u8* dest, u32 length) { - u32 i; - u8 dataByte; - int shiftAmount; - - // Wait for the card to be non-busy - for (i = 0; i < RESPONSE_TIMEOUT; i++) { - dataByte = _M3SD_getByte(); - if (dataByte != SD_CARD_BUSY) { - break; - } - } - - if (dest == NULL) { - return true; - } - - // Still busy after the timeout has passed - if (dataByte == 0xff) { - return false; - } - - // Read response into buffer - for ( i = 0; i < length; i++) { - dest[i] = dataByte; - dataByte = _M3SD_getByte(); - } - // dataByte will contain the last piece of the response - - // Send 16 more clocks, 8 more than the delay required between a response and the next command - i = _M3SD_getByte(); - i = _M3SD_getByte(); - - // Shift response so that the bytes are correctly aligned - // The register may not contain properly aligned data - for (shiftAmount = 0; ((dest[0] << shiftAmount) & 0x80) != 0x00; shiftAmount++) { - if (shiftAmount >= 7) { - return false; - } - } - - for (i = 0; i < length - 1; i++) { - dest[i] = (dest[i] << shiftAmount) | (dest[i+1] >> (8-shiftAmount)); - } - // Get the last piece of the response from dataByte - dest[i] = (dest[i] << shiftAmount) | (dataByte >> (8-shiftAmount)); - - return true; -} - - -static inline bool _M3SD_getResponse_R1 (u8* dest) { - return _M3SD_getResponse (dest, 6); -} - -static inline bool _M3SD_getResponse_R1b (u8* dest) { - return _M3SD_getResponse (dest, 6); -} - -static inline bool _M3SD_getResponse_R2 (u8* dest) { - return _M3SD_getResponse (dest, 17); -} - -static inline bool _M3SD_getResponse_R3 (u8* dest) { - return _M3SD_getResponse (dest, 6); -} - -static inline bool _M3SD_getResponse_R6 (u8* dest) { - return _M3SD_getResponse (dest, 6); -} - -static void _M3SD_sendClocks (u32 numClocks) { - while (numClocks--) { - _M3SD_sendByte(0xff); - } -} - -static void _M3SD_getClocks (u32 numClocks) { - while (numClocks--) { - _M3SD_getByte(); - } -} - -bool _M3SD_cmd_6byte_response (u8* responseBuffer, u8 command, u32 data) { - _M3SD_sendCommand (command, data); - return _M3SD_getResponse (responseBuffer, 6); -} - -bool _M3SD_cmd_17byte_response (u8* responseBuffer, u8 command, u32 data) { - _M3SD_sendCommand (command, data); - return _M3SD_getResponse (responseBuffer, 17); -} - -static bool _M3SD_initCard (void) { - // Give the card time to stabilise - _M3SD_sendClocks (NUM_STARTUP_CLOCKS); - - // Reset the card - if (!_M3SD_sendCommand (GO_IDLE_STATE, 0)) { - return false; - } - - _M3SD_getClocks (NUM_STARTUP_CLOCKS); - - // Card is now reset, including it's address - _M3SD_relativeCardAddress = 0; - - // Init the card - return _SD_InitCard (_M3SD_cmd_6byte_response, - _M3SD_cmd_17byte_response, - true, - &_M3SD_relativeCardAddress); -} - -static bool _M3SD_readData (void* buffer) { - u32 i; - u8* buff_u8 = (u8*)buffer; - u16* buff = (u16*)buffer; - u16 temp; - - REG_M3SD_DIR = 0x49; - if (!_M3SD_waitForDataReady()) { - REG_M3SD_DIR = 0x09; - return false; - } - REG_M3SD_DIR = 0x09; - - REG_M3SD_DIR = 0x8; - REG_M3SD_STS = 0x4; - - i = REG_M3SD_DIR; - // Read data - i=256; - if ((u32)buff_u8 & 0x01) { - while(i--) - { - temp = REG_M3SD_DIR; - *buff_u8++ = temp & 0xFF; - *buff_u8++ = temp >> 8; - } - } else { - while(i--) - *buff++ = REG_M3SD_DIR; - } - // Read end checksum - i = REG_M3SD_DIR + REG_M3SD_DIR + REG_M3SD_DIR + REG_M3SD_DIR; - - return true; -} - -static void _M3SD_clkout (void) { - REG_M3SD_DIR = 0x4; - REG_M3SD_DIR = 0xc; -/* __asm volatile ( - "ldr r1, =0x08800000 \n" - "mov r0, #0x04 \n" - "strh r0, [r1] \n" - "mov r0, r0 \n" - "mov r0, r0 \n" - "mov r0, #0x0c \n" - "strh r0, [r1] \n" - : // Outputs - : // Inputs - : "r0", "r1" // Clobber list - );*/ -} - -static void _M3SD_clkin (void) { - REG_M3SD_DIR = 0x0; - REG_M3SD_DIR = 0x8; -/* __asm volatile ( - "ldr r1, =0x08800000 \n" - "mov r0, #0x00 \n" - "strh r0, [r1] \n" - "mov r0, r0 \n" - "mov r0, r0 \n" - "mov r0, #0x08 \n" - "strh r0, [r1] \n" - : // Outputs - : // Inputs - : "r0", "r1" // Clobber list - );*/ -} - -static bool _M3SD_writeData (u8* data, u8* crc) { - int i; - u8 temp; - - do { - _M3SD_clkin(); - } while ((REG_M3SD_DAT & 0x100) == 0); - - REG_M3SD_DAT = 0; // Start bit - - _M3SD_clkout(); - - for (i = 0; i < BYTES_PER_READ; i++) { - temp = (*data++); - REG_M3SD_DAT = temp >> 4; - _M3SD_clkout(); - REG_M3SD_DAT = temp; - _M3SD_clkout(); - } - - if (crc != NULL) { - for (i = 0; i < 8; i++) { - temp = (*crc++); - REG_M3SD_DAT = temp >> 4; - _M3SD_clkout(); - REG_M3SD_DAT = temp; - _M3SD_clkout(); - } - } - - i = 32; - while (i--) { - temp += 2; // a NOP to stop the compiler optimising out the loop - } - - for (i = 0; i < 32; i++) { - REG_M3SD_DAT = 0xff; - _M3SD_clkout(); - } - - do { - _M3SD_clkin(); - } while ((REG_M3SD_DAT & 0x100) == 0); - - return true; -} - -//--------------------------------------------------------------- -// Functions needed for the external interface - -bool _M3SD_startUp (void) { - _M3SD_unlock(); - return _M3SD_initCard(); -} - -bool _M3SD_isInserted (void) { - u8 responseBuffer [6]; - // Make sure the card receives the command - if (!_M3SD_sendCommand (SEND_STATUS, 0)) { - return false; - } - // Make sure the card responds - if (!_M3SD_getResponse_R1 (responseBuffer)) { - return false; - } - // Make sure the card responded correctly - if (responseBuffer[0] != SEND_STATUS) { - return false; - } - return true; -} - -bool _M3SD_readSectors (u32 sector, u32 numSectors, void* buffer) { - u32 i; - u8* dest = (u8*) buffer; - u8 responseBuffer[6]; - - if (numSectors == 1) { - // If it's only reading one sector, use the (slightly faster) READ_SINGLE_BLOCK - if (!_M3SD_sendCommand (READ_SINGLE_BLOCK, sector * BYTES_PER_READ)) { - return false; - } - - if (!_M3SD_readData (buffer)) { - return false; - } - - } else { - // Stream the required number of sectors from the card - if (!_M3SD_sendCommand (READ_MULTIPLE_BLOCK, sector * BYTES_PER_READ)) { - return false; - } - - for(i=0; i < numSectors; i++, dest+=BYTES_PER_READ) { - if (!_M3SD_readData(dest)) { - return false; - } - REG_M3SD_STS = 0x8; - } - - // Stop the streaming - _M3SD_sendCommand (STOP_TRANSMISSION, 0); - _M3SD_getResponse_R1b (responseBuffer); - } - - return true; -} - -bool _M3SD_writeSectors (u32 sector, u32 numSectors, const void* buffer) { - u8 crc[8]; - u8 responseBuffer[6]; - u32 offset = sector * BYTES_PER_READ; - u8* data = (u8*) buffer; - int i; - // Precalculate the data CRC - _SD_CRC16 ( data, BYTES_PER_READ, crc); - - while (numSectors--) { - // Send a single sector write command - _M3SD_sendCommand (WRITE_BLOCK, offset); - if (!_M3SD_getResponse_R1 (responseBuffer)) { - return false; - } - - REG_M3SD_DIR = 0x4; - REG_M3SD_STS = 0x0; - - // Send the data - if (! _M3SD_writeData( data, crc)) { - return false; - } - - if (numSectors > 0) { - offset += BYTES_PER_READ; - data += BYTES_PER_READ; - // Calculate the next CRC while waiting for the card to finish writing - _SD_CRC16 ( data, BYTES_PER_READ, crc); - } - - // Wait for the card to be ready for the next transfer - i = WRITE_TIMEOUT; - responseBuffer[3] = 0; - do { - _M3SD_sendCommand (SEND_STATUS, _M3SD_relativeCardAddress); - _M3SD_getResponse_R1 (responseBuffer); - i--; - if (i <= 0) { - return false; - } - } while (((responseBuffer[3] & 0x1f) != ((SD_STATE_TRAN << 1) | READY_FOR_DATA))); - } - - return true; - -} - -bool _M3SD_clearStatus (void) { - return _M3SD_initCard (); -} - -bool _M3SD_shutdown (void) { - _M3_changeMode (M3_MODE_ROM); - return true; -} - -const IO_INTERFACE _io_m3sd = { - DEVICE_TYPE_M3SD, - FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_SLOT_GBA, - (FN_MEDIUM_STARTUP)&_M3SD_startUp, - (FN_MEDIUM_ISINSERTED)&_M3SD_isInserted, - (FN_MEDIUM_READSECTORS)&_M3SD_readSectors, - (FN_MEDIUM_WRITESECTORS)&_M3SD_writeSectors, - (FN_MEDIUM_CLEARSTATUS)&_M3SD_clearStatus, - (FN_MEDIUM_SHUTDOWN)&_M3SD_shutdown -} ; - - diff --git a/source/disc_io/io_m3sd.h b/source/disc_io/io_m3sd.h deleted file mode 100644 index f838bca..0000000 --- a/source/disc_io/io_m3sd.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - io_m3sd.h - - Hardware Routines for reading a Secure Digital card - using the M3 SD - - Some code based on M3 SD drivers supplied by M3Adapter. - Some code written by SaTa may have been unknowingly used. - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release -*/ - -#ifndef IO_M3SD_H -#define IO_M3SD_H - -// 'M3SD' -#define DEVICE_TYPE_M3SD 0x4453334D - -#include "../disc.h" - -// export interface -extern const IO_INTERFACE _io_m3sd ; - -#endif // define IO_M3SD_H diff --git a/source/disc_io/io_mpcf.c b/source/disc_io/io_mpcf.c deleted file mode 100644 index 22cfac4..0000000 --- a/source/disc_io/io_mpcf.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - io_mpcf.c based on - - compact_flash.c - By chishm (Michael Chisholm) - - Hardware Routines for reading a compact flash card - using the GBA Movie Player - - CF routines modified with help from Darkfader - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include "io_mpcf.h" -#include "io_cf_common.h" - -//--------------------------------------------------------------- -// DMA -#ifdef _IO_USE_DMA - #ifndef NDS - #include "gba_dma.h" - #else - #include - #ifdef ARM9 - #include - #endif - #endif -#endif - -//--------------------------------------------------------------- -// GBAMP CF Addresses -#define REG_MPCF_STS ((vu16*)0x098C0000) // Status of the CF Card / Device control -#define REG_MPCF_CMD ((vu16*)0x090E0000) // Commands sent to control chip and status return -#define REG_MPCF_ERR ((vu16*)0x09020000) // Errors / Features - -#define REG_MPCF_SEC ((vu16*)0x09040000) // Number of sector to transfer -#define REG_MPCF_LBA1 ((vu16*)0x09060000) // 1st byte of sector address -#define REG_MPCF_LBA2 ((vu16*)0x09080000) // 2nd byte of sector address -#define REG_MPCF_LBA3 ((vu16*)0x090A0000) // 3rd byte of sector address -#define REG_MPCF_LBA4 ((vu16*)0x090C0000) // last nibble of sector address | 0xE0 - -#define REG_MPCF_DATA ((vu16*)0x09000000) // Pointer to buffer of CF data transered from card - -static const CF_REGISTERS _MPCF_Registers = { - REG_MPCF_DATA, - REG_MPCF_STS, - REG_MPCF_CMD, - REG_MPCF_ERR, - REG_MPCF_SEC, - REG_MPCF_LBA1, - REG_MPCF_LBA2, - REG_MPCF_LBA3, - REG_MPCF_LBA4 -}; - -/*----------------------------------------------------------------- -_MPCF_startup -initializes the CF interface, returns true if successful, -otherwise returns false ------------------------------------------------------------------*/ -bool _MPCF_startup(void) { - return _CF_startup(&_MPCF_Registers); -} - -/*----------------------------------------------------------------- -the actual interface structure ------------------------------------------------------------------*/ -const IO_INTERFACE _io_mpcf = { - DEVICE_TYPE_MPCF, - FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_SLOT_GBA, - (FN_MEDIUM_STARTUP)&_MPCF_startup, - (FN_MEDIUM_ISINSERTED)&_CF_isInserted, - (FN_MEDIUM_READSECTORS)&_CF_readSectors, - (FN_MEDIUM_WRITESECTORS)&_CF_writeSectors, - (FN_MEDIUM_CLEARSTATUS)&_CF_clearStatus, - (FN_MEDIUM_SHUTDOWN)&_CF_shutdown -} ; diff --git a/source/disc_io/io_mpcf.h b/source/disc_io/io_mpcf.h deleted file mode 100644 index 7e85e9b..0000000 --- a/source/disc_io/io_mpcf.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - io_mpcf.h - - Hardware Routines for reading a compact flash card - using the GBA Movie Player - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release -*/ - -#ifndef IO_MPCF_H -#define IO_MPCF_H - -// 'MPCF' -#define DEVICE_TYPE_MPCF 0x4643504D - -#include "../disc.h" - -// export interface -extern const IO_INTERFACE _io_mpcf ; - -#endif // define IO_MPCF_H diff --git a/source/disc_io/io_njsd.c b/source/disc_io/io_njsd.c deleted file mode 100644 index de369ad..0000000 --- a/source/disc_io/io_njsd.c +++ /dev/null @@ -1,595 +0,0 @@ -/* - io_njsd.c - - Hardware Routines for reading an SD card using - a NinjaDS SD adapter. - - Original code supplied by NinjaMod - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-08-05 - Chishm - * First release - - 2006-08-06 - Chishm - * Removed unneeded _NJSD_writeRAM function - * Removed casts for calls to cardWriteCommand - - 2006-08-07 - Chishm - * Moved the SD initialization to a common function -*/ - -#include "io_njsd.h" - -#ifdef NDS - -#include -#include -#include "io_sd_common.h" - -#define _NJSD_SYNC - -//--------------------------------------------------------------- -// Card communication speeds -#define SD_CLK_167KHz 00 -#define SD_CLK_250KHz 01 -#define SD_CLK_5MHz 02 -#define SD_CLK_25MHz 03 - -//--------------------------------------------------------------- -// Response types -#define SD_RSP_48 0 -#define SD_RSP_136 1 -#define SD_RSP_DATA 2 -#define SD_RSP_STREAM 3 - -//--------------------------------------------------------------- -// Send / receive timeouts, to stop infinite wait loops -#define IRQ_TIMEOUT 1000000 -#define RESET_TIMEOUT 10000 -#define COMMAND_TIMEOUT 100000 -#define WRITE_TIMEOUT 3000 // Time to wait for the card to finish writing - - -static const u8 _NJSD_read_cmd[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40}; -static const u8 _NJSD_read_end_cmd[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x41}; - -static int _NJSD_speed = SD_CLK_5MHz; // Default speed; - -static u32 _NJSD_cardFlags; - -static u32 _NJSD_relativeCardAddress = 0; - -static inline bool _NJSD_waitIRQ(void) { - int i = IRQ_TIMEOUT; - while (!(REG_IF & 0x100000) && --i); - REG_IF = 0x100000; - if (i <= 0) { - return false; - } else { - return true; - } -} - -static inline void _NJSD_writeCardCommand - (u8 cmd0, u8 cmd1, u8 cmd2, u8 cmd3, u8 cmd4, u8 cmd5, u8 cmd6, u8 cmd7) -{ - CARD_COMMAND[0] = cmd0; - CARD_COMMAND[1] = cmd1; - CARD_COMMAND[2] = cmd2; - CARD_COMMAND[3] = cmd3; - CARD_COMMAND[4] = cmd4; - CARD_COMMAND[5] = cmd5; - CARD_COMMAND[6] = cmd6; - CARD_COMMAND[7] = cmd7; -} - -static bool _NJSD_reset (void) { - int i; - CARD_CR1H = CARD_CR1_ENABLE; - _NJSD_writeCardCommand (0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - CARD_CR2 = 0xA0406000; - i = RESET_TIMEOUT; - while ((CARD_CR2 & CARD_BUSY) && --i); - if (i <= 0) { - return false; - } - - return true; -} - -static bool _NJSD_init (u32 flags) { - _NJSD_cardFlags = flags; - - REG_IF = 0x100000; // Clear cart IRQ. - - irqDisable (IRQ_CARD_LINE); - - if (! _NJSD_reset() ) { - return false; - } - return true; -} - -static bool _NJSD_sendCMDR (int speed, u8 *rsp_buf, int type, u8 cmd, u32 param) { - int i; - u32 data; - -#ifdef _NJSD_SYNC - u32 old_REG_IME; - old_REG_IME = REG_IME; - REG_IME = 0; -#endif - - REG_IF = 0x100000; - - CARD_CR1H = CARD_CR1_ENABLE; - - if ((type & 3) < 2) { - CARD_COMMAND[0] = 0xF0 | (speed << 2) | 1 | (type << 1); - } else if ((type & 3) == 2) { - CARD_COMMAND[0] = 0xE0 | (speed << 2) | 0 | (1 << 1); - } else { - CARD_COMMAND[0] = 0xF0 | (speed << 2) | 0 | (1 << 1); - } - - CARD_COMMAND[1] = (type & 0x40) | ((( type >> 2) & 7) << 3); - CARD_COMMAND[2] = 0x40 | cmd; - CARD_COMMAND[3] = (param>>24) & 0xFF; - CARD_COMMAND[4] = (param>>16) & 0xFF; - CARD_COMMAND[5] = (param>>8) & 0xFF; - CARD_COMMAND[6] = (param>>0) & 0xFF; - CARD_COMMAND[7] = 0; // offset = 0 - - if ((type & 3) < 2) { - CARD_CR2 = _NJSD_cardFlags | 0x01000000; - - // wait for ninja DS to be done! - if (!_NJSD_waitIRQ ()) { -#ifdef _NJSD_SYNC - REG_IME = old_REG_IME; -#endif - return false; - } - - i = 0; - do { - // Read data if available - if (CARD_CR2 & CARD_DATA_READY) { - data=CARD_DATA_RD; - if (rsp_buf != NULL) { - if (i == 4) { - rsp_buf[0] = (data>>0)&0xFF; - rsp_buf[1] = (data>>8)&0xFF; - rsp_buf[2] = (data>>16)&0xFF; - rsp_buf[3] = (data>>24)&0xFF; - } else if (i == 5) { - rsp_buf[4] = (data>>0)&0xFF; - rsp_buf[5] = (data>>8)&0xFF; - } - } - i++; - } - } while (CARD_CR2 & CARD_BUSY); - } else { - CARD_CR2 = _NJSD_cardFlags; - while (CARD_CR2 & CARD_BUSY); - - // wait for ninja DS to be done! - if (!_NJSD_waitIRQ ()) { -#ifdef _NJSD_SYNC - REG_IME = old_REG_IME; -#endif - return false; - } - } - -#ifdef _NJSD_SYNC - REG_IME = old_REG_IME; -#endif - return true; -} - -static bool _NJSD_writeSector (u8 *buffer, u8 *crc_buf, u32 offset) { - int i; - u8 responseBuffer[6]; - u32 data; - -#ifdef _NJSD_SYNC - u32 old_REG_IME; - old_REG_IME = REG_IME; - REG_IME = 0; -#endif - - CARD_CR1H = CARD_CR1_ENABLE; - _NJSD_writeCardCommand (0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - CARD_CR2 = 0xA0406000; - i = COMMAND_TIMEOUT; - while ((CARD_CR2 & CARD_BUSY) && --i); - if (i <= 0) { -#ifdef _NJSD_SYNC - REG_IME = old_REG_IME; -#endif - return false; - } - - for (i = 0; i < 65; i++) - { - CARD_CR1H = CARD_CR1_ENABLE; // | CARD_CR1_IRQ; - if (i < 64) - { - _NJSD_writeCardCommand (buffer[i*8+0], buffer[i*8+1], buffer[i*8+2], buffer[i*8+3], - buffer[i*8+4], buffer[i*8+5], buffer[i*8+6], buffer[i*8+7]); - } else { - _NJSD_writeCardCommand (crc_buf[0], crc_buf[1], crc_buf[2], crc_buf[3], - crc_buf[4], crc_buf[5], crc_buf[6], crc_buf[7]); - } - CARD_CR2 = 0xA7406000; - - do { - // Read data if available - if (CARD_CR2 & CARD_DATA_READY) { - data=CARD_DATA_RD; - } - } while (CARD_CR2 & CARD_BUSY); - } - - CARD_CR1H = CARD_CR1_ENABLE; - _NJSD_writeCardCommand (0xF0 | (1 << 2) | 1, 0x80, 0x40 | WRITE_BLOCK, (u8)(offset>>24), - (u8)(offset>>16), (u8)(offset>>8), (u8)(offset>>0), 0x00); - CARD_CR2 = 0xA7406000; - - // wait for ninja DS to be done! - if (!_NJSD_waitIRQ ()) { -#ifdef _NJSD_SYNC - REG_IME = old_REG_IME; -#endif - return false; - } - - i = 0; - do { - // Read data if available - if (CARD_CR2 & CARD_DATA_READY) { - data = CARD_DATA_RD; - if (i == 2) { - responseBuffer[0] = (u8)(data>>0); - responseBuffer[1] = (u8)(data>>8); - responseBuffer[2] = (u8)(data>>16); - responseBuffer[3] = (u8)(data>>24); - } else if (i == 3) { - responseBuffer[4] = (u8)(data>>0); - responseBuffer[5] = (u8)(data>>8); - } - i++; - } - } while (CARD_CR2 & CARD_BUSY); - - i = WRITE_TIMEOUT; - responseBuffer[3] = 0; - do { - _NJSD_sendCMDR (SD_CLK_167KHz, responseBuffer, SD_RSP_48, SEND_STATUS, _NJSD_relativeCardAddress); - i--; - if (i <= 0) { -#ifdef _NJSD_SYNC - REG_IME = old_REG_IME; -#endif - return false; - } - } while (((responseBuffer[3] & 0x1f) != ((SD_STATE_TRAN << 1) | READY_FOR_DATA))); - - -#ifdef _NJSD_SYNC - REG_IME = old_REG_IME; -#endif - - return true; -} - -static bool _NJSD_sendCLK (int speed, int count) { - int i; - -#ifdef _NJSD_SYNC - u32 old_REG_IME; - old_REG_IME = REG_IME; - REG_IME = 0; - - REG_IF = 0x100000; -#endif - - //CARD_CR1H = CARD_CR1_ENABLE; // | CARD_CR1_IRQ; - _NJSD_writeCardCommand (0xE0 | ((speed & 3) << 2), 0, (count - 1), 0, 0, 0, 0, 0); - - CARD_CR2 = _NJSD_cardFlags; - i = COMMAND_TIMEOUT; - while ((CARD_CR2 & CARD_BUSY) && --i); - if (i <= 0) { -#ifdef _NJSD_SYNC - REG_IME = old_REG_IME; -#endif - return false; - } - - // wait for ninja DS to be done! - if (!_NJSD_waitIRQ ()) { -#ifdef _NJSD_SYNC - REG_IME = old_REG_IME; -#endif - return false; - } - -#ifdef _NJSD_SYNC - REG_IME = old_REG_IME; -#endif - return true; -} - -static bool _NJSD_sendCMDN (int speed, u8 cmd, u32 param) { - int i; - -#ifdef _NJSD_SYNC - u32 old_REG_IME; - old_REG_IME = REG_IME; - REG_IME = 0; -#endif - - REG_IF = 0x100000; - - CARD_CR1H = CARD_CR1_ENABLE; // | CARD_CR1_IRQ; - _NJSD_writeCardCommand (0xF0 | ((speed & 3) << 2), 0x00, 0x40 | cmd, (param>>24) & 0xFF, - (param>>16) & 0xFF, (param>>8) & 0xFF, (param>>0) & 0xFF, 0x00); - - CARD_CR2 = _NJSD_cardFlags; - i = COMMAND_TIMEOUT; - while ((CARD_CR2 & CARD_BUSY) && --i); - if (i <= 0) { -#ifdef _NJSD_SYNC - REG_IME = old_REG_IME; -#endif - return false; - } - - // wait for ninja DS to be done! - if (!_NJSD_waitIRQ ()) { -#ifdef _NJSD_SYNC - REG_IME = old_REG_IME; -#endif - return false; - } - -#ifdef _NJSD_SYNC - REG_IME = old_REG_IME; -#endif - return true; -} - -bool _NJSD_cmd_6byte_response (u8* responseBuffer, u8 command, u32 data) { - return _NJSD_sendCMDR (SD_CLK_167KHz, responseBuffer, SD_RSP_48, command, data); -} - -bool _NJSD_cmd_17byte_response (u8* responseBuffer, u8 command, u32 data) { - return _NJSD_sendCMDR (SD_CLK_167KHz, responseBuffer, SD_RSP_136, command, data); -} - -static bool _NJSD_cardInit (void) { - // If the commands succeed the first time, assume they'll always succeed - if (! _NJSD_sendCLK (SD_CLK_167KHz, 256) ) { - return false; - } - if (! _NJSD_sendCMDN (SD_CLK_167KHz, GO_IDLE_STATE, 0) ) { - return false; - } - _NJSD_sendCLK (SD_CLK_167KHz, 8); - - _NJSD_sendCLK (SD_CLK_167KHz, 256); - _NJSD_sendCMDN (SD_CLK_167KHz, GO_IDLE_STATE, 0); - _NJSD_sendCLK (SD_CLK_167KHz, 8); - - return _SD_InitCard (_NJSD_cmd_6byte_response, - _NJSD_cmd_17byte_response, - true, - &_NJSD_relativeCardAddress); -} - - -bool _NJSD_isInserted(void) { - u8 responseBuffer [8]; - _NJSD_sendCMDR (SD_CLK_167KHz, responseBuffer, SD_RSP_48, SEND_STATUS, 0); - - // Make sure the card responded correctly - if (responseBuffer[0] != SEND_STATUS) { - return false; - } - return true; -} - -bool _NJSD_clearStatus (void) { - return _NJSD_reset(); -} - -bool _NJSD_shutdown(void) { - return _NJSD_clearStatus(); -} - -bool _NJSD_startup(void) { - if (! _NJSD_init(0xA0406000) ) { - return false; - } - if (! _NJSD_cardInit() ) { - return false; - } - return true; -} - - -bool _NJSD_writeSectors (u32 sector, u32 numSectors, const void* buffer) { - u8 crc[8]; - u32 offset = sector * BYTES_PER_READ; - u8* data = (u8*) buffer; - - while (numSectors--) { - _SD_CRC16 ( data, BYTES_PER_READ, crc); - - if (! _NJSD_writeSector (data, crc, offset)) { - return false; - } - offset += BYTES_PER_READ; - data += BYTES_PER_READ; - } - return true; -} - -#ifdef _IO_ALLOW_UNALIGNED -bool _NJSD_readSectors (u32 sector, u32 numSectors, void* buffer) { - u32 tmp[BYTES_PER_READ>>2]; - int i; - -#ifdef _NJSD_SYNC - u32 old_REG_IME; -#endif - - u8* tbuf = (u8*)buffer; - - if (numSectors == 0) { - return false; - } - -#ifdef _NJSD_SYNC - old_REG_IME = REG_IME; - REG_IME = 0; -#endif - - if (numSectors > 1) { - _NJSD_sendCMDR (_NJSD_speed, NULL, SD_RSP_DATA, READ_MULTIPLE_BLOCK, sector * BYTES_PER_READ); - for (i = 0; i < numSectors - 2; i++) { - if (((int)buffer & 0x03) != 0){ - cardPolledTransfer (0xA1406000, tmp, BYTES_PER_READ, _NJSD_read_cmd); - memcpy (tbuf + i * BYTES_PER_READ, tmp, BYTES_PER_READ); - } else { - cardPolledTransfer (0xA1406000, (u32*)(tbuf + i * BYTES_PER_READ), BYTES_PER_READ, _NJSD_read_cmd); - } - if (!_NJSD_waitIRQ ()) { -#ifdef _NJSD_SYNC - REG_IME = old_REG_IME; -#endif - return false; - } - } - if (((int)buffer & 0x03) != 0){ - cardPolledTransfer (0xA1406000, tmp, BYTES_PER_READ, _NJSD_read_end_cmd); - memcpy (tbuf + (numSectors - 2) * BYTES_PER_READ, tmp, BYTES_PER_READ); - } else { - cardPolledTransfer (0xA1406000, (u32*)(tbuf + (numSectors - 2) * BYTES_PER_READ), BYTES_PER_READ, _NJSD_read_end_cmd); - } - if (!_NJSD_waitIRQ ()) { -#ifdef _NJSD_SYNC - REG_IME = old_REG_IME; -#endif - return false; - } - - if (((int)buffer & 0x03) != 0){ - cardPolledTransfer (0xA1406000, tmp, BYTES_PER_READ, _NJSD_read_cmd); - memcpy (tbuf + (numSectors - 1) * BYTES_PER_READ, tmp, BYTES_PER_READ); - } else { - cardPolledTransfer (0xA1406000, (u32*)(tbuf + (numSectors - 1) * BYTES_PER_READ), BYTES_PER_READ, _NJSD_read_cmd); - } - } else { - _NJSD_sendCMDR (_NJSD_speed, NULL, SD_RSP_STREAM, READ_SINGLE_BLOCK, sector * BYTES_PER_READ); - if (((int)buffer & 0x03) != 0){ - cardPolledTransfer (0xA1406000, tmp, BYTES_PER_READ, _NJSD_read_cmd); - memcpy (tbuf, tmp, BYTES_PER_READ); - } else { - cardPolledTransfer (0xA1406000, (u32*)tbuf, BYTES_PER_READ, _NJSD_read_cmd); - } - } - -#ifdef _NJSD_SYNC - REG_IME = old_REG_IME; -#endif - return true; -} -#else // not defined _IO_ALLOW_UNALIGNED -bool _NJSD_readSectors (u32 sector, u32 numSectors, void* buffer) { - int i; - -#ifdef _NJSD_SYNC - u32 old_REG_IME; -#endif - - u8* tbuf = (u8*)buffer; - - if (numSectors == 0) { - return false; - } - -#ifdef _NJSD_SYNC - old_REG_IME = REG_IME; - REG_IME = 0; -#endif - - if (numSectors > 1) { - _NJSD_sendCMDR (_NJSD_speed, NULL, SD_RSP_DATA, READ_MULTIPLE_BLOCK, sector * BYTES_PER_READ); - for (i = 0; i < numSectors - 2; i++) { - cardPolledTransfer (0xA1406000, (u32*)(tbuf + i * BYTES_PER_READ), BYTES_PER_READ, _NJSD_read_cmd); - if (!_NJSD_waitIRQ ()) { -#ifdef _NJSD_SYNC - REG_IME = old_REG_IME; -#endif - return false; - } - } - cardPolledTransfer (0xA1406000, (u32*)(tbuf + (numSectors - 2) * BYTES_PER_READ), BYTES_PER_READ, _NJSD_read_end_cmd); - if (!_NJSD_waitIRQ ()) { -#ifdef _NJSD_SYNC - REG_IME = old_REG_IME; -#endif - return false; - } - - cardPolledTransfer (0xA1406000, (u32*)(tbuf + (numSectors - 1) * BYTES_PER_READ), BYTES_PER_READ, _NJSD_read_cmd); - } else { - _NJSD_sendCMDR (_NJSD_speed, NULL, SD_RSP_STREAM, READ_SINGLE_BLOCK, sector * BYTES_PER_READ); - cardPolledTransfer (0xA1406000, (u32*)tbuf, BYTES_PER_READ, _NJSD_read_cmd); - } - -#ifdef _NJSD_SYNC - REG_IME = old_REG_IME; -#endif - return true; -} -#endif // _IO_ALLOW_UNALIGNED - -const IO_INTERFACE _io_njsd = { - DEVICE_TYPE_NJSD, - FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_SLOT_NDS, - (FN_MEDIUM_STARTUP)&_NJSD_startup, - (FN_MEDIUM_ISINSERTED)&_NJSD_isInserted, - (FN_MEDIUM_READSECTORS)&_NJSD_readSectors, - (FN_MEDIUM_WRITESECTORS)&_NJSD_writeSectors, - (FN_MEDIUM_CLEARSTATUS)&_NJSD_clearStatus, - (FN_MEDIUM_SHUTDOWN)&_NJSD_shutdown -} ; - -#endif // defined NDS diff --git a/source/disc_io/io_njsd.h b/source/disc_io/io_njsd.h deleted file mode 100644 index 7586638..0000000 --- a/source/disc_io/io_njsd.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - io_njsd.h - - Hardware Routines for reading an SD card using - a NinjaDS SD adapter. - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-08-02 - Chishm - * Original release -*/ - -#ifndef IO_NJSD_H -#define IO_NJSD_H - -#include "../disc.h" - -#ifdef NDS - -// 'NJSD' -#define DEVICE_TYPE_NJSD 0x44534A4E - - -// export interface -extern const IO_INTERFACE _io_njsd; - -#endif // defined NDS - -#endif // define IO_NJSD_H diff --git a/source/disc_io/io_nmmc.c b/source/disc_io/io_nmmc.c deleted file mode 100644 index 19283eb..0000000 --- a/source/disc_io/io_nmmc.c +++ /dev/null @@ -1,348 +0,0 @@ -/* - io_nmmc.c - - Hardware Routines for reading an SD or MMC card using - a Neoflash MK2 or MK3. - - Written by www.neoflash.com - - Submit bug reports for this device to the NeoFlash forums - - See license.txt for license details. - - 2006-02-09 - www.neoflash.com: - * First stable release - - 2006-02-13 - Chishm - * Added ReadMK2Config function - * Added read config test to init function so no unnecessary card commands are sent - * Changed data read and write functions to use multiple block commands -*/ - -#include "io_nmmc.h" - -#ifdef NDS - -#include - -int _NMMC_spi_freq = 3; - -#define MK2_CONFIG_ZIP_RAM_CLOSE (1 << 5) -#define MK2_CONFIG_GAME_FLASH_CLOSE ((1 << 4) | (1 << 0)) -//#define MK2_CONFIG_ZIP_RAM_CLOSE ((1 << 5) | (1 << 1)) -//#define MK2_CONFIG_GAME_FLASH_CLOSE (1 << 4) - -#define MMC_READ_MULTIPLE_BLOCK 18 -#define MMC_READ_BLOCK 17 -#define MMC_WRITE_MULTIPLE_BLOCK 25 -#define MMC_WRITE_BLOCK 24 -#define MMC_STOP_TRANSMISSION 12 -#define MMC_SET_BLOCKLEN 16 -#define MMC_SET_BLOCK_COUNT 23 -#define MMC_SEND_CSD 9 - -// SPI functions - -static inline void _Neo_OpenSPI( u8 frequency ) -{ - CARD_CR1 = 0x0000A040 | frequency; -} - -static inline u8 _Neo_SPI( u8 dataByte ) -{ - CARD_EEPDATA = dataByte; - while (CARD_CR1 & 0x80); // card busy - return CARD_EEPDATA; -} - -static inline void _Neo_CloseSPI ( void ) -{ - CARD_CR1 = 0; -} - -static inline void _Neo_MK2GameMode() { - _Neo_OpenSPI(_NMMC_spi_freq); // Enable DS Card's SPI port - _Neo_SPI(0xF1); // Switch to game mode - _Neo_CloseSPI(); // Disable DS Card's SPI port -} - -static inline void _Neo_EnableEEPROM( bool enable ) { - _Neo_OpenSPI(_NMMC_spi_freq); - if(enable) _Neo_SPI(0x06); - else _Neo_SPI(0x0E); - _Neo_CloseSPI(); -} - -static void _Neo_WriteMK2Config(u8 config) { - _Neo_EnableEEPROM(true); - _Neo_OpenSPI(_NMMC_spi_freq); - _Neo_SPI(0xFA); // Send mem conf write command - _Neo_SPI(0x01); // Send high byte (0x01) - _Neo_SPI(config); // Send low byte - _Neo_CloseSPI(); - _Neo_EnableEEPROM(false); -} - -static u8 _Neo_ReadMK2Config(void) -{ - u8 config; - _Neo_EnableEEPROM(true); - _Neo_OpenSPI(_NMMC_spi_freq); - _Neo_SPI(0xf8); // Send mem conf read command - _Neo_SPI(0x01); // Send high byte - config = _Neo_SPI(0x00); // Get low byte - _Neo_CloseSPI(); - _Neo_EnableEEPROM(false); - return config; -} - -// Low level functions - -u8 selectMMC_command [8] = {0xFF, 0x00, 0x6A, 0xDF, 0x37, 0x59, 0x33, 0xA3}; - -static void _Neo_SelectMMC (u8 dataByte) -{ - selectMMC_command[1] = dataByte; // Set enable / disable byte - cardWriteCommand (selectMMC_command); // Send "5. Use the EEPROM CS to access the MK2 MMC/SD card" - CARD_CR2 = CARD_ACTIVATE | CARD_nRESET; - while (CARD_CR2 & CARD_BUSY); - return; -} - -static void _Neo_EnableMMC( bool enable ) -{ - if ( enable == false) { - _Neo_CloseSPI (); - _Neo_SelectMMC (0); - _Neo_SelectMMC (0); - } else { - _Neo_SelectMMC (1); - _Neo_SelectMMC (1); - _Neo_OpenSPI (_NMMC_spi_freq); - } - return; -} - -static void _Neo_SendMMCCommand( u8 command, u32 argument ) -{ - _Neo_SPI (0xFF); - _Neo_SPI (command | 0x40); - _Neo_SPI ((argument >> 24) & 0xff); - _Neo_SPI ((argument >> 16) & 0xff); - _Neo_SPI ((argument >> 8) & 0xff) ; - _Neo_SPI (argument & 0xff); - _Neo_SPI (0x95); - _Neo_SPI (0xFF); - return; -} - -static bool _Neo_CheckMMCResponse( u8 response, u8 mask ) { - u32 i; - for(i=0;i<256;i++) { - if( ( _Neo_SPI( 0xFF ) & mask ) == response ) - return true; - } - return false; -} - -// Neo MMC functions - -static bool _Neo_InitMMC() { - _Neo_MK2GameMode(); - _Neo_WriteMK2Config( MK2_CONFIG_ZIP_RAM_CLOSE | MK2_CONFIG_GAME_FLASH_CLOSE); - - // Make sure the configuration was accepted - if (_Neo_ReadMK2Config() != (MK2_CONFIG_ZIP_RAM_CLOSE | MK2_CONFIG_GAME_FLASH_CLOSE)) { - return false; // If not, then it wasn't initialised properly - } - - return true; -} - -// Neo MMC driver functions - -bool _NMMC_isInserted(void) { - int i; - - _Neo_EnableMMC( true ); // Open SPI port to MMC card - _Neo_SendMMCCommand(MMC_SEND_CSD, 0); - if( _Neo_CheckMMCResponse( 0x00, 0xFF ) == false ) { // Make sure no errors occured - _Neo_EnableMMC( false ); - return false; - } - if( _Neo_CheckMMCResponse( 0xFE, 0xFF ) == false ) { // Check for Start Block token - _Neo_EnableMMC( false ); - return false; - } - - // consume data from card, and send clocks. - for (i = 0; i < 28; i++) { - _Neo_SPI(0xff); - } - - return true; -} - -bool _NMMC_clearStatus (void) { - u32 i; - - _Neo_EnableMMC( true ); // Open SPI port to MMC card - for (i = 0; i < 10; i++) { - _Neo_SPI(0xFF); // Send 10 0xFF bytes to MMC card - } - _Neo_SendMMCCommand(0, 0); // Send GO_IDLE_STATE command - if( _Neo_CheckMMCResponse( 0x01, 0xFF ) == false ) { // Check that it replied with 0x01 (not idle, no other error) - _Neo_EnableMMC( false ); - return false; - } - for(i=0;i<256;i++) { - _Neo_SendMMCCommand(1, 0); // Poll with SEND_OP_COND - if( _Neo_CheckMMCResponse( 0x00, 0x01 ) == true ) { // Check for idle state - _Neo_EnableMMC( false ); // Close SPI port to MMC card - return true; // Card is now idle - } - } - _Neo_EnableMMC( false ); - return false; -} - -bool _NMMC_shutdown(void) { - return _NMMC_clearStatus(); -} - -bool _NMMC_startUp(void) { - int i; - int transSpeed; - if (_Neo_InitMMC() == false) { - return false; - } - if (_NMMC_clearStatus() == false) { - return false; - } - _Neo_EnableMMC( true ); // Open SPI port to MMC card - - // Set block length - _Neo_SendMMCCommand(MMC_SET_BLOCKLEN, BYTES_PER_READ ); - if( _Neo_CheckMMCResponse( 0x00, 0xFF ) == false ) { // Make sure no errors occured - _Neo_EnableMMC( false ); - return false; - } - - // Check if we can use a higher SPI frequency - _Neo_SendMMCCommand(MMC_SEND_CSD, 0); - if( _Neo_CheckMMCResponse( 0x00, 0xFF ) == false ) { // Make sure no errors occured - _Neo_EnableMMC( false ); - return false; - } - if( _Neo_CheckMMCResponse( 0xFE, 0xFF ) == false ) { // Check for Start Block token - _Neo_EnableMMC( false ); - return false; - } - for (i = 0; i < 3; i++) { - _Neo_SPI(0xFF); - } - transSpeed = _Neo_SPI (0xFF); - for (i = 0; i < 24; i++) { - _Neo_SPI(0xFF); - } - if ((transSpeed & 0xf0) >= 0x30) { - _NMMC_spi_freq = 0; - } - - _Neo_EnableMMC( false ); - - return true; -} - - -bool _NMMC_writeSectors (u32 sector, u32 totalSecs, const void* buffer) -{ - u32 i; - u8 *p=(u8*)buffer; - - sector *= BYTES_PER_READ; - - _Neo_EnableMMC( true ); // Open SPI port to MMC card - _Neo_SendMMCCommand( 25, sector ); - if( _Neo_CheckMMCResponse( 0x00, 0xFF ) == false ) { // Make sure no errors occured - _Neo_EnableMMC( false ); - return false; - } - - while (totalSecs--) { - _Neo_SPI( 0xFC ); // Send Start Block token - for( i = 0; i < BYTES_PER_READ; i++ ) // Send a block of data - _Neo_SPI( *p++ ); - _Neo_SPI( 0xFF ); // Send fake CRC16 - _Neo_SPI( 0xFF ); // Send fake CRC16 - - if( ( _Neo_SPI( 0xFF ) & 0x0F ) != 0x05 ) { // Make sure the block was accepted - _Neo_EnableMMC( false ); - return false; - } - while( _Neo_SPI( 0xFF ) == 0x00 ); // Wait for the block to be written - } - - // Stop transmission block - _Neo_SPI( 0xFD ); // Send Stop Transmission Block token - for( i = 0; i < BYTES_PER_READ; i++ ) // Send a block of fake data - _Neo_SPI( 0xFF ); - _Neo_SPI( 0xFF ); // Send fake CRC16 - _Neo_SPI( 0xFF ); // Send fake CRC16 - - _Neo_SPI (0xFF); // Send 8 clocks - while( _Neo_SPI( 0xFF ) == 0x00 ); // Wait for the busy signal to clear - - - for ( i = 0; i < 0x10; i++) { - _Neo_SPI (0xFF); // Send clocks for the MMC card to finish what it's doing - } - - _Neo_EnableMMC( false ); // Close SPI port to MMC card - return true; -} - -bool _NMMC_readSectors (u32 sector, u32 totalSecs, void* buffer) -{ - u32 i; - u8 *p=(u8*)buffer; - - sector *= BYTES_PER_READ; - - _Neo_EnableMMC( true ); // Open SPI port to MMC card - - while (totalSecs--) { - _Neo_SendMMCCommand(MMC_READ_BLOCK, sector ); - if( _Neo_CheckMMCResponse( 0x00, 0xFF ) == false ) { // Make sure no errors occured - _Neo_EnableMMC( false ); - return false; - } - - if( _Neo_CheckMMCResponse( 0xFE, 0xFF ) == false ) { // Check for Start Block token - _Neo_EnableMMC( false ); - return false; - } - for( i = 0; i < BYTES_PER_READ; i++ ) // Read in a block of data - *p++ = _Neo_SPI( 0xFF ); - _Neo_SPI( 0xFF ); // Ignore CRC16 - _Neo_SPI( 0xFF ); // Ignore CRC16 - sector += BYTES_PER_READ; - } - - _Neo_EnableMMC( false ); // Close SPI port to MMC card - return true; -} - - -const IO_INTERFACE _io_nmmc = { - DEVICE_TYPE_NMMC, - FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_SLOT_NDS, - (FN_MEDIUM_STARTUP)&_NMMC_startUp, - (FN_MEDIUM_ISINSERTED)&_NMMC_isInserted, - (FN_MEDIUM_READSECTORS)&_NMMC_readSectors, - (FN_MEDIUM_WRITESECTORS)&_NMMC_writeSectors, - (FN_MEDIUM_CLEARSTATUS)&_NMMC_clearStatus, - (FN_MEDIUM_SHUTDOWN)&_NMMC_shutdown -} ; - -#endif // defined NDS diff --git a/source/disc_io/io_nmmc.h b/source/disc_io/io_nmmc.h deleted file mode 100644 index 34c93d6..0000000 --- a/source/disc_io/io_nmmc.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - io_nmmc.h - - Hardware Routines for reading an SD or MMC card using - a Neoflash MK2 or MK3. - - Original version written by www.neoflash.com, - moddified and used with permission of www.neoflash.com - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release -*/ - -#ifndef IO_NMMC_H -#define IO_NMMC_H - -#include "../disc.h" - -#ifdef NDS - -// 'NMMC' -#define DEVICE_TYPE_NMMC 0x434D4D4E - - -// export interface -extern const IO_INTERFACE _io_nmmc; - -#endif // defined NDS - -#endif // define IO_NMMC_H diff --git a/source/disc_io/io_sc_common.c b/source/disc_io/io_sc_common.c deleted file mode 100644 index 7035e12..0000000 --- a/source/disc_io/io_sc_common.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - io_m3_common.h - - Routines common to all version of the Super Card - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "io_sc_common.h" - -/*----------------------------------------------------------------- -_SC_changeMode (was SC_Unlock) -Added by MightyMax -Modified by Chishm -Modified again by loopy -1=ram(readonly), 5=ram, 3=SD interface? ------------------------------------------------------------------*/ -void _SC_changeMode(u8 mode) { - vu16 *unlockAddress = (vu16*)0x09FFFFFE; - *unlockAddress = 0xA55A ; - *unlockAddress = 0xA55A ; - *unlockAddress = mode ; - *unlockAddress = mode ; -} - - diff --git a/source/disc_io/io_sc_common.h b/source/disc_io/io_sc_common.h deleted file mode 100644 index 1a98268..0000000 --- a/source/disc_io/io_sc_common.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - io_sc_common.h - - Routines common to all version of the Super Card - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release - - 2007-01-29 - Chishm - * Added SC_MODE_FLASH -*/ - -#ifndef IO_SC_COMMON_H -#define IO_SC_COMMON_H - -#include "../disc.h" - -// Values for changing mode -#define SC_MODE_FLASH 0x1510 -#define SC_MODE_RAM 0x5 -#define SC_MODE_MEDIA 0x3 -#define SC_MODE_RAM_RO 0x1 - -extern void _SC_changeMode (u8 mode); - -#endif // IO_SC_COMMON_H diff --git a/source/disc_io/io_sccf.c b/source/disc_io/io_sccf.c deleted file mode 100644 index ec78b29..0000000 --- a/source/disc_io/io_sccf.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - io_sccf.c based on - - compact_flash.c - By chishm (Michael Chisholm) - - Hardware Routines for reading a compact flash card - using the Super Card CF - - CF routines modified with help from Darkfader - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include "io_sccf.h" -#include "io_sc_common.h" -#include "io_cf_common.h" - -//--------------------------------------------------------------- -// SC CF Addresses -#define REG_SCCF_STS ((vu16*)0x098C0000) // Status of the CF Card / Device control -#define REG_SCCF_CMD ((vu16*)0x090E0000) // Commands sent to control chip and status return -#define REG_SCCF_ERR ((vu16*)0x09020000) // Errors / Features - -#define REG_SCCF_SEC ((vu16*)0x09040000) // Number of sector to transfer -#define REG_SCCF_LBA1 ((vu16*)0x09060000) // 1st byte of sector address -#define REG_SCCF_LBA2 ((vu16*)0x09080000) // 2nd byte of sector address -#define REG_SCCF_LBA3 ((vu16*)0x090A0000) // 3rd byte of sector address -#define REG_SCCF_LBA4 ((vu16*)0x090C0000) // last nibble of sector address | 0xE0 - -#define REG_SCCF_DATA ((vu16*)0x09000000) // Pointer to buffer of CF data transered from card - -static const CF_REGISTERS _SCCF_Registers = { - REG_SCCF_DATA, - REG_SCCF_STS, - REG_SCCF_CMD, - REG_SCCF_ERR, - REG_SCCF_SEC, - REG_SCCF_LBA1, - REG_SCCF_LBA2, - REG_SCCF_LBA3, - REG_SCCF_LBA4 -}; - - -bool _SCCF_startup(void) { - _SC_changeMode (SC_MODE_MEDIA); - return _CF_startup(&_SCCF_Registers); -} - - -const IO_INTERFACE _io_sccf = { - DEVICE_TYPE_SCCF, - FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_SLOT_GBA, - (FN_MEDIUM_STARTUP)&_SCCF_startup, - (FN_MEDIUM_ISINSERTED)&_CF_isInserted, - (FN_MEDIUM_READSECTORS)&_CF_readSectors, - (FN_MEDIUM_WRITESECTORS)&_CF_writeSectors, - (FN_MEDIUM_CLEARSTATUS)&_CF_clearStatus, - (FN_MEDIUM_SHUTDOWN)&_CF_shutdown -} ; diff --git a/source/disc_io/io_sccf.h b/source/disc_io/io_sccf.h deleted file mode 100644 index 12fc491..0000000 --- a/source/disc_io/io_sccf.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - io_sccf.h - - Hardware Routines for reading a compact flash card - using the Supercard CF - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release -*/ - -#ifndef IO_SCCF_H -#define IO_SCCF_H - -// 'SCCF' -#define DEVICE_TYPE_SCCF 0x46434353 - -#include "../disc.h" - -// export interface -extern const IO_INTERFACE _io_sccf; - -#endif // define IO_SCCF_H diff --git a/source/disc_io/io_scsd.c b/source/disc_io/io_scsd.c deleted file mode 100644 index bdb4b1e..0000000 --- a/source/disc_io/io_scsd.c +++ /dev/null @@ -1,399 +0,0 @@ -/* - io_scsd.c - - Hardware Routines for reading a Secure Digital card - using the SC SD - - Some code based on scsd_c.c, written by Amadeus - and Jean-Pierre Thomasset as part of DSLinux. - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-22 - Chishm - * First release of stable code - - 2006-07-25 - Chishm - * Improved startup function that doesn't delay hundreds of seconds - before reporting no card inserted. - - 2006-08-05 - Chishm - * Tries multiple times to get a Relative Card Address at startup - - 2006-08-07 - Chishm - * Moved the SD initialization to a common function - - 2006-08-19 - Chishm - * Added SuperCard Lite support -*/ - -#include "io_scsd.h" -#include "io_sd_common.h" -#include "io_sc_common.h" - -//--------------------------------------------------------------- -// SCSD register addresses -#define REG_SCSD_CMD (*(vu16*)(0x09800000)) - /* bit 0: command bit to read */ - /* bit 7: command bit to write */ - -#define REG_SCSD_DATAWRITE (*(vu16*)(0x09000000)) -#define REG_SCSD_DATAREAD (*(vu16*)(0x09100000)) -#define REG_SCSD_DATAREAD_32 (*(vu32*)(0x09100000)) -#define REG_SCSD_LITE_ENABLE (*(vu16*)(0x09440000)) -#define REG_SCSD_LOCK (*(vu16*)(0x09FFFFFE)) - /* bit 0: 1 */ - /* bit 1: enable IO interface (SD,CF) */ - /* bit 2: enable R/W SDRAM access */ - -//--------------------------------------------------------------- -// Responses -#define SCSD_STS_BUSY 0x100 -#define SCSD_STS_INSERTED 0x300 - -//--------------------------------------------------------------- -// Send / receive timeouts, to stop infinite wait loops -#define NUM_STARTUP_CLOCKS 100 // Number of empty (0xFF when sending) bytes to send/receive to/from the card -#define TRANSMIT_TIMEOUT 100000 // Time to wait for the SC to respond to transmit or receive requests -#define RESPONSE_TIMEOUT 256 // Number of clocks sent to the SD card before giving up -#define BUSY_WAIT_TIMEOUT 500000 -#define WRITE_TIMEOUT 3000 // Time to wait for the card to finish writing -//--------------------------------------------------------------- -// Variables required for tracking SD state -static u32 _SCSD_relativeCardAddress = 0; // Preshifted Relative Card Address - -//--------------------------------------------------------------- -// Internal SC SD functions - -extern bool _SCSD_writeData_s (u8 *data, u16* crc); - -static inline void _SCSD_unlock (void) { - _SC_changeMode (SC_MODE_MEDIA); -} - -static inline void _SCSD_enable_lite (void) { - REG_SCSD_LITE_ENABLE = 0; -} - -static bool _SCSD_sendCommand (u8 command, u32 argument) { - u8 databuff[6]; - u8 *tempDataPtr = databuff; - int length = 6; - u16 dataByte; - int curBit; - int i; - - *tempDataPtr++ = command | 0x40; - *tempDataPtr++ = argument>>24; - *tempDataPtr++ = argument>>16; - *tempDataPtr++ = argument>>8; - *tempDataPtr++ = argument; - *tempDataPtr = _SD_CRC7 (databuff, 5); - - i = BUSY_WAIT_TIMEOUT; - while (((REG_SCSD_CMD & 0x01) == 0) && (--i)); - if (i == 0) { - return false; - } - - dataByte = REG_SCSD_CMD; - - tempDataPtr = databuff; - - while (length--) { - dataByte = *tempDataPtr++; - for (curBit = 7; curBit >=0; curBit--){ - REG_SCSD_CMD = dataByte; - dataByte = dataByte << 1; - } - } - - return true; -} - -// Returns the response from the SD card to a previous command. -static bool _SCSD_getResponse (u8* dest, u32 length) { - u32 i; - int dataByte; - int numBits = length * 8; - - // Wait for the card to be non-busy - i = BUSY_WAIT_TIMEOUT; - while (((REG_SCSD_CMD & 0x01) != 0) && (--i)); - if (dest == NULL) { - return true; - } - - if (i == 0) { - // Still busy after the timeout has passed - return false; - } - - // The first bit is always 0 - dataByte = 0; - numBits--; - // Read the remaining bits in the response. - // It's always most significant bit first - while (numBits--) { - dataByte = (dataByte << 1) | (REG_SCSD_CMD & 0x01); - if ((numBits & 0x7) == 0) { - // It's read a whole byte, so store it - *dest++ = (u8)dataByte; - dataByte = 0; - } - } - - // Send 16 more clocks, 8 more than the delay required between a response and the next command - for (i = 0; i < 16; i++) { - dataByte = REG_SCSD_CMD; - } - - return true; -} - -static inline bool _SCSD_getResponse_R1 (u8* dest) { - return _SCSD_getResponse (dest, 6); -} - -static inline bool _SCSD_getResponse_R1b (u8* dest) { - return _SCSD_getResponse (dest, 6); -} - -static inline bool _SCSD_getResponse_R2 (u8* dest) { - return _SCSD_getResponse (dest, 17); -} - -static inline bool _SCSD_getResponse_R3 (u8* dest) { - return _SCSD_getResponse (dest, 6); -} - -static inline bool _SCSD_getResponse_R6 (u8* dest) { - return _SCSD_getResponse (dest, 6); -} - -static void _SCSD_sendClocks (u32 numClocks) { - u16 temp; - do { - temp = REG_SCSD_CMD; - } while (numClocks--); -} - -bool _SCSD_cmd_6byte_response (u8* responseBuffer, u8 command, u32 data) { - _SCSD_sendCommand (command, data); - return _SCSD_getResponse (responseBuffer, 6); -} - -bool _SCSD_cmd_17byte_response (u8* responseBuffer, u8 command, u32 data) { - _SCSD_sendCommand (command, data); - return _SCSD_getResponse (responseBuffer, 17); -} - - -static bool _SCSD_initCard (void) { - _SCSD_enable_lite(); - - // Give the card time to stabilise - _SCSD_sendClocks (NUM_STARTUP_CLOCKS); - - // Reset the card - if (!_SCSD_sendCommand (GO_IDLE_STATE, 0)) { - return false; - } - - _SCSD_sendClocks (NUM_STARTUP_CLOCKS); - - // Card is now reset, including it's address - _SCSD_relativeCardAddress = 0; - - // Init the card - return _SD_InitCard (_SCSD_cmd_6byte_response, - _SCSD_cmd_17byte_response, - true, - &_SCSD_relativeCardAddress); -} - -static bool _SCSD_readData (void* buffer) { - u8* buff_u8 = (u8*)buffer; - u16* buff = (u16*)buffer; - volatile register u32 temp; - int i; - - i = BUSY_WAIT_TIMEOUT; - while ((REG_SCSD_DATAREAD & SCSD_STS_BUSY) && (--i)); - if (i == 0) { - return false; - } - - i=256; - if ((u32)buff_u8 & 0x01) { - while(i--) { - temp = REG_SCSD_DATAREAD_32; - temp = REG_SCSD_DATAREAD_32 >> 16; - *buff_u8++ = (u8)temp; - *buff_u8++ = (u8)(temp >> 8); - } - } else { - while(i--) { - temp = REG_SCSD_DATAREAD_32; - temp = REG_SCSD_DATAREAD_32 >> 16; - *buff++ = temp; - } - } - - - for (i = 0; i < 8; i++) { - temp = REG_SCSD_DATAREAD_32; - } - - temp = REG_SCSD_DATAREAD; - - return true; -} - -//--------------------------------------------------------------- -// Functions needed for the external interface - -bool _SCSD_startUp (void) { - _SCSD_unlock(); - return _SCSD_initCard(); -} - -bool _SCSD_isInserted (void) { - u8 responseBuffer [6]; - - // Make sure the card receives the command - if (!_SCSD_sendCommand (SEND_STATUS, 0)) { - return false; - } - // Make sure the card responds - if (!_SCSD_getResponse_R1 (responseBuffer)) { - return false; - } - // Make sure the card responded correctly - if (responseBuffer[0] != SEND_STATUS) { - return false; - } - return true; -} - -bool _SCSD_readSectors (u32 sector, u32 numSectors, void* buffer) { - u32 i; - u8* dest = (u8*) buffer; - u8 responseBuffer[6]; - - if (numSectors == 1) { - // If it's only reading one sector, use the (slightly faster) READ_SINGLE_BLOCK - if (!_SCSD_sendCommand (READ_SINGLE_BLOCK, sector * BYTES_PER_READ)) { - return false; - } - - if (!_SCSD_readData (buffer)) { - return false; - } - - } else { - // Stream the required number of sectors from the card - if (!_SCSD_sendCommand (READ_MULTIPLE_BLOCK, sector * BYTES_PER_READ)) { - return false; - } - - for(i=0; i < numSectors; i++, dest+=BYTES_PER_READ) { - if (!_SCSD_readData(dest)) { - return false; - } - } - - // Stop the streaming - _SCSD_sendCommand (STOP_TRANSMISSION, 0); - _SCSD_getResponse_R1b (responseBuffer); - } - - _SCSD_sendClocks(0x10); - return true; -} - -bool _SCSD_writeSectors (u32 sector, u32 numSectors, const void* buffer) { - u16 crc[4]; // One per data line - u8 responseBuffer[6]; - u32 offset = sector * BYTES_PER_READ; - u8* data = (u8*) buffer; - int i; - - while (numSectors--) { - // Calculate the CRC16 - _SD_CRC16 ( data, BYTES_PER_READ, (u8*)crc); - - // Send write command and get a response - _SCSD_sendCommand (WRITE_BLOCK, offset); - if (!_SCSD_getResponse_R1 (responseBuffer)) { - return false; - } - - // Send the data and CRC - if (! _SCSD_writeData_s (data, crc)) { - return false; - } - - // Send a few clocks to the SD card - _SCSD_sendClocks(0x10); - - offset += BYTES_PER_READ; - data += BYTES_PER_READ; - - // Wait until card is finished programming - i = WRITE_TIMEOUT; - responseBuffer[3] = 0; - do { - _SCSD_sendCommand (SEND_STATUS, _SCSD_relativeCardAddress); - _SCSD_getResponse_R1 (responseBuffer); - i--; - if (i <= 0) { - return false; - } - } while (((responseBuffer[3] & 0x1f) != ((SD_STATE_TRAN << 1) | READY_FOR_DATA))); - } - - return true; -} - -bool _SCSD_clearStatus (void) { - return _SCSD_initCard (); -} - -bool _SCSD_shutdown (void) { - _SC_changeMode (SC_MODE_RAM_RO); - return true; -} - -const IO_INTERFACE _io_scsd = { - DEVICE_TYPE_SCSD, - FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_SLOT_GBA, - (FN_MEDIUM_STARTUP)&_SCSD_startUp, - (FN_MEDIUM_ISINSERTED)&_SCSD_isInserted, - (FN_MEDIUM_READSECTORS)&_SCSD_readSectors, - (FN_MEDIUM_WRITESECTORS)&_SCSD_writeSectors, - (FN_MEDIUM_CLEARSTATUS)&_SCSD_clearStatus, - (FN_MEDIUM_SHUTDOWN)&_SCSD_shutdown -} ; - - diff --git a/source/disc_io/io_scsd.h b/source/disc_io/io_scsd.h deleted file mode 100644 index d2594b7..0000000 --- a/source/disc_io/io_scsd.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - io_scsd.h - - Hardware Routines for reading a Secure Digital card - using the Supercard SD - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release - - 2006-07-22 - Chishm - * First release of stable code -*/ - -#ifndef IO_SCSD_H -#define IO_SCSD_H - -// 'SCSD' -#define DEVICE_TYPE_SCSD 0x44534353 - -#include "../disc.h" - -// export interface -extern const IO_INTERFACE _io_scsd ; - -#endif // define IO_SCSD_H diff --git a/source/disc_io/io_scsd_s.s b/source/disc_io/io_scsd_s.s deleted file mode 100644 index 2b68d3f..0000000 --- a/source/disc_io/io_scsd_s.s +++ /dev/null @@ -1,139 +0,0 @@ -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@ io_scsd_s.s -@ -@ Hardware Routines for reading a Secure Digital card -@ using the SC SD -@ -@ Based on code supplied by Romman -@ -@ Copyright (c) 2006 Michael "Chishm" Chisholm -@ -@ Redistribution and use in source and binary forms, with or without modification, -@ are permitted provided that the following conditions are met: -@ -@ 1. Redistributions of source code must retain the above copyright notice, -@ this list of conditions and the following disclaimer. -@ 2. Redistributions in binary form must reproduce the above copyright notice, -@ this list of conditions and the following disclaimer in the documentation and/or -@ other materials provided with the distribution. -@ 3. The name of the author may not be used to endorse or promote products derived -@ from this software without specific prior written permission. -@ -@ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -@ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY -@ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE -@ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -@ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -@ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -@ -@ 2006-07-22 - Chishm -@ * First release of stable code -@ -@ 2006-08-19 - Chishm -@ * Added SuperCard Lite support -@ -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ - - .align 4 - .arm - - .equ REG_SCSD_DATAWRITE, 0x09000000 - .equ BYTES_PER_READ, 0x200 - .equ SCSD_STS_BUSY, 0x100 - .equ BUSY_WAIT_TIMEOUT, 0x10000 - .equ FALSE, 0 - .equ TRUE, 1 - -@ bool _SCSD_writeData_s (u8 *data, u16* crc) - - .global _SCSD_writeData_s - -_SCSD_writeData_s: - stmfd r13!, {r4-r5} - mov r5, #BYTES_PER_READ - mov r2, #REG_SCSD_DATAWRITE - -@ Wait for a free data buffer on the SD card - mov r4, #BUSY_WAIT_TIMEOUT -_SCSD_writeData_busy_wait: - @ Test for timeout - subs r4, r4, #1 - moveq r0, #FALSE @ return false on failure - beq _SCSD_writeData_return - @ Check the busy bit of the status register - ldrh r3, [r2] - tst r3, #SCSD_STS_BUSY - beq _SCSD_writeData_busy_wait - - ldrh r3, [r2] @ extra clock - - mov r3, #0 @ start bit - strh r3,[r2] - -@ Check if the data buffer is aligned on a halfword boundary - tst r0, #1 - beq _SCSD_writeData_data_loop - -@ Used when the source data is unaligned -_SCSD_writeData_data_loop_unaligned: - ldrb r3, [r0], #1 - ldrb r4, [r0], #1 - orr r3, r3, r4, lsl #8 - stmia r2, {r3-r4} - subs r5, r5, #2 - bne _SCSD_writeData_data_loop_unaligned - b _SCSD_writeData_crc - -@ Write the data to the card -@ 4 halfwords are transmitted to the Supercard at once, for timing purposes -@ Only the first halfword needs to contain data for standard SuperCards -@ For the SuperCard Lite, the data is split into 4 nibbles, one per halfword -_SCSD_writeData_data_loop: - ldrh r3, [r0], #2 - -@ This bit added for SCLite. Notice that the shift is not the same as in -@ the original (buggy) code supplied by Romman - add r3, r3, r3, lsl #20 - mov r4, r3, lsr #8 - - stmia r2, {r3-r4} - - subs r5, r5, #2 - bne _SCSD_writeData_data_loop - -@ Send the data CRC -_SCSD_writeData_crc: - cmp r1, #0 - movne r0, r1 - movne r1, #0 - movne r5, #8 - bne _SCSD_writeData_data_loop - - mov r3, #0xff @ end bit - strh r3, [r2] - -@ Wait for the SD card to signal that it is finished recieving - mov r4, #BUSY_WAIT_TIMEOUT -_SCSD_writeData_finished_wait: - @ Test for timeout - subs r4, r4, #1 - moveq r0, #FALSE @ return false on failure - beq _SCSD_writeData_return - @ Check the busy bit of the status register - ldrh r3, [r2] - tst r3, #0x100 - bne _SCSD_writeData_finished_wait - -@ Send 8 more clocks, as required by the SD card - ldmia r2, {r3-r4} - -@ return true for success - mov r0, #TRUE - -_SCSD_writeData_return: - ldmfd r13!,{r4-r5} - bx r14 - diff --git a/source/disc_io/io_sd_common.c b/source/disc_io/io_sd_common.c deleted file mode 100644 index 24f6873..0000000 --- a/source/disc_io/io_sd_common.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - io_sd_common.c - - By chishm (Michael Chisholm) - - Common SD card routines - - SD routines partially based on sd.s by Romman - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-08-07 - Chishm - * Moved the SD initialization to a common function - * Increased timeouts for slower cards - - 2006-08-08 - Chishm - * Init aborts when it doesn't get a valid response to APP_CMD - speeds up detection when no card is inserted -*/ - -#include "io_sd_common.h" - -#define MAX_STARTUP_TRIES 1000 // Arbitrary value, check if the card is ready 20 times before giving up -#define RESPONSE_TIMEOUT 256 // Number of clocks sent to the SD card before giving up - -/* -Improved CRC7 function provided by cory1492 -Calculates the CRC of an SD command, and includes the end bit in the byte -*/ -u8 _SD_CRC7(u8* data, int cnt) { - int i, a; - u8 crc, temp; - - crc = 0; - for (a = 0; a < cnt; a++) - { - temp = data[a]; - for (i = 0; i < 8; i++) - { - crc <<= 1; - if ((temp & 0x80) ^ (crc & 0x80)) crc ^= 0x09; - temp <<= 1; - } - } - crc = (crc << 1) | 1; - return(crc); -} - -/* -Calculates the CRC16 for a sector of data. Calculates it -as 4 separate lots, merged into one buffer. This is used -for 4 SD data lines, not for 1 data line alone. -*/ -void _SD_CRC16 (u8* buff, int buffLength, u8* crc16buff) { - u32 a, b, c, d; - int count; - u32 bitPattern = 0x80808080; // r7 - u32 crcConst = 0x1021; // r8 - u32 dataByte = 0; // r2 - - a = 0; // r3 - b = 0; // r4 - c = 0; // r5 - d = 0; // r6 - - buffLength = buffLength * 8; - - - do { - if (bitPattern & 0x80) dataByte = *buff++; - - a = a << 1; - if ( a & 0x10000) a ^= crcConst; - if (dataByte & (bitPattern >> 24)) a ^= crcConst; - - b = b << 1; - if (b & 0x10000) b ^= crcConst; - if (dataByte & (bitPattern >> 25)) b ^= crcConst; - - c = c << 1; - if (c & 0x10000) c ^= crcConst; - if (dataByte & (bitPattern >> 26)) c ^= crcConst; - - d = d << 1; - if (d & 0x10000) d ^= crcConst; - if (dataByte & (bitPattern >> 27)) d ^= crcConst; - - bitPattern = (bitPattern >> 4) | (bitPattern << 28); - } while (buffLength-=4); - - count = 16; // r8 - - do { - bitPattern = bitPattern << 4; - if (a & 0x8000) bitPattern |= 8; - if (b & 0x8000) bitPattern |= 4; - if (c & 0x8000) bitPattern |= 2; - if (d & 0x8000) bitPattern |= 1; - - a = a << 1; - b = b << 1; - c = c << 1; - d = d << 1; - - count--; - - if (!(count & 0x01)) { - *crc16buff++ = (u8)(bitPattern & 0xff); - } - } while (count != 0); - - return; -} - -/* -Initialise the SD card, after it has been sent into an Idle state -cmd_6byte_response: a pointer to a function that sends the SD card a command and gets a 6 byte response -cmd_17byte_response: a pointer to a function that sends the SD card a command and gets a 17 byte response -use4bitBus: initialise card to use a 4 bit data bus when communicating with the card -RCA: a pointer to the location to store the card's Relative Card Address, preshifted up by 16 bits. -*/ -bool _SD_InitCard (_SD_FN_CMD_6BYTE_RESPONSE cmd_6byte_response, - _SD_FN_CMD_17BYTE_RESPONSE cmd_17byte_response, - bool use4bitBus, - u32 *RCA) -{ - u8 responseBuffer[17] = {0}; - int i; - - for (i = 0; i < MAX_STARTUP_TRIES ; i++) { - cmd_6byte_response (responseBuffer, APP_CMD, 0); - // Check that the card gave the correct response - if (responseBuffer[0] != APP_CMD) { - return false; - } - if ( - cmd_6byte_response (responseBuffer, SD_APP_OP_COND, SD_OCR_VALUE) && - ((responseBuffer[1] & 0x80) != 0)) - { - // Card is ready to receive commands now - break; - } - } - if (i >= MAX_STARTUP_TRIES) { - return false; - } - - // The card's name, as assigned by the manufacturer - cmd_17byte_response (responseBuffer, ALL_SEND_CID, 0); - - // Get a new address - for (i = 0; i < MAX_STARTUP_TRIES ; i++) { - cmd_6byte_response (responseBuffer, SEND_RELATIVE_ADDR, 0); - *RCA = (responseBuffer[1] << 24) | (responseBuffer[2] << 16); - if ((responseBuffer[3] & 0x1e) != (SD_STATE_STBY << 1)) { - break; - } - } - if (i >= MAX_STARTUP_TRIES) { - return false; - } - - // Some cards won't go to higher speeds unless they think you checked their capabilities - cmd_17byte_response (responseBuffer, SEND_CSD, *RCA); - - // Only this card should respond to all future commands - cmd_6byte_response (responseBuffer, SELECT_CARD, *RCA); - - if (use4bitBus) { - // Set a 4 bit data bus - cmd_6byte_response (responseBuffer, APP_CMD, *RCA); - cmd_6byte_response (responseBuffer, SET_BUS_WIDTH, 2); // 4-bit mode. - } - - // Use 512 byte blocks - cmd_6byte_response (responseBuffer, SET_BLOCKLEN, 512); // 512 byte blocks - - // Wait until card is ready for data - i = 0; - do { - if (i >= RESPONSE_TIMEOUT) { - return false; - } - i++; - } while (!cmd_6byte_response (responseBuffer, SEND_STATUS, *RCA) && ((responseBuffer[3] & 0x1f) != ((SD_STATE_TRAN << 1) | READY_FOR_DATA))); - - return true; -} - - diff --git a/source/disc_io/io_sd_common.h b/source/disc_io/io_sd_common.h deleted file mode 100644 index 91e7fc2..0000000 --- a/source/disc_io/io_sd_common.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - io_sd_common.h - - By chishm (Michael Chisholm) - - Common SD card routines - - SD routines partially based on sd.s by Romman - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release - - 2006-07-28 - Chishm - * Changed voltage range that the SD card can use - - 2006-11-14 - Chishm - * Reduced voltage range again. Hopefully fixes MicroSD cards. -*/ - -#ifndef IO_SD_COMMON_H -#define IO_SD_COMMON_H - -#include "../disc.h" - -/* SD commands */ -#define GO_IDLE_STATE 0 -#define ALL_SEND_CID 2 -#define SEND_RELATIVE_ADDR 3 -#define SELECT_CARD 7 -#define SEND_CSD 9 -#define STOP_TRANSMISSION 12 -#define SEND_STATUS 13 -#define GO_INACTIVE_STATE 15 -#define SET_BLOCKLEN 16 -#define READ_SINGLE_BLOCK 17 -#define READ_MULTIPLE_BLOCK 18 -#define WRITE_BLOCK 24 -#define WRITE_MULTIPLE_BLOCK 25 -#define APP_CMD 55 - -/* SD App commands */ -#define SET_BUS_WIDTH 6 -#define SD_APP_OP_COND 41 - -/* OCR (Operating Conditions Register) send value */ -#define SD_OCR_VALUE 0x00030000 /* 2.8V to 3.0V */ -//#define SD_OCR_VALUE 0x003F8000 /* 2.7V to 3.4V */ -//#define SD_OCR_VALUE 0x00FC0000 - -/* SD Data repsonses */ -#define SD_CARD_BUSY 0xff - -/* SD states */ -#define SD_STATE_IDLE 0 // Idle state, after power on or GO_IDLE_STATE command -#define SD_STATE_READY 1 // Ready state, after card replies non-busy to SD_APP_OP_COND -#define SD_STATE_IDENT 2 // Identification state, after ALL_SEND_CID -#define SD_STATE_STBY 3 // Standby state, when card is deselected -#define SD_STATE_TRAN 4 // Transfer state, after card is selected and ready for data transfer -#define SD_STATE_DATA 5 // -#define SD_STATE_RCV 6 // Receive data state -#define SD_STATE_PRG 7 // Programming state -#define SD_STATE_DIS 8 // Disconnect state -#define SD_STATE_INA 9 // Inactive state, after GO_INACTIVE_STATE - -#define READY_FOR_DATA 1 // bit 8 in card status - -/* -Calculate the CRC7 of a command and return it preshifted with -an end bit added -*/ -extern u8 _SD_CRC7(u8* data, int size); - -/* -Calculate the CRC16 of a block of data, ready for transmission on -four data lines at once -*/ -extern void _SD_CRC16 (u8* buff, int buffLength, u8* crc16buff); - -typedef bool (*_SD_FN_CMD_6BYTE_RESPONSE) (u8* responseBuffer, u8 command, u32 data); -typedef bool (*_SD_FN_CMD_17BYTE_RESPONSE) (u8* responseBuffer, u8 command, u32 data); - -/* -Initialise the SD card, after it has been sent into an Idle state -cmd_6byte_response: a pointer to a function that sends the SD card a command and gets a 6 byte response -cmd_17byte_response: a pointer to a function that sends the SD card a command and gets a 17 byte response -use4bitBus: initialise card to use a 4 bit data bus when communicating with the card -RCA: a pointer to the location to store the card's Relative Card Address, preshifted up by 16 bits. -*/ -extern bool _SD_InitCard (_SD_FN_CMD_6BYTE_RESPONSE cmd_6byte_response, - _SD_FN_CMD_17BYTE_RESPONSE cmd_17byte_response, - bool use4bitBus, - u32 *RCA); - -#endif // define IO_SD_COMMON_H diff --git a/source/fatdir.c b/source/fatdir.c index 6e3a88b..c89b384 100644 --- a/source/fatdir.c +++ b/source/fatdir.c @@ -26,29 +26,6 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-08-13 - Chishm - * Moved all externally visible directory related functions to fatdir - * Added _FAT_mkdir_r - - 2006-08-14 - Chishm - * Added directory iterator functions - - 2006-08-19 - Chishm - * Updated dirnext return values to return correctly - - 2006-10-01 - Chishm - * Now clears the whole cluster when creating a new directory, bug found by Hermes - - 2007-01-10 - Chishm - * Updated directory iterator functions for DevkitPro r20 - - 2007-10-25 - Chishm - * Use CLUSTER_ERROR when an error occurs with the FAT, not CLUSTER_FREE - * Added statvfs functionality - - 2008-09-11 - Chishm - * Fixed unlink not freeing cluster chains -- discovered by rodries */ #include @@ -70,15 +47,11 @@ int _FAT_stat_r (struct _reent *r, const char *path, struct stat *st) { PARTITION* partition = NULL; - DIR_ENTRY dirEntry; // Get the partition this file is on - _FAT_lock(); partition = _FAT_partition_getPartitionFromPath (path); - if (partition == NULL) { - _FAT_unlock(); r->_errno = ENODEV; return -1; } @@ -88,14 +61,15 @@ int _FAT_stat_r (struct _reent *r, const char *path, struct stat *st) { path = strchr (path, ':') + 1; } if (strchr (path, ':') != NULL) { - _FAT_unlock(); r->_errno = EINVAL; return -1; } + _FAT_lock(&partition->lock); + // Search for the file on the disc if (!_FAT_directory_entryFromPath (partition, &dirEntry, path, NULL)) { - _FAT_unlock(); + _FAT_unlock(&partition->lock); r->_errno = ENOENT; return -1; } @@ -103,7 +77,7 @@ int _FAT_stat_r (struct _reent *r, const char *path, struct stat *st) { // Fill in the stat struct _FAT_directory_entryStat (partition, &dirEntry, st); - _FAT_unlock(); + _FAT_unlock(&partition->lock); return 0; } @@ -116,23 +90,19 @@ int _FAT_unlink_r (struct _reent *r, const char *path) { PARTITION* partition = NULL; DIR_ENTRY dirEntry; DIR_ENTRY dirContents; - u32 cluster; + uint32_t cluster; bool nextEntry; bool errorOccured = false; // Get the partition this directory is on - _FAT_lock(); partition = _FAT_partition_getPartitionFromPath (path); - if (partition == NULL) { - _FAT_unlock(); r->_errno = ENODEV; return -1; } // Make sure we aren't trying to write to a read-only disc if (partition->readOnly) { - _FAT_unlock(); r->_errno = EROFS; return -1; } @@ -142,14 +112,15 @@ int _FAT_unlink_r (struct _reent *r, const char *path) { path = strchr (path, ':') + 1; } if (strchr (path, ':') != NULL) { - _FAT_unlock(); r->_errno = EINVAL; return -1; } + _FAT_lock(&partition->lock); + // Search for the file on the disc if (!_FAT_directory_entryFromPath (partition, &dirEntry, path, NULL)) { - _FAT_unlock(); + _FAT_unlock(&partition->lock); r->_errno = ENOENT; return -1; } @@ -164,7 +135,7 @@ int _FAT_unlink_r (struct _reent *r, const char *path) { while (nextEntry) { if (!_FAT_directory_isDot (&dirContents)) { // The directory had something in it that isn't a reference to itself or it's parent - _FAT_unlock(); + _FAT_unlock(&partition->lock); r->_errno = EPERM; return -1; } @@ -192,7 +163,7 @@ int _FAT_unlink_r (struct _reent *r, const char *path) { errorOccured = true; } - _FAT_unlock(); + _FAT_unlock(&partition->lock); if (errorOccured) { return -1; } else { @@ -204,11 +175,8 @@ int _FAT_chdir_r (struct _reent *r, const char *path) { PARTITION* partition = NULL; // Get the partition this directory is on - _FAT_lock(); partition = _FAT_partition_getPartitionFromPath (path); - if (partition == NULL) { - _FAT_unlock(); r->_errno = ENODEV; return -1; } @@ -218,26 +186,20 @@ int _FAT_chdir_r (struct _reent *r, const char *path) { path = strchr (path, ':') + 1; } if (strchr (path, ':') != NULL) { - _FAT_unlock(); r->_errno = EINVAL; return -1; } - // Set the default device to match this one - if (!_FAT_partition_setDefaultPartition (partition)) { - _FAT_unlock(); - r->_errno = ENOENT; - return -1; - } + _FAT_lock(&partition->lock); // Try changing directory if (_FAT_directory_chdir (partition, path)) { // Successful - _FAT_unlock(); + _FAT_unlock(&partition->lock); return 0; } else { // Failed - _FAT_unlock(); + _FAT_unlock(&partition->lock); r->_errno = ENOTDIR; return -1; } @@ -248,28 +210,27 @@ int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName) { DIR_ENTRY oldDirEntry; DIR_ENTRY newDirEntry; const char *pathEnd; - u32 dirCluster; + uint32_t dirCluster; // Get the partition this directory is on - _FAT_lock(); partition = _FAT_partition_getPartitionFromPath (oldName); - if (partition == NULL) { - _FAT_unlock(); r->_errno = ENODEV; return -1; } + _FAT_lock(&partition->lock); + // Make sure the same partition is used for the old and new names if (partition != _FAT_partition_getPartitionFromPath (newName)) { - _FAT_unlock(); + _FAT_unlock(&partition->lock); r->_errno = EXDEV; return -1; } // Make sure we aren't trying to write to a read-only disc if (partition->readOnly) { - _FAT_unlock(); + _FAT_unlock(&partition->lock); r->_errno = EROFS; return -1; } @@ -279,7 +240,7 @@ int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName) { oldName = strchr (oldName, ':') + 1; } if (strchr (oldName, ':') != NULL) { - _FAT_unlock(); + _FAT_unlock(&partition->lock); r->_errno = EINVAL; return -1; } @@ -287,21 +248,21 @@ int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName) { newName = strchr (newName, ':') + 1; } if (strchr (newName, ':') != NULL) { - _FAT_unlock(); + _FAT_unlock(&partition->lock); r->_errno = EINVAL; return -1; } // Search for the file on the disc if (!_FAT_directory_entryFromPath (partition, &oldDirEntry, oldName, NULL)) { - _FAT_unlock(); + _FAT_unlock(&partition->lock); r->_errno = ENOENT; return -1; } // Make sure there is no existing file / directory with the new name if (_FAT_directory_entryFromPath (partition, &newDirEntry, newName, NULL)) { - _FAT_unlock(); + _FAT_unlock(&partition->lock); r->_errno = EEXIST; return -1; } @@ -318,7 +279,7 @@ int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName) { // Recycling newDirEntry, since it needs to be recreated anyway if (!_FAT_directory_entryFromPath (partition, &newDirEntry, newName, pathEnd) || !_FAT_directory_isDirectory(&newDirEntry)) { - _FAT_unlock(); + _FAT_unlock(&partition->lock); r->_errno = ENOTDIR; return -1; } @@ -335,26 +296,26 @@ int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName) { // Write the new entry if (!_FAT_directory_addEntry (partition, &newDirEntry, dirCluster)) { - _FAT_unlock(); + _FAT_unlock(&partition->lock); r->_errno = ENOSPC; return -1; } // Remove the old entry if (!_FAT_directory_removeEntry (partition, &oldDirEntry)) { - _FAT_unlock(); + _FAT_unlock(&partition->lock); r->_errno = EIO; return -1; } // Flush any sectors in the disc cache if (!_FAT_cache_flush (partition->cache)) { - _FAT_unlock(); + _FAT_unlock(&partition->lock); r->_errno = EIO; return -1; } - _FAT_unlock(); + _FAT_unlock(&partition->lock); return 0; } @@ -363,14 +324,11 @@ int _FAT_mkdir_r (struct _reent *r, const char *path, int mode) { bool fileExists; DIR_ENTRY dirEntry; const char* pathEnd; - u32 parentCluster, dirCluster; - u8 newEntryData[DIR_ENTRY_DATA_SIZE]; + uint32_t parentCluster, dirCluster; + uint8_t newEntryData[DIR_ENTRY_DATA_SIZE]; - _FAT_lock(); partition = _FAT_partition_getPartitionFromPath (path); - if (partition == NULL) { - _FAT_unlock(); r->_errno = ENODEV; return -1; } @@ -380,24 +338,25 @@ int _FAT_mkdir_r (struct _reent *r, const char *path, int mode) { path = strchr (path, ':') + 1; } if (strchr (path, ':') != NULL) { - _FAT_unlock(); r->_errno = EINVAL; return -1; } + _FAT_lock(&partition->lock); + // Search for the file/directory on the disc fileExists = _FAT_directory_entryFromPath (partition, &dirEntry, path, NULL); // Make sure it doesn't exist if (fileExists) { - _FAT_unlock(); + _FAT_unlock(&partition->lock); r->_errno = EEXIST; return -1; } if (partition->readOnly) { // We can't write to a read-only partition - _FAT_unlock(); + _FAT_unlock(&partition->lock); r->_errno = EROFS; return -1; } @@ -413,7 +372,7 @@ int _FAT_mkdir_r (struct _reent *r, const char *path, int mode) { // Recycling dirEntry, since it needs to be recreated anyway if (!_FAT_directory_entryFromPath (partition, &dirEntry, path, pathEnd) || !_FAT_directory_isDirectory(&dirEntry)) { - _FAT_unlock(); + _FAT_unlock(&partition->lock); r->_errno = ENOTDIR; return -1; } @@ -437,7 +396,7 @@ int _FAT_mkdir_r (struct _reent *r, const char *path, int mode) { dirCluster = _FAT_fat_linkFreeClusterCleared (partition, CLUSTER_FREE); if (!_FAT_fat_isValidCluster(partition, dirCluster)) { // No space left on disc for the cluster - _FAT_unlock(); + _FAT_unlock(&partition->lock); r->_errno = ENOSPC; return -1; } @@ -446,7 +405,7 @@ int _FAT_mkdir_r (struct _reent *r, const char *path, int mode) { // Write the new directory's entry to it's parent if (!_FAT_directory_addEntry (partition, &dirEntry, parentCluster)) { - _FAT_unlock(); + _FAT_unlock(&partition->lock); r->_errno = ENOSPC; return -1; } @@ -475,30 +434,29 @@ int _FAT_mkdir_r (struct _reent *r, const char *path, int mode) { // Flush any sectors in the disc cache if (!_FAT_cache_flush(partition->cache)) { - _FAT_unlock(); + _FAT_unlock(&partition->lock); r->_errno = EIO; return -1; } - _FAT_unlock(); + _FAT_unlock(&partition->lock); return 0; } int _FAT_statvfs_r (struct _reent *r, const char *path, struct statvfs *buf) { PARTITION* partition = NULL; - u32 freeClusterCount; + unsigned int freeClusterCount; // Get the partition of the requested path - _FAT_lock(); partition = _FAT_partition_getPartitionFromPath (path); - if (partition == NULL) { - _FAT_unlock(); r->_errno = ENODEV; return -1; } + _FAT_lock(&partition->lock); + freeClusterCount = _FAT_fat_freeClusterCount (partition); // FAT clusters = POSIX blocks @@ -523,7 +481,7 @@ int _FAT_statvfs_r (struct _reent *r, const char *path, struct statvfs *buf) // Maximum filename length. buf->f_namemax = MAX_FILENAME_LENGTH; - _FAT_unlock(); + _FAT_unlock(&partition->lock); return 0; } @@ -532,11 +490,8 @@ DIR_ITER* _FAT_diropen_r(struct _reent *r, DIR_ITER *dirState, const char *path) DIR_STATE_STRUCT* state = (DIR_STATE_STRUCT*) (dirState->dirStruct); bool fileExists; - _FAT_lock(); state->partition = _FAT_partition_getPartitionFromPath (path); - if (state->partition == NULL) { - _FAT_unlock(); r->_errno = ENODEV; return NULL; } @@ -546,22 +501,24 @@ DIR_ITER* _FAT_diropen_r(struct _reent *r, DIR_ITER *dirState, const char *path) path = strchr (path, ':') + 1; } if (strchr (path, ':') != NULL) { - _FAT_unlock(); r->_errno = EINVAL; return NULL; } + + _FAT_lock(&state->partition->lock); + // Get the start cluster of the directory fileExists = _FAT_directory_entryFromPath (state->partition, &dirEntry, path, NULL); if (!fileExists) { - _FAT_unlock(); + _FAT_unlock(&state->partition->lock); r->_errno = ENOENT; return NULL; } // Make sure it is a directory if (! _FAT_directory_isDirectory (&dirEntry)) { - _FAT_unlock(); + _FAT_unlock(&state->partition->lock); r->_errno = ENOTDIR; return NULL; } @@ -575,17 +532,18 @@ DIR_ITER* _FAT_diropen_r(struct _reent *r, DIR_ITER *dirState, const char *path) // We are now using this entry state->inUse = true; - _FAT_unlock(); + _FAT_unlock(&state->partition->lock); return (DIR_ITER*) state; } int _FAT_dirreset_r (struct _reent *r, DIR_ITER *dirState) { DIR_STATE_STRUCT* state = (DIR_STATE_STRUCT*) (dirState->dirStruct); + _FAT_lock(&state->partition->lock); + // Make sure we are still using this entry - _FAT_lock(); if (!state->inUse) { - _FAT_unlock(); + _FAT_unlock(&state->partition->lock); r->_errno = EBADF; return -1; } @@ -594,24 +552,25 @@ int _FAT_dirreset_r (struct _reent *r, DIR_ITER *dirState) { state->validEntry = _FAT_directory_getFirstEntry (state->partition, &(state->currentEntry), state->startCluster); - _FAT_unlock(); + _FAT_unlock(&state->partition->lock); return 0; } int _FAT_dirnext_r (struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *filestat) { DIR_STATE_STRUCT* state = (DIR_STATE_STRUCT*) (dirState->dirStruct); + _FAT_lock(&state->partition->lock); + // Make sure we are still using this entry - _FAT_lock(); if (!state->inUse) { - _FAT_unlock(); + _FAT_unlock(&state->partition->lock); r->_errno = EBADF; return -1; } // Make sure there is another file to report on if (! state->validEntry) { - _FAT_unlock(); + _FAT_unlock(&state->partition->lock); r->_errno = ENOENT; return -1; } @@ -627,7 +586,7 @@ int _FAT_dirnext_r (struct _reent *r, DIR_ITER *dirState, char *filename, struct state->validEntry = _FAT_directory_getNextEntry (state->partition, &(state->currentEntry)); - _FAT_unlock(); + _FAT_unlock(&state->partition->lock); return 0; } @@ -635,9 +594,9 @@ int _FAT_dirclose_r (struct _reent *r, DIR_ITER *dirState) { DIR_STATE_STRUCT* state = (DIR_STATE_STRUCT*) (dirState->dirStruct); // We are no longer using this entry - _FAT_lock(); + _FAT_lock(&state->partition->lock); state->inUse = false; - _FAT_unlock(); + _FAT_unlock(&state->partition->lock); return 0; } diff --git a/source/fatdir.h b/source/fatdir.h index 55c8f9f..426dd30 100644 --- a/source/fatdir.h +++ b/source/fatdir.h @@ -26,19 +26,6 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-08-13 - Chishm - * Moved all externally visible directory related functions to fatdir - * Added _FAT_mkdir_r - - 2006-08-14 - Chishm - * Added directory iterator functions - - 2007-01-10 - Chishm - * Updated directory iterator functions for DevkitPro r20 - - 2007-10-25 - Chishm - * Added statvfs functionality */ @@ -54,10 +41,10 @@ typedef struct { PARTITION* partition; - DIR_ENTRY currentEntry; - u32 startCluster; - bool inUse; - bool validEntry; + DIR_ENTRY currentEntry; + uint32_t startCluster; + bool inUse; + bool validEntry; } DIR_STATE_STRUCT; extern int _FAT_stat_r (struct _reent *r, const char *path, struct stat *st); diff --git a/source/fatfile.c b/source/fatfile.c index 8b65648..6b8fa8d 100644 --- a/source/fatfile.c +++ b/source/fatfile.c @@ -26,42 +26,6 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release - - 2006-07-17 - Chishm - * Made all path inputs const char* - * Added _FAT_rename_r - - 2006-08-02 - Chishm - * Fixed _FAT_seek_r - - 2006-08-13 - Chishm - * Moved all externally visible directory related functions to fatdir - - 2007-02-11 - Chishm - * Propagate disc errors up to the user app - - 2007-02-25 - Chishm - * Fixed seek to the end of a file bug - - 2007-04-12 - Chishm - * Fixed seek to end of file when reading - - 2007-11-04 - Chishm - * file_extend_r renamed to _FAT_file_extend_r - * A cluster is only allocated for a file when data is written, instead of when the file is opened - - 2008-05-12 - Chishm - * Modified WinterMute's seek then write fix for elegance - * Removed resetPosition - - 2008-05-12 - WinterMute - * Modified Chishm's elegant fix to reset the read/write positions - - 2008-11-12 - Chishm - * Only set append position when file is opened for append, as suggested by rodries. Improves open speed for large files. */ @@ -84,7 +48,7 @@ int _FAT_open_r (struct _reent *r, void *fileStruct, const char *path, int flags bool fileExists; DIR_ENTRY dirEntry; const char* pathEnd; - u32 dirCluster; + uint32_t dirCluster; FILE_STRUCT* file = (FILE_STRUCT*) fileStruct; partition = _FAT_partition_getPartitionFromPath (path); @@ -130,19 +94,19 @@ int _FAT_open_r (struct _reent *r, void *fileStruct, const char *path, int flags } // Search for the file on the disc - _FAT_lock(); + _FAT_lock(&partition->lock); fileExists = _FAT_directory_entryFromPath (partition, &dirEntry, path, NULL); // The file shouldn't exist if we are trying to create it if ((flags & O_CREAT) && (flags & O_EXCL) && fileExists) { - _FAT_unlock(); + _FAT_unlock(&partition->lock); r->_errno = EEXIST; return -1; } // It should not be a directory if we're openning a file, if (fileExists && _FAT_directory_isDirectory(&dirEntry)) { - _FAT_unlock(); + _FAT_unlock(&partition->lock); r->_errno = EISDIR; return -1; } @@ -152,7 +116,7 @@ int _FAT_open_r (struct _reent *r, void *fileStruct, const char *path, int flags if (flags & O_CREAT) { if (partition->readOnly) { // We can't write to a read-only partition - _FAT_unlock(); + _FAT_unlock(&partition->lock); r->_errno = EROFS; return -1; } @@ -168,7 +132,7 @@ int _FAT_open_r (struct _reent *r, void *fileStruct, const char *path, int flags // Recycling dirEntry, since it needs to be recreated anyway if (!_FAT_directory_entryFromPath (partition, &dirEntry, path, pathEnd) || !_FAT_directory_isDirectory(&dirEntry)) { - _FAT_unlock(); + _FAT_unlock(&partition->lock); r->_errno = ENOTDIR; return -1; } @@ -186,13 +150,13 @@ int _FAT_open_r (struct _reent *r, void *fileStruct, const char *path, int flags u16_to_u8array (dirEntry.entryData, DIR_ENTRY_cDate, _FAT_filetime_getDateFromRTC()); if (!_FAT_directory_addEntry (partition, &dirEntry, dirCluster)) { - _FAT_unlock(); + _FAT_unlock(&partition->lock); r->_errno = ENOSPC; return -1; } } else { // file doesn't exist, and we aren't creating it - _FAT_unlock(); + _FAT_unlock(&partition->lock); r->_errno = ENOENT; return -1; } @@ -210,7 +174,7 @@ int _FAT_open_r (struct _reent *r, void *fileStruct, const char *path, int flags // Make sure we aren't trying to write to a read-only file if (file->write && !_FAT_directory_isWritable(&dirEntry)) { - _FAT_unlock(); + _FAT_unlock(&partition->lock); r->_errno = EROFS; return -1; } @@ -257,25 +221,39 @@ int _FAT_open_r (struct _reent *r, void *fileStruct, const char *path, int flags file->appendPosition = file->rwPosition; } + file->modified = false; + file->inUse = true; + // Insert this file into the double-linked list of open files partition->openFileCount += 1; - _FAT_unlock(); + if (partition->firstOpenFile) { + file->nextOpenFile = partition->firstOpenFile; + partition->firstOpenFile->prevOpenFile = file; + } else { + file->nextOpenFile = NULL; + } + file->prevOpenFile = NULL; + partition->firstOpenFile = file; + + _FAT_unlock(&partition->lock); return (int) file; } -int _FAT_close_r (struct _reent *r, int fd) { - FILE_STRUCT* file = (FILE_STRUCT*) fd; - u8 dirEntryData[DIR_ENTRY_DATA_SIZE]; - - _FAT_lock(); - if (!file->inUse) { - _FAT_unlock(); - r->_errno = EBADF; - return -1; +/* +Synchronizes the file data to disc. +Does no locking of its own -- lock the partition before calling. +Returns 0 on success, an error code on failure. +*/ +int _FAT_syncToDisc (FILE_STRUCT* file) { + uint8_t dirEntryData[DIR_ENTRY_DATA_SIZE]; + + if (!file || !file->inUse) { + return EBADF; } - if (file->write) { + + if (file->write && file->modified) { // Load the old entry _FAT_cache_readPartialSector (file->partition->cache, dirEntryData, _FAT_fat_clusterToSector(file->partition, file->dirEntryEnd.cluster) + file->dirEntryEnd.sector, @@ -295,6 +273,9 @@ int _FAT_close_r (struct _reent *r, int fd) { // Access date u16_to_u8array (dirEntryData, DIR_ENTRY_aDate, _FAT_filetime_getDateFromRTC()); + + // Set archive attribute + dirEntryData[DIR_ENTRY_attributes] |= ATTRIB_ARCH; // Write the new entry _FAT_cache_writePartialSector (file->partition->cache, dirEntryData, @@ -303,47 +284,73 @@ int _FAT_close_r (struct _reent *r, int fd) { // Flush any sectors in the disc cache if (!_FAT_cache_flush(file->partition->cache)) { - _FAT_unlock(); - r->_errno = EIO; - return -1; + return EIO; } - } - file->inUse = false; - file->partition->openFileCount -= 1; - _FAT_unlock(); + file->modified = false; return 0; } -int _FAT_read_r (struct _reent *r, int fd, char *ptr, int len) { + +int _FAT_close_r (struct _reent *r, int fd) { FILE_STRUCT* file = (FILE_STRUCT*) fd; + int ret = 0; + if (!file->inUse) { + r->_errno = EBADF; + return -1; + } + + _FAT_lock(&file->partition->lock); + + ret = _FAT_syncToDisc (file); + if (ret != 0) { + r->_errno = ret; + ret = -1; + } + + file->inUse = false; + + // Remove this file from the double-linked list of open files + file->partition->openFileCount -= 1; + if (file->nextOpenFile) { + file->nextOpenFile->prevOpenFile = file->prevOpenFile; + } + if (file->prevOpenFile) { + file->prevOpenFile->nextOpenFile = file->nextOpenFile; + } else { + file->partition->firstOpenFile = file->nextOpenFile; + } + + _FAT_unlock(&file->partition->lock); + + return ret; +} + +ssize_t _FAT_read_r (struct _reent *r, int fd, char *ptr, size_t len) { + FILE_STRUCT* file = (FILE_STRUCT*) fd; PARTITION* partition; CACHE* cache; - FILE_POSITION position; - u32 tempNextCluster; - - int tempVar; - - u32 remain; - + uint32_t tempNextCluster; + unsigned int tempVar; + size_t remain; bool flagNoError = true; // Make sure we can actually read from the file - _FAT_lock(); if ((file == NULL) || !file->inUse || !file->read) { - _FAT_unlock(); r->_errno = EBADF; return -1; } + partition = file->partition; + _FAT_lock(&partition->lock); + // Don't try to read if the read pointer is past the end of file if (file->currentPosition >= file->filesize || file->startCluster == CLUSTER_FREE) { r->_errno = EOVERFLOW; - _FAT_unlock(); return 0; } @@ -355,15 +362,11 @@ int _FAT_read_r (struct _reent *r, int fd, char *ptr, int len) { // Short circuit cases where len is 0 (or less) if (len <= 0) { - _FAT_unlock(); return 0; } remain = len; - position = file->rwPosition; - - partition = file->partition; cache = file->partition->cache; // Align to sector @@ -480,7 +483,7 @@ int _FAT_read_r (struct _reent *r, int fd, char *ptr, int len) { file->rwPosition = position; file->currentPosition += len; - _FAT_unlock(); + _FAT_unlock(&partition->lock); return len; } @@ -490,37 +493,33 @@ Extend a file so that the size is the same as the rwPosition static bool _FAT_file_extend_r (struct _reent *r, FILE_STRUCT* file) { PARTITION* partition = file->partition; CACHE* cache = file->partition->cache; - FILE_POSITION position; - - u32 remain; - - u8 zeroBuffer [BYTES_PER_READ] = {0}; - - u32 tempNextCluster; + uint8_t zeroBuffer [BYTES_PER_READ] = {0}; + uint32_t remain; + uint32_t tempNextCluster; position.byte = file->filesize % BYTES_PER_READ; position.sector = (file->filesize % partition->bytesPerCluster) / BYTES_PER_READ; // It is assumed that there is always a startCluster // This will be true when _FAT_file_extend_r is called from _FAT_write_r position.cluster = _FAT_fat_lastCluster (partition, file->startCluster); - + remain = file->currentPosition - file->filesize; - if ((remain > 0) && (file->filesize > 0) && (position.sector == 0)) { + if ((remain > 0) && (file->filesize > 0) && (position.sector == 0) && (position.byte == 0)) { // Get a new cluster on the edge of a cluster boundary tempNextCluster = _FAT_fat_linkFreeCluster(partition, position.cluster); if (!_FAT_fat_isValidCluster(partition, tempNextCluster)) { // Couldn't get a cluster, so abort r->_errno = ENOSPC; return false; - } else { - position.cluster = tempNextCluster; - } + } + position.cluster = tempNextCluster; + position.sector = 0; } - // Only need to clear to the end of the sector if (remain + position.byte < BYTES_PER_READ) { + // Only need to clear to the end of the sector _FAT_cache_writePartialSector (cache, zeroBuffer, _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, position.byte, remain); position.byte += remain; @@ -543,9 +542,8 @@ static bool _FAT_file_extend_r (struct _reent *r, FILE_STRUCT* file) { // Couldn't get a cluster, so abort r->_errno = ENOSPC; return false; - } else { - position.cluster = tempNextCluster; } + position.cluster = tempNextCluster; } _FAT_disc_writeSectors (partition->disc, @@ -566,9 +564,8 @@ static bool _FAT_file_extend_r (struct _reent *r, FILE_STRUCT* file) { // Couldn't get a cluster, so abort r->_errno = ENOSPC; return false; - } else { - position.cluster = tempNextCluster; } + position.cluster = tempNextCluster; } if (remain > 0) { @@ -584,46 +581,45 @@ static bool _FAT_file_extend_r (struct _reent *r, FILE_STRUCT* file) { } -int _FAT_write_r (struct _reent *r,int fd, const char *ptr, int len) { +ssize_t _FAT_write_r (struct _reent *r, int fd, const char *ptr, size_t len) { FILE_STRUCT* file = (FILE_STRUCT*) fd; - PARTITION* partition; CACHE* cache; - FILE_POSITION position; - u32 tempNextCluster; - - int tempVar; - - u32 remain; - + uint32_t tempNextCluster; + unsigned int tempVar; + size_t remain; bool flagNoError = true; bool flagAppending = false; // Make sure we can actually write to the file - _FAT_lock(); if ((file == NULL) || !file->inUse || !file->write) { - _FAT_unlock(); r->_errno = EBADF; return -1; } + partition = file->partition; + cache = file->partition->cache; + _FAT_lock(&partition->lock); + + // Only write up to the maximum file size, taking into account wrap-around of ints + if (remain + file->filesize > FILE_MAX_SIZE || len + file->filesize < file->filesize) { + len = FILE_MAX_SIZE - file->filesize; + } + remain = len; + // Short circuit cases where len is 0 (or less) if (len <= 0) { - _FAT_unlock(); + _FAT_unlock(&partition->lock); return 0; } - partition = file->partition; - cache = file->partition->cache; - remain = len; - // Get a new cluster for the start of the file if required if (file->startCluster == CLUSTER_FREE) { tempNextCluster = _FAT_fat_linkFreeCluster (partition, CLUSTER_FREE); if (!_FAT_fat_isValidCluster(partition, tempNextCluster)) { // Couldn't get a cluster, so abort immediately - _FAT_unlock(); + _FAT_unlock(&partition->lock); r->_errno = ENOSPC; return -1; } @@ -646,7 +642,7 @@ int _FAT_write_r (struct _reent *r,int fd, const char *ptr, int len) { // If the write pointer is past the end of the file, extend the file to that size if (file->currentPosition > file->filesize) { if (!_FAT_file_extend_r (r, file)) { - _FAT_unlock(); + _FAT_unlock(&partition->lock); return -1; } } @@ -796,10 +792,11 @@ int _FAT_write_r (struct _reent *r,int fd, const char *ptr, int len) { } - // Amount read is the originally requested amount minus stuff remaining + // Amount written is the originally requested amount minus stuff remaining len = len - remain; // Update file information + file->modified = true; if (file->append) { // Appending doesn't affect the read pointer file->appendPosition = position; @@ -813,59 +810,61 @@ int _FAT_write_r (struct _reent *r,int fd, const char *ptr, int len) { } } - _FAT_unlock(); + _FAT_unlock(&partition->lock); return len; } -int _FAT_seek_r (struct _reent *r, int fd, int pos, int dir) { +off_t _FAT_seek_r (struct _reent *r, int fd, off_t pos, int dir) { FILE_STRUCT* file = (FILE_STRUCT*) fd; - PARTITION* partition; - - u32 cluster, nextCluster; + uint32_t cluster, nextCluster; int clusCount; - int position; + off_t newPosition; + uint32_t position; - _FAT_lock(); if ((file == NULL) || (file->inUse == false)) { // invalid file - _FAT_unlock(); r->_errno = EBADF; return -1; } partition = file->partition; + _FAT_lock(&partition->lock); switch (dir) { case SEEK_SET: - position = pos; + newPosition = pos; break; case SEEK_CUR: - position = file->currentPosition + pos; + newPosition = (off_t)file->currentPosition + pos; break; case SEEK_END: - position = file->filesize + pos; + newPosition = (off_t)file->filesize + pos; break; default: - _FAT_unlock(); + _FAT_unlock(&partition->lock); r->_errno = EINVAL; return -1; } - if ((pos > 0) && (position < 0)) { + if ((pos > 0) && (newPosition < 0)) { + _FAT_unlock(&partition->lock); r->_errno = EOVERFLOW; - _FAT_unlock(); return -1; } - if (position < 0) { - _FAT_unlock(); + // newPosition can only be larger than the FILE_MAX_SIZE on platforms where + // off_t is larger than 32 bits. + if (newPosition < 0 || ((sizeof(newPosition) > 4) && newPosition > (off_t)FILE_MAX_SIZE)) { + _FAT_unlock(&partition->lock); r->_errno = EINVAL; return -1; } + position = (uint32_t)newPosition; + // Only change the read/write position if it is within the bounds of the current filesize, // or at the very edge of the file if (position <= file->filesize && file->startCluster != CLUSTER_FREE) { @@ -897,7 +896,7 @@ int _FAT_seek_r (struct _reent *r, int fd, int pos, int dir) { file->rwPosition.sector = partition->sectorsPerCluster; file->rwPosition.byte = 0; } else { - _FAT_unlock(); + _FAT_unlock(&partition->lock); r->_errno = EINVAL; return -1; } @@ -909,7 +908,7 @@ int _FAT_seek_r (struct _reent *r, int fd, int pos, int dir) { // Save position file->currentPosition = position; - _FAT_unlock(); + _FAT_unlock(&partition->lock); return position; } @@ -917,27 +916,24 @@ int _FAT_seek_r (struct _reent *r, int fd, int pos, int dir) { int _FAT_fstat_r (struct _reent *r, int fd, struct stat *st) { FILE_STRUCT* file = (FILE_STRUCT*) fd; - PARTITION* partition; - DIR_ENTRY fileEntry; - _FAT_lock(); if ((file == NULL) || (file->inUse == false)) { // invalid file - _FAT_unlock(); r->_errno = EBADF; return -1; } partition = file->partition; + _FAT_lock(&partition->lock); // Get the file's entry data fileEntry.dataStart = file->dirEntryStart; fileEntry.dataEnd = file->dirEntryEnd; if (!_FAT_directory_entryFromPosition (partition, &fileEntry)) { - _FAT_unlock(); + _FAT_unlock(&partition->lock); r->_errno = EIO; return -1; } @@ -949,7 +945,142 @@ int _FAT_fstat_r (struct _reent *r, int fd, struct stat *st) { st->st_ino = (ino_t)(file->startCluster); // The file serial number is the start cluster st->st_size = file->filesize; // File size - _FAT_unlock(); + _FAT_unlock(&partition->lock); return 0; } + +int _FAT_ftruncate_r (struct _reent *r, int fd, off_t len) { + FILE_STRUCT* file = (FILE_STRUCT*) fd; + PARTITION* partition; + int ret=0; + uint32_t newSize = (uint32_t)len; + + if (len < 0) { + // Trying to truncate to a negative size + r->_errno = EINVAL; + return -1; + } + + if ((sizeof(len) > 4) && len > (off_t)FILE_MAX_SIZE) { + // Trying to extend the file beyond what FAT supports + r->_errno = EFBIG; + return -1; + } + + if (!file || !file->inUse) { + // invalid file + r->_errno = EBADF; + return -1; + } + + if (!file->write) { + // Read-only file + r->_errno = EINVAL; + return -1; + } + + partition = file->partition; + _FAT_lock(&partition->lock); + + if (newSize > file->filesize) { + // Expanding the file + FILE_POSITION savedPosition; + uint32_t savedOffset; + // Get a new cluster for the start of the file if required + if (file->startCluster == CLUSTER_FREE) { + uint32_t tempNextCluster = _FAT_fat_linkFreeCluster (partition, CLUSTER_FREE); + if (!_FAT_fat_isValidCluster(partition, tempNextCluster)) { + // Couldn't get a cluster, so abort immediately + _FAT_unlock(&partition->lock); + r->_errno = ENOSPC; + return -1; + } + file->startCluster = tempNextCluster; + + file->rwPosition.cluster = file->startCluster; + file->rwPosition.sector = 0; + file->rwPosition.byte = 0; + } + // Save the read/write pointer + savedPosition = file->rwPosition; + savedOffset = file->currentPosition; + // Set the position to the new size + file->currentPosition = newSize; + // Extend the file to the new position + if (!_FAT_file_extend_r (r, file)) { + ret = -1; + } + // Set the append position to the new rwPointer + if (file->append) { + file->appendPosition = file->rwPosition; + } + // Restore the old rwPointer; + file->rwPosition = savedPosition; + file->currentPosition = savedOffset; + } else if (newSize < file->filesize){ + // Shrinking the file + if (len == 0) { + // Cutting the file down to nothing, clear all clusters used + _FAT_fat_clearLinks (partition, file->startCluster); + file->startCluster = CLUSTER_FREE; + + file->appendPosition.cluster = CLUSTER_FREE; + file->appendPosition.sector = 0; + file->appendPosition.byte = 0; + } else { + // Trimming the file down to the required size + unsigned int chainLength; + uint32_t lastCluster; + + // Drop the unneeded end of the cluster chain. + // If the end falls on a cluster boundary, drop that cluster too, + // then set a flag to allocate a cluster as needed + chainLength = ((newSize-1) / partition->bytesPerCluster) + 1; + lastCluster = _FAT_fat_trimChain (partition, file->startCluster, chainLength); + + if (file->append) { + file->appendPosition.byte = newSize % BYTES_PER_READ; + // Does the end of the file fall on the edge of a cluster? + if (newSize % partition->bytesPerCluster == 0) { + // Set a flag to allocate a new cluster + file->appendPosition.sector = partition->sectorsPerCluster; + } else { + file->appendPosition.sector = (newSize % partition->bytesPerCluster) / BYTES_PER_READ; + } + file->appendPosition.cluster = lastCluster; + } + } + } else { + // Truncating to same length, so don't do anything + } + + file->filesize = newSize; + file->modified = true; + + _FAT_unlock(&partition->lock); + return ret; +} + +int _FAT_fsync_r (struct _reent *r, int fd) { + FILE_STRUCT* file = (FILE_STRUCT*) fd; + int ret = 0; + + if (!file->inUse) { + r->_errno = EBADF; + return -1; + } + + _FAT_lock(&file->partition->lock); + + ret = _FAT_syncToDisc (file); + if (ret != 0) { + r->_errno = ret; + ret = -1; + } + + _FAT_unlock(&file->partition->lock); + + return ret; +} + diff --git a/source/fatfile.h b/source/fatfile.h index 47910af..0b26455 100644 --- a/source/fatfile.h +++ b/source/fatfile.h @@ -26,19 +26,6 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release - - 2006-07-17 - Chishm - * Made all path inputs const char* - * Added _FAT_rename_r - - 2006-07-24 - Chishm - * Removed padding workaround from FILE_STRUCT - - 2006-08-13 - Chishm - * Moved all externally visible directory related functions to fatdir */ @@ -52,36 +39,45 @@ #include "partition.h" #include "directory.h" -typedef struct { - u32 cluster; - u32 sector; - s32 byte; -} FILE_POSITION; +#define FILE_MAX_SIZE ((uint32_t)0xFFFFFFFF) // 4GiB - 1B typedef struct { - u32 filesize; - u32 startCluster; - u32 currentPosition; - FILE_POSITION rwPosition; - FILE_POSITION appendPosition; - bool read; - bool write; - bool append; - bool inUse; - PARTITION* partition; - DIR_ENTRY_POSITION dirEntryStart; // Points to the start of the LFN entries of a file, or the alias for no LFN - DIR_ENTRY_POSITION dirEntryEnd; // Always points to the file's alias entry -} FILE_STRUCT; + u32 cluster; + sec_t sector; + s32 byte; +} FILE_POSITION; + +struct _FILE_STRUCT; + +struct _FILE_STRUCT { + uint32_t filesize; + uint32_t startCluster; + uint32_t currentPosition; + FILE_POSITION rwPosition; + FILE_POSITION appendPosition; + bool read; + bool write; + bool append; + bool inUse; + bool modified; + DIR_ENTRY_POSITION dirEntryStart; // Points to the start of the LFN entries of a file, or the alias for no LFN + DIR_ENTRY_POSITION dirEntryEnd; // Always points to the file's alias entry + PARTITION* partition; + struct _FILE_STRUCT* prevOpenFile; // The previous entry in a double-linked list of open files + struct _FILE_STRUCT* nextOpenFile; // The next entry in a double-linked list of open files +}; + +typedef struct _FILE_STRUCT FILE_STRUCT; extern int _FAT_open_r (struct _reent *r, void *fileStruct, const char *path, int flags, int mode); extern int _FAT_close_r (struct _reent *r, int fd); -extern int _FAT_write_r (struct _reent *r,int fd, const char *ptr, int len); +extern ssize_t _FAT_write_r (struct _reent *r,int fd, const char *ptr, size_t len); -extern int _FAT_read_r (struct _reent *r, int fd, char *ptr, int len); +extern ssize_t _FAT_read_r (struct _reent *r, int fd, char *ptr, size_t len); -extern int _FAT_seek_r (struct _reent *r, int fd,int pos, int dir); +extern off_t _FAT_seek_r (struct _reent *r, int fd, off_t pos, int dir); extern int _FAT_fstat_r (struct _reent *r, int fd, struct stat *st); @@ -95,4 +91,15 @@ extern int _FAT_chdir_r (struct _reent *r, const char *name); extern int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName); +extern int _FAT_ftruncate_r (struct _reent *r, int fd, off_t len); + +extern int _FAT_fsync_r (struct _reent *r, int fd); + +/* +Synchronizes the file data to disc. +Does no locking of its own -- lock the partition before calling. +Returns 0 on success, an error code on failure. +*/ +extern int _FAT_syncToDisc (FILE_STRUCT* file); + #endif // _FATFILE_H diff --git a/source/file_allocation_table.c b/source/file_allocation_table.c index 84d991d..f783781 100644 --- a/source/file_allocation_table.c +++ b/source/file_allocation_table.c @@ -25,21 +25,6 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release - - 2006-07-11 - Chishm - * Made several fixes related to free clusters, thanks to Loopy - - 2006-10-01 - Chishm - * Added _FAT_fat_linkFreeClusterCleared to clear a cluster when it is allocated - - 2007-10-25 - Chishm - * Use CLUSTER_ERROR when an error occurs with the FAT, not CLUSTER_FREE - - 2007-11-04 - Chishm - * _FAT_fat_nextCluster returns CLUSTER_FREE when input cluster is CLUSTER_FREE */ @@ -50,10 +35,10 @@ /* Gets the cluster linked from input cluster */ -u32 _FAT_fat_nextCluster(PARTITION* partition, u32 cluster) +uint32_t _FAT_fat_nextCluster(PARTITION* partition, uint32_t cluster) { - u32 nextCluster = CLUSTER_FREE; - u32 sector; + uint32_t nextCluster = CLUSTER_FREE; + sec_t sector; int offset; if (cluster == CLUSTER_FREE) { @@ -66,7 +51,9 @@ u32 _FAT_fat_nextCluster(PARTITION* partition, u32 cluster) return CLUSTER_ERROR; break; - case FS_FAT12: + case FS_FAT12: + { + u32 nextCluster_h; sector = partition->fat.fatStart + (((cluster * 3) / 2) / BYTES_PER_READ); offset = ((cluster * 3) / 2) % BYTES_PER_READ; @@ -79,7 +66,7 @@ u32 _FAT_fat_nextCluster(PARTITION* partition, u32 cluster) offset = 0; sector++; } - u32 nextCluster_h = 0; + nextCluster_h = 0; _FAT_cache_readLittleEndianValue (partition->cache, &nextCluster_h, sector, offset, sizeof(u8)); nextCluster |= (nextCluster_h << 8); @@ -96,15 +83,14 @@ u32 _FAT_fat_nextCluster(PARTITION* partition, u32 cluster) } break; - + } case FS_FAT16: sector = partition->fat.fatStart + ((cluster << 1) / BYTES_PER_READ); offset = (cluster % (BYTES_PER_READ >> 1)) << 1; _FAT_cache_readLittleEndianValue (partition->cache, &nextCluster, sector, offset, sizeof(u16)); - if (nextCluster >= 0xFFF7) - { + if (nextCluster >= 0xFFF7) { nextCluster = CLUSTER_EOF; } break; @@ -115,8 +101,7 @@ u32 _FAT_fat_nextCluster(PARTITION* partition, u32 cluster) _FAT_cache_readLittleEndianValue (partition->cache, &nextCluster, sector, offset, sizeof(u32)); - if (nextCluster >= 0x0FFFFFF7) - { + if (nextCluster >= 0x0FFFFFF7) { nextCluster = CLUSTER_EOF; } break; @@ -133,10 +118,10 @@ u32 _FAT_fat_nextCluster(PARTITION* partition, u32 cluster) writes value into the correct offset within a partition's FAT, based on the cluster number. */ -static bool _FAT_fat_writeFatEntry (PARTITION* partition, u32 cluster, u32 value) { - u32 sector; +static bool _FAT_fat_writeFatEntry (PARTITION* partition, uint32_t cluster, uint32_t value) { + sec_t sector; int offset; - u32 oldValue; + uint32_t oldValue; if ((cluster < CLUSTER_FIRST) || (cluster > partition->fat.lastCluster /* This will catch CLUSTER_ERROR */)) { @@ -218,10 +203,10 @@ to end of file, links the input cluster to it then returns the cluster number If an error occurs, return CLUSTER_ERROR -----------------------------------------------------------------*/ -u32 _FAT_fat_linkFreeCluster(PARTITION* partition, u32 cluster) { - u32 firstFree; - u32 curLink; - u32 lastCluster; +uint32_t _FAT_fat_linkFreeCluster(PARTITION* partition, uint32_t cluster) { + uint32_t firstFree; + uint32_t curLink; + uint32_t lastCluster; bool loopedAroundFAT = false; lastCluster = partition->fat.lastCluster; @@ -278,10 +263,10 @@ to end of file, links the input cluster to it, clears the new cluster to 0 valued bytes, then returns the cluster number If an error occurs, return CLUSTER_ERROR -----------------------------------------------------------------*/ -u32 _FAT_fat_linkFreeClusterCleared (PARTITION* partition, u32 cluster) { - u32 newCluster; - int i; - u8 emptySector[BYTES_PER_READ]; +uint32_t _FAT_fat_linkFreeClusterCleared (PARTITION* partition, uint32_t cluster) { + uint32_t newCluster; + uint32_t i; + uint8_t emptySector[BYTES_PER_READ]; // Link the cluster newCluster = _FAT_fat_linkFreeCluster(partition, cluster); @@ -306,8 +291,8 @@ u32 _FAT_fat_linkFreeClusterCleared (PARTITION* partition, u32 cluster) { _FAT_fat_clearLinks frees any cluster used by a file -----------------------------------------------------------------*/ -bool _FAT_fat_clearLinks (PARTITION* partition, u32 cluster) { - u32 nextCluster; +bool _FAT_fat_clearLinks (PARTITION* partition, uint32_t cluster) { + uint32_t nextCluster; if ((cluster < CLUSTER_FIRST) || (cluster > partition->fat.lastCluster /* This will catch CLUSTER_ERROR */)) return false; @@ -331,11 +316,48 @@ bool _FAT_fat_clearLinks (PARTITION* partition, u32 cluster) { return true; } +/*----------------------------------------------------------------- +_FAT_fat_trimChain +Drop all clusters past the chainLength. +If chainLength is 0, all clusters are dropped. +If chainLength is 1, the first cluster is kept and the rest are +dropped, and so on. +Return the last cluster left in the chain. +-----------------------------------------------------------------*/ +uint32_t _FAT_fat_trimChain (PARTITION* partition, uint32_t startCluster, unsigned int chainLength) { + uint32_t nextCluster; + + if (chainLength == 0) { + // Drop the entire chain + _FAT_fat_clearLinks (partition, startCluster); + return CLUSTER_FREE; + } else { + // Find the last cluster in the chain, and the one after it + chainLength--; + nextCluster = _FAT_fat_nextCluster (partition, startCluster); + while ((chainLength > 0) && (nextCluster != CLUSTER_FREE) && (nextCluster != CLUSTER_EOF)) { + chainLength--; + startCluster = nextCluster; + nextCluster = _FAT_fat_nextCluster (partition, startCluster); + } + + // Drop all clusters after the last in the chain + if (nextCluster != CLUSTER_FREE && nextCluster != CLUSTER_EOF) { + _FAT_fat_clearLinks (partition, nextCluster); + } + + // Mark the last cluster in the chain as the end of the file + _FAT_fat_writeFatEntry (partition, startCluster, CLUSTER_EOF); + + return startCluster; + } +} + /*----------------------------------------------------------------- _FAT_fat_lastCluster Trace the cluster links until the last one is found -----------------------------------------------------------------*/ -u32 _FAT_fat_lastCluster (PARTITION* partition, u32 cluster) { +uint32_t _FAT_fat_lastCluster (PARTITION* partition, uint32_t cluster) { while ((_FAT_fat_nextCluster(partition, cluster) != CLUSTER_FREE) && (_FAT_fat_nextCluster(partition, cluster) != CLUSTER_EOF)) { cluster = _FAT_fat_nextCluster(partition, cluster); } @@ -346,9 +368,9 @@ u32 _FAT_fat_lastCluster (PARTITION* partition, u32 cluster) { _FAT_fat_freeClusterCount Return the number of free clusters available -----------------------------------------------------------------*/ -u32 _FAT_fat_freeClusterCount (PARTITION* partition) { - u32 count = 0; - u32 curCluster; +unsigned int _FAT_fat_freeClusterCount (PARTITION* partition) { + unsigned int count = 0; + uint32_t curCluster; for (curCluster = CLUSTER_FIRST; curCluster <= partition->fat.lastCluster; curCluster++) { if (_FAT_fat_nextCluster(partition, curCluster) == CLUSTER_FREE) { diff --git a/source/file_allocation_table.h b/source/file_allocation_table.h index eb17b69..560c616 100644 --- a/source/file_allocation_table.h +++ b/source/file_allocation_table.h @@ -25,18 +25,6 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release - - 2006-10-01 - Chishm - * Added _FAT_fat_linkFreeClusterCleared to clear a cluster when it is allocated - - 2007-10-25 - Chishm - * Use CLUSTER_ERROR when an error occurs with the FAT, not CLUSTER_FREE - - 2008-08-17 - Chishm - * Added CLUSTER_ROOT definition */ #ifndef _FAT_H @@ -56,22 +44,26 @@ #define CLUSTERS_PER_FAT16 65525 -u32 _FAT_fat_nextCluster(PARTITION* partition, u32 cluster); +uint32_t _FAT_fat_nextCluster(PARTITION* partition, uint32_t cluster); -u32 _FAT_fat_linkFreeCluster(PARTITION* partition, u32 cluster); -u32 _FAT_fat_linkFreeClusterCleared (PARTITION* partition, u32 cluster); +uint32_t _FAT_fat_linkFreeCluster(PARTITION* partition, uint32_t cluster); +uint32_t _FAT_fat_linkFreeClusterCleared (PARTITION* partition, uint32_t cluster); -bool _FAT_fat_clearLinks (PARTITION* partition, u32 cluster); +bool _FAT_fat_clearLinks (PARTITION* partition, uint32_t cluster); -u32 _FAT_fat_lastCluster (PARTITION* partition, u32 cluster); +uint32_t _FAT_fat_trimChain (PARTITION* partition, uint32_t startCluster, unsigned int chainLength); -u32 _FAT_fat_freeClusterCount (PARTITION* partition); +uint32_t _FAT_fat_lastCluster (PARTITION* partition, uint32_t cluster); -static inline u32 _FAT_fat_clusterToSector (PARTITION* partition, u32 cluster) { - return (cluster >= CLUSTER_FIRST) ? ((cluster - CLUSTER_FIRST) * partition->sectorsPerCluster) + partition->dataStart : partition->rootDirStart; +unsigned int _FAT_fat_freeClusterCount (PARTITION* partition); + +static inline sec_t _FAT_fat_clusterToSector (PARTITION* partition, uint32_t cluster) { + return (cluster >= CLUSTER_FIRST) ? + ((cluster - CLUSTER_FIRST) * (sec_t)partition->sectorsPerCluster) + partition->dataStart : + partition->rootDirStart; } -static inline bool _FAT_fat_isValidCluster (PARTITION* partition, u32 cluster) { +static inline bool _FAT_fat_isValidCluster (PARTITION* partition, uint32_t cluster) { return (cluster >= CLUSTER_FIRST) && (cluster <= partition->fat.lastCluster /* This will catch CLUSTER_ERROR */); } diff --git a/source/filetime.c b/source/filetime.c index 67514cd..25034e7 100644 --- a/source/filetime.c +++ b/source/filetime.c @@ -24,27 +24,12 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release - - 2006-09-30 - Chishm - * Validity checks performed on the time supplied by the IPC - * Cleaned up magic numbers - - 2006-10-01 - Chishm - * Fixed incorrect use of bitwise-or instead of logical-or - - 2007-10-30 - Chishm - * Uses standard POSIX time functions - - 2007-11-04 - Chishm - * Fix off-by-one error for months value */ #include #include "filetime.h" +#include "common.h" #define MAX_HOUR 23 #define MAX_MINUTE 59 @@ -55,8 +40,8 @@ #define MAX_DAY 31 #define MIN_DAY 1 -u16 _FAT_filetime_getTimeFromRTC (void) { -#ifndef GBA +uint16_t _FAT_filetime_getTimeFromRTC (void) { +#ifdef USE_RTC_TIME struct tm timeParts; time_t epochTime; @@ -82,8 +67,8 @@ u16 _FAT_filetime_getTimeFromRTC (void) { } -u16 _FAT_filetime_getDateFromRTC (void) { -#ifndef GBA +uint16_t _FAT_filetime_getDateFromRTC (void) { +#ifdef USE_RTC_TIME struct tm timeParts; time_t epochTime; @@ -105,7 +90,7 @@ u16 _FAT_filetime_getDateFromRTC (void) { #endif } -time_t _FAT_filetime_to_time_t (u16 t, u16 d) { +time_t _FAT_filetime_to_time_t (uint16_t t, uint16_t d) { struct tm timeParts; timeParts.tm_hour = t >> 11; diff --git a/source/filetime.h b/source/filetime.h index d45f6d2..3bfd8ed 100644 --- a/source/filetime.h +++ b/source/filetime.h @@ -24,12 +24,6 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release - - 2007-10-30 - Chishm - * Uses standard POSIX time functions */ #ifndef _FILETIME_H @@ -38,10 +32,10 @@ #include "common.h" #include -u16 _FAT_filetime_getTimeFromRTC (void); -u16 _FAT_filetime_getDateFromRTC (void); +uint16_t _FAT_filetime_getTimeFromRTC (void); +uint16_t _FAT_filetime_getDateFromRTC (void); -time_t _FAT_filetime_to_time_t (u16 t, u16 d); +time_t _FAT_filetime_to_time_t (uint16_t t, uint16_t d); #endif // _FILETIME_H diff --git a/source/libfat.c b/source/libfat.c index ec756a5..d2128b0 100644 --- a/source/libfat.c +++ b/source/libfat.c @@ -24,24 +24,6 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release - - 2006-08-13 - Chishm - * Moved all externally visible directory related functions to fatdir - - 2006-08-14 - Chishm - * Added extended devoptab_t functions - - 2007-01-10 - Chishm - * fatInit now sets the correct path when setAsDefaultDevice - - 2007-01-11 - Chishm - * Added missing #include - - 2007-10-25 - Chishm - * Added statvfs functionality */ #include @@ -53,14 +35,10 @@ #include "fatfile.h" #include "fatdir.h" #include "lock.h" +#include "mem_allocate.h" +#include "disc.h" -#ifdef GBA -#define DEFAULT_CACHE_PAGES 2 -#else -#define DEFAULT_CACHE_PAGES 8 -#endif - -const devoptab_t dotab_fat = { +static const devoptab_t dotab_fat = { "fat", sizeof (FILE_STRUCT), _FAT_open_r, @@ -80,48 +58,116 @@ const devoptab_t dotab_fat = { _FAT_dirreset_r, _FAT_dirnext_r, _FAT_dirclose_r, - _FAT_statvfs_r + _FAT_statvfs_r, + _FAT_ftruncate_r, + _FAT_fsync_r, + NULL /* Device data */ }; -bool fatInit (u32 cacheSize, bool setAsDefaultDevice) { - int i; - bool device = false, setDefault = false; - - if ( PI_MAX_PARTITIONS == 1 ) { - if ( _FAT_partition_mount ( 0 , cacheSize) ) { - _FAT_partition_setDefaultInterface (0); - } else { - return false; - } - - } else { +bool fatMount (const char* name, const DISC_INTERFACE* interface, sec_t startSector, uint32_t cacheSize) { + PARTITION* partition; + devoptab_t* devops; + char* nameCopy; - for ( i = 1; i < PI_MAX_PARTITIONS; i++ ) { - device = _FAT_partition_mount ( i , cacheSize); - if ( device && !setDefault ) { - _FAT_partition_setDefaultInterface (i); - setDefault = true; + devops = _FAT_mem_allocate (sizeof(devoptab_t) + strlen(name) + 1); + if (!devops) { + return false; + } + // Use the space allocated at the end of the devoptab struct for storing the name + nameCopy = (char*)(devops+1); + + // Initialize the file system + partition = _FAT_partition_constructor (interface, cacheSize, startSector); + if (!partition) { + _FAT_mem_free (devops); + return false; + } + + // Add an entry for this device to the devoptab table + memcpy (devops, &dotab_fat, sizeof(dotab_fat)); + strcpy (nameCopy, name); + devops->name = nameCopy; + devops->deviceData = partition; + + AddDevice (devops); + + return true; +} + +bool fatMountSimple (const char* name, const DISC_INTERFACE* interface) { + return fatMount (name, interface, 0, DEFAULT_CACHE_PAGES); +} + +void fatUnmount (const char* name) { + devoptab_t *devops; + PARTITION* partition; + + devops = (devoptab_t*)GetDeviceOpTab (name); + if (!devops) { + return; + } + + // Perform a quick check to make sure we're dealing with a libfat controlled device + if (devops->open_r != dotab_fat.open_r) { + return; + } + + if (!RemoveDevice (name)) { + return; + } + + partition = (PARTITION*)devops->deviceData; + _FAT_partition_destructor (partition); + _FAT_mem_free (devops); +} + +bool fatInit (uint32_t cacheSize, bool setAsDefaultDevice) { + int i; + int defaultDevice = -1; + const DISC_INTERFACE *disc; + + for (i = 0; + _FAT_disc_interfaces[i].name != NULL && _FAT_disc_interfaces[i].getInterface != NULL; + i++) + { + disc = _FAT_disc_interfaces[i].getInterface(); + if (disc->startup() && fatMount (_FAT_disc_interfaces[i].name, disc, 0, cacheSize)) { + // The first device to successfully mount is set as the default + if (defaultDevice < 0) { + defaultDevice = i; } } - if ( !setDefault ) return false; } - - AddDevice (&dotab_fat); + + if (defaultDevice < 0) { + // None of our devices mounted + return false; + } if (setAsDefaultDevice) { - char filePath[MAXPATHLEN * 2] = "fat:/"; -#ifndef GBA + char filePath[MAXPATHLEN * 2]; + strcpy (filePath, _FAT_disc_interfaces[defaultDevice].name); + strcat (filePath, ":/"); +#ifdef ARGV_MAGIC if ( __system_argv->argvMagic == ARGV_MAGIC && __system_argv->argc >= 1 ) { - - if ( !strncasecmp( __system_argv->argv[0], "fat", 3)) { - - strcpy(filePath, __system_argv->argv[0]); - char *lastSlash = strrchr( filePath, '/' ); + // Check the app's path against each of our mounted devices, to see + // if we can support it. If so, change to that path. + for (i = 0; + _FAT_disc_interfaces[i].name != NULL && _FAT_disc_interfaces[i].getInterface != NULL; + i++) + { + if ( !strncasecmp( __system_argv->argv[0], _FAT_disc_interfaces[i].name, + strlen(_FAT_disc_interfaces[i].name))) + { + char *lastSlash; + strcpy(filePath, __system_argv->argv[0]); + lastSlash = strrchr( filePath, '/' ); - if ( NULL != lastSlash) { - if ( *(lastSlash - 1) == ':') lastSlash++; - *lastSlash = 0; + if ( NULL != lastSlash) { + if ( *(lastSlash - 1) == ':') lastSlash++; + *lastSlash = 0; + } } } } @@ -129,8 +175,6 @@ bool fatInit (u32 cacheSize, bool setAsDefaultDevice) { chdir (filePath); } - _FAT_lock_init(); - return true; } @@ -138,23 +182,4 @@ bool fatInitDefault (void) { return fatInit (DEFAULT_CACHE_PAGES, true); } -bool fatMountNormalInterface (PARTITION_INTERFACE partitionNumber, u32 cacheSize) { - return _FAT_partition_mount (partitionNumber, cacheSize); -} -bool fatMountCustomInterface (const IO_INTERFACE* device, u32 cacheSize) { - return _FAT_partition_mountCustomInterface (device, cacheSize); -} - -bool fatUnmount (PARTITION_INTERFACE partitionNumber) { - return _FAT_partition_unmount (partitionNumber); -} - - -bool fatUnsafeUnmount (PARTITION_INTERFACE partitionNumber) { - return _FAT_partition_unsafeUnmount (partitionNumber); -} - -bool fatSetDefaultInterface (PARTITION_INTERFACE partitionNumber) { - return _FAT_partition_setDefaultInterface (partitionNumber); -} diff --git a/source/lock.c b/source/lock.c deleted file mode 100644 index 98106cd..0000000 --- a/source/lock.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - lock.h - - Copyright (c) 2008 Sven Peter - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "lock.h" - -#if defined(__wii__) || defined(__gamecube__) - -mutex_t _FAT_mutex; - -#endif /* __wii__ || __gamecube__ */ diff --git a/source/lock.h b/source/lock.h index 814b7db..77fa6a3 100644 --- a/source/lock.h +++ b/source/lock.h @@ -31,55 +31,56 @@ #include "common.h" -#if defined(__wii__) || defined(__gamecube__) +#ifdef USE_LWP_LOCK -#include - -extern mutex_t _FAT_mutex; - -static inline void _FAT_lock_init() +static inline void _FAT_lock_init(mutex_t *mutex) { - LWP_MutexInit(&_FAT_mutex, false); + LWP_MutexInit(mutex, false); } -static inline void _FAT_lock_deinit() +static inline void _FAT_lock_deinit(mutex_t *mutex) { - LWP_MutexDestroy(_FAT_mutex); + LWP_MutexDestroy(*mutex); } -static inline void _FAT_lock() +static inline void _FAT_lock(mutex_t *mutex) { - LWP_MutexLock(_FAT_mutex); + LWP_MutexLock(*mutex); } -static inline void _FAT_unlock() +static inline void _FAT_unlock(mutex_t *mutex) { - LWP_MutexUnlock(_FAT_mutex); + LWP_MutexUnlock(*mutex); } #else -static inline void _FAT_lock_init() +// We still need a blank lock type +#ifndef mutex_t +typedef int mutex_t; +#endif + +static inline void _FAT_lock_init(mutex_t *mutex) { return; } -static inline void _FAT_lock_deinit() +static inline void _FAT_lock_deinit(mutex_t *mutex) { return; } -static inline void _FAT_lock() +static inline void _FAT_lock(mutex_t *mutex) { return; } -static inline void _FAT_unlock() +static inline void _FAT_unlock(mutex_t *mutex) { return; } -#endif /* __wii__ || __gamecube__ */ +#endif // USE_LWP_LOCK #endif // _CACHE_H diff --git a/source/mem_allocate.h b/source/mem_allocate.h index 49d0c35..1c83196 100644 --- a/source/mem_allocate.h +++ b/source/mem_allocate.h @@ -26,9 +26,6 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release */ #ifndef _MEM_ALLOCATE_H @@ -41,7 +38,7 @@ static inline void* _FAT_mem_allocate (size_t size) { } static inline void _FAT_mem_free (void* mem) { - return free (mem); + free (mem); } #endif // _MEM_ALLOCATE_H diff --git a/source/ogc_io/disc.c b/source/ogc_io/disc.c deleted file mode 100644 index 2ea93fe..0000000 --- a/source/ogc_io/disc.c +++ /dev/null @@ -1,169 +0,0 @@ -/* - - disc.c - - uniformed io-interface to work with Chishm's FAT library - - Written by MightyMax - - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2005-11-06 - Chishm - * Added WAIT_CR modifications for NDS - - 2006-02-03 www.neoflash.com - * Added SUPPORT_* defines, comment out any of the SUPPORT_* defines in disc_io.h to remove support - for the given interface and stop code being linked to the binary - - * Added support for MK2 MMC interface - - * Added disc_Cache* functions - - 2006-02-05 - Chishm - * Added Supercard SD support - - 2006-02-26 - Cytex - * Added EFA2 support - - 2006-05-18 - Chishm - * Rewritten for FATlib disc.c - - 2006-06-19 - Chishm - * Changed read and write interface to accept a u32 instead of a u8 for the number of sectors - - 2006-07-11 - Chishm - * Removed disc_Cache* functions, since there is now a proper unified cache - * Removed SUPPORT_* defines - * Rewrote device detection functions - * First libfat release - - 2006-07-25 - Chishm - * Changed IO_INTERFACEs to const - - 2006-08-02 - Chishm - * Added NinjaDS - - 2006-12-25 - Chishm - * Added DLDI - * Removed experimental interfaces - - 2007-05-01 - Chishm - * Removed FCSR -*/ - -#include "../disc.h" -#include "wiisd.h" -#include "gcsd.h" - - -const IO_INTERFACE* ioInterfaces[] = { -#ifdef __gamecube__ - &__io_gcsda, - &__io_gcsdb, -#endif -#ifdef __wii__ - &__io_wiisd -#endif -}; - -#ifdef __wii__ -const IO_INTERFACE* _FAT_disc_wiiFindInterface(void) -{ - int i; - - for (i = 0; i < (sizeof(ioInterfaces) / sizeof(IO_INTERFACE*)); i++) { - if ((ioInterfaces[i]->ioType == DEVICE_TYPE_WII) && (ioInterfaces[i]->fn_startup())) { - return ioInterfaces[i]; - } - } - return NULL; -} -#endif - -const IO_INTERFACE* _FAT_disc_gcFindInterface(void) -{ - int i; - - - for (i = 0; i < (sizeof(ioInterfaces) / sizeof(IO_INTERFACE*)); i++) { - if ((ioInterfaces[i]->ioType == DEVICE_TYPE_GC) && (ioInterfaces[i]->fn_startup())) { - return ioInterfaces[i]; - } - } - return NULL; -} - -const IO_INTERFACE* _FAT_disc_gcFindInterfaceSlot(int slot) -{ - int i; - int mask; - - if(slot == 0) - mask = FEATURE_GAMECUBE_SLOTA; - else if(slot == 1) - mask = FEATURE_GAMECUBE_SLOTB; - else - return NULL; - - for (i = 0; i < (sizeof(ioInterfaces) / sizeof(IO_INTERFACE*)); i++) { - if ((ioInterfaces[i]->ioType == DEVICE_TYPE_GC) && (ioInterfaces[i]->features & mask) && (ioInterfaces[i]->fn_startup())) { - return ioInterfaces[i]; - } - } - return NULL; -} - - -const IO_INTERFACE* _FAT_disc_findInterface(void) -{ -#ifdef __wii__ - return _FAT_disc_wiiFindInterface(); -#else - return _FAT_disc_gcFindInterface(); -#endif -} - -const IO_INTERFACE* _FAT_disc_findInterfaceSlot (PARTITION_INTERFACE partitionNumber) -{ - switch(partitionNumber) - { -#ifdef __gamecube__ - case PI_SDGECKO_A: - return _FAT_disc_gcFindInterfaceSlot(0); - break; - case PI_SDGECKO_B: - return _FAT_disc_gcFindInterfaceSlot(1); - break; -#endif -#ifdef __wii__ - case PI_INTERNAL_SD: - return _FAT_disc_wiiFindInterface(); - break; -#endif - default: - return NULL; - break; - } -} diff --git a/source/ogc_io/gcsd.h b/source/ogc_io/gcsd.h deleted file mode 100644 index b7e15a0..0000000 --- a/source/ogc_io/gcsd.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - - gcsd.h - - Hardware routines for reading and writing to SD geckos connected - to the memory card ports. - - These functions are just wrappers around libsdcard's functions. - - Copyright (c) 2008 Sven "svpe" Peter - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef __GCSD_H__ -#define __GCSD_H__ - -#include -#include "../disc.h" - -extern const IO_INTERFACE __io_gcsda; -extern const IO_INTERFACE __io_gcsdb; - -#endif diff --git a/source/ogc_io/wiisd.h b/source/ogc_io/wiisd.h deleted file mode 100644 index 6af0baf..0000000 --- a/source/ogc_io/wiisd.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - - wiisd.c - - Hardware routines for reading and writing to the Wii's internal - SD slot. - - Copyright (c) 2008 Sven "svpe" Peter - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef __WIISD_H__ -#define __WIISD_H__ - -#include -#include "../disc.h" - - -extern const IO_INTERFACE __io_wiisd; - -#endif diff --git a/source/partition.c b/source/partition.c index a5fa275..dbfc12d 100644 --- a/source/partition.c +++ b/source/partition.c @@ -25,15 +25,6 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release - - 2006-08-10 - Chishm - * Fixed problem when openning files starting with "fat" - - 2006-10-28 - Chishm - * _partitions changed to _FAT_partitions to maintain the same style of naming as the functions */ @@ -41,11 +32,12 @@ #include "bit_ops.h" #include "file_allocation_table.h" #include "directory.h" +#include "mem_allocate.h" +#include "fatfile.h" #include #include - -#include "mem_allocate.h" +#include /* This device name, as known by devkitPro toolchains @@ -102,25 +94,13 @@ enum BPB { BPB_bootSig_AA = 0x1FF }; -#if defined(__wii__) -#define MAXIMUM_PARTITIONS 5 -#elif defined(__gamecube__) -#define MAXIMUM_PARTITIONS 4 -#elif defined(NDS) -#define MAXIMUM_PARTITIONS 4 -#else // not defined NDS -#define MAXIMUM_PARTITIONS 1 -#endif // defined NDS -PARTITION* _FAT_partitions[MAXIMUM_PARTITIONS] = {NULL}; - -// Use a single static buffer for the partitions +static const char FAT_SIG[3] = {'F', 'A', 'T'}; -static PARTITION* _FAT_partition_constructor ( const IO_INTERFACE* disc, u32 cacheSize) { +PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cacheSize, sec_t startSector) { PARTITION* partition; int i; - u32 bootSector; - u8 sectorBuffer[BYTES_PER_READ] = {0}; + uint8_t sectorBuffer[BYTES_PER_READ] = {0}; // Read first sector of disc if ( !_FAT_disc_readSectors (disc, 0, 1, sectorBuffer)) { @@ -132,12 +112,14 @@ static PARTITION* _FAT_partition_constructor ( const IO_INTERFACE* disc, u32 cac return NULL; } - // Check if there is a FAT string, which indicates this is a boot sector - if ((sectorBuffer[0x36] == 'F') && (sectorBuffer[0x37] == 'A') && (sectorBuffer[0x38] == 'T')) { - bootSector = 0; - } else if ((sectorBuffer[0x52] == 'F') && (sectorBuffer[0x53] == 'A') && (sectorBuffer[0x54] == 'T')) { + if (startSector != 0) { + // We're told where to start the partition, so just accept it + } else if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG))) { + // Check if there is a FAT string, which indicates this is a boot sector + startSector = 0; + } else if (!memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) { // Check for FAT32 - bootSector = 0; + startSector = 0; } else { // This is an MBR // Find first valid partition from MBR @@ -151,14 +133,21 @@ static PARTITION* _FAT_partition_constructor ( const IO_INTERFACE* disc, u32 cac // Go to first valid partition if ( i != 0x1FE) { // Make sure it found a partition - bootSector = u8array_to_u32(sectorBuffer, 0x8 + i); + startSector = u8array_to_u32(sectorBuffer, 0x8 + i); } else { - bootSector = 0; // No partition found, assume this is a MBR free disk + startSector = 0; // No partition found, assume this is a MBR free disk } } + // Now verify that this is indeed a FAT partition + if (memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) && + memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) + { + return NULL; + } + // Read in boot sector - if ( !_FAT_disc_readSectors (disc, bootSector, 1, sectorBuffer)) { + if ( !_FAT_disc_readSectors (disc, startSector, 1, sectorBuffer)) { return NULL; } @@ -167,6 +156,9 @@ static PARTITION* _FAT_partition_constructor ( const IO_INTERFACE* disc, u32 cac return NULL; } + // Init the partition lock + _FAT_lock_init(&partition->lock); + // Set partition's disc interface partition->disc = disc; @@ -184,15 +176,16 @@ static PARTITION* _FAT_partition_constructor ( const IO_INTERFACE* disc, u32 cac partition->bytesPerSector = BYTES_PER_READ; // Sector size is redefined to be 512 bytes partition->sectorsPerCluster = sectorBuffer[BPB_sectorsPerCluster] * u8array_to_u16(sectorBuffer, BPB_bytesPerSector) / BYTES_PER_READ; partition->bytesPerCluster = partition->bytesPerSector * partition->sectorsPerCluster; - partition->fat.fatStart = bootSector + u8array_to_u16(sectorBuffer, BPB_reservedSectors); + partition->fat.fatStart = startSector + u8array_to_u16(sectorBuffer, BPB_reservedSectors); partition->rootDirStart = partition->fat.fatStart + (sectorBuffer[BPB_numFATs] * partition->fat.sectorsPerFat); - partition->dataStart = partition->rootDirStart + (( u8array_to_u16(sectorBuffer, BPB_rootEntries) * DIR_ENTRY_DATA_SIZE) / partition->bytesPerSector); + partition->dataStart = partition->rootDirStart + + (( u8array_to_u16(sectorBuffer, BPB_rootEntries) * DIR_ENTRY_DATA_SIZE) / partition->bytesPerSector); - partition->totalSize = (partition->numberOfSectors - partition->dataStart) * partition->bytesPerSector; + partition->totalSize = ((uint64_t)partition->numberOfSectors - (partition->dataStart - startSector)) * (uint64_t)partition->bytesPerSector; // Store info about FAT - partition->fat.lastCluster = (partition->numberOfSectors - partition->dataStart) / partition->sectorsPerCluster; + partition->fat.lastCluster = (partition->numberOfSectors - (uint32_t)(partition->dataStart - startSector)) / partition->sectorsPerCluster; partition->fat.firstFree = CLUSTER_FIRST; if (partition->fat.lastCluster < CLUSTERS_PER_FAT12) { @@ -230,195 +223,38 @@ static PARTITION* _FAT_partition_constructor ( const IO_INTERFACE* disc, u32 cac return partition; } -static void _FAT_partition_destructor (PARTITION* partition) { +void _FAT_partition_destructor (PARTITION* partition) { + FILE_STRUCT* nextFile; + + _FAT_lock(&partition->lock); + + // Synchronize open files + nextFile = partition->firstOpenFile; + while (nextFile) { + _FAT_syncToDisc (nextFile); + nextFile = nextFile->nextOpenFile; + } + + // Free memory used by the cache, writing it to disc at the same time _FAT_cache_destructor (partition->cache); - _FAT_disc_shutdown (partition->disc); + + // Unlock the partition and destroy the lock + _FAT_unlock(&partition->lock); + _FAT_lock_deinit(&partition->lock); + + // Free memory used by the partition _FAT_mem_free (partition); } -bool _FAT_partition_mount (PARTITION_INTERFACE partitionNumber, u32 cacheSize) { - int i; - const IO_INTERFACE* disc = NULL; - - if (_FAT_partitions[partitionNumber] != NULL) { - return false; - } - - disc = _FAT_disc_findInterfaceSlot (partitionNumber); - if (disc == NULL) { - return false; - } - - // See if that disc is already in use, if so, then just copy the partition pointer - for (i = 0; i < MAXIMUM_PARTITIONS; i++) { - if ((_FAT_partitions[i] != NULL) && (_FAT_partitions[i]->disc == disc)) { - _FAT_partitions[partitionNumber] = _FAT_partitions[i]; - return true; - } - } - - _FAT_partitions[partitionNumber] = _FAT_partition_constructor (disc, cacheSize); - - if (_FAT_partitions[partitionNumber] == NULL) { - return false; - } - - return true; -} - -bool _FAT_partition_mountCustomInterface (const IO_INTERFACE* device, u32 cacheSize) { - - -#ifdef GBA - if (_FAT_partitions[0] != NULL) return false; - - if (device == NULL) return false; - - // Only ever one partition on GBA - _FAT_partitions[0] = _FAT_partition_constructor (device, cacheSize); -#else - int i; - - if (_FAT_partitions[PI_CUSTOM] != NULL) return false; - - if (device == NULL) return false; - - // See if that disc is already in use, if so, then just copy the partition pointer - for (i = 0; i < MAXIMUM_PARTITIONS; i++) { - if ((_FAT_partitions[i] != NULL) && (_FAT_partitions[i]->disc == device)) { - _FAT_partitions[PI_CUSTOM] = _FAT_partitions[i]; - return true; - } - } - - _FAT_partitions[PI_CUSTOM] = _FAT_partition_constructor (device, cacheSize); - - if (_FAT_partitions[PI_CUSTOM] == NULL) { - return false; - } -#endif - return true; -} - -bool _FAT_partition_setDefaultInterface (PARTITION_INTERFACE partitionNumber) { -#ifndef GBA // Can only set the default partition when there is more than 1, so doesn't apply to GBA - if ((partitionNumber < 1) || (partitionNumber >= MAXIMUM_PARTITIONS)) { - return false; - } - - if (_FAT_partitions[partitionNumber] == NULL) { - return false; - } - - _FAT_partitions[PI_DEFAULT] = _FAT_partitions[partitionNumber]; -#endif - return true; -} - -bool _FAT_partition_setDefaultPartition (PARTITION* partition) { -#ifndef GBA // Can only set the default partition when there is more than 1, so doesn't apply to GBA - int i; - - if (partition == NULL) { - return false; - } - - // Ensure that this device is already in the list - for (i = 1; i < MAXIMUM_PARTITIONS; i++) { - if (_FAT_partitions[i] == partition) { - break; - } - } - - // It wasn't in the list, so fail - if (i == MAXIMUM_PARTITIONS) { - return false; - } - - // Change the default partition / device to this one - _FAT_partitions[PI_DEFAULT] = partition; - -#endif - return true; -} - -bool _FAT_partition_unmount (PARTITION_INTERFACE partitionNumber) { - int i; - PARTITION* partition = _FAT_partitions[partitionNumber]; - - if (partition == NULL) { - return false; - } - - if (partition->openFileCount > 0) { - // There are still open files that need closing - return false; - } - - // Remove all references to this partition - for (i = 0; i < MAXIMUM_PARTITIONS; i++) { - if (_FAT_partitions[i] == partition) { - _FAT_partitions[i] = NULL; - } - } - - _FAT_partition_destructor (partition); - return true; -} - -bool _FAT_partition_unsafeUnmount (PARTITION_INTERFACE partitionNumber) { - int i; - PARTITION* partition = _FAT_partitions[partitionNumber]; - - if (partition == NULL) { - return false; - } - - // Remove all references to this partition - for (i = 0; i < MAXIMUM_PARTITIONS; i++) { - if (_FAT_partitions[i] == partition) { - _FAT_partitions[i] = NULL; - } - } - - _FAT_cache_invalidate (partition->cache); - _FAT_partition_destructor (partition); - return true; -} PARTITION* _FAT_partition_getPartitionFromPath (const char* path) { - -#ifdef GBA - return _FAT_partitions[0]; -#else - int namelen; - int partitionNumber; + const devoptab_t *devops; - // Device name extraction code taken from DevKitPro - namelen = strlen(DEVICE_NAME); - if (strchr (path, ':') == NULL) { - // No device specified - partitionNumber = PI_DEFAULT; - } else if( strncmp(DEVICE_NAME, path, namelen) == 0 ) { - if ( path[namelen] == ':' ) { - // Only the device name is specified - partitionNumber = PI_DEFAULT; - } else if (isdigit(path[namelen]) && path[namelen+1] ==':' ) { - // Device name and number specified - partitionNumber = path[namelen] - '0'; - } else { - // Incorrect device name - return NULL; - } - } else { - // Incorrect device name + devops = GetDeviceOpTab (path); + + if (!devops) { return NULL; } - if ((partitionNumber < 0) || (partitionNumber >= MAXIMUM_PARTITIONS)) { - return NULL; - } - - return _FAT_partitions[partitionNumber]; -#endif + return (PARTITION*)devops->deviceData; } diff --git a/source/partition.h b/source/partition.h index e68b525..b3d18d1 100644 --- a/source/partition.h +++ b/source/partition.h @@ -25,9 +25,6 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release */ #ifndef _PARTITION_H @@ -35,6 +32,7 @@ #include "common.h" #include "cache.h" +#include "lock.h" // Device name extern const char* DEVICE_NAME; @@ -42,75 +40,48 @@ extern const char* DEVICE_NAME; // Filesystem type typedef enum {FS_UNKNOWN, FS_FAT12, FS_FAT16, FS_FAT32} FS_TYPE; - typedef struct { - u32 fatStart; - u32 sectorsPerFat; - u32 lastCluster; - u32 firstFree; + sec_t fatStart; + uint32_t sectorsPerFat; + uint32_t lastCluster; + uint32_t firstFree; } FAT; typedef struct { - const IO_INTERFACE* disc; - CACHE* cache; + const DISC_INTERFACE* disc; + CACHE* cache; // Info about the partition - bool readOnly; // If this is set, then do not try writing to the disc - FS_TYPE filesysType; - u32 totalSize; - u32 rootDirStart; - u32 rootDirCluster; - u32 numberOfSectors; - u32 dataStart; - u32 bytesPerSector; - u32 sectorsPerCluster; - u32 bytesPerCluster; - FAT fat; + bool readOnly; // If this is set, then do not try writing to the disc + FS_TYPE filesysType; + uint64_t totalSize; + sec_t rootDirStart; + uint32_t rootDirCluster; + uint32_t numberOfSectors; + sec_t dataStart; + uint32_t bytesPerSector; + uint32_t sectorsPerCluster; + uint32_t bytesPerCluster; + FAT fat; // Values that may change after construction - u32 cwdCluster; // Current working directory cluser - u32 openFileCount; + uint32_t cwdCluster; // Current working directory cluster + int openFileCount; + struct _FILE_STRUCT* firstOpenFile; // The start of a linked list of files + mutex_t lock; // A lock for partition operations } PARTITION; /* -Mount the device specified by partitionDevice -PD_DEFAULT is not allowed, use _FAT_partition_setDefaultDevice -PD_CUSTOM is not allowed, use _FAT_partition_mountCustomDevice +Mount the supplied device and return a pointer to the struct necessary to use it */ -bool _FAT_partition_mount (PARTITION_INTERFACE partitionNumber, u32 cacheSize); +PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cacheSize, sec_t startSector); /* -Mount a partition on a custom device +Dismount the device and free all structures used. +Will also attempt to synchronise all open files to disc. */ -bool _FAT_partition_mountCustomInterface (const IO_INTERFACE* device, u32 cacheSize); +void _FAT_partition_destructor (PARTITION* partition); /* -Unmount the partition specified by partitionNumber -If there are open files, it will fail -*/ -bool _FAT_partition_unmount (PARTITION_INTERFACE partitionNumber); - -/* -Forcibly unmount the partition specified by partitionNumber -Any open files on the partition will become invalid -The cache will be invalidated, and any unflushed writes will be lost -*/ -bool _FAT_partition_unsafeUnmount (PARTITION_INTERFACE partitionNumber); - -/* -Set the default device for access by fat: and fat0:, -based on the device number -*/ -bool _FAT_partition_setDefaultInterface (PARTITION_INTERFACE partitionNumber); - -/* -Set the default device for access by fat: and fat0:, -based on the partition pointer -*/ -bool _FAT_partition_setDefaultPartition (PARTITION* partition); - -/* -Return the partition specified in a path -For instance, "fat0:", "fat:", "/" and "fat:/" will all -return the default partition +Return the partition specified in a path, as taken from the devoptab. */ PARTITION* _FAT_partition_getPartitionFromPath (const char* path);