diff --git a/lib/SdFat_NoArduino/src/ExFatLib/ExFatPartition.cpp b/lib/SdFat_NoArduino/src/ExFatLib/ExFatPartition.cpp index dbb00327..4a96b7a5 100644 --- a/lib/SdFat_NoArduino/src/ExFatLib/ExFatPartition.cpp +++ b/lib/SdFat_NoArduino/src/ExFatLib/ExFatPartition.cpp @@ -285,7 +285,7 @@ bool ExFatPartition::init(FsBlockDevice* dev, uint8_t part) { if (part >= 1) { mbr = reinterpret_cast(cache); mp = &mbr->part[part - 1]; - if ((mp->boot != 0 && mp->boot != 0X80) || mp->type == 0) { + if (mp->type == 0) { DBG_FAIL_MACRO; goto fail; } diff --git a/lib/SdFat_NoArduino/src/FatLib/FatPartition.cpp b/lib/SdFat_NoArduino/src/FatLib/FatPartition.cpp index feb2f38d..5862980d 100644 --- a/lib/SdFat_NoArduino/src/FatLib/FatPartition.cpp +++ b/lib/SdFat_NoArduino/src/FatLib/FatPartition.cpp @@ -416,7 +416,7 @@ bool FatPartition::init(FsBlockDevice* dev, uint8_t part) { (dataCachePrepare(0, FsCache::CACHE_FOR_READ)); MbrPart_t* mp = mbr->part + part - 1; - if (!mbr || mp->type == 0 || (mp->boot != 0 && mp->boot != 0X80)) { + if (!mbr || mp->type == 0) { DBG_FAIL_MACRO; goto fail; } diff --git a/lib/ZuluSCSI_platform_GD32F205/gd32_sdio_sdcard.c b/lib/ZuluSCSI_platform_GD32F205/gd32_sdio_sdcard.c index bf6725ad..41ee2b50 100644 --- a/lib/ZuluSCSI_platform_GD32F205/gd32_sdio_sdcard.c +++ b/lib/ZuluSCSI_platform_GD32F205/gd32_sdio_sdcard.c @@ -305,50 +305,46 @@ sd_error_enum sd_power_on(void) sdcardtype = SD_HIGH_CAPACITY; } - /* send CMD55(APP_CMD) to indicate next command is application specific command */ - sdio_csm_disable(); - sdio_command_response_config(SD_CMD_APP_CMD, (uint32_t)0x0, SDIO_RESPONSETYPE_SHORT); - sdio_wait_type_set(SDIO_WAITTYPE_NO); - sdio_csm_enable(); - - if(SD_OK == r1_error_check(SD_CMD_APP_CMD)) { - /* SD memory card */ - while((!busyflag) && (count < SD_MAX_VOLT_VALIDATION)) { - /* send CMD55(APP_CMD) to indicate next command is application specific command */ - sdio_csm_disable(); - sdio_command_response_config(SD_CMD_APP_CMD, (uint32_t)0x0, SDIO_RESPONSETYPE_SHORT); - sdio_wait_type_set(SDIO_WAITTYPE_NO); - sdio_csm_enable(); - /* check if some error occurs */ - status = r1_error_check(SD_CMD_APP_CMD); - if(SD_OK != status) { - return status; - } + while((!busyflag) && (count < SD_MAX_VOLT_VALIDATION)) { + /* send CMD55(APP_CMD) to indicate next command is application specific command */ + sdio_csm_disable(); + sdio_command_response_config(SD_CMD_APP_CMD, (uint32_t)0x0, SDIO_RESPONSETYPE_SHORT); + sdio_wait_type_set(SDIO_WAITTYPE_NO); + sdio_csm_enable(); - /* send ACMD41(SD_SEND_OP_COND) to get host capacity support information (HCS) and OCR content */ - sdio_csm_disable(); - sdio_command_response_config(SD_APPCMD_SD_SEND_OP_COND, (SD_VOLTAGE_WINDOW | sdcardtype), SDIO_RESPONSETYPE_SHORT); - sdio_wait_type_set(SDIO_WAITTYPE_NO); - sdio_csm_enable(); - /* check if some error occurs */ - status = r3_error_check(); - if(SD_OK != status) { - return status; - } - /* get the response and check card power up status bit(busy) */ - response = sdio_response_get(SDIO_RESPONSE0); - busyflag = (uint8_t)((response >> 31) & (uint32_t)0x01); - ++count; - } - if(count >= SD_MAX_VOLT_VALIDATION) { - status = SD_VOLTRANGE_INVALID; + + /* check if some error occurs */ + /* ignoring return value, SD_ILLEGAL_COMMAND, for v1.x spec SD cards */ + status = r1_error_check(SD_CMD_APP_CMD); + if(SD_OK != status && SD_ILLEGAL_COMMAND != status) { return status; } - if(response &= SD_HIGH_CAPACITY) { - /* SDHC card */ - cardtype = SDIO_HIGH_CAPACITY_SD_CARD; + + /* send ACMD41(SD_SEND_OP_COND) to get host capacity support information (HCS) and OCR content */ + sdio_csm_disable(); + sdio_command_response_config(SD_APPCMD_SD_SEND_OP_COND, (SD_VOLTAGE_WINDOW | sdcardtype), SDIO_RESPONSETYPE_SHORT); + sdio_wait_type_set(SDIO_WAITTYPE_NO); + sdio_csm_enable(); + /* check if some error occurs */ + + status = r3_error_check(); + if(SD_OK != status) { + return status; } + /* get the response and check card power up status bit(busy) */ + response = sdio_response_get(SDIO_RESPONSE0); + busyflag = (uint8_t)((response >> 31) & (uint32_t)0x01); + ++count; } + if(count >= SD_MAX_VOLT_VALIDATION) { + status = SD_VOLTRANGE_INVALID; + return status; + } + if(response &= SD_HIGH_CAPACITY) { + /* SDHC card */ + cardtype = SDIO_HIGH_CAPACITY_SD_CARD; + } + return status; } diff --git a/lib/ZuluSCSI_platform_GD32F205/sd_card_sdio.cpp b/lib/ZuluSCSI_platform_GD32F205/sd_card_sdio.cpp index 760f2532..df8022e5 100644 --- a/lib/ZuluSCSI_platform_GD32F205/sd_card_sdio.cpp +++ b/lib/ZuluSCSI_platform_GD32F205/sd_card_sdio.cpp @@ -17,6 +17,7 @@ static uint32_t g_sdio_card_status; static uint32_t g_sdio_clk_kHz; static sdio_card_type_enum g_sdio_card_type; static uint16_t g_sdio_card_rca; +static uint32_t g_sdio_sector_count; #define checkReturnOk(call) ((g_sdio_error = (call)) == SD_OK ? true : logSDError(__LINE__)) static bool logSDError(int line) @@ -44,7 +45,8 @@ bool SdioCard::begin(SdioConfig sdioConfig) && checkReturnOk(sd_card_select_deselect(g_sdio_card_rca)) && checkReturnOk(sd_cardstatus_get(&g_sdio_card_status)) && checkReturnOk(sd_bus_mode_config(SDIO_BUSMODE_4BIT)) - && checkReturnOk(sd_transfer_mode_config(sdioConfig.useDma() ? SD_DMA_MODE : SD_POLLING_MODE)); + && checkReturnOk(sd_transfer_mode_config(sdioConfig.useDma() ? SD_DMA_MODE : SD_POLLING_MODE)) + && (g_sdio_sector_count = sectorCount()); } uint8_t SdioCard::errorCode() const @@ -262,6 +264,20 @@ bool SdioCard::readSector(uint32_t sector, uint8_t* dst) bool SdioCard::readSectors(uint32_t sector, uint8_t* dst, size_t n) { + if (sector + n >= g_sdio_sector_count) + { + // sd_multiblocks_read() seems to have trouble reading the very last sector + for (int i = 0; i < n; i++) + { + if (!readSector(sector + i, dst + i * 512)) + { + azlog("End of drive read failed at ", sector, " + ", i); + return false; + } + } + return true; + } + return checkReturnOk(sd_multiblocks_read((uint32_t*)dst, (uint64_t)sector * 512, 512, n, get_stream_callback(dst, n * 512))); } diff --git a/src/ZuluSCSI.cpp b/src/ZuluSCSI.cpp index 1a4113f3..9946eb3a 100644 --- a/src/ZuluSCSI.cpp +++ b/src/ZuluSCSI.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include "ZuluSCSI_config.h" #include "ZuluSCSI_platform.h" @@ -212,6 +213,35 @@ bool findHDDImages() if (is_hd || is_cd) { + // Check file extension + // We accept anything except known compressed files + bool is_compressed = false; + const char *extension = strrchr(name, '.'); + if (extension) + { + const char *archive_exts[] = { + ".tar", ".tgz", ".gz", ".bz2", ".tbz2", ".xz", ".zst", ".z", + ".zip", ".zipx", ".rar", ".lzh", ".7z", ".s7z", ".arj", + ".dmg", + NULL + }; + + for (int i = 0; archive_exts[i]; i++) + { + if (strcasecmp(extension, archive_exts[i]) == 0) + { + is_compressed = true; + break; + } + } + } + + if (is_compressed) + { + azlog("-- Ignoring compressed file ", name); + continue; + } + // Defaults for Hard Disks int id = 1; // 0 and 3 are common in Macs for physical HD and CD, so avoid them. int lun = 0; @@ -223,8 +253,7 @@ bool findHDDImages() blk = 2048; } - // Positionally read in and coerase the chars to integers. - // We only require the minimum and read in the next if provided. + // Parse SCSI device ID int file_name_length = strlen(name); if(file_name_length > 2) { // HD[N] int tmp_id = name[HDIMG_ID_POS] - '0'; @@ -238,38 +267,35 @@ bool findHDDImages() id = usedDefaultId++; } } + + // Parse SCSI LUN number if(file_name_length > 3) { // HD0[N] int tmp_lun = name[HDIMG_LUN_POS] - '0'; - if(tmp_lun > -1 && tmp_lun < 2) { + if(tmp_lun > -1 && tmp_lun < NUM_SCSILUN) { lun = tmp_lun; // If valid id, set it, else use default } } - int blk1 = 0, blk2 = 0, blk3 = 0, blk4 = 0; - if(file_name_length > 8) { // HD00_[111] - blk1 = name[HDIMG_BLK_POS] - '0'; - blk2 = name[HDIMG_BLK_POS+1] - '0'; - blk3 = name[HDIMG_BLK_POS+2] - '0'; - if(file_name_length > 9) // HD00_NNN[1] - blk4 = name[HDIMG_BLK_POS+3] - '0'; - } - if(blk1 == 2 && blk2 == 5 && blk3 == 6) { - blk = 256; - } else if(blk1 == 1 && blk2 == 0 && blk3 == 2 && blk4 == 4) { - blk = 1024; - } else if(blk1 == 2 && blk2 == 0 && blk3 == 4 && blk4 == 8) { - blk = 2048; - } else if(blk1 == 4 && blk2 == 0 && blk3 == 9 && blk4 == 6) { - blk = 4096; - } else if(blk1 == 8 && blk2 == 1 && blk3 == 9 && blk4 == 2) { - blk = 8192; + + // Parse block size (HD00_NNNN) + const char *blksize = strchr(name, '_'); + if (blksize) + { + int blktmp = strtoul(blksize + 1, NULL, 10); + if (blktmp == 256 || blktmp == 512 || blktmp == 1024 || + blktmp == 2048 || blktmp == 4096 || blktmp == 8192) + { + blk = blktmp; + } } + // Add the directory name to get the full file path char fullname[MAX_FILE_PATH * 2 + 2] = {0}; strncpy(fullname, imgdir, MAX_FILE_PATH); if (fullname[strlen(fullname) - 1] != '/') strcat(fullname, "/"); strcat(fullname, name); + // Check whether this SCSI ID has been configured yet const S2S_TargetCfg* cfg = s2s_getConfigByIndex(id); if (cfg && (cfg->scsiId & S2S_CFG_TARGET_ENABLED)) { @@ -277,6 +303,7 @@ bool findHDDImages() continue; } + // Open the image file if(id < NUM_SCSIID && lun < NUM_SCSILUN) { azlog("-- Opening ", fullname, " for id:", id, " lun:", lun); imageReady = scsiDiskOpenHDDImage(id, fullname, id, lun, blk, is_cd); diff --git a/src/ZuluSCSI_disk.cpp b/src/ZuluSCSI_disk.cpp index aeea736b..93d4b59f 100644 --- a/src/ZuluSCSI_disk.cpp +++ b/src/ZuluSCSI_disk.cpp @@ -1100,10 +1100,19 @@ static void diskDataIn() // This was the last block, verify that everything finishes #ifdef PREFETCH_BUFFER_SIZE + image_config_t &img = *(image_config_t*)scsiDev.target->cfg; uint32_t prefetch_sectors = PREFETCH_BUFFER_SIZE / bytesPerSector; + uint32_t img_sector_count = img.file.size() / bytesPerSector; g_scsi_prefetch.sector = transfer.lba + transfer.blocks; g_scsi_prefetch.bytes = 0; g_scsi_prefetch.scsiId = scsiDev.target->cfg->scsiId; + + if (g_scsi_prefetch.sector + prefetch_sectors > img_sector_count) + { + // Don't try to read past image end. + prefetch_sectors = img_sector_count - g_scsi_prefetch.sector; + } + while (!scsiIsWriteFinished(NULL) && prefetch_sectors > 0) { // Check if prefetch buffer is free @@ -1118,9 +1127,15 @@ static void diskDataIn() // is part of a longer linear read. g_disk_transfer.bytes_sd = bytesPerSector; g_disk_transfer.bytes_scsi = bytesPerSector; // Tell callback not to send to SCSI - image_config_t &img = *(image_config_t*)scsiDev.target->cfg; azplatform_set_sd_callback(&diskDataIn_callback, g_disk_transfer.buffer); - g_scsi_prefetch.bytes += img.file.read(g_disk_transfer.buffer, bytesPerSector); + int status = img.file.read(g_disk_transfer.buffer, bytesPerSector); + if (status <= 0) + { + azlog("Prefetch read failed"); + prefetch_sectors = 0; + break; + } + g_scsi_prefetch.bytes += status; azplatform_set_sd_callback(NULL, NULL); prefetch_sectors--; } diff --git a/src/ZuluSCSI_log.cpp b/src/ZuluSCSI_log.cpp index 962c4bf2..77cd42c2 100644 --- a/src/ZuluSCSI_log.cpp +++ b/src/ZuluSCSI_log.cpp @@ -2,7 +2,7 @@ #include "ZuluSCSI_config.h" #include "ZuluSCSI_platform.h" -const char *g_azlog_firmwareversion = "1.0.1" " " __DATE__ " " __TIME__; +const char *g_azlog_firmwareversion = "1.0.3" " " __DATE__ " " __TIME__; bool g_azlog_debug = true; // This memory buffer can be read by debugger and is also saved to zululog.txt