diff --git a/mmc.c b/mmc.c index db7f0b1..f98a16e 100644 --- a/mmc.c +++ b/mmc.c @@ -26,6 +26,13 @@ along with this program. If not, see . // 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.��.�.@.� +//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 diff --git a/mmc.h b/mmc.h index f887e15..904ef0e 100644 --- a/mmc.h +++ b/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(); diff --git a/usb/hid.c b/usb/hid.c index 00b0d90..676155d 100644 --- a/usb/hid.c +++ b/usb/hid.c @@ -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] & diff --git a/user_io.c b/user_io.c index c21d4ad..e43892c 100644 --- a/user_io.c +++ b/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; } } diff --git a/user_io.h b/user_io.h index cfbcf6d..2e6a3e8 100644 --- a/user_io.h +++ b/user_io.h @@ -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)