1
0
mirror of https://github.com/mist-devel/mist-firmware.git synced 2026-04-29 13:33:04 +00:00

Implement MMC_WriteMultiple, use it in IDE and ACSI

This commit is contained in:
Gyorgy Szombathelyi
2021-08-30 17:28:28 +02:00
parent a690edcfcc
commit a8eef6235f
5 changed files with 141 additions and 70 deletions

View File

@@ -149,15 +149,14 @@ DRESULT disk_write (
switch (pdrv) {
case DEV_MMC :
// translate the arguments here
while (count) {
result = MMC_Write(sector++, buff);
if (!result) return RES_ERROR;
count--;
buff += 512;
}
// translate the reslut code here
if (count == 1)
result = MMC_Write(sector, buff);
else
result = MMC_WriteMultiple(sector, buff, count);
return RES_OK;
// translate the reslut code here
res = result ? RES_OK : RES_ERROR;
return res;
/*
case DEV_USB :
// translate the arguments here

67
hdd.c
View File

@@ -481,7 +481,8 @@ static inline void ATA_ReadSectors(unsigned char* tfr, unsigned short sector, un
static inline void ATA_WriteSectors(unsigned char* tfr, unsigned short sector, unsigned short cylinder, unsigned char head, unsigned char unit, unsigned short sector_count, char multiple, char lbamode)
{
unsigned short i;
unsigned short block_count;
unsigned short block_count, block_size, sectors;
unsigned char *buf;
long lba=chs2lba(cylinder, head, sector, unit, lbamode);
// write sectors
@@ -498,52 +499,64 @@ static inline void ATA_WriteSectors(unsigned char* tfr, unsigned short sector, u
if (multiple && block_count > hdf[unit].sectors_per_block)
block_count = hdf[unit].sectors_per_block;
while(block_count--)
{
while (!(GetFPGAStatus() & CMD_IDEDAT)); // wait for full write buffer
EnableFpga();
SPI(CMD_IDE_DATA_RD); // read data command
SPI(0x00);
SPI(0x00);
SPI(0x00);
SPI(0x00);
SPI(0x00);
spi_block_read(sector_buffer);
DisableFpga();
UINT bw;
while(block_count)
{
block_size = (block_count > SECTOR_BUFFER_SIZE/512) ? (SECTOR_BUFFER_SIZE/512) : block_count;
sectors = block_size;
buf = sector_buffer;
while(sectors--) {
while (!(GetFPGAStatus() & CMD_IDEDAT)); // wait for full write buffer
EnableFpga();
SPI(CMD_IDE_DATA_RD); // read data command
SPI(0x00);
SPI(0x00);
SPI(0x00);
SPI(0x00);
SPI(0x00);
spi_block_read(buf);
DisableFpga();
buf += 512;
}
switch(hdf[unit].type) {
case HDF_FILE | HDF_SYNTHRDB:
case HDF_FILE:
if (f_size(&hdf[unit].idxfile->file) && (lba>-1)) {
// Don't attempt to write to fake RDB
FileWriteBlock(&hdf[unit].idxfile->file, sector_buffer);
f_write(&hdf[unit].idxfile->file, sector_buffer, 512*block_size, &bw);
}
lba++;
lba+=block_size;
break;
case HDF_CARD:
case HDF_CARDPART0:
case HDF_CARDPART1:
case HDF_CARDPART2:
case HDF_CARDPART3:
MMC_Write(lba,sector_buffer);
lba++;
MMC_WriteMultiple(lba, sector_buffer, block_size);
lba+=block_size;
break;
}
// decrease sector count
if (sector_count!=1) {
if (sector == hdf[unit].sectors) {
sector = 1;
head++;
if (head == hdf[unit].heads) {
head = 0;
cylinder++;
sectors = block_size;
while(sectors--) {
if (sector_count!=1) {
if (sector == hdf[unit].sectors) {
sector = 1;
head++;
if (head == hdf[unit].heads) {
head = 0;
cylinder++;
}
} else {
sector++;
}
} else {
sector++;
}
sector_count--; // decrease sector count
}
sector_count--; // decrease sector count
block_count-=block_size;
}
if (hdf[unit].type & HDF_FILE)

View File

@@ -396,29 +396,8 @@ unsigned char MMC_ReadMultiple(unsigned long lba, unsigned char *pReadBuffer, un
return(1);
}
// write 512-byte block
unsigned char MMC_Write(unsigned long lba, const unsigned char *pWriteBuffer)
static char MMC_SendDataBlock(const unsigned char *pWriteBuffer)
{
unsigned long i;
// check of card has been removed and try to re-initialize it
if(!check_card()) return 0;
if (CardType != CARDTYPE_SDHC) // SDHC cards are addressed in sectors not bytes
lba = lba << 9; // otherwise convert sector adddress to byte address
EnableCard();
if (MMC_Command(CMD24, lba))
{
iprintf("CMD24 (WRITE_BLOCK): invalid response 0x%02X (lba=%lu)\r", response, lba);
DisableCard();
return(0);
}
SPI(0xFF); // one byte gap
SPI(0xFE); // send Data Token
// send sector bytes
spi_block_write(pWriteBuffer);
spi_wait4xfer_end();
@@ -435,32 +414,94 @@ unsigned char MMC_Write(unsigned long lba, const unsigned char *pWriteBuffer)
response &= 0x1F;
if (response != 0x05)
{
iprintf("CMD24 (WRITE_BLOCK): invalid status 0x%02X (lba=%lu)\r", response, lba);
iprintf("MMC: SendDataBlock: invalid status 0x%02X\r", response);
return(0);
}
timeout = 0;
while (SPI(0xFF) != 0xFF) // wait until the card is not busy
{
if (timeout++ >= 1000000)
{
iprintf("MMC: SendDataBlock: busy wait timeout!\r");
return(0);
}
}
}
// write 512-byte block
unsigned char MMC_Write(unsigned long lba, const unsigned char *pWriteBuffer)
{
// check of card has been removed and try to re-initialize it
if(!check_card()) return 0;
if (CardType != CARDTYPE_SDHC) // SDHC cards are addressed in sectors not bytes
lba = lba << 9; // otherwise convert sector address to byte address
EnableCard();
if (MMC_Command(CMD24, lba))
{
iprintf("CMD24 (WRITE_BLOCK): invalid response 0x%02X (lba=%lu)\r", response, lba);
DisableCard();
return(0);
}
// TODO: Move this to the beginning of MMC_Command to interleave Core and SD card better
SPI(0xFF); // one byte gap
SPI(0xFE); // send Data Token
if(!MMC_SendDataBlock(pWriteBuffer)) {
DisableCard();
return(0);
}
DisableCard();
return(1);
}
// write 512-byte block
unsigned char MMC_WriteMultiple(unsigned long lba, const unsigned char *pWriteBuffer, unsigned long nBlockCount)
{
//iprintf("MMC_WriteMultiple (lba=%d, count=%d)\n", lba, nBlockCount);
// check of card has been removed and try to re-initialize it
if(!check_card()) return 0;
if (CardType != CARDTYPE_SDHC) // SDHC cards are addressed in sectors not bytes
lba = lba << 9; // otherwise convert sector address to byte address
EnableCard();
if (MMC_Command(CMD25, lba))
{
iprintf("CMD25 (WRITE_MULTIPLE_BLOCK): invalid response 0x%02X (lba=%lu)\r", response, lba);
DisableCard();
return(0);
}
do {
SPI(0xFC); // send Data Token
if(!MMC_SendDataBlock(pWriteBuffer)) {
DisableCard();
return(0);
}
pWriteBuffer += 512;
} while (--nBlockCount);
SPI(0xFD); // stop Token
timeout = 0;
while (spi_in() == 0x00) // wait until the card is not busy
while (SPI(0xFF) != 0xFF) // wait until the card is not busy
{
if (timeout++ >= 1000000)
{
iprintf("CMD24 (WRITE_BLOCK): busy wait timeout! (lba=%lu)\r", lba);
iprintf("CMD25 (WRITE_MULTIPLE_BLOCK): busy wait timeout! (lba=%lu)\r", lba);
DisableCard();
return(0);
}
}
// real life values here are ~500 until card becomes not busy again
// iprintf("W:%d\n", timeout);
DisableCard();
return(1);
}
// MMC command
static RAMFUNC unsigned char MMC_Command(unsigned char cmd, unsigned long arg)
{

View File

@@ -79,6 +79,7 @@ unsigned char MMC_Init(void);
unsigned char MMC_Read(unsigned long lba, unsigned char *pReadBuffer) RAMFUNC;
unsigned char MMC_Write(unsigned long lba, const unsigned char *pWriteBuffer);
unsigned char MMC_ReadMultiple(unsigned long lba, unsigned char *pReadBuffer, unsigned long nBlockCount);
unsigned char MMC_WriteMultiple(unsigned long lba, const unsigned char *pWriteBuffer, unsigned long nBlockCount);
unsigned char MMC_GetCSD(unsigned char *);
unsigned char MMC_GetCID(unsigned char *);
unsigned long MMC_GetCapacity(); // Returns the capacity in 512 byte blocks

27
tos.c
View File

@@ -239,6 +239,7 @@ static void dma_nak(void) {
}
static void handle_acsi(unsigned char *buffer) {
static unsigned char asc[2] = { 0,0 };
unsigned char target = buffer[10] >> 5;
unsigned char device = buffer[1] >> 5;
@@ -246,6 +247,11 @@ static void handle_acsi(unsigned char *buffer) {
unsigned long lba = 256 * 256 * (buffer[1] & 0x1f) +
256 * buffer[2] + buffer[3];
unsigned short length = buffer[4];
unsigned short blocklen;
unsigned char *buf;
unsigned short blocks;
if(length == 0) length = 256;
if(user_io_dip_switch1()) {
@@ -389,17 +395,28 @@ static void handle_acsi(unsigned char *buffer) {
if(lba+length <= blocks) {
DISKLED_ON;
while(length) {
mist_memory_read_block(sector_buffer);
UINT bw;
blocklen = (length > SECTOR_BUFFER_SIZE/512) ? SECTOR_BUFFER_SIZE/512 : length;
buf = sector_buffer;
blocks = blocklen;
while (blocks--) {
mist_memory_read_block(buf);
buf+=512;
}
if(hdd_direct && target == 0) {
if(user_io_dip_switch1())
tos_debugf("ACSI: direct write %ld", lba);
MMC_Write(lba++, sector_buffer);
if (blocklen == 1)
MMC_Write(lba++, sector_buffer);
else
MMC_WriteMultiple(lba++, sector_buffer, blocklen);
} else {
IDXSeek(&sd_image[target+2], lba);
FileWriteBlock(&sd_image[target+2].file, sector_buffer);
lba++;
f_write(&sd_image[target+2].file, sector_buffer, blocklen*512, &bw);
}
length--;
lba+=blocklen;
length-=blocklen;
}
DISKLED_OFF;
dma_ack(0x00);