mirror of
https://github.com/wiiu-env/libfat.git
synced 2024-11-22 09:59:18 +01:00
Changed _CF_USE_DMA and _CF_ALLOW_UNALIGNED to _IO_USE_DMA and _IO_ALLOW_UNALIGNED respectively.
Combined all CF-based hardware drivers into one set of routines with different sets of registers. Speed should remain the same, but size should be reduced.
This commit is contained in:
parent
6b6d0f51c0
commit
3a9b3b5e3a
@ -27,6 +27,10 @@
|
|||||||
|
|
||||||
2006-07-11 - Chishm
|
2006-07-11 - Chishm
|
||||||
* Original release
|
* Original release
|
||||||
|
|
||||||
|
2006-07-16 - Chishm
|
||||||
|
* Renamed _CF_USE_DMA to _IO_USE_DMA
|
||||||
|
* Renamed _CF_ALLOW_UNALIGNED to _IO_ALLOW_UNALIGNED
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _DISC_IO_H
|
#ifndef _DISC_IO_H
|
||||||
@ -38,14 +42,14 @@
|
|||||||
// Customisable features
|
// Customisable features
|
||||||
|
|
||||||
// Use DMA to read the card, remove this line to use normal reads/writes
|
// Use DMA to read the card, remove this line to use normal reads/writes
|
||||||
// #define _CF_USE_DMA
|
// #define _IO_USE_DMA
|
||||||
|
|
||||||
// Allow buffers not alligned to 16 bits when reading files.
|
// 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.
|
// Note that this will slow down access speed, so only use if you have to.
|
||||||
// It is also incompatible with DMA
|
// It is also incompatible with DMA
|
||||||
#define _CF_ALLOW_UNALIGNED
|
#define _IO_ALLOW_UNALIGNED
|
||||||
|
|
||||||
#if defined _CF_USE_DMA && defined _CF_ALLOW_UNALIGNED
|
#if defined _IO_USE_DMA && defined _IO_ALLOW_UNALIGNED
|
||||||
#error You can't use both DMA and unaligned memory
|
#error You can't use both DMA and unaligned memory
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
322
source/disc_io/io_cf_common.c
Normal file
322
source/disc_io/io_cf_common.c
Normal file
@ -0,0 +1,322 @@
|
|||||||
|
/*
|
||||||
|
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 <nds/dma.h>
|
||||||
|
#ifdef ARM9
|
||||||
|
#include <nds/arm9/cache.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
@ -30,6 +30,9 @@
|
|||||||
|
|
||||||
2006-07-11 - Chishm
|
2006-07-11 - Chishm
|
||||||
* Original release
|
* Original release
|
||||||
|
|
||||||
|
2006-07-16 - Chishm
|
||||||
|
* Combined all CF interfaces into one common set of routines
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef IO_CF_COMMON_H
|
#ifndef IO_CF_COMMON_H
|
||||||
@ -37,6 +40,19 @@
|
|||||||
|
|
||||||
#include "disc_io.h"
|
#include "disc_io.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
|
// CF Card status
|
||||||
#define CF_STS_INSERTED 0x50
|
#define CF_STS_INSERTED 0x50
|
||||||
#define CF_STS_REMOVED 0x00
|
#define CF_STS_REMOVED 0x00
|
||||||
@ -52,4 +68,11 @@
|
|||||||
|
|
||||||
#define CF_CARD_TIMEOUT 10000000
|
#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
|
#endif // define IO_CF_COMMON_H
|
||||||
|
@ -195,7 +195,7 @@ bool _EFA2_readSectors (u32 sector, u32 numSecs, void* buffer)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
#ifndef _CF_ALLOW_UNALIGNED
|
#ifndef _IO_ALLOW_UNALIGNED
|
||||||
u8 byte;
|
u8 byte;
|
||||||
u16 word;
|
u16 word;
|
||||||
#endif
|
#endif
|
||||||
@ -234,7 +234,7 @@ bool _EFA2_readSectors (u32 sector, u32 numSecs, void* buffer)
|
|||||||
while (numSecs--)
|
while (numSecs--)
|
||||||
{
|
{
|
||||||
// read page data
|
// read page data
|
||||||
#ifdef _CF_ALLOW_UNALIGNED
|
#ifdef _IO_ALLOW_UNALIGNED
|
||||||
// slow byte access to RAM, but works in principle
|
// slow byte access to RAM, but works in principle
|
||||||
for (i=0 ; i < 512 ; i++)
|
for (i=0 ; i < 512 ; i++)
|
||||||
((u8*)buffer)[i] = REG_EFA2_NAND_RD;
|
((u8*)buffer)[i] = REG_EFA2_NAND_RD;
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
|
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
// DMA
|
// DMA
|
||||||
#ifdef _CF_USE_DMA
|
#ifdef _IO_USE_DMA
|
||||||
#ifndef NDS
|
#ifndef NDS
|
||||||
#include "gba_dma.h"
|
#include "gba_dma.h"
|
||||||
#else
|
#else
|
||||||
@ -155,7 +155,7 @@ bool _FCSR_readSectors (u32 sector, u32 numSectors, void* buffer)
|
|||||||
}
|
}
|
||||||
} else { // Reading from Cart ROM
|
} else { // Reading from Cart ROM
|
||||||
|
|
||||||
#ifdef _CF_USE_DMA
|
#ifdef _IO_USE_DMA
|
||||||
#ifdef NDS
|
#ifdef NDS
|
||||||
#ifdef ARM9
|
#ifdef ARM9
|
||||||
DC_FlushRange( buffer, readLength);
|
DC_FlushRange( buffer, readLength);
|
||||||
@ -166,9 +166,9 @@ bool _FCSR_readSectors (u32 sector, u32 numSectors, void* buffer)
|
|||||||
#else // ! NDS
|
#else // ! NDS
|
||||||
DMA3COPY ( src, buffer, (readLength >> 1) | DMA16 | DMA_ENABLE);
|
DMA3COPY ( src, buffer, (readLength >> 1) | DMA16 | DMA_ENABLE);
|
||||||
#endif // NDS
|
#endif // NDS
|
||||||
#else // !_CF_USE_DMA
|
#else // !_IO_USE_DMA
|
||||||
memcpy (buffer, src, readLength);
|
memcpy (buffer, src, readLength);
|
||||||
#endif // _CF_USE_DMA
|
#endif // _IO_USE_DMA
|
||||||
|
|
||||||
} // if (flagSramSector)
|
} // if (flagSramSector)
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
|
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
// DMA
|
// DMA
|
||||||
#ifdef _CF_USE_DMA
|
#ifdef _IO_USE_DMA
|
||||||
#ifndef NDS
|
#ifndef NDS
|
||||||
#include "gba_dma.h"
|
#include "gba_dma.h"
|
||||||
#else
|
#else
|
||||||
@ -52,303 +52,45 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
// CF Addresses & Commands
|
|
||||||
|
|
||||||
// M3 CF Addresses
|
// M3 CF Addresses
|
||||||
#define REG_M3CF_STS (*(vu16*)0x080C0000) // Status of the CF Card / Device control
|
#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_CMD ((vu16*)0x088E0000) // Commands sent to control chip and status return
|
||||||
#define REG_M3CF_ERR (*(vu16*)0x08820000) // Errors / Features
|
#define REG_M3CF_ERR ((vu16*)0x08820000) // Errors / Features
|
||||||
|
|
||||||
#define REG_M3CF_SEC (*(vu16*)0x08840000) // Number of sector to transfer
|
#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_LBA1 ((vu16*)0x08860000) // 1st byte of sector address
|
||||||
#define REG_M3CF_LBA2 (*(vu16*)0x08880000) // 2nd 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_LBA3 ((vu16*)0x088A0000) // 3rd byte of sector address
|
||||||
#define REG_M3CF_LBA4 (*(vu16*)0x088C0000) // last nibble of sector address | 0xE0
|
#define REG_M3CF_LBA4 ((vu16*)0x088C0000) // last nibble of sector address | 0xE0
|
||||||
|
|
||||||
#define M3_DATA ((vu16*)0x08800000) // Pointer to buffer of CF data transered from card
|
#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) {
|
||||||
_M3CF_isInserted
|
|
||||||
Is a compact flash card inserted?
|
|
||||||
bool return OUT: true if a CF card is inserted
|
|
||||||
-----------------------------------------------------------------*/
|
|
||||||
bool _M3CF_isInserted (void)
|
|
||||||
{
|
|
||||||
// Change register, then check if value did change
|
|
||||||
REG_M3CF_STS = CF_STS_INSERTED;
|
|
||||||
return ((REG_M3CF_STS & 0xff) == CF_STS_INSERTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------
|
|
||||||
_M3CF_clearStatus
|
|
||||||
Tries to make the CF card go back to idle mode
|
|
||||||
bool return OUT: true if a CF card is idle
|
|
||||||
-----------------------------------------------------------------*/
|
|
||||||
bool _M3CF_clearStatus (void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
// Wait until CF card is finished previous commands
|
|
||||||
i=0;
|
|
||||||
while ((REG_M3CF_CMD & CF_STS_BUSY) && (i < CF_CARD_TIMEOUT))
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait until card is ready for commands
|
|
||||||
i = 0;
|
|
||||||
while ((!(REG_M3CF_STS & CF_STS_INSERTED)) && (i < CF_CARD_TIMEOUT))
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (i >= CF_CARD_TIMEOUT)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------
|
|
||||||
_M3CF_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 _M3CF_readSectors (u32 sector, u32 numSectors, void* buffer)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
u16 *buff = (u16*)buffer;
|
|
||||||
#ifdef _CF_ALLOW_UNALIGNED
|
|
||||||
u8 *buff_u8 = (u8*)buffer;
|
|
||||||
int temp;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined _CF_USE_DMA && defined NDS && defined ARM9
|
|
||||||
DC_FlushRange( buffer, numSectors * BYTES_PER_READ);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Wait until CF card is finished previous commands
|
|
||||||
i=0;
|
|
||||||
while ((REG_M3CF_CMD & CF_STS_BUSY) && (i < CF_CARD_TIMEOUT))
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait until card is ready for commands
|
|
||||||
i = 0;
|
|
||||||
while ((!(REG_M3CF_STS & CF_STS_INSERTED)) && (i < CF_CARD_TIMEOUT))
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (i >= CF_CARD_TIMEOUT)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Set number of sectors to read
|
|
||||||
REG_M3CF_SEC = (numSectors < 256 ? numSectors : 0); // Read a maximum of 256 sectors, 0 means 256
|
|
||||||
|
|
||||||
// Set read sector
|
|
||||||
REG_M3CF_LBA1 = sector & 0xFF; // 1st byte of sector number
|
|
||||||
REG_M3CF_LBA2 = (sector >> 8) & 0xFF; // 2nd byte of sector number
|
|
||||||
REG_M3CF_LBA3 = (sector >> 16) & 0xFF; // 3rd byte of sector number
|
|
||||||
REG_M3CF_LBA4 = ((sector >> 24) & 0x0F )| CF_CMD_LBA; // last nibble of sector number
|
|
||||||
|
|
||||||
// Set command to read
|
|
||||||
REG_M3CF_CMD = CF_CMD_READ;
|
|
||||||
|
|
||||||
|
|
||||||
while (numSectors--)
|
|
||||||
{
|
|
||||||
// Wait until card is ready for reading
|
|
||||||
i = 0;
|
|
||||||
while (((REG_M3CF_STS & 0xff) != CF_STS_READY) && (i < CF_CARD_TIMEOUT))
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (i >= CF_CARD_TIMEOUT)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Read data
|
|
||||||
#ifdef _CF_USE_DMA
|
|
||||||
#ifdef NDS
|
|
||||||
DMA3_SRC = (u32)M3_DATA;
|
|
||||||
DMA3_DEST = (u32)buff;
|
|
||||||
DMA3_CR = 256 | DMA_COPY_HALFWORDS | DMA_SRC_FIX;
|
|
||||||
#else
|
|
||||||
DMA3COPY ( M3_DATA, buff, 256 | DMA16 | DMA_ENABLE | DMA_SRC_FIXED);
|
|
||||||
#endif
|
|
||||||
buff += BYTES_PER_READ / 2;
|
|
||||||
#elif defined _CF_ALLOW_UNALIGNED
|
|
||||||
i=256;
|
|
||||||
if ((u32)buff_u8 & 0x01) {
|
|
||||||
while(i--)
|
|
||||||
{
|
|
||||||
temp = *M3_DATA;
|
|
||||||
*buff_u8++ = temp & 0xFF;
|
|
||||||
*buff_u8++ = temp >> 8;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
while(i--)
|
|
||||||
*buff++ = *M3_DATA;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
i=256;
|
|
||||||
while(i--)
|
|
||||||
*buff++ = *M3_DATA;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#if defined _CF_USE_DMA && defined NDS
|
|
||||||
// Wait for end of transfer before returning
|
|
||||||
while(DMA3_CR & DMA_BUSY);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------
|
|
||||||
_M3CF_writeSectors
|
|
||||||
Write 512 byte sector numbered "sector" from "buffer"
|
|
||||||
u32 sector IN: address of 512 byte sector on CF card to read
|
|
||||||
u32 numSecs IN: number of 512 byte sectors to read,
|
|
||||||
1 to 256 sectors can be read, 0 = 256
|
|
||||||
void* buffer IN: pointer to 512 byte buffer to read data from
|
|
||||||
bool return OUT: true if successful
|
|
||||||
-----------------------------------------------------------------*/
|
|
||||||
bool _M3CF_writeSectors (u32 sector, u32 numSectors, void* buffer)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
u16 *buff = (u16*)buffer;
|
|
||||||
#ifdef _CF_ALLOW_UNALIGNED
|
|
||||||
u8 *buff_u8 = (u8*)buffer;
|
|
||||||
int temp;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined _CF_USE_DMA && defined NDS && defined ARM9
|
|
||||||
DC_FlushRange( buffer, numSectors * BYTES_PER_READ);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Wait until CF card is finished previous commands
|
|
||||||
i=0;
|
|
||||||
while ((REG_M3CF_CMD & CF_STS_BUSY) && (i < CF_CARD_TIMEOUT))
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait until card is ready for commands
|
|
||||||
i = 0;
|
|
||||||
while ((!(REG_M3CF_STS & CF_STS_INSERTED)) && (i < CF_CARD_TIMEOUT))
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (i >= CF_CARD_TIMEOUT)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Set number of sectors to write
|
|
||||||
REG_M3CF_SEC = (numSectors < 256 ? numSectors : 0); // Max of 256, 0 means 256
|
|
||||||
|
|
||||||
// Set write sector
|
|
||||||
REG_M3CF_LBA1 = sector & 0xFF; // 1st byte of sector number
|
|
||||||
REG_M3CF_LBA2 = (sector >> 8) & 0xFF; // 2nd byte of sector number
|
|
||||||
REG_M3CF_LBA3 = (sector >> 16) & 0xFF; // 3rd byte of sector number
|
|
||||||
REG_M3CF_LBA4 = ((sector >> 24) & 0x0F )| CF_CMD_LBA; // last nibble of sector number
|
|
||||||
|
|
||||||
// Set command to write
|
|
||||||
REG_M3CF_CMD = CF_CMD_WRITE;
|
|
||||||
|
|
||||||
while (numSectors--)
|
|
||||||
{
|
|
||||||
// Wait until card is ready for writing
|
|
||||||
i = 0;
|
|
||||||
while (((REG_M3CF_STS & 0xff) != CF_STS_READY) && (i < CF_CARD_TIMEOUT))
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (i >= CF_CARD_TIMEOUT)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Write data
|
|
||||||
#ifdef _CF_USE_DMA
|
|
||||||
#ifdef NDS
|
|
||||||
DMA3_SRC = (u32)buff;
|
|
||||||
DMA3_DEST = (u32)M3_DATA;
|
|
||||||
DMA3_CR = 256 | DMA_COPY_HALFWORDS | DMA_DST_FIX;
|
|
||||||
#else
|
|
||||||
DMA3COPY( buff, M3_DATA, 256 | DMA16 | DMA_ENABLE | DMA_DST_FIXED);
|
|
||||||
#endif
|
|
||||||
buff += BYTES_PER_READ / 2;
|
|
||||||
#elif defined _CF_ALLOW_UNALIGNED
|
|
||||||
i=256;
|
|
||||||
if ((u32)buff_u8 & 0x01) {
|
|
||||||
while(i--)
|
|
||||||
{
|
|
||||||
temp = *buff_u8++;
|
|
||||||
temp |= *buff_u8++ << 8;
|
|
||||||
*M3_DATA = temp;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
while(i--)
|
|
||||||
*M3_DATA = *buff++;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
i=256;
|
|
||||||
while(i--)
|
|
||||||
*M3_DATA = *buff++;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#if defined _CF_USE_DMA && defined NDS
|
|
||||||
// Wait for end of transfer before returning
|
|
||||||
while(DMA3_CR & DMA_BUSY);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------
|
|
||||||
M3_Unlock
|
|
||||||
Returns true if M3 was unlocked, false if failed
|
|
||||||
Added by MightyMax
|
|
||||||
-----------------------------------------------------------------*/
|
|
||||||
static bool _M3CF_unlock(void)
|
|
||||||
{
|
|
||||||
u16 temp;
|
|
||||||
_M3_changeMode (M3_MODE_MEDIA);
|
_M3_changeMode (M3_MODE_MEDIA);
|
||||||
// test that we have register access
|
return _CF_startup (&_M3CF_Registers);
|
||||||
temp = REG_M3CF_LBA1;
|
|
||||||
temp = (~temp & 0xFF);
|
|
||||||
REG_M3CF_LBA1 = temp;
|
|
||||||
// did it change?
|
|
||||||
return (REG_M3CF_LBA1 == temp) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool _M3CF_shutdown(void) {
|
|
||||||
if ( !_M3CF_clearStatus() ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
_M3_changeMode (M3_MODE_ROM);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool _M3CF_startUp(void) {
|
|
||||||
return _M3CF_unlock() ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
IO_INTERFACE _io_m3cf = {
|
IO_INTERFACE _io_m3cf = {
|
||||||
DEVICE_TYPE_M3CF,
|
DEVICE_TYPE_M3CF,
|
||||||
FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_SLOT_GBA,
|
FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_SLOT_GBA,
|
||||||
(FN_MEDIUM_STARTUP)&_M3CF_startUp,
|
(FN_MEDIUM_STARTUP)&_M3CF_startup,
|
||||||
(FN_MEDIUM_ISINSERTED)&_M3CF_isInserted,
|
(FN_MEDIUM_ISINSERTED)&_CF_isInserted,
|
||||||
(FN_MEDIUM_READSECTORS)&_M3CF_readSectors,
|
(FN_MEDIUM_READSECTORS)&_CF_readSectors,
|
||||||
(FN_MEDIUM_WRITESECTORS)&_M3CF_writeSectors,
|
(FN_MEDIUM_WRITESECTORS)&_CF_writeSectors,
|
||||||
(FN_MEDIUM_CLEARSTATUS)&_M3CF_clearStatus,
|
(FN_MEDIUM_CLEARSTATUS)&_CF_clearStatus,
|
||||||
(FN_MEDIUM_SHUTDOWN)&_M3CF_shutdown
|
(FN_MEDIUM_SHUTDOWN)&_CF_shutdown
|
||||||
} ;
|
} ;
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
|
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
// DMA
|
// DMA
|
||||||
#ifdef _CF_USE_DMA
|
#ifdef _IO_USE_DMA
|
||||||
#ifndef NDS
|
#ifndef NDS
|
||||||
#include "gba_dma.h"
|
#include "gba_dma.h"
|
||||||
#else
|
#else
|
||||||
@ -51,288 +51,39 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
// CF Addresses & Commands
|
|
||||||
|
|
||||||
// Max Media Player CF Addresses
|
// Max Media Player CF Addresses
|
||||||
#define REG_MMP_STS (*(vu16*)0x080E0000) // Status of the CF Card / Device control
|
#define REG_MMCF_STS ((vu16*)0x080E0000) // Status of the CF Card / Device control
|
||||||
#define REG_MMP_CMD (*(vu16*)0x080E0000) // Commands sent to control chip and status return
|
#define REG_MMCF_CMD ((vu16*)0x080E0000) // Commands sent to control chip and status return
|
||||||
#define REG_MMP_ERR (*(vu16*)0x08020000) // Errors / Features
|
#define REG_MMCF_ERR ((vu16*)0x08020000) // Errors / Features
|
||||||
|
|
||||||
#define REG_MMP_SEC (*(vu16*)0x08040000) // Number of sector to transfer
|
#define REG_MMCF_SEC ((vu16*)0x08040000) // Number of sector to transfer
|
||||||
#define REG_MMP_LBA1 (*(vu16*)0x08060000) // 1st byte of sector address
|
#define REG_MMCF_LBA1 ((vu16*)0x08060000) // 1st byte of sector address
|
||||||
#define REG_MMP_LBA2 (*(vu16*)0x08080000) // 2nd byte of sector address
|
#define REG_MMCF_LBA2 ((vu16*)0x08080000) // 2nd byte of sector address
|
||||||
#define REG_MMP_LBA3 (*(vu16*)0x080A0000) // 3rd byte of sector address
|
#define REG_MMCF_LBA3 ((vu16*)0x080A0000) // 3rd byte of sector address
|
||||||
#define REG_MMP_LBA4 (*(vu16*)0x080C0000) // last nibble of sector address | 0xE0
|
#define REG_MMCF_LBA4 ((vu16*)0x080C0000) // last nibble of sector address | 0xE0
|
||||||
|
|
||||||
#define MMP_DATA ((vu16*)0x09000000) // Pointer to buffer of CF data transered from card
|
#define REG_MMCF_DATA ((vu16*)0x09000000) // Pointer to buffer of CF data transered from card
|
||||||
|
|
||||||
|
static const CF_REGISTERS _MMCF_Registers = {
|
||||||
|
REG_MMCF_DATA,
|
||||||
|
REG_MMCF_STS,
|
||||||
|
REG_MMCF_CMD,
|
||||||
|
REG_MMCF_ERR,
|
||||||
|
REG_MMCF_SEC,
|
||||||
|
REG_MMCF_LBA1,
|
||||||
|
REG_MMCF_LBA2,
|
||||||
|
REG_MMCF_LBA3,
|
||||||
|
REG_MMCF_LBA4
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------
|
|
||||||
_MMCF_isInserted
|
|
||||||
Is a compact flash card inserted?
|
|
||||||
bool return OUT: true if a CF card is inserted
|
|
||||||
-----------------------------------------------------------------*/
|
|
||||||
bool _MMCF_isInserted (void) {
|
|
||||||
// Change register, then check if value did change
|
|
||||||
REG_MMP_STS = CF_STS_INSERTED;
|
|
||||||
return ((REG_MMP_STS & 0xff) == CF_STS_INSERTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------
|
|
||||||
_MMCF_clearStatus
|
|
||||||
Tries to make the CF card go back to idle mode
|
|
||||||
bool return OUT: true if a CF card is idle
|
|
||||||
-----------------------------------------------------------------*/
|
|
||||||
bool _MMCF_clearStatus (void) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
// Wait until CF card is finished previous commands
|
|
||||||
i=0;
|
|
||||||
while ((REG_MMP_CMD & CF_STS_BUSY) && (i < CF_CARD_TIMEOUT))
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait until card is ready for commands
|
|
||||||
i = 0;
|
|
||||||
while ((!(REG_MMP_STS & CF_STS_INSERTED)) && (i < CF_CARD_TIMEOUT))
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (i >= CF_CARD_TIMEOUT)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------
|
|
||||||
_MMCF_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 _MMCF_readSectors (u32 sector, u32 numSectors, void* buffer) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
u16 *buff = (u16*)buffer;
|
|
||||||
#ifdef _CF_ALLOW_UNALIGNED
|
|
||||||
u8 *buff_u8 = (u8*)buffer;
|
|
||||||
int temp;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (defined _CF_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 ((REG_MMP_CMD & CF_STS_BUSY) && (i < CF_CARD_TIMEOUT))
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait until card is ready for commands
|
|
||||||
i = 0;
|
|
||||||
while ((!(REG_MMP_STS & CF_STS_INSERTED)) && (i < CF_CARD_TIMEOUT))
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (i >= CF_CARD_TIMEOUT)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Set number of sectors to read
|
|
||||||
REG_MMP_SEC = (numSectors < 256 ? numSectors : 0); // Read a maximum of 256 sectors, 0 means 256
|
|
||||||
|
|
||||||
// Set read sector
|
|
||||||
REG_MMP_LBA1 = sector & 0xFF; // 1st byte of sector number
|
|
||||||
REG_MMP_LBA2 = (sector >> 8) & 0xFF; // 2nd byte of sector number
|
|
||||||
REG_MMP_LBA3 = (sector >> 16) & 0xFF; // 3rd byte of sector number
|
|
||||||
REG_MMP_LBA4 = ((sector >> 24) & 0x0F )| CF_CMD_LBA; // last nibble of sector number
|
|
||||||
|
|
||||||
// Set command to read
|
|
||||||
REG_MMP_CMD = CF_CMD_READ;
|
|
||||||
|
|
||||||
|
|
||||||
while (numSectors--)
|
|
||||||
{
|
|
||||||
// Wait until card is ready for reading
|
|
||||||
i = 0;
|
|
||||||
while (((REG_MMP_STS & 0xff)!= CF_STS_READY) && (i < CF_CARD_TIMEOUT))
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (i >= CF_CARD_TIMEOUT)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Read data
|
|
||||||
#ifdef _CF_USE_DMA
|
|
||||||
#ifdef NDS
|
|
||||||
DMA3_SRC = (u32)MMP_DATA;
|
|
||||||
DMA3_DEST = (u32)buff;
|
|
||||||
DMA3_CR = 256 | DMA_COPY_HALFWORDS | DMA_SRC_FIX;
|
|
||||||
#else
|
|
||||||
DMA3COPY ( MMP_DATA, buff, 256 | DMA16 | DMA_ENABLE | DMA_SRC_FIXED);
|
|
||||||
#endif
|
|
||||||
buff += BYTES_PER_READ / 2;
|
|
||||||
#elif defined _CF_ALLOW_UNALIGNED
|
|
||||||
i=256;
|
|
||||||
if ((u32)buff_u8 & 0x01) {
|
|
||||||
while(i--)
|
|
||||||
{
|
|
||||||
temp = *MMP_DATA;
|
|
||||||
*buff_u8++ = temp & 0xFF;
|
|
||||||
*buff_u8++ = temp >> 8;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
while(i--)
|
|
||||||
*buff++ = *MMP_DATA;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
i=256;
|
|
||||||
while(i--)
|
|
||||||
*buff++ = *MMP_DATA;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#if (defined _CF_USE_DMA) && (defined NDS)
|
|
||||||
// Wait for end of transfer before returning
|
|
||||||
while(DMA3_CR & DMA_BUSY);
|
|
||||||
#endif
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------
|
|
||||||
_MMCF_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 _MMCF_writeSectors (u32 sector, u32 numSectors, void* buffer) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
u16 *buff = (u16*)buffer;
|
|
||||||
#ifdef _CF_ALLOW_UNALIGNED
|
|
||||||
u8 *buff_u8 = (u8*)buffer;
|
|
||||||
int temp;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined _CF_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 ((REG_MMP_CMD & CF_STS_BUSY) && (i < CF_CARD_TIMEOUT))
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait until card is ready for commands
|
|
||||||
i = 0;
|
|
||||||
while ((!(REG_MMP_STS & CF_STS_INSERTED)) && (i < CF_CARD_TIMEOUT))
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (i >= CF_CARD_TIMEOUT)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Set number of sectors to write
|
|
||||||
REG_MMP_SEC = (numSectors < 256 ? numSectors : 0); // Write a maximum of 256 sectors, 0 means 256
|
|
||||||
|
|
||||||
// Set write sector
|
|
||||||
REG_MMP_LBA1 = sector & 0xFF; // 1st byte of sector number
|
|
||||||
REG_MMP_LBA2 = (sector >> 8) & 0xFF; // 2nd byte of sector number
|
|
||||||
REG_MMP_LBA3 = (sector >> 16) & 0xFF; // 3rd byte of sector number
|
|
||||||
REG_MMP_LBA4 = ((sector >> 24) & 0x0F )| CF_CMD_LBA; // last nibble of sector number
|
|
||||||
|
|
||||||
// Set command to write
|
|
||||||
REG_MMP_CMD = CF_CMD_WRITE;
|
|
||||||
|
|
||||||
while (numSectors--)
|
|
||||||
{
|
|
||||||
// Wait until card is ready for writing
|
|
||||||
i = 0;
|
|
||||||
while (((REG_MMP_STS & 0xff) != CF_STS_READY) && (i < CF_CARD_TIMEOUT))
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (i >= CF_CARD_TIMEOUT)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Write data
|
|
||||||
#ifdef _CF_USE_DMA
|
|
||||||
#ifdef NDS
|
|
||||||
DMA3_SRC = (u32)buff;
|
|
||||||
DMA3_DEST = (u32)MMP_DATA;
|
|
||||||
DMA3_CR = 256 | DMA_COPY_HALFWORDS | DMA_DST_FIX;
|
|
||||||
#else
|
|
||||||
DMA3COPY( buff, MMP_DATA, 256 | DMA16 | DMA_ENABLE | DMA_DST_FIXED);
|
|
||||||
#endif
|
|
||||||
buff += BYTES_PER_READ / 2;
|
|
||||||
#elif defined _CF_ALLOW_UNALIGNED
|
|
||||||
i=256;
|
|
||||||
if ((u32)buff_u8 & 0x01) {
|
|
||||||
while(i--)
|
|
||||||
{
|
|
||||||
temp = *buff_u8++;
|
|
||||||
temp |= *buff_u8++ << 8;
|
|
||||||
*MMP_DATA = temp;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
while(i--)
|
|
||||||
*MMP_DATA = *buff++;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
i=256;
|
|
||||||
while(i--)
|
|
||||||
*MMP_DATA = *buff++;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#if defined _CF_USE_DMA && defined NDS
|
|
||||||
// Wait for end of transfer before returning
|
|
||||||
while(DMA3_CR & DMA_BUSY);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------
|
|
||||||
_MMCF_Shutdown
|
|
||||||
unload the GBAMP CF interface
|
|
||||||
-----------------------------------------------------------------*/
|
|
||||||
bool _MMCF_shutdown(void) {
|
|
||||||
return _MMCF_clearStatus() ;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------
|
/*-----------------------------------------------------------------
|
||||||
_MMCF_startUp
|
_MMCF_startUp
|
||||||
initializes the CF interface, returns true if successful,
|
initializes the CF interface, returns true if successful,
|
||||||
otherwise returns false
|
otherwise returns false
|
||||||
-----------------------------------------------------------------*/
|
-----------------------------------------------------------------*/
|
||||||
bool _MMCF_startUp(void) {
|
bool _MMCF_startup(void) {
|
||||||
// See if there is a read/write register
|
return _CF_startup (&_MMCF_Registers);
|
||||||
u16 temp = REG_MMP_LBA1;
|
|
||||||
REG_MMP_LBA1 = (~temp & 0xFF);
|
|
||||||
temp = (~temp & 0xFF);
|
|
||||||
if (!(REG_MMP_LBA1 == temp)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Make sure it is 8 bit
|
|
||||||
REG_MMP_LBA1 = 0xAA55;
|
|
||||||
if (REG_MMP_LBA1 == 0xAA55) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------
|
/*-----------------------------------------------------------------
|
||||||
@ -341,10 +92,10 @@ the actual interface structure
|
|||||||
IO_INTERFACE _io_mmcf = {
|
IO_INTERFACE _io_mmcf = {
|
||||||
DEVICE_TYPE_MMCF,
|
DEVICE_TYPE_MMCF,
|
||||||
FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_SLOT_GBA,
|
FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_SLOT_GBA,
|
||||||
(FN_MEDIUM_STARTUP)&_MMCF_startUp,
|
(FN_MEDIUM_STARTUP)&_MMCF_startup,
|
||||||
(FN_MEDIUM_ISINSERTED)&_MMCF_isInserted,
|
(FN_MEDIUM_ISINSERTED)&_CF_isInserted,
|
||||||
(FN_MEDIUM_READSECTORS)&_MMCF_readSectors,
|
(FN_MEDIUM_READSECTORS)&_CF_readSectors,
|
||||||
(FN_MEDIUM_WRITESECTORS)&_MMCF_writeSectors,
|
(FN_MEDIUM_WRITESECTORS)&_CF_writeSectors,
|
||||||
(FN_MEDIUM_CLEARSTATUS)&_MMCF_clearStatus,
|
(FN_MEDIUM_CLEARSTATUS)&_CF_clearStatus,
|
||||||
(FN_MEDIUM_SHUTDOWN)&_MMCF_shutdown
|
(FN_MEDIUM_SHUTDOWN)&_CF_shutdown
|
||||||
} ;
|
} ;
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
|
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
// DMA
|
// DMA
|
||||||
#ifdef _CF_USE_DMA
|
#ifdef _IO_USE_DMA
|
||||||
#ifndef NDS
|
#ifndef NDS
|
||||||
#include "gba_dma.h"
|
#include "gba_dma.h"
|
||||||
#else
|
#else
|
||||||
@ -51,286 +51,38 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
// CF Addresses & Commands
|
|
||||||
|
|
||||||
// GBAMP CF Addresses
|
// GBAMP CF Addresses
|
||||||
#define REG_MPCF_STS (*(vu16*)0x098C0000) // Status of the CF Card / Device control
|
#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_CMD ((vu16*)0x090E0000) // Commands sent to control chip and status return
|
||||||
#define REG_MPCF_ERR (*(vu16*)0x09020000) // Errors / Features
|
#define REG_MPCF_ERR ((vu16*)0x09020000) // Errors / Features
|
||||||
|
|
||||||
#define REG_MPCF_SEC (*(vu16*)0x09040000) // Number of sector to transfer
|
#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_LBA1 ((vu16*)0x09060000) // 1st byte of sector address
|
||||||
#define REG_MPCF_LBA2 (*(vu16*)0x09080000) // 2nd 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_LBA3 ((vu16*)0x090A0000) // 3rd byte of sector address
|
||||||
#define REG_MPCF_LBA4 (*(vu16*)0x090C0000) // last nibble of sector address | 0xE0
|
#define REG_MPCF_LBA4 ((vu16*)0x090C0000) // last nibble of sector address | 0xE0
|
||||||
|
|
||||||
#define MP_DATA ((vu16*)0x09000000) // Pointer to buffer of CF data transered from card
|
|
||||||
|
|
||||||
|
#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_isInserted
|
_MPCF_startup
|
||||||
Is a compact flash card inserted?
|
|
||||||
bool return OUT: true if a CF card is inserted
|
|
||||||
-----------------------------------------------------------------*/
|
|
||||||
bool _MPCF_isInserted (void) {
|
|
||||||
// Change register, then check if value did change
|
|
||||||
REG_MPCF_STS = CF_STS_INSERTED;
|
|
||||||
return ((REG_MPCF_STS & 0xff) == CF_STS_INSERTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------
|
|
||||||
_MPCF_clearStatus
|
|
||||||
Tries to make the CF card go back to idle mode
|
|
||||||
bool return OUT: true if a CF card is idle
|
|
||||||
-----------------------------------------------------------------*/
|
|
||||||
bool _MPCF_clearStatus (void) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
// Wait until CF card is finished previous commands
|
|
||||||
i=0;
|
|
||||||
while ((REG_MPCF_CMD & CF_STS_BUSY) && (i < CF_CARD_TIMEOUT))
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait until card is ready for commands
|
|
||||||
i = 0;
|
|
||||||
while ((!(REG_MPCF_STS & CF_STS_INSERTED)) && (i < CF_CARD_TIMEOUT))
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (i >= CF_CARD_TIMEOUT)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------
|
|
||||||
_MPCF_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 _MPCF_readSectors (u32 sector, u32 numSectors, void* buffer) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
u16 *buff = (u16*)buffer;
|
|
||||||
#ifdef _CF_ALLOW_UNALIGNED
|
|
||||||
u8 *buff_u8 = (u8*)buffer;
|
|
||||||
int temp;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (defined _CF_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 ((REG_MPCF_CMD & CF_STS_BUSY) && (i < CF_CARD_TIMEOUT)) {
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait until card is ready for commands
|
|
||||||
i = 0;
|
|
||||||
while ((!(REG_MPCF_STS & CF_STS_INSERTED)) && (i < CF_CARD_TIMEOUT)) {
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (i >= CF_CARD_TIMEOUT)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Set number of sectors to read
|
|
||||||
REG_MPCF_SEC = (numSectors < 256 ? numSectors : 0); // Read a maximum of 256 sectors, 0 means 256
|
|
||||||
|
|
||||||
// Set read sector
|
|
||||||
REG_MPCF_LBA1 = sector & 0xFF; // 1st byte of sector number
|
|
||||||
REG_MPCF_LBA2 = (sector >> 8) & 0xFF; // 2nd byte of sector number
|
|
||||||
REG_MPCF_LBA3 = (sector >> 16) & 0xFF; // 3rd byte of sector number
|
|
||||||
REG_MPCF_LBA4 = ((sector >> 24) & 0x0F )| CF_CMD_LBA; // last nibble of sector number
|
|
||||||
|
|
||||||
// Set command to read
|
|
||||||
REG_MPCF_CMD = CF_CMD_READ;
|
|
||||||
|
|
||||||
|
|
||||||
while (numSectors--)
|
|
||||||
{
|
|
||||||
// Wait until card is ready for reading
|
|
||||||
i = 0;
|
|
||||||
while (((REG_MPCF_STS & 0xff)!= CF_STS_READY) && (i < CF_CARD_TIMEOUT))
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (i >= CF_CARD_TIMEOUT)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Read data
|
|
||||||
#ifdef _CF_USE_DMA
|
|
||||||
#ifdef NDS
|
|
||||||
DMA3_SRC = (u32)MP_DATA;
|
|
||||||
DMA3_DEST = (u32)buff;
|
|
||||||
DMA3_CR = 256 | DMA_COPY_HALFWORDS | DMA_SRC_FIX;
|
|
||||||
#else
|
|
||||||
DMA3COPY ( MP_DATA, buff, 256 | DMA16 | DMA_ENABLE | DMA_SRC_FIXED);
|
|
||||||
#endif
|
|
||||||
buff += BYTES_PER_READ / 2;
|
|
||||||
#elif defined _CF_ALLOW_UNALIGNED
|
|
||||||
i=256;
|
|
||||||
if ((u32)buff_u8 & 0x01) {
|
|
||||||
while(i--)
|
|
||||||
{
|
|
||||||
temp = *MP_DATA;
|
|
||||||
*buff_u8++ = temp & 0xFF;
|
|
||||||
*buff_u8++ = temp >> 8;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
while(i--)
|
|
||||||
*buff++ = *MP_DATA;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
i=256;
|
|
||||||
while(i--)
|
|
||||||
*buff++ = *MP_DATA;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#if (defined _CF_USE_DMA) && (defined NDS)
|
|
||||||
// Wait for end of transfer before returning
|
|
||||||
while(DMA3_CR & DMA_BUSY);
|
|
||||||
#endif
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------
|
|
||||||
_MPCF_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 _MPCF_writeSectors (u32 sector, u32 numSectors, void* buffer) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
u16 *buff = (u16*)buffer;
|
|
||||||
#ifdef _CF_ALLOW_UNALIGNED
|
|
||||||
u8 *buff_u8 = (u8*)buffer;
|
|
||||||
int temp;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined _CF_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 ((REG_MPCF_CMD & CF_STS_BUSY) && (i < CF_CARD_TIMEOUT))
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait until card is ready for commands
|
|
||||||
i = 0;
|
|
||||||
while ((!(REG_MPCF_STS & CF_STS_INSERTED)) && (i < CF_CARD_TIMEOUT))
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (i >= CF_CARD_TIMEOUT)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Set number of sectors to write
|
|
||||||
REG_MPCF_SEC = (numSectors < 256 ? numSectors : 0); // Write a maximum of 256 sectors, 0 means 256
|
|
||||||
|
|
||||||
// Set write sector
|
|
||||||
REG_MPCF_LBA1 = sector & 0xFF; // 1st byte of sector number
|
|
||||||
REG_MPCF_LBA2 = (sector >> 8) & 0xFF; // 2nd byte of sector number
|
|
||||||
REG_MPCF_LBA3 = (sector >> 16) & 0xFF; // 3rd byte of sector number
|
|
||||||
REG_MPCF_LBA4 = ((sector >> 24) & 0x0F )| CF_CMD_LBA; // last nibble of sector number
|
|
||||||
|
|
||||||
// Set command to write
|
|
||||||
REG_MPCF_CMD = CF_CMD_WRITE;
|
|
||||||
|
|
||||||
while (numSectors--)
|
|
||||||
{
|
|
||||||
// Wait until card is ready for writing
|
|
||||||
i = 0;
|
|
||||||
while (((REG_MPCF_STS & 0xff) != CF_STS_READY) && (i < CF_CARD_TIMEOUT))
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (i >= CF_CARD_TIMEOUT)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Write data
|
|
||||||
#ifdef _CF_USE_DMA
|
|
||||||
#ifdef NDS
|
|
||||||
DMA3_SRC = (u32)buff;
|
|
||||||
DMA3_DEST = (u32)MP_DATA;
|
|
||||||
DMA3_CR = 256 | DMA_COPY_HALFWORDS | DMA_DST_FIX;
|
|
||||||
#else
|
|
||||||
DMA3COPY( buff, MP_DATA, 256 | DMA16 | DMA_ENABLE | DMA_DST_FIXED);
|
|
||||||
#endif
|
|
||||||
buff += BYTES_PER_READ / 2;
|
|
||||||
#elif defined _CF_ALLOW_UNALIGNED
|
|
||||||
i=256;
|
|
||||||
if ((u32)buff_u8 & 0x01) {
|
|
||||||
while(i--)
|
|
||||||
{
|
|
||||||
temp = *buff_u8++;
|
|
||||||
temp |= *buff_u8++ << 8;
|
|
||||||
*MP_DATA = temp;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
while(i--)
|
|
||||||
*MP_DATA = *buff++;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
i=256;
|
|
||||||
while(i--)
|
|
||||||
*MP_DATA = *buff++;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#if defined _CF_USE_DMA && defined NDS
|
|
||||||
// Wait for end of transfer before returning
|
|
||||||
while(DMA3_CR & DMA_BUSY);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------
|
|
||||||
_MPCF_Shutdown
|
|
||||||
unload the GBAMP CF interface
|
|
||||||
-----------------------------------------------------------------*/
|
|
||||||
bool _MPCF_shutdown(void) {
|
|
||||||
return _MPCF_clearStatus() ;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------
|
|
||||||
_MPCF_startUp
|
|
||||||
initializes the CF interface, returns true if successful,
|
initializes the CF interface, returns true if successful,
|
||||||
otherwise returns false
|
otherwise returns false
|
||||||
-----------------------------------------------------------------*/
|
-----------------------------------------------------------------*/
|
||||||
bool _MPCF_startUp(void) {
|
bool _MPCF_startup(void) {
|
||||||
// See if there is a read/write register
|
return _CF_startup(&_MPCF_Registers);
|
||||||
u16 temp = REG_MPCF_LBA1;
|
|
||||||
REG_MPCF_LBA1 = (~temp & 0xFF);
|
|
||||||
temp = (~temp & 0xFF);
|
|
||||||
if (!(REG_MPCF_LBA1 == temp)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Make sure it is 8 bit
|
|
||||||
REG_MPCF_LBA1 = 0xAA55;
|
|
||||||
if (REG_MPCF_LBA1 == 0xAA55) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------
|
/*-----------------------------------------------------------------
|
||||||
@ -339,10 +91,10 @@ the actual interface structure
|
|||||||
IO_INTERFACE _io_mpcf = {
|
IO_INTERFACE _io_mpcf = {
|
||||||
DEVICE_TYPE_MPCF,
|
DEVICE_TYPE_MPCF,
|
||||||
FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_SLOT_GBA,
|
FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_SLOT_GBA,
|
||||||
(FN_MEDIUM_STARTUP)&_MPCF_startUp,
|
(FN_MEDIUM_STARTUP)&_MPCF_startup,
|
||||||
(FN_MEDIUM_ISINSERTED)&_MPCF_isInserted,
|
(FN_MEDIUM_ISINSERTED)&_CF_isInserted,
|
||||||
(FN_MEDIUM_READSECTORS)&_MPCF_readSectors,
|
(FN_MEDIUM_READSECTORS)&_CF_readSectors,
|
||||||
(FN_MEDIUM_WRITESECTORS)&_MPCF_writeSectors,
|
(FN_MEDIUM_WRITESECTORS)&_CF_writeSectors,
|
||||||
(FN_MEDIUM_CLEARSTATUS)&_MPCF_clearStatus,
|
(FN_MEDIUM_CLEARSTATUS)&_CF_clearStatus,
|
||||||
(FN_MEDIUM_SHUTDOWN)&_MPCF_shutdown
|
(FN_MEDIUM_SHUTDOWN)&_CF_shutdown
|
||||||
} ;
|
} ;
|
||||||
|
@ -36,52 +36,48 @@
|
|||||||
|
|
||||||
#include "io_sccf.h"
|
#include "io_sccf.h"
|
||||||
#include "io_sc_common.h"
|
#include "io_sc_common.h"
|
||||||
|
#include "io_cf_common.h"
|
||||||
|
|
||||||
/*-----------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
Since all CF addresses and commands are the same for the GBAMP,
|
// SC CF Addresses
|
||||||
simply use it's functions instead.
|
#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
|
||||||
|
|
||||||
extern bool _MPCF_isInserted (void);
|
#define REG_SCCF_SEC ((vu16*)0x09040000) // Number of sector to transfer
|
||||||
extern bool _MPCF_clearStatus (void);
|
#define REG_SCCF_LBA1 ((vu16*)0x09060000) // 1st byte of sector address
|
||||||
extern bool _MPCF_readSectors (u32 sector, u32 numSectors, void* buffer);
|
#define REG_SCCF_LBA2 ((vu16*)0x09080000) // 2nd byte of sector address
|
||||||
extern bool _MPCF_writeSectors (u32 sector, u32 numSectors, void* buffer);
|
#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) {
|
||||||
_SCCF_unlock
|
|
||||||
Returns true if SuperCard was unlocked, false if failed
|
|
||||||
Added by MightyMax
|
|
||||||
Modified by Chishm
|
|
||||||
-----------------------------------------------------------------*/
|
|
||||||
bool _SCCF_unlock(void) {
|
|
||||||
#define CF_REG_LBA1 (*(vu16*)0x09060000)
|
|
||||||
unsigned char temp;
|
|
||||||
_SC_changeMode (SC_MODE_MEDIA);
|
_SC_changeMode (SC_MODE_MEDIA);
|
||||||
// provoke a ready reply
|
return _CF_startup(&_SCCF_Registers);
|
||||||
temp = CF_REG_LBA1;
|
}
|
||||||
CF_REG_LBA1 = (~temp & 0xFF);
|
|
||||||
temp = (~temp & 0xFF);
|
|
||||||
return (CF_REG_LBA1 == temp);
|
|
||||||
#undef CF_REG_LBA1
|
|
||||||
}
|
|
||||||
|
|
||||||
bool _SCCF_shutdown(void) {
|
|
||||||
return _MPCF_clearStatus() ;
|
|
||||||
} ;
|
|
||||||
|
|
||||||
bool _SCCF_startUp(void) {
|
|
||||||
return _SCCF_unlock() ;
|
|
||||||
} ;
|
|
||||||
|
|
||||||
|
|
||||||
IO_INTERFACE _io_sccf = {
|
IO_INTERFACE _io_sccf = {
|
||||||
DEVICE_TYPE_SCCF,
|
DEVICE_TYPE_SCCF,
|
||||||
FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_SLOT_GBA,
|
FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_SLOT_GBA,
|
||||||
(FN_MEDIUM_STARTUP)&_SCCF_startUp,
|
(FN_MEDIUM_STARTUP)&_SCCF_startup,
|
||||||
(FN_MEDIUM_ISINSERTED)&_MPCF_isInserted,
|
(FN_MEDIUM_ISINSERTED)&_CF_isInserted,
|
||||||
(FN_MEDIUM_READSECTORS)&_MPCF_readSectors,
|
(FN_MEDIUM_READSECTORS)&_CF_readSectors,
|
||||||
(FN_MEDIUM_WRITESECTORS)&_MPCF_writeSectors,
|
(FN_MEDIUM_WRITESECTORS)&_CF_writeSectors,
|
||||||
(FN_MEDIUM_CLEARSTATUS)&_MPCF_clearStatus,
|
(FN_MEDIUM_CLEARSTATUS)&_CF_clearStatus,
|
||||||
(FN_MEDIUM_SHUTDOWN)&_SCCF_shutdown
|
(FN_MEDIUM_SHUTDOWN)&_CF_shutdown
|
||||||
} ;
|
} ;
|
||||||
|
Loading…
Reference in New Issue
Block a user