mirror of
https://github.com/mist-devel/mist-firmware.git
synced 2026-01-13 15:17:43 +00:00
SD card emulation finished
This commit is contained in:
parent
e5d0c6284e
commit
e7bfaf6eea
140
mmc.c
140
mmc.c
@ -26,6 +26,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// FIXME - get capacity from SD card
|
||||
|
||||
//1GB:
|
||||
//CSD:
|
||||
//0000: 00 7f 00 32 5b 59 83 bc f6 db ff 9f 96 40 00 93 ...2[Y.<2E><>.<2E>.@.<2E>
|
||||
//CID:
|
||||
//0000: 3e 00 00 34 38 32 44 00 00 73 2f 6f 93 00 c7 cd >..482D..s/o<>...
|
||||
|
||||
|
||||
#include "stdio.h"
|
||||
#include "string.h"
|
||||
#include "hardware.h"
|
||||
@ -39,8 +46,6 @@ static unsigned long timeout;
|
||||
static unsigned char response;
|
||||
static unsigned char CardType;
|
||||
|
||||
static unsigned char CSDData[16];
|
||||
|
||||
// internal functions
|
||||
static void MMC_CRC(unsigned char c) RAMFUNC;
|
||||
static unsigned char MMC_Command(unsigned char cmd, unsigned long arg) RAMFUNC;
|
||||
@ -114,7 +119,6 @@ unsigned char MMC_Init(void)
|
||||
{ // check CCS (Card Capacity Status) bit in the OCR
|
||||
for (n = 0; n < 4; n++)
|
||||
ocr[n] = SPI(0xFF);
|
||||
|
||||
CardType = (ocr[0] & 0x40) ? CARDTYPE_SDHC : CARDTYPE_SD; // if CCS set then the card is SDHC compatible
|
||||
}
|
||||
else
|
||||
@ -288,91 +292,75 @@ RAMFUNC unsigned char MMC_Read(unsigned long lba, unsigned char *pReadBuffer)
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
// Read CSD register
|
||||
unsigned char MMC_GetCSD()
|
||||
{
|
||||
int i;
|
||||
EnableCard();
|
||||
|
||||
if (MMC_Command(CMD9,0))
|
||||
{
|
||||
iprintf("CMD9 (GET_CSD): invalid response 0x%02X \r", response);
|
||||
DisableCard();
|
||||
return(0);
|
||||
}
|
||||
|
||||
// now we are waiting for data token, it takes around 300us
|
||||
timeout = 0;
|
||||
while ((SPI(0xFF)) != 0xFE)
|
||||
{
|
||||
if (timeout++ >= 1000000) // we can't wait forever
|
||||
{
|
||||
iprintf("CMD9 (READ_BLOCK): no data token!\r");
|
||||
DisableCard();
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
CSDData[i]=SPI(0xFF);
|
||||
|
||||
SPI(0xFF); // read CRC lo byte
|
||||
SPI(0xFF); // read CRC hi byte
|
||||
|
||||
static unsigned char MMC_GetCXD(unsigned char cmd, unsigned char *ptr) {
|
||||
int i;
|
||||
EnableCard();
|
||||
|
||||
if (MMC_Command(cmd,0)) {
|
||||
iprintf("CMD%d (GET_C%cD): invalid response 0x%02X \r",
|
||||
(cmd==CMD9)?9:10, (cmd==CMD9)?'S':'I', response);
|
||||
DisableCard();
|
||||
return(1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
// now we are waiting for data token, it takes around 300us
|
||||
timeout = 0;
|
||||
while ((SPI(0xFF)) != 0xFE) {
|
||||
if (timeout++ >= 1000000) { // we can't wait forever
|
||||
iprintf("CMD%d (GET_C%cD): no data token!\r",
|
||||
(cmd==CMD9)?9:10, (cmd==CMD9)?'S':'I');
|
||||
DisableCard();
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
ptr[i]=SPI(0xFF);
|
||||
|
||||
DisableCard();
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
// Read CSD register
|
||||
unsigned char MMC_GetCSD(unsigned char *csd) {
|
||||
return MMC_GetCXD(CMD9, csd);
|
||||
}
|
||||
|
||||
// Read CID register
|
||||
unsigned char MMC_GetCID(unsigned char *cid) {
|
||||
return MMC_GetCXD(CMD10, cid);
|
||||
}
|
||||
|
||||
// MMC get capacity
|
||||
unsigned long MMC_GetCapacity()
|
||||
{
|
||||
unsigned long result=0;
|
||||
MMC_GetCSD();
|
||||
// switch(CardType)
|
||||
// {
|
||||
// case CARDTYPE_SDHC:
|
||||
// result=(CSDData[7]&0x3f)<<26;
|
||||
// result|=CSDData[8]<<18;
|
||||
// result|=CSDData[9]<<10;
|
||||
// result+=1024;
|
||||
// return(result);
|
||||
// break;
|
||||
// default:
|
||||
// int blocksize=CSDData[5]&15; // READ_BL_LEN
|
||||
// blocksize=1<<(blocksize-9); // Now a scalar: physical block size / 512.
|
||||
// result=(CSDData[6]&3)<<10;
|
||||
// result|=CSDData[7]<<2;
|
||||
// result|=(CSDData[8]>>6)&3; // result now contains C_SIZE
|
||||
// int cmult=(CSDData[9]&3)<<1;
|
||||
// cmult|=(CSDData[10]>>7) & 1;
|
||||
// ++result;
|
||||
// result<<=cmult+2;
|
||||
// return(result);
|
||||
// break;
|
||||
// }
|
||||
if ((CSDData[0] & 0xC0)==0x40) //CSD Version 2.0 - SDHC
|
||||
{
|
||||
result=(CSDData[7]&0x3f)<<26;
|
||||
result|=CSDData[8]<<18;
|
||||
result|=CSDData[9]<<10;
|
||||
result+=1024;
|
||||
unsigned char CSDData[16];
|
||||
|
||||
MMC_GetCSD(CSDData);
|
||||
|
||||
if ((CSDData[0] & 0xC0)==0x40) //CSD Version 2.0 - SDHC
|
||||
{
|
||||
result=(CSDData[7]&0x3f)<<26;
|
||||
result|=CSDData[8]<<18;
|
||||
result|=CSDData[9]<<10;
|
||||
result+=1024;
|
||||
return(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
int blocksize=CSDData[5]&15; // READ_BL_LEN
|
||||
blocksize=1<<(blocksize-9); // Now a scalar: physical block size / 512.
|
||||
result=(CSDData[6]&3)<<10;
|
||||
result|=CSDData[7]<<2;
|
||||
result|=(CSDData[8]>>6)&3; // result now contains C_SIZE
|
||||
int cmult=(CSDData[9]&3)<<1;
|
||||
cmult|=(CSDData[10]>>7) & 1;
|
||||
++result;
|
||||
result<<=cmult+2;
|
||||
return(result);
|
||||
}
|
||||
int blocksize=CSDData[5]&15; // READ_BL_LEN
|
||||
blocksize=1<<(blocksize-9); // Now a scalar: physical block size / 512.
|
||||
result=(CSDData[6]&3)<<10;
|
||||
result|=CSDData[7]<<2;
|
||||
result|=(CSDData[8]>>6)&3; // result now contains C_SIZE
|
||||
int cmult=(CSDData[9]&3)<<1;
|
||||
cmult|=(CSDData[10]>>7) & 1;
|
||||
++result;
|
||||
result<<=cmult+2;
|
||||
return(result);
|
||||
}
|
||||
}
|
||||
|
||||
// read multiple 512-byte blocks
|
||||
|
||||
3
mmc.h
3
mmc.h
@ -78,7 +78,8 @@ unsigned char MMC_Init(void);
|
||||
unsigned char MMC_Read(unsigned long lba, unsigned char *pReadBuffer) RAMFUNC;
|
||||
unsigned char MMC_Write(unsigned long lba, unsigned char *pWriteBuffer);
|
||||
unsigned char MMC_ReadMultiple(unsigned long lba, unsigned char *pReadBuffer, unsigned long nBlockCount);
|
||||
unsigned char MMC_GetCSD();
|
||||
unsigned char MMC_GetCSD(unsigned char *);
|
||||
unsigned char MMC_GetCID(unsigned char *);
|
||||
unsigned long MMC_GetCapacity(); // Returns the capacity in 512 byte blocks
|
||||
unsigned char MMC_CheckCard(); // frequently check if card has been removed
|
||||
unsigned char MMC_IsSDHC();
|
||||
|
||||
@ -372,6 +372,8 @@ static uint8_t usb_hid_poll(usb_device_t *dev) {
|
||||
ay = buf[conf->joystick.axis_byte_offset[1]];
|
||||
if(ay < 64) jmap |= JOY_UP;
|
||||
if(ay > 192) jmap |= JOY_DOWN;
|
||||
|
||||
// iprintf("ax = %d ay = %d\n", ax, ay);
|
||||
|
||||
// ... and buttons
|
||||
if(buf[conf->joystick.button_byte_offset] &
|
||||
|
||||
109
user_io.c
109
user_io.c
@ -152,6 +152,10 @@ void user_io_detect_core_type() {
|
||||
case CORE_TYPE_8BIT: {
|
||||
puts("Identified 8BIT core");
|
||||
|
||||
// forward SD card config to core in case it uses the local
|
||||
// SD card implementation
|
||||
user_io_sd_set_config();
|
||||
|
||||
// check if core has a config string
|
||||
core_type_8bit_with_config_string = (user_io_8bit_get_string(0) != NULL);
|
||||
|
||||
@ -255,6 +259,25 @@ void user_io_eth_send_mac(uint8_t *mac) {
|
||||
DisableIO();
|
||||
}
|
||||
|
||||
// set SD card info in FPGA (CSD, CID)
|
||||
void user_io_sd_set_config(void) {
|
||||
unsigned char data[33];
|
||||
|
||||
// get CSD and CID from SD card
|
||||
MMC_GetCID(data);
|
||||
MMC_GetCSD(data+16);
|
||||
// byte 32 is a generic config byte
|
||||
data[32] = MMC_IsSDHC()?1:0;
|
||||
|
||||
// and forward it to the FPGA
|
||||
EnableIO();
|
||||
SPI(UIO_SET_SDCONF);
|
||||
SPI_write(data, sizeof(data));
|
||||
DisableIO();
|
||||
|
||||
hexdump(data, sizeof(data), 0);
|
||||
}
|
||||
|
||||
// read 8+32 bit sd card status word from FPGA
|
||||
uint8_t user_io_sd_get_status(uint32_t *lba) {
|
||||
uint32_t s;
|
||||
@ -497,15 +520,6 @@ char *user_io_8bit_get_string(char index) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
uint8_t checksum(uint8_t *buffer) {
|
||||
int i;
|
||||
uint8_t sum=0;
|
||||
for(i=0;i<512;i++)
|
||||
sum += buffer[i];
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
unsigned char user_io_8bit_set_status(unsigned char new_status, unsigned char mask) {
|
||||
static unsigned char status = 0;
|
||||
|
||||
@ -660,7 +674,7 @@ void user_io_poll() {
|
||||
}
|
||||
|
||||
if(core_type == CORE_TYPE_8BIT) {
|
||||
unsigned char c = 1, f;
|
||||
unsigned char c = 1, f, p=0;
|
||||
|
||||
// check for serial data to be sent
|
||||
|
||||
@ -670,16 +684,17 @@ void user_io_poll() {
|
||||
EnableIO();
|
||||
SPI(UIO_SERIAL_IN);
|
||||
// status byte is 1000000A with A=1 if data is available
|
||||
if((f = SPI(0)) == 0x81) {
|
||||
if((f = SPI(0xff)) == 0x81) {
|
||||
iprintf("\033[1;36m");
|
||||
|
||||
// character 0xff is returned if FPGA isn't configured
|
||||
while((f == 0x81) && (c!= 0xff) && (c != 0x00)) {
|
||||
c = SPI(0);
|
||||
if(c != 0xff && c != 0x00) {
|
||||
while((f == 0x81) && (c!= 0xff) && (c != 0x00) && (p < 32)) {
|
||||
c = SPI(0xff);
|
||||
if(c != 0xff && c != 0x00)
|
||||
iprintf("%c", c);
|
||||
f = SPI(0);
|
||||
}
|
||||
|
||||
f = SPI(0xff);
|
||||
p++;
|
||||
}
|
||||
iprintf("\033[0m");
|
||||
}
|
||||
@ -689,16 +704,27 @@ void user_io_poll() {
|
||||
{
|
||||
static char buffer[512];
|
||||
static uint32_t buffer_lba = 0xffffffff;
|
||||
static uint8_t buffer_chk;
|
||||
uint32_t lba;
|
||||
uint8_t c = user_io_sd_get_status(&lba);
|
||||
|
||||
// valid sd commands start with "5x" to avoid problems with
|
||||
// cores that don't implement this command
|
||||
if((c & 0xf0) == 0x50) {
|
||||
|
||||
// debug: If the io controller reports and non-sdhc card, then
|
||||
// the core should never set the sdhc flag
|
||||
if((c & 3) && !MMC_IsSDHC() && (c & 0x04))
|
||||
iprintf("WARNING: SDHC access to non-sdhc card\n");
|
||||
|
||||
// check if core requests configuration
|
||||
if(c & 0x08) {
|
||||
iprintf("core requests SD config\n");
|
||||
user_io_sd_set_config();
|
||||
}
|
||||
|
||||
// check if system is trying to access a sdhc card from
|
||||
// a sd/mmc setup
|
||||
|
||||
|
||||
// check if an SDHC card is inserted
|
||||
if(MMC_IsSDHC()) {
|
||||
static char using_sdhc = 1;
|
||||
@ -719,55 +745,54 @@ void user_io_poll() {
|
||||
using_sdhc = 1;
|
||||
}
|
||||
|
||||
if((c & 0x03) == 0x01) {
|
||||
// iprintf("%s sector read %ld\n", (c&0x04)?"SDHC":"SD", lba);
|
||||
if((c & 0x03) == 0x02) {
|
||||
// only write if the inserted card is not sdhc or
|
||||
// if the core uses sdhc
|
||||
if((!MMC_IsSDHC()) || (c & 0x04)) {
|
||||
uint8_t wr_buf[512];
|
||||
|
||||
// Fetch sector data from FPGA ...
|
||||
EnableIO();
|
||||
SPI(UIO_SECTOR_WR);
|
||||
SPI_block_read(wr_buf);
|
||||
DisableIO();
|
||||
|
||||
// ... and write it to disk
|
||||
DISKLED_ON;
|
||||
MMC_Write(lba, wr_buf);
|
||||
DISKLED_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
if((c & 0x03) == 0x01) {
|
||||
// sector read
|
||||
// read sector from sd card if it is not already present in
|
||||
// the buffer
|
||||
if(buffer_lba != lba) {
|
||||
DISKLED_ON;
|
||||
if(MMC_Read(lba, buffer)) {
|
||||
if(MMC_Read(lba, buffer))
|
||||
buffer_lba = lba;
|
||||
buffer_chk = checksum(buffer);
|
||||
}
|
||||
|
||||
DISKLED_OFF;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// verify by re-read
|
||||
{ char buf2[512];
|
||||
if(MMC_Read(lba, buf2)) {
|
||||
if(memcmp(buffer, buf2, 512) != 0)
|
||||
iprintf("verify error lba %d\n", lba);
|
||||
} else
|
||||
iprintf("read error lba %d\n", lba);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(buffer_lba == lba) {
|
||||
// data is now stored in buffer. send it to fpga
|
||||
EnableIO();
|
||||
SPI(UIO_SECTOR_RD);
|
||||
SPI_block_write(buffer);
|
||||
SPI(buffer_chk);
|
||||
DisableIO();
|
||||
|
||||
// the end of this transfer acknowledges the FPGA internal
|
||||
// sd card emulation
|
||||
|
||||
// read status byte incl the checksum verification bit
|
||||
c = user_io_sd_get_status(NULL);
|
||||
if(!(c & 0x08)) iprintf("checksum failure in lbs %d\n", lba);
|
||||
}
|
||||
|
||||
// just load the next sector now, so it may be prefetched
|
||||
// for the next request already
|
||||
DISKLED_ON;
|
||||
if(MMC_Read(lba+1, buffer)) {
|
||||
if(MMC_Read(lba+1, buffer))
|
||||
buffer_lba = lba+1;
|
||||
buffer_chk = checksum(buffer);
|
||||
}
|
||||
|
||||
DISKLED_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,7 +44,8 @@
|
||||
#define UIO_GET_SDSTAT 0x16 // read status of sd card emulation
|
||||
#define UIO_SECTOR_RD 0x17 // SD card sector read
|
||||
#define UIO_SECTOR_WR 0x18 // SD card sector write
|
||||
#define UIO_ASTICK 0x19
|
||||
#define UIO_SET_SDCONF 0x19 // send SD card configuration (CSD, CID)
|
||||
#define UIO_ASTICK 0x1a
|
||||
|
||||
// codes as used by 8bit (atari 800, zx81) via SS2
|
||||
#define UIO_GET_STATUS 0x50
|
||||
@ -90,6 +91,7 @@ void user_io_serial_tx(char *, uint16_t);
|
||||
char *user_io_8bit_get_string(char);
|
||||
unsigned char user_io_8bit_set_status(unsigned char, unsigned char);
|
||||
void user_io_file_tx(fileTYPE *);
|
||||
void user_io_sd_set_config(void);
|
||||
|
||||
// io controllers interface for FPGA ethernet emulation using usb ethernet
|
||||
// devices attached to the io controller (ethernec emulation)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user