\r
#include <string.h>\r
\r
-static const uint16_t FIRMWARE_VERSION = 0x0632;\r
-\r
-// Optional static config\r
-extern uint8_t* __fixed_config;\r
+static const uint16_t FIRMWARE_VERSION = 0x0640;\r
\r
// 1 flash row\r
-static const uint8_t DEFAULT_CONFIG[128] =\r
+const uint8_t DEFAULT_TARGET_CONFIG[128] =\r
{\r
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3F, 0x00,\r
0x00, 0x02, 0x3F, 0x00, 0xFF, 0x00, 0x20, 0x63, 0x6F, 0x64, 0x65, 0x73,\r
{\r
usbInEpState = USB_IDLE;\r
\r
- if (memcmp(__fixed_config, "BCFG", 4) == 0)\r
- {\r
- // Use hardcoded config\r
- memcpy(s2s_cfg, __fixed_config, S2S_CFG_SIZE);\r
- memcpy(config, s2s_cfg, sizeof(S2S_BoardCfg));\r
- }\r
-\r
- else if ((blockDev.state & DISK_PRESENT) && sdCard.capacity)\r
- {\r
- int cfgSectors = (S2S_CFG_SIZE + 511) / 512;\r
- BSP_SD_ReadBlocks_DMA(\r
- (uint32_t*) &s2s_cfg[0],\r
- (sdCard.capacity - cfgSectors) * 512ll,\r
- 512,\r
- cfgSectors);\r
-\r
- memcpy(config, s2s_cfg, sizeof(S2S_BoardCfg));\r
-\r
- if (memcmp(config->magic, "BCFG", 4))\r
- {\r
- // Invalid SD card config, use default.\r
- memset(&s2s_cfg[0], 0, S2S_CFG_SIZE);\r
- memcpy(config, s2s_cfg, sizeof(S2S_BoardCfg));\r
- memcpy(config->magic, "BCFG", 4);\r
- config->selectionDelay = 255; // auto\r
- config->flags6 = S2S_CFG_ENABLE_TERMINATOR;\r
-\r
- memcpy(\r
- &s2s_cfg[0] + sizeof(S2S_BoardCfg),\r
- DEFAULT_CONFIG,\r
- sizeof(S2S_TargetCfg));\r
- }\r
- }\r
- else\r
+ if (!s2s_DeviceGetBoardConfig(config))\r
{\r
// No SD card, use existing config if valid\r
if (memcmp(config->magic, "BCFG", 4))\r
response[23] = scsiDev.msgCount;\r
response[24] = scsiDev.cmdCount;\r
response[25] = scsiDev.watchdogTick;\r
- response[26] = blockDev.state;\r
+ response[26] = 0; // OBSOLETE. Previously media state;\r
response[27] = scsiDev.lastSenseASC >> 8;\r
response[28] = scsiDev.lastSenseASC;\r
response[29] = *SCSI_STS_DBX & 0xff; // What we've read\r
}\r
\r
\r
-\r
-// Public method for storing MODE SELECT results.\r
-void s2s_configSave(int scsiId, uint16_t bytesPerSector)\r
-{\r
- S2S_TargetCfg* cfg = (S2S_TargetCfg*) s2s_getConfigById(scsiId);\r
- cfg->bytesPerSector = bytesPerSector;\r
-\r
- BSP_SD_WriteBlocks_DMA(\r
- (uint32_t*) &s2s_cfg[0],\r
- (sdCard.capacity - S2S_CFG_SIZE) * 512ll,\r
- 512,\r
- (S2S_CFG_SIZE + 511) / 512);\r
-}\r
-\r
-\r
-const S2S_TargetCfg* s2s_getConfigByIndex(int i)\r
-{\r
- return (const S2S_TargetCfg*)\r
- (s2s_cfg + sizeof(S2S_BoardCfg) + (i * sizeof(S2S_TargetCfg)));\r
-}\r
-\r
-const S2S_TargetCfg* s2s_getConfigById(int scsiId)\r
-{\r
- int i;\r
- for (i = 0; i < S2S_MAX_TARGETS; ++i)\r
- {\r
- const S2S_TargetCfg* tgt = s2s_getConfigByIndex(i);\r
- if ((tgt->scsiId & S2S_CFG_TARGET_ID_BITS) == scsiId)\r
- {\r
- return tgt;\r
- }\r
- }\r
- return NULL;\r
-\r
-}\r
-\r
#define S2S_Config_H\r
\r
#include "scsi2sd.h"\r
+#include "device.h"\r
\r
void s2s_configInit(S2S_BoardCfg* config);\r
void s2s_debugInit(void);\r
void s2s_configPoll(void);\r
-void s2s_configSave(int scsiId, uint16_t byesPerSector);\r
\r
-const S2S_TargetCfg* s2s_getConfigByIndex(int index);\r
-const S2S_TargetCfg* s2s_getConfigById(int scsiId);\r
+extern const uint8_t DEFAULT_TARGET_CONFIG[128];\r
+\r
+// Optional static config\r
+extern uint8_t* __fixed_config;\r
+\r
\r
#endif\r
#include "sd.h"
#include <stddef.h>
+#include <string.h>
+
+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)
{
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;
}
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;
+}
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;
struct S2S_TargetStruct
{
- uint8_t id;
-
S2S_Device* device;
S2S_TargetCfg* cfg;
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
#include <string.h>\r
\r
// Global\r
-BlockDevice blockDev;\r
Transfer transfer;\r
\r
-static int doSdInit()\r
-{\r
- int result = 0;\r
- if (blockDev.state & DISK_PRESENT)\r
- {\r
- blockDev.state = blockDev.state | DISK_INITIALISED;\r
- }\r
- return result;\r
-}\r
-\r
// Callback once all data has been read in the data out phase.\r
static void doFormatUnitComplete(void)\r
{\r
if (! DSP) // disable save parameters\r
{\r
// Save the "MODE SELECT savable parameters"\r
- s2s_configSave(\r
- scsiDev.target->id,\r
- scsiDev.target->state.bytesPerSector);\r
+ scsiDev.target->device->saveConfig(scsiDev.target);\r
}\r
\r
if (IP)\r
\r
uint32_t bytesPerSector = scsiDev.target->state.bytesPerSector;\r
\r
- if (unlikely(blockDev.state & DISK_WP) ||\r
+ if (unlikely(scsiDev.target->device->mediaState & MEDIA_WP) ||\r
unlikely(scsiDev.target->cfg->deviceType == S2S_CFG_OPTICAL))\r
\r
{\r
// No need for single-block writes atm. Overhead of the\r
// multi-block write is minimal.\r
transfer.multiBlock = 1;\r
-\r
-\r
- // TODO uint32_t sdLBA =\r
-// TODO SCSISector2SD(\r
- // TODO scsiDev.target->cfg->sdSectorStart,\r
- // TODO bytesPerSector,\r
- // TODO lba);\r
- // TODO uint32_t sdBlocks = blocks * SDSectorsPerSCSISector(bytesPerSector);\r
- // TODO sdWriteMultiSectorPrep(sdLBA, sdBlocks);\r
}\r
}\r
\r
\r
static int doTestUnitReady()\r
{\r
+ MEDIA_STATE* mediaState = &(scsiDev.target->device->mediaState);\r
+\r
int ready = 1;\r
- if (likely(blockDev.state == (DISK_STARTED | DISK_PRESENT | DISK_INITIALISED)))\r
+ if (likely(*mediaState == (MEDIA_STARTED | MEDIA_PRESENT | MEDIA_INITIALISED)))\r
{\r
// nothing to do.\r
}\r
- else if (unlikely(!(blockDev.state & DISK_STARTED)))\r
+ else if (unlikely(!(*mediaState & MEDIA_STARTED)))\r
{\r
ready = 0;\r
scsiDev.status = CHECK_CONDITION;\r
scsiDev.target->state.sense.asc = LOGICAL_UNIT_NOT_READY_INITIALIZING_COMMAND_REQUIRED;\r
scsiDev.phase = STATUS;\r
}\r
- else if (unlikely(!(blockDev.state & DISK_PRESENT)))\r
+ else if (unlikely(!(*mediaState & MEDIA_PRESENT)))\r
{\r
ready = 0;\r
scsiDev.status = CHECK_CONDITION;\r
scsiDev.target->state.sense.asc = MEDIUM_NOT_PRESENT;\r
scsiDev.phase = STATUS;\r
}\r
- else if (unlikely(!(blockDev.state & DISK_INITIALISED)))\r
+ else if (unlikely(!(*mediaState & MEDIA_INITIALISED)))\r
{\r
ready = 0;\r
scsiDev.status = CHECK_CONDITION;\r
//int immed = scsiDev.cdb[1] & 1;\r
int start = scsiDev.cdb[4] & 1;\r
\r
+ MEDIA_STATE* mediaState = &(scsiDev.target->device->mediaState);\r
if (start)\r
{\r
- blockDev.state = blockDev.state | DISK_STARTED;\r
- if (!(blockDev.state & DISK_INITIALISED))\r
+ *mediaState = *mediaState | MEDIA_STARTED;\r
+ if (!(*mediaState & MEDIA_INITIALISED))\r
{\r
- doSdInit();\r
+ if (*mediaState & MEDIA_PRESENT)\r
+ {\r
+ *mediaState = *mediaState | MEDIA_INITIALISED;\r
+ }\r
}\r
}\r
else\r
{\r
- blockDev.state &= ~DISK_STARTED;\r
+ *mediaState &= ~MEDIA_STARTED;\r
}\r
}\r
else if (unlikely(command == 0x00))\r
void scsiDiskInit()\r
{\r
scsiDiskReset();\r
-\r
- // Don't require the host to send us a START STOP UNIT command\r
- blockDev.state = DISK_STARTED;\r
}\r
\r
#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.
uint32_t currentBlock;
} Transfer;
-extern BlockDevice blockDev;
extern Transfer transfer;
void scsiDiskInit(void);
#include "usb_device/usbd_msc_storage_sd.h"\r
\r
const char* Notice = "Copyright (C) 2020 Michael McMaster <michael@codesrc.com>";\r
-uint32_t lastSDPoll;\r
\r
static int isUsbStarted;\r
\r
\r
s2s_ledInit();\r
s2s_fpgaInit();\r
-\r
+ s2s_deviceEarlyInit();\r
scsiPhyInit();\r
\r
scsiDiskInit();\r
++delaySeconds;\r
}\r
\r
- lastSDPoll = s2s_getTime_ms();\r
}\r
\r
void mainLoop()\r
s2s_configPoll();\r
s2s_usbDevicePoll();\r
\r
-#if 0\r
- sdPoll();\r
-#endif\r
-\r
if (unlikely(scsiDev.phase == BUS_FREE))\r
{\r
- if (unlikely(s2s_elapsedTime_ms(lastSDPoll) > 200))\r
- {\r
- lastSDPoll = s2s_getTime_ms();\r
- if (sdInit())\r
- {\r
- s2s_configInit(&scsiDev.boardCfg);\r
- scsiPhyConfig();\r
- scsiInit();\r
-\r
- // Is a USB host connected ?\r
-/* TODO DEAL WITH THIS\r
- if (isUsbStarted)\r
- {\r
- USBD_Stop(&hUsbDeviceFS);\r
- s2s_delay_ms(128);\r
- USBD_Start(&hUsbDeviceFS);\r
- }\r
-*/ \r
- }\r
-\r
-/* TODO DEAL WITH THIS\r
- // Can we speed up the SD card ?\r
- // Don't combine with the above block because that won't\r
- // run if the SD card is present at startup.\r
- // Don't use VBUS monitoring because that just tells us about\r
- // power, which could be from a charger\r
- if ((blockDev.state & DISK_PRESENT) &&\r
- isUsbStarted &&\r
- (scsiDev.cmdCount > 0) && // no need for speed without scsi\r
- !USBD_Composite_IsConfigured(&hUsbDeviceFS) &&\r
- (scsiDev.boardCfg.scsiSpeed == S2S_CFG_SPEED_TURBO))\r
- {\r
- if (HAL_SD_HighSpeed(&hsd) == SD_OK)\r
- {\r
- USBD_Stop(&hUsbDeviceFS);\r
- s2s_setFastClock();\r
- isUsbStarted = 0;\r
- }\r
- }\r
-\r
- else if (!(blockDev.state & DISK_PRESENT) && !isUsbStarted)\r
- {\r
- // Good time to restart USB.\r
- s2s_setNormalClock();\r
- USBD_Start(&hUsbDeviceFS);\r
- isUsbStarted = 1;\r
- }\r
- */\r
- }\r
- else\r
+ if (s2s_pollMediaChange())\r
{\r
- // TODO this hurts performance significantly! Work out why __WFI()\r
- // doesn't wake up immediately !\r
-#if 0\r
- // Wait for our 1ms timer to save some power.\r
- // There's an interrupt on the SEL signal to ensure we respond\r
- // quickly to any SCSI commands. The selection abort time is\r
- // only 250us, and new SCSI-3 controllers time-out very\r
- // not long after that, so we need to ensure we wake up quickly.\r
- uint32_t interruptState = __get_PRIMASK();\r
- __disable_irq();\r
-\r
- if (!*SCSI_STS_SELECTED)\r
- {\r
- //__WFI(); // Will wake on interrupt, regardless of mask\r
- }\r
- if (!interruptState)\r
- {\r
- __enable_irq();\r
- }\r
-#endif\r
+ s2s_configInit(&scsiDev.boardCfg);\r
+ scsiPhyConfig();\r
+ scsiInit();\r
}\r
}\r
+#warning MOVE THIS CODE TO SD READ/WRITE METHODS\r
+#if 0\r
else if ((scsiDev.phase >= 0) && (blockDev.state & DISK_PRESENT))\r
{\r
// don't waste time scanning SD cards while we're doing disk IO\r
lastSDPoll = s2s_getTime_ms();\r
}\r
+#endif\r
}\r
\r
}\r
\r
static void doModeSense(\r
- int sixByteCmd, int dbd, int pc, int pageCode, int allocLength)\r
+ S2S_Device* dev,\r
+ int sixByteCmd,\r
+ int dbd,\r
+ int pc,\r
+ int pageCode,\r
+ int allocLength)\r
{\r
////////////// Mode Parameter Header\r
////////////////////////////////////\r
mediumType = 0; // We should support various floppy types here!\r
// Contains cache bits (0) and a Write-Protect bit.\r
deviceSpecificParam =\r
- (blockDev.state & DISK_WP) ? 0x80 : 0;\r
+ (dev->mediaState & MEDIA_WP) ? 0x80 : 0;\r
density = 0; // reserved for direct access\r
break;\r
\r
case S2S_CFG_FLOPPY_14MB:\r
mediumType = 0x1E; // 90mm/3.5"\r
deviceSpecificParam =\r
- (blockDev.state & DISK_WP) ? 0x80 : 0;\r
+ (dev->mediaState & MEDIA_WP) ? 0x80 : 0;\r
density = 0; // reserved for direct access\r
break;\r
\r
case S2S_CFG_SEQUENTIAL:\r
mediumType = 0; // reserved\r
deviceSpecificParam =\r
- (blockDev.state & DISK_WP) ? 0x80 : 0;\r
- density = 0x13; // DAT Data Storage, X3B5/88-185A \r
+ (dev->mediaState & MEDIA_WP) ? 0x80 : 0;\r
+ density = 0x13; // DAT Data Storage, X3B5/88-185A\r
break;\r
\r
case S2S_CFG_MO:\r
mediumType = 0x03; // Optical reversible or erasable medium\r
deviceSpecificParam =\r
- (blockDev.state & DISK_WP) ? 0x80 : 0;\r
+ (dev->mediaState & MEDIA_WP) ? 0x80 : 0;\r
density = 0x00; // Default\r
break;\r
\r
scsiDev.target->state.bytesPerSector = bytesPerSector;\r
if (bytesPerSector != scsiDev.target->cfg->bytesPerSector)\r
{\r
- s2s_configSave(scsiDev.target->id, bytesPerSector);\r
+ scsiDev.target->device->saveConfig(scsiDev.target);\r
}\r
}\r
}\r
scsiDev.target->state.bytesPerSector = bytesPerSector;\r
if (scsiDev.cdb[1] & 1) // SP Save Pages flag\r
{\r
- s2s_configSave(scsiDev.target->id, bytesPerSector);\r
+ scsiDev.target->device->saveConfig(scsiDev.target);\r
}\r
}\r
break;\r
scsiDev.phase = STATUS;\r
}\r
\r
-int scsiModeCommand()\r
+int scsiModeCommand(S2S_Device* dev)\r
{\r
int commandHandled = 1;\r
\r
// SCSI1 standard: (CCS X3T9.2/86-52)\r
// "An Allocation Length of zero indicates that no MODE SENSE data shall\r
// be transferred. This condition shall not be considered as an error."\r
- doModeSense(1, dbd, pc, pageCode, allocLength);\r
+ doModeSense(dev, 1, dbd, pc, pageCode, allocLength);\r
}\r
else if (command == 0x5A)\r
{\r
int allocLength =\r
(((uint16_t) scsiDev.cdb[7]) << 8) +\r
scsiDev.cdb[8];\r
- doModeSense(0, dbd, pc, pageCode, allocLength);\r
+ doModeSense(dev, 0, dbd, pc, pageCode, allocLength);\r
}\r
else if (command == 0x15)\r
{\r
#ifndef MODE_H
#define MODE_H
-int scsiModeCommand(void);
+int scsiModeCommand(S2S_Device* dev);
#endif
}\r
else if (scsiDev.target->cfg->quirks == S2S_CFG_QUIRKS_OMTI)\r
{\r
- scsiDev.status |= (scsiDev.target->id & 0x03) << 5;\r
+ scsiDev.status |= (scsiDev.target->cfg->scsiId & 0x03) << 5;\r
scsiWriteByte(scsiDev.status);\r
}\r
else\r
{\r
scsiReadBuffer();\r
}\r
- else if (!scsiModeCommand() && !scsiVendorCommand())\r
+ else if (!scsiModeCommand(scsiDev.target->device) && !scsiVendorCommand())\r
{\r
scsiDev.target->state.sense.code = ILLEGAL_REQUEST;\r
scsiDev.target->state.sense.asc = INVALID_COMMAND_OPERATION_CODE;\r
\r
state->syncOffset = 0;\r
state->syncPeriod = 0;\r
-\r
- // TODO This should probably be done in a device-specific init function.\r
- targets[i].cfg = s2s_getConfigByIndex(i);\r
- targets[i].id = targets[i].cfg->scsiId;\r
- targets[i].device = &(devices[deviceIdx]);\r
}\r
}\r
firstInit = 0;\r
uint8_t idMask = 0;\r
for (int i = 0; i < 8; ++i)\r
{\r
- const S2S_TargetCfg* cfg = s2s_getConfigById(i);\r
- if (cfg && (cfg->scsiId & S2S_CFG_TARGET_ENABLED))\r
+ const S2S_Target* tgt = s2s_DeviceFindByScsiId(i);\r
+ if (tgt && (tgt->cfg->scsiId & S2S_CFG_TARGET_ENABLED))\r
{\r
idMask |= (1 << i);\r
}\r
\r
#include <string.h>\r
\r
+static void sd_earlyInit(S2S_Device* dev);\r
static const S2S_BoardCfg* sd_getBoardConfig(S2S_Device* dev);\r
-//static const S2S_TargetCfg* sd_findByScsiId(S2S_Device* dev, int scsiId);\r
static S2S_Target* sd_getTargets(S2S_Device* dev, int* count);\r
static uint32_t sd_getCapacity(S2S_Device* dev);\r
+static int sd_pollMediaChange(S2S_Device* dev);\r
+static void sd_saveConfig(S2S_Target* target);\r
\r
// Global\r
SdCard sdCard S2S_DMA_ALIGN = {\r
{\r
+ sd_earlyInit,\r
sd_getBoardConfig,\r
- //sd_findByScsiId,\r
sd_getTargets,\r
- sd_getCapacity\r
+ sd_getCapacity,\r
+ sd_pollMediaChange,\r
+ sd_saveConfig\r
}\r
};\r
\r
S2S_Device* sdDevice = &(sdCard.dev);\r
\r
-static int sdCmdActive = 0;\r
+static int sdCmdActive = 0; // TODO MOVE to sdCard\r
\r
int\r
sdReadDMAPoll(uint32_t remainingSectors)\r
memcpy(sdCard.csd, &SDCardInfo.SD_csd, sizeof(sdCard.csd));\r
memcpy(sdCard.cid, &SDCardInfo.SD_cid, sizeof(sdCard.cid));\r
sdCard.capacity = SDCardInfo.CardCapacity / SD_SECTOR_SIZE;\r
- blockDev.state |= DISK_PRESENT | DISK_INITIALISED;\r
+ sdCard.dev.mediaState |= MEDIA_PRESENT | MEDIA_INITIALISED;\r
result = 1;\r
\r
// SD Benchmark code\r
}\r
\r
//bad:\r
- blockDev.state &= ~(DISK_PRESENT | DISK_INITIALISED);\r
+ sdCard.dev.mediaState &= ~(MEDIA_PRESENT | MEDIA_INITIALISED);\r
\r
sdCard.capacity = 0;\r
\r
\r
if (firstInit)\r
{\r
- blockDev.state &= ~(DISK_PRESENT | DISK_INITIALISED);\r
+ sdCard.dev.mediaState &= ~(MEDIA_PRESENT | MEDIA_INITIALISED);\r
sdClear();\r
sdInitDMA();\r
}\r
uint8_t cs = HAL_GPIO_ReadPin(nSD_CD_GPIO_Port, nSD_CD_Pin) ? 0 : 1;\r
uint8_t wp = HAL_GPIO_ReadPin(nSD_WP_GPIO_Port, nSD_WP_Pin) ? 0 : 1;\r
\r
- if (cs && !(blockDev.state & DISK_PRESENT))\r
+ if (cs && !(sdCard.dev.mediaState & MEDIA_PRESENT))\r
{\r
s2s_ledOn();\r
\r
\r
if (sdDoInit())\r
{\r
- blockDev.state |= DISK_PRESENT | DISK_INITIALISED;\r
+ sdCard.dev.mediaState |= MEDIA_PRESENT | MEDIA_INITIALISED;\r
\r
if (wp)\r
{\r
- blockDev.state |= DISK_WP;\r
+ sdCard.dev.mediaState |= MEDIA_WP;\r
}\r
else\r
{\r
- blockDev.state &= ~DISK_WP;\r
+ sdCard.dev.mediaState &= ~MEDIA_WP;\r
}\r
\r
// Always "start" the device. Many systems (eg. Apple System 7)\r
// LOGICAL_UNIT_NOT_READY_INITIALIZING_COMMAND_REQUIRED sense\r
// code, even if they stopped it first with\r
// START STOP UNIT command.\r
- blockDev.state |= DISK_STARTED;\r
+ sdCard.dev.mediaState |= MEDIA_STARTED;\r
\r
result = 1;\r
\r
s2s_ledOff();\r
}\r
}\r
- else if (!cs && (blockDev.state & DISK_PRESENT))\r
+ else if (!cs && (sdCard.dev.mediaState & MEDIA_PRESENT))\r
{\r
sdCard.capacity = 0;\r
- blockDev.state &= ~DISK_PRESENT;\r
- blockDev.state &= ~DISK_INITIALISED;\r
+ sdCard.dev.mediaState &= ~MEDIA_PRESENT;\r
+ sdCard.dev.mediaState &= ~MEDIA_INITIALISED;\r
int i;\r
for (i = 0; i < S2S_MAX_TARGETS; ++i)\r
{\r
return result;\r
}\r
\r
+static void sd_earlyInit(S2S_Device* dev)\r
+{\r
+ SdCard* sdCardDevice = (SdCard*)dev;\r
+\r
+ for (int i = 0; i < S2S_MAX_TARGETS; ++i)\r
+ {\r
+ sdCardDevice->targets[i].device = dev;\r
+ sdCardDevice->targets[i].cfg = (const S2S_TargetCfg*)\r
+ (&(sdCardDevice->cfg[0]) + sizeof(S2S_BoardCfg) + (i * sizeof(S2S_TargetCfg)));\r
+ }\r
+ sdCardDevice->lastPollMediaTime = s2s_getTime_ms();\r
+\r
+ // Don't require the host to send us a START STOP UNIT command\r
+ sdCardDevice->dev.mediaState = MEDIA_STARTED;\r
+\r
+}\r
+\r
static const S2S_BoardCfg* sd_getBoardConfig(S2S_Device* dev)\r
{\r
SdCard* sdCardDevice = (SdCard*)dev;\r
\r
- if ((blockDev.state & DISK_PRESENT) && sdCardDevice->capacity)\r
+ if (memcmp(__fixed_config, "BCFG", 4) == 0)\r
+ {\r
+ // Use hardcoded config if available. Hardcoded config always refers\r
+ // to the SD card.\r
+ memcpy(&(sdCardDevice->cfg[0]), __fixed_config, S2S_CFG_SIZE);\r
+ return (S2S_BoardCfg*) &(sdCardDevice->cfg[0]);\r
+ }\r
+ else if ((sdCard.dev.mediaState & MEDIA_PRESENT) && sdCardDevice->capacity)\r
{\r
int cfgSectors = (S2S_CFG_SIZE + 511) / 512;\r
BSP_SD_ReadBlocks_DMA(\r
- (uint32_t*) &(sdCardDevice->boardCfg[0]),\r
+ (uint32_t*) &(sdCardDevice->cfg[0]),\r
(sdCardDevice->capacity - cfgSectors) * 512ll,\r
512,\r
cfgSectors);\r
\r
- S2S_BoardCfg* cfg = (S2S_BoardCfg*) &(sdCardDevice->boardCfg[0]);\r
+ S2S_BoardCfg* cfg = (S2S_BoardCfg*) &(sdCardDevice->cfg[0]);\r
if (memcmp(cfg->magic, "BCFG", 4))\r
{\r
+ // Set a default Target disk config\r
+ memcpy(\r
+ &(sdCardDevice->cfg[0]) + sizeof(S2S_BoardCfg),\r
+ DEFAULT_TARGET_CONFIG,\r
+ sizeof(DEFAULT_TARGET_CONFIG));\r
+\r
return NULL;\r
}\r
else\r
return NULL;\r
}\r
\r
-//static const S2S_TargetCfg* sd_findByScsiId(S2S_Device* dev, int scsiId)\r
static S2S_Target* sd_getTargets(S2S_Device* dev, int* count)\r
{\r
SdCard* sdCardDevice = (SdCard*)dev;\r
SdCard* sdCardDevice = (SdCard*)dev;\r
return sdCardDevice->capacity;\r
}\r
+\r
+static int sd_pollMediaChange(S2S_Device* dev)\r
+{\r
+ SdCard* sdCardDevice = (SdCard*)dev;\r
+ if (s2s_elapsedTime_ms(sdCardDevice->lastPollMediaTime) > 200)\r
+ {\r
+ sdCardDevice->lastPollMediaTime = s2s_getTime_ms();\r
+ return sdInit();\r
+ }\r
+ else\r
+ {\r
+ return 0;\r
+ }\r
+}\r
+\r
+static void sd_saveConfig(S2S_Target* target)\r
+{\r
+ SdCard* sdCardDevice = (SdCard*)target->device;\r
+ target->cfg->bytesPerSector = target->state.bytesPerSector;\r
+\r
+ BSP_SD_WriteBlocks_DMA(\r
+ (uint32_t*) (&(sdCardDevice->cfg[0])),\r
+ (sdCardDevice->capacity - S2S_CFG_SIZE) * 512ll,\r
+ 512,\r
+ (S2S_CFG_SIZE + 511) / 512);\r
+}\r
{
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];
uint8_t csd[16]; // Unparsed CSD
uint8_t cid[16]; // Unparsed CID
+
+ uint32_t lastPollMediaTime;
+
} SdCard;
extern SdCard sdCard; // TODO move to .c file
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,