From 4981bd7d77a00f3b175c08242890cbe5619348eb Mon Sep 17 00:00:00 2001 From: Michael McMaster Date: Tue, 8 Dec 2020 22:28:37 +1000 Subject: [PATCH] Move blockDev states into device independent struct and deal with config loading --- src/firmware/config.c | 80 +-------------- src/firmware/config.h | 9 +- src/firmware/device.c | 42 +++++++- src/firmware/device.h | 22 ++++- src/firmware/disk.c | 51 +++------- src/firmware/disk.h | 14 --- src/firmware/main.c | 85 ++-------------- src/firmware/mode.c | 27 +++--- src/firmware/mode.h | 2 +- src/firmware/scsi.c | 9 +- src/firmware/scsiPhy.c | 4 +- src/firmware/sd.c | 97 +++++++++++++++---- src/firmware/sd.h | 5 +- src/firmware/usb_device/usbd_msc_storage_sd.c | 7 +- 14 files changed, 200 insertions(+), 254 deletions(-) diff --git a/src/firmware/config.c b/src/firmware/config.c index 1c7b21c3..b19492e4 100755 --- a/src/firmware/config.c +++ b/src/firmware/config.c @@ -37,13 +37,10 @@ #include -static const uint16_t FIRMWARE_VERSION = 0x0632; - -// Optional static config -extern uint8_t* __fixed_config; +static const uint16_t FIRMWARE_VERSION = 0x0640; // 1 flash row -static const uint8_t DEFAULT_CONFIG[128] = +const uint8_t DEFAULT_TARGET_CONFIG[128] = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x02, 0x3F, 0x00, 0xFF, 0x00, 0x20, 0x63, 0x6F, 0x64, 0x65, 0x73, @@ -90,40 +87,7 @@ void s2s_configInit(S2S_BoardCfg* config) { usbInEpState = USB_IDLE; - if (memcmp(__fixed_config, "BCFG", 4) == 0) - { - // Use hardcoded config - memcpy(s2s_cfg, __fixed_config, S2S_CFG_SIZE); - memcpy(config, s2s_cfg, sizeof(S2S_BoardCfg)); - } - - else if ((blockDev.state & DISK_PRESENT) && sdCard.capacity) - { - int cfgSectors = (S2S_CFG_SIZE + 511) / 512; - BSP_SD_ReadBlocks_DMA( - (uint32_t*) &s2s_cfg[0], - (sdCard.capacity - cfgSectors) * 512ll, - 512, - cfgSectors); - - memcpy(config, s2s_cfg, sizeof(S2S_BoardCfg)); - - if (memcmp(config->magic, "BCFG", 4)) - { - // Invalid SD card config, use default. - memset(&s2s_cfg[0], 0, S2S_CFG_SIZE); - memcpy(config, s2s_cfg, sizeof(S2S_BoardCfg)); - memcpy(config->magic, "BCFG", 4); - config->selectionDelay = 255; // auto - config->flags6 = S2S_CFG_ENABLE_TERMINATOR; - - memcpy( - &s2s_cfg[0] + sizeof(S2S_BoardCfg), - DEFAULT_CONFIG, - sizeof(S2S_TargetCfg)); - } - } - else + if (!s2s_DeviceGetBoardConfig(config)) { // No SD card, use existing config if valid if (memcmp(config->magic, "BCFG", 4)) @@ -225,7 +189,7 @@ debugCommand() response[23] = scsiDev.msgCount; response[24] = scsiDev.cmdCount; response[25] = scsiDev.watchdogTick; - response[26] = blockDev.state; + response[26] = 0; // OBSOLETE. Previously media state; response[27] = scsiDev.lastSenseASC >> 8; response[28] = scsiDev.lastSenseASC; response[29] = *SCSI_STS_DBX & 0xff; // What we've read @@ -435,39 +399,3 @@ void s2s_debugTimer() } - -// Public method for storing MODE SELECT results. -void s2s_configSave(int scsiId, uint16_t bytesPerSector) -{ - S2S_TargetCfg* cfg = (S2S_TargetCfg*) s2s_getConfigById(scsiId); - cfg->bytesPerSector = bytesPerSector; - - BSP_SD_WriteBlocks_DMA( - (uint32_t*) &s2s_cfg[0], - (sdCard.capacity - S2S_CFG_SIZE) * 512ll, - 512, - (S2S_CFG_SIZE + 511) / 512); -} - - -const S2S_TargetCfg* s2s_getConfigByIndex(int i) -{ - return (const S2S_TargetCfg*) - (s2s_cfg + sizeof(S2S_BoardCfg) + (i * sizeof(S2S_TargetCfg))); -} - -const S2S_TargetCfg* s2s_getConfigById(int scsiId) -{ - int i; - for (i = 0; i < S2S_MAX_TARGETS; ++i) - { - const S2S_TargetCfg* tgt = s2s_getConfigByIndex(i); - if ((tgt->scsiId & S2S_CFG_TARGET_ID_BITS) == scsiId) - { - return tgt; - } - } - return NULL; - -} - diff --git a/src/firmware/config.h b/src/firmware/config.h index bed86a4c..e415528c 100755 --- a/src/firmware/config.h +++ b/src/firmware/config.h @@ -18,13 +18,16 @@ #define S2S_Config_H #include "scsi2sd.h" +#include "device.h" void s2s_configInit(S2S_BoardCfg* config); void s2s_debugInit(void); void s2s_configPoll(void); -void s2s_configSave(int scsiId, uint16_t byesPerSector); -const S2S_TargetCfg* s2s_getConfigByIndex(int index); -const S2S_TargetCfg* s2s_getConfigById(int scsiId); +extern const uint8_t DEFAULT_TARGET_CONFIG[128]; + +// Optional static config +extern uint8_t* __fixed_config; + #endif diff --git a/src/firmware/device.c b/src/firmware/device.c index e3ff9ea0..78e74fac 100644 --- a/src/firmware/device.c +++ b/src/firmware/device.c @@ -19,6 +19,24 @@ #include "sd.h" #include +#include + +int s2s_DeviceGetBoardConfig(S2S_BoardCfg* config) +{ + int deviceCount; + S2S_Device* devices = s2s_GetDevices(&deviceCount); + for (int deviceIdx = 0; deviceIdx < deviceCount; ++deviceIdx) + { + const S2S_BoardCfg* devCfg = devices[deviceIdx].getBoardConfig(devices + deviceIdx); + if (devCfg) + { + memcpy(config, devCfg, sizeof(S2S_BoardCfg)); + return 1; + } + } + + return 0; +} S2S_Target* s2s_DeviceFindByScsiId(int scsiId) { @@ -33,7 +51,7 @@ S2S_Target* s2s_DeviceFindByScsiId(int scsiId) S2S_Target* target = targets + targetIdx; if (target && (target->cfg->scsiId & S2S_CFG_TARGET_ENABLED) && - ((target->cfg->scsiId & 7) == scsiId)) + ((target->cfg->scsiId & S2S_CFG_TARGET_ID_BITS) == scsiId)) { return target; } @@ -49,3 +67,25 @@ S2S_Device* s2s_GetDevices(int* count) return sdDevice; } +void s2s_deviceEarlyInit() +{ + int count; + S2S_Device* devices = s2s_GetDevices(&count); + for (int i = 0; i < count; ++i) + { + devices[i].earlyInit(&(devices[i])); + } +} + +int s2s_pollMediaChange() +{ + int result = 0; + int count; + S2S_Device* devices = s2s_GetDevices(&count); + for (int i = 0; i < count; ++i) + { + int devResult = devices[i].pollMediaChange(&(devices[i])); + result = result || devResult; + } + return result; +} diff --git a/src/firmware/device.h b/src/firmware/device.h index 324c266c..73a6a7d6 100644 --- a/src/firmware/device.h +++ b/src/firmware/device.h @@ -31,6 +31,14 @@ typedef struct S2S_TargetStruct S2S_Target; struct S2S_TargetStateStruct; typedef struct S2S_TargetStateStruct S2S_TargetState; +typedef enum +{ + MEDIA_STARTED = 1, // Controlled via START STOP UNIT + MEDIA_PRESENT = 2, // SD card is physically present + MEDIA_INITIALISED = 4, // SD card responded to init sequence + MEDIA_WP = 8 // Write-protect. +} MEDIA_STATE; + struct S2S_TargetStateStruct { ScsiSense sense; @@ -52,8 +60,6 @@ struct S2S_TargetStateStruct struct S2S_TargetStruct { - uint8_t id; - S2S_Device* device; S2S_TargetCfg* cfg; @@ -62,20 +68,28 @@ struct S2S_TargetStruct struct S2S_DeviceStruct { + void (*earlyInit)(S2S_Device* dev); + const S2S_BoardCfg* (*getBoardConfig)(S2S_Device* dev); - //const S2S_Target* (*findByScsiId)(S2S_Device* dev, int scsiId); S2S_Target* (*getTargets)(S2S_Device* dev, int* count); // Get the number of 512 byte blocks uint32_t (*getCapacity)(S2S_Device* dev); + int (*pollMediaChange)(S2S_Device* dev); + + void (*saveConfig)(S2S_Target* target); + + MEDIA_STATE mediaState; }; -void s2s_DeviceGetBoardConfig(S2S_BoardCfg* config); +int s2s_DeviceGetBoardConfig(S2S_BoardCfg* config); S2S_Target* s2s_DeviceFindByScsiId(int scsiId); S2S_Device* s2s_GetDevices(int* count); +void s2s_deviceEarlyInit(); +int s2s_pollMediaChange(); #endif diff --git a/src/firmware/disk.c b/src/firmware/disk.c index 79951b0a..99f5624b 100755 --- a/src/firmware/disk.c +++ b/src/firmware/disk.c @@ -36,19 +36,8 @@ #include // Global -BlockDevice blockDev; Transfer transfer; -static int doSdInit() -{ - int result = 0; - if (blockDev.state & DISK_PRESENT) - { - blockDev.state = blockDev.state | DISK_INITIALISED; - } - return result; -} - // Callback once all data has been read in the data out phase. static void doFormatUnitComplete(void) { @@ -94,9 +83,7 @@ static void doFormatUnitHeader(void) if (! DSP) // disable save parameters { // Save the "MODE SELECT savable parameters" - s2s_configSave( - scsiDev.target->id, - scsiDev.target->state.bytesPerSector); + scsiDev.target->device->saveConfig(scsiDev.target); } if (IP) @@ -178,7 +165,7 @@ static void doWrite(uint32_t lba, uint32_t blocks) uint32_t bytesPerSector = scsiDev.target->state.bytesPerSector; - if (unlikely(blockDev.state & DISK_WP) || + if (unlikely(scsiDev.target->device->mediaState & MEDIA_WP) || unlikely(scsiDev.target->cfg->deviceType == S2S_CFG_OPTICAL)) { @@ -213,15 +200,6 @@ static void doWrite(uint32_t lba, uint32_t blocks) // No need for single-block writes atm. Overhead of the // multi-block write is minimal. transfer.multiBlock = 1; - - - // TODO uint32_t sdLBA = -// TODO SCSISector2SD( - // TODO scsiDev.target->cfg->sdSectorStart, - // TODO bytesPerSector, - // TODO lba); - // TODO uint32_t sdBlocks = blocks * SDSectorsPerSCSISector(bytesPerSector); - // TODO sdWriteMultiSectorPrep(sdLBA, sdBlocks); } } @@ -308,12 +286,14 @@ static void doSeek(uint32_t lba) static int doTestUnitReady() { + MEDIA_STATE* mediaState = &(scsiDev.target->device->mediaState); + int ready = 1; - if (likely(blockDev.state == (DISK_STARTED | DISK_PRESENT | DISK_INITIALISED))) + if (likely(*mediaState == (MEDIA_STARTED | MEDIA_PRESENT | MEDIA_INITIALISED))) { // nothing to do. } - else if (unlikely(!(blockDev.state & DISK_STARTED))) + else if (unlikely(!(*mediaState & MEDIA_STARTED))) { ready = 0; scsiDev.status = CHECK_CONDITION; @@ -321,7 +301,7 @@ static int doTestUnitReady() scsiDev.target->state.sense.asc = LOGICAL_UNIT_NOT_READY_INITIALIZING_COMMAND_REQUIRED; scsiDev.phase = STATUS; } - else if (unlikely(!(blockDev.state & DISK_PRESENT))) + else if (unlikely(!(*mediaState & MEDIA_PRESENT))) { ready = 0; scsiDev.status = CHECK_CONDITION; @@ -329,7 +309,7 @@ static int doTestUnitReady() scsiDev.target->state.sense.asc = MEDIUM_NOT_PRESENT; scsiDev.phase = STATUS; } - else if (unlikely(!(blockDev.state & DISK_INITIALISED))) + else if (unlikely(!(*mediaState & MEDIA_INITIALISED))) { ready = 0; scsiDev.status = CHECK_CONDITION; @@ -354,17 +334,21 @@ int scsiDiskCommand() //int immed = scsiDev.cdb[1] & 1; int start = scsiDev.cdb[4] & 1; + MEDIA_STATE* mediaState = &(scsiDev.target->device->mediaState); if (start) { - blockDev.state = blockDev.state | DISK_STARTED; - if (!(blockDev.state & DISK_INITIALISED)) + *mediaState = *mediaState | MEDIA_STARTED; + if (!(*mediaState & MEDIA_INITIALISED)) { - doSdInit(); + if (*mediaState & MEDIA_PRESENT) + { + *mediaState = *mediaState | MEDIA_INITIALISED; + } } } else { - blockDev.state &= ~DISK_STARTED; + *mediaState &= ~MEDIA_STARTED; } } else if (unlikely(command == 0x00)) @@ -965,8 +949,5 @@ void scsiDiskReset() void scsiDiskInit() { scsiDiskReset(); - - // Don't require the host to send us a START STOP UNIT command - blockDev.state = DISK_STARTED; } diff --git a/src/firmware/disk.h b/src/firmware/disk.h index b1f958fb..0456e2a8 100755 --- a/src/firmware/disk.h +++ b/src/firmware/disk.h @@ -17,25 +17,12 @@ #ifndef DISK_H #define DISK_H -typedef enum -{ - DISK_STARTED = 1, // Controlled via START STOP UNIT - DISK_PRESENT = 2, // SD card is physically present - DISK_INITIALISED = 4, // SD card responded to init sequence - DISK_WP = 8 // Write-protect. -} DISK_STATE; - typedef enum { TRANSFER_READ, TRANSFER_WRITE } TRANSFER_DIR; -typedef struct -{ - int state; -} BlockDevice; - typedef struct { int multiBlock; // True if we're using a multi-block SPI transfer. @@ -45,7 +32,6 @@ typedef struct uint32_t currentBlock; } Transfer; -extern BlockDevice blockDev; extern Transfer transfer; void scsiDiskInit(void); diff --git a/src/firmware/main.c b/src/firmware/main.c index 6392c4fb..f3041f81 100755 --- a/src/firmware/main.c +++ b/src/firmware/main.c @@ -33,7 +33,6 @@ #include "usb_device/usbd_msc_storage_sd.h" const char* Notice = "Copyright (C) 2020 Michael McMaster "; -uint32_t lastSDPoll; static int isUsbStarted; @@ -53,7 +52,7 @@ void mainInit() s2s_ledInit(); s2s_fpgaInit(); - + s2s_deviceEarlyInit(); scsiPhyInit(); scsiDiskInit(); @@ -79,7 +78,6 @@ void mainInit() ++delaySeconds; } - lastSDPoll = s2s_getTime_ms(); } void mainLoop() @@ -91,89 +89,22 @@ void mainLoop() s2s_configPoll(); s2s_usbDevicePoll(); -#if 0 - sdPoll(); -#endif - if (unlikely(scsiDev.phase == BUS_FREE)) { - if (unlikely(s2s_elapsedTime_ms(lastSDPoll) > 200)) - { - lastSDPoll = s2s_getTime_ms(); - if (sdInit()) - { - s2s_configInit(&scsiDev.boardCfg); - scsiPhyConfig(); - scsiInit(); - - // Is a USB host connected ? -/* TODO DEAL WITH THIS - if (isUsbStarted) - { - USBD_Stop(&hUsbDeviceFS); - s2s_delay_ms(128); - USBD_Start(&hUsbDeviceFS); - } -*/ - } - -/* TODO DEAL WITH THIS - // Can we speed up the SD card ? - // Don't combine with the above block because that won't - // run if the SD card is present at startup. - // Don't use VBUS monitoring because that just tells us about - // power, which could be from a charger - if ((blockDev.state & DISK_PRESENT) && - isUsbStarted && - (scsiDev.cmdCount > 0) && // no need for speed without scsi - !USBD_Composite_IsConfigured(&hUsbDeviceFS) && - (scsiDev.boardCfg.scsiSpeed == S2S_CFG_SPEED_TURBO)) - { - if (HAL_SD_HighSpeed(&hsd) == SD_OK) - { - USBD_Stop(&hUsbDeviceFS); - s2s_setFastClock(); - isUsbStarted = 0; - } - } - - else if (!(blockDev.state & DISK_PRESENT) && !isUsbStarted) - { - // Good time to restart USB. - s2s_setNormalClock(); - USBD_Start(&hUsbDeviceFS); - isUsbStarted = 1; - } - */ - } - else + if (s2s_pollMediaChange()) { - // TODO this hurts performance significantly! Work out why __WFI() - // doesn't wake up immediately ! -#if 0 - // Wait for our 1ms timer to save some power. - // There's an interrupt on the SEL signal to ensure we respond - // quickly to any SCSI commands. The selection abort time is - // only 250us, and new SCSI-3 controllers time-out very - // not long after that, so we need to ensure we wake up quickly. - uint32_t interruptState = __get_PRIMASK(); - __disable_irq(); - - if (!*SCSI_STS_SELECTED) - { - //__WFI(); // Will wake on interrupt, regardless of mask - } - if (!interruptState) - { - __enable_irq(); - } -#endif + s2s_configInit(&scsiDev.boardCfg); + scsiPhyConfig(); + scsiInit(); } } +#warning MOVE THIS CODE TO SD READ/WRITE METHODS +#if 0 else if ((scsiDev.phase >= 0) && (blockDev.state & DISK_PRESENT)) { // don't waste time scanning SD cards while we're doing disk IO lastSDPoll = s2s_getTime_ms(); } +#endif } diff --git a/src/firmware/mode.c b/src/firmware/mode.c index 64823e7b..6fa6641d 100755 --- a/src/firmware/mode.c +++ b/src/firmware/mode.c @@ -257,7 +257,12 @@ static void pageIn(int pc, int dataIdx, const uint8_t* pageData, int pageLen) } static void doModeSense( - int sixByteCmd, int dbd, int pc, int pageCode, int allocLength) + S2S_Device* dev, + int sixByteCmd, + int dbd, + int pc, + int pageCode, + int allocLength) { ////////////// Mode Parameter Header //////////////////////////////////// @@ -276,14 +281,14 @@ static void doModeSense( mediumType = 0; // We should support various floppy types here! // Contains cache bits (0) and a Write-Protect bit. deviceSpecificParam = - (blockDev.state & DISK_WP) ? 0x80 : 0; + (dev->mediaState & MEDIA_WP) ? 0x80 : 0; density = 0; // reserved for direct access break; case S2S_CFG_FLOPPY_14MB: mediumType = 0x1E; // 90mm/3.5" deviceSpecificParam = - (blockDev.state & DISK_WP) ? 0x80 : 0; + (dev->mediaState & MEDIA_WP) ? 0x80 : 0; density = 0; // reserved for direct access break; @@ -296,14 +301,14 @@ static void doModeSense( case S2S_CFG_SEQUENTIAL: mediumType = 0; // reserved deviceSpecificParam = - (blockDev.state & DISK_WP) ? 0x80 : 0; - density = 0x13; // DAT Data Storage, X3B5/88-185A + (dev->mediaState & MEDIA_WP) ? 0x80 : 0; + density = 0x13; // DAT Data Storage, X3B5/88-185A break; case S2S_CFG_MO: mediumType = 0x03; // Optical reversible or erasable medium deviceSpecificParam = - (blockDev.state & DISK_WP) ? 0x80 : 0; + (dev->mediaState & MEDIA_WP) ? 0x80 : 0; density = 0x00; // Default break; @@ -611,7 +616,7 @@ static void doModeSelect(void) scsiDev.target->state.bytesPerSector = bytesPerSector; if (bytesPerSector != scsiDev.target->cfg->bytesPerSector) { - s2s_configSave(scsiDev.target->id, bytesPerSector); + scsiDev.target->device->saveConfig(scsiDev.target); } } } @@ -644,7 +649,7 @@ static void doModeSelect(void) scsiDev.target->state.bytesPerSector = bytesPerSector; if (scsiDev.cdb[1] & 1) // SP Save Pages flag { - s2s_configSave(scsiDev.target->id, bytesPerSector); + scsiDev.target->device->saveConfig(scsiDev.target); } } break; @@ -667,7 +672,7 @@ out: scsiDev.phase = STATUS; } -int scsiModeCommand() +int scsiModeCommand(S2S_Device* dev) { int commandHandled = 1; @@ -687,7 +692,7 @@ int scsiModeCommand() // SCSI1 standard: (CCS X3T9.2/86-52) // "An Allocation Length of zero indicates that no MODE SENSE data shall // be transferred. This condition shall not be considered as an error." - doModeSense(1, dbd, pc, pageCode, allocLength); + doModeSense(dev, 1, dbd, pc, pageCode, allocLength); } else if (command == 0x5A) { @@ -698,7 +703,7 @@ int scsiModeCommand() int allocLength = (((uint16_t) scsiDev.cdb[7]) << 8) + scsiDev.cdb[8]; - doModeSense(0, dbd, pc, pageCode, allocLength); + doModeSense(dev, 0, dbd, pc, pageCode, allocLength); } else if (command == 0x15) { diff --git a/src/firmware/mode.h b/src/firmware/mode.h index 819b1f53..887e91ab 100755 --- a/src/firmware/mode.h +++ b/src/firmware/mode.h @@ -17,6 +17,6 @@ #ifndef MODE_H #define MODE_H -int scsiModeCommand(void); +int scsiModeCommand(S2S_Device* dev); #endif diff --git a/src/firmware/scsi.c b/src/firmware/scsi.c index 51f68684..db7224df 100755 --- a/src/firmware/scsi.c +++ b/src/firmware/scsi.c @@ -190,7 +190,7 @@ void process_Status() } else if (scsiDev.target->cfg->quirks == S2S_CFG_QUIRKS_OMTI) { - scsiDev.status |= (scsiDev.target->id & 0x03) << 5; + scsiDev.status |= (scsiDev.target->cfg->scsiId & 0x03) << 5; scsiWriteByte(scsiDev.status); } else @@ -479,7 +479,7 @@ static void process_Command() { scsiReadBuffer(); } - else if (!scsiModeCommand() && !scsiVendorCommand()) + else if (!scsiModeCommand(scsiDev.target->device) && !scsiVendorCommand()) { scsiDev.target->state.sense.code = ILLEGAL_REQUEST; scsiDev.target->state.sense.asc = INVALID_COMMAND_OPERATION_CODE; @@ -1152,11 +1152,6 @@ void scsiInit() state->syncOffset = 0; state->syncPeriod = 0; - - // TODO This should probably be done in a device-specific init function. - targets[i].cfg = s2s_getConfigByIndex(i); - targets[i].id = targets[i].cfg->scsiId; - targets[i].device = &(devices[deviceIdx]); } } firstInit = 0; diff --git a/src/firmware/scsiPhy.c b/src/firmware/scsiPhy.c index 887b3d08..b4623e97 100755 --- a/src/firmware/scsiPhy.c +++ b/src/firmware/scsiPhy.c @@ -875,8 +875,8 @@ void scsiPhyConfig() uint8_t idMask = 0; for (int i = 0; i < 8; ++i) { - const S2S_TargetCfg* cfg = s2s_getConfigById(i); - if (cfg && (cfg->scsiId & S2S_CFG_TARGET_ENABLED)) + const S2S_Target* tgt = s2s_DeviceFindByScsiId(i); + if (tgt && (tgt->cfg->scsiId & S2S_CFG_TARGET_ENABLED)) { idMask |= (1 << i); } diff --git a/src/firmware/sd.c b/src/firmware/sd.c index 7f4b7e8b..e694b893 100755 --- a/src/firmware/sd.c +++ b/src/firmware/sd.c @@ -31,24 +31,28 @@ #include +static void sd_earlyInit(S2S_Device* dev); static const S2S_BoardCfg* sd_getBoardConfig(S2S_Device* dev); -//static const S2S_TargetCfg* sd_findByScsiId(S2S_Device* dev, int scsiId); static S2S_Target* sd_getTargets(S2S_Device* dev, int* count); static uint32_t sd_getCapacity(S2S_Device* dev); +static int sd_pollMediaChange(S2S_Device* dev); +static void sd_saveConfig(S2S_Target* target); // Global SdCard sdCard S2S_DMA_ALIGN = { { + sd_earlyInit, sd_getBoardConfig, - //sd_findByScsiId, sd_getTargets, - sd_getCapacity + sd_getCapacity, + sd_pollMediaChange, + sd_saveConfig } }; S2S_Device* sdDevice = &(sdCard.dev); -static int sdCmdActive = 0; +static int sdCmdActive = 0; // TODO MOVE to sdCard int sdReadDMAPoll(uint32_t remainingSectors) @@ -160,7 +164,7 @@ static int sdDoInit() memcpy(sdCard.csd, &SDCardInfo.SD_csd, sizeof(sdCard.csd)); memcpy(sdCard.cid, &SDCardInfo.SD_cid, sizeof(sdCard.cid)); sdCard.capacity = SDCardInfo.CardCapacity / SD_SECTOR_SIZE; - blockDev.state |= DISK_PRESENT | DISK_INITIALISED; + sdCard.dev.mediaState |= MEDIA_PRESENT | MEDIA_INITIALISED; result = 1; // SD Benchmark code @@ -193,7 +197,7 @@ static int sdDoInit() } //bad: - blockDev.state &= ~(DISK_PRESENT | DISK_INITIALISED); + sdCard.dev.mediaState &= ~(MEDIA_PRESENT | MEDIA_INITIALISED); sdCard.capacity = 0; @@ -211,7 +215,7 @@ int sdInit() if (firstInit) { - blockDev.state &= ~(DISK_PRESENT | DISK_INITIALISED); + sdCard.dev.mediaState &= ~(MEDIA_PRESENT | MEDIA_INITIALISED); sdClear(); sdInitDMA(); } @@ -221,7 +225,7 @@ int sdInit() uint8_t cs = HAL_GPIO_ReadPin(nSD_CD_GPIO_Port, nSD_CD_Pin) ? 0 : 1; uint8_t wp = HAL_GPIO_ReadPin(nSD_WP_GPIO_Port, nSD_WP_Pin) ? 0 : 1; - if (cs && !(blockDev.state & DISK_PRESENT)) + if (cs && !(sdCard.dev.mediaState & MEDIA_PRESENT)) { s2s_ledOn(); @@ -233,15 +237,15 @@ int sdInit() if (sdDoInit()) { - blockDev.state |= DISK_PRESENT | DISK_INITIALISED; + sdCard.dev.mediaState |= MEDIA_PRESENT | MEDIA_INITIALISED; if (wp) { - blockDev.state |= DISK_WP; + sdCard.dev.mediaState |= MEDIA_WP; } else { - blockDev.state &= ~DISK_WP; + sdCard.dev.mediaState &= ~MEDIA_WP; } // Always "start" the device. Many systems (eg. Apple System 7) @@ -249,7 +253,7 @@ int sdInit() // LOGICAL_UNIT_NOT_READY_INITIALIZING_COMMAND_REQUIRED sense // code, even if they stopped it first with // START STOP UNIT command. - blockDev.state |= DISK_STARTED; + sdCard.dev.mediaState |= MEDIA_STARTED; result = 1; @@ -268,11 +272,11 @@ int sdInit() s2s_ledOff(); } } - else if (!cs && (blockDev.state & DISK_PRESENT)) + else if (!cs && (sdCard.dev.mediaState & MEDIA_PRESENT)) { sdCard.capacity = 0; - blockDev.state &= ~DISK_PRESENT; - blockDev.state &= ~DISK_INITIALISED; + sdCard.dev.mediaState &= ~MEDIA_PRESENT; + sdCard.dev.mediaState &= ~MEDIA_INITIALISED; int i; for (i = 0; i < S2S_MAX_TARGETS; ++i) { @@ -287,22 +291,52 @@ int sdInit() return result; } +static void sd_earlyInit(S2S_Device* dev) +{ + SdCard* sdCardDevice = (SdCard*)dev; + + for (int i = 0; i < S2S_MAX_TARGETS; ++i) + { + sdCardDevice->targets[i].device = dev; + sdCardDevice->targets[i].cfg = (const S2S_TargetCfg*) + (&(sdCardDevice->cfg[0]) + sizeof(S2S_BoardCfg) + (i * sizeof(S2S_TargetCfg))); + } + sdCardDevice->lastPollMediaTime = s2s_getTime_ms(); + + // Don't require the host to send us a START STOP UNIT command + sdCardDevice->dev.mediaState = MEDIA_STARTED; + +} + static const S2S_BoardCfg* sd_getBoardConfig(S2S_Device* dev) { SdCard* sdCardDevice = (SdCard*)dev; - if ((blockDev.state & DISK_PRESENT) && sdCardDevice->capacity) + if (memcmp(__fixed_config, "BCFG", 4) == 0) + { + // Use hardcoded config if available. Hardcoded config always refers + // to the SD card. + memcpy(&(sdCardDevice->cfg[0]), __fixed_config, S2S_CFG_SIZE); + return (S2S_BoardCfg*) &(sdCardDevice->cfg[0]); + } + else if ((sdCard.dev.mediaState & MEDIA_PRESENT) && sdCardDevice->capacity) { int cfgSectors = (S2S_CFG_SIZE + 511) / 512; BSP_SD_ReadBlocks_DMA( - (uint32_t*) &(sdCardDevice->boardCfg[0]), + (uint32_t*) &(sdCardDevice->cfg[0]), (sdCardDevice->capacity - cfgSectors) * 512ll, 512, cfgSectors); - S2S_BoardCfg* cfg = (S2S_BoardCfg*) &(sdCardDevice->boardCfg[0]); + S2S_BoardCfg* cfg = (S2S_BoardCfg*) &(sdCardDevice->cfg[0]); if (memcmp(cfg->magic, "BCFG", 4)) { + // Set a default Target disk config + memcpy( + &(sdCardDevice->cfg[0]) + sizeof(S2S_BoardCfg), + DEFAULT_TARGET_CONFIG, + sizeof(DEFAULT_TARGET_CONFIG)); + return NULL; } else @@ -314,7 +348,6 @@ static const S2S_BoardCfg* sd_getBoardConfig(S2S_Device* dev) return NULL; } -//static const S2S_TargetCfg* sd_findByScsiId(S2S_Device* dev, int scsiId) static S2S_Target* sd_getTargets(S2S_Device* dev, int* count) { SdCard* sdCardDevice = (SdCard*)dev; @@ -327,3 +360,29 @@ static uint32_t sd_getCapacity(S2S_Device* dev) SdCard* sdCardDevice = (SdCard*)dev; return sdCardDevice->capacity; } + +static int sd_pollMediaChange(S2S_Device* dev) +{ + SdCard* sdCardDevice = (SdCard*)dev; + if (s2s_elapsedTime_ms(sdCardDevice->lastPollMediaTime) > 200) + { + sdCardDevice->lastPollMediaTime = s2s_getTime_ms(); + return sdInit(); + } + else + { + return 0; + } +} + +static void sd_saveConfig(S2S_Target* target) +{ + SdCard* sdCardDevice = (SdCard*)target->device; + target->cfg->bytesPerSector = target->state.bytesPerSector; + + BSP_SD_WriteBlocks_DMA( + (uint32_t*) (&(sdCardDevice->cfg[0])), + (sdCardDevice->capacity - S2S_CFG_SIZE) * 512ll, + 512, + (S2S_CFG_SIZE + 511) / 512); +} diff --git a/src/firmware/sd.h b/src/firmware/sd.h index 3a3fd556..31a75f73 100755 --- a/src/firmware/sd.h +++ b/src/firmware/sd.h @@ -27,7 +27,7 @@ typedef struct { S2S_Device dev; - uint8_t boardCfg[S2S_CFG_SIZE] S2S_DMA_ALIGN; + uint8_t cfg[S2S_CFG_SIZE] S2S_DMA_ALIGN; S2S_Target targets[S2S_MAX_TARGETS]; @@ -36,6 +36,9 @@ typedef struct uint8_t csd[16]; // Unparsed CSD uint8_t cid[16]; // Unparsed CID + + uint32_t lastPollMediaTime; + } SdCard; extern SdCard sdCard; // TODO move to .c file diff --git a/src/firmware/usb_device/usbd_msc_storage_sd.c b/src/firmware/usb_device/usbd_msc_storage_sd.c index b9666ad9..8ec82db9 100755 --- a/src/firmware/usb_device/usbd_msc_storage_sd.c +++ b/src/firmware/usb_device/usbd_msc_storage_sd.c @@ -129,15 +129,16 @@ int8_t s2s_usbd_storage_IsReady (uint8_t lun) const S2S_Target* target = getUsbTarget(lun); return ( target && - (blockDev.state & DISK_PRESENT) && - (blockDev.state & DISK_INITIALISED) + (target->device->mediaState & MEDIA_PRESENT) && + (target->device->mediaState & MEDIA_INITIALISED) ) ? 0 : 1; // inverse logic } int8_t s2s_usbd_storage_IsWriteProtected (uint8_t lun) { - return blockDev.state & DISK_WP; + const S2S_Target* target = getUsbTarget(lun); + return target->device->mediaState & MEDIA_WP; } int8_t s2s_usbd_storage_Read (uint8_t lun, -- 2.38.5