if (track > 1)
{
scsiDev.status = CHECK_CONDITION;
- scsiDev.target->sense.code = ILLEGAL_REQUEST;
- scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;
+ scsiDev.target->state.sense.asc = INVALID_FIELD_IN_CDB;
scsiDev.phase = STATUS;
}
else
memcpy(scsiDev.data, SimpleTOC, len);
uint32_t capacity = getScsiCapacity(
+ scsoDev.target->device,
scsiDev.target->cfg->sdSectorStart,
- scsiDev.target->liveCfg.bytesPerSector,
+ scsiDev.target->state.bytesPerSector,
scsiDev.target->cfg->scsiSectors);
// Replace start of leadout track
if (session > 1)
{
scsiDev.status = CHECK_CONDITION;
- scsiDev.target->sense.code = ILLEGAL_REQUEST;
- scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;
+ scsiDev.target->state.sense.asc = INVALID_FIELD_IN_CDB;
scsiDev.phase = STATUS;
}
else
default:
{
scsiDev.status = CHECK_CONDITION;
- scsiDev.target->sense.code = ILLEGAL_REQUEST;
- scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;
+ scsiDev.target->state.sense.asc = INVALID_FIELD_IN_CDB;
scsiDev.phase = STATUS;
}
}
\r
#include <string.h>\r
\r
-static const uint16_t FIRMWARE_VERSION = 0x0484;\r
+static const uint16_t FIRMWARE_VERSION = 0x0485;\r
\r
// 1 flash row\r
static const uint8_t DEFAULT_CONFIG[256] =\r
static void\r
sdInfoCommand()\r
{\r
- uint8_t response[sizeof(sdDev.csd) + sizeof(sdDev.cid)];\r
- memcpy(response, sdDev.csd, sizeof(sdDev.csd));\r
- memcpy(response + sizeof(sdDev.csd), sdDev.cid, sizeof(sdDev.cid));\r
+ uint8_t response[sizeof(sdCard.csd) + sizeof(sdCard.cid)];\r
+ memcpy(response, sdCard.csd, sizeof(sdCard.csd));\r
+ memcpy(response + sizeof(sdCard.csd), sdCard.cid, sizeof(sdCard.cid));\r
\r
hidPacket_send(response, sizeof(response));\r
}\r
hidBuffer[23] = scsiDev.msgCount;\r
hidBuffer[24] = scsiDev.cmdCount;\r
hidBuffer[25] = scsiDev.watchdogTick;\r
- hidBuffer[26] = blockDev.state;\r
+ hidBuffer[26] = 0; // OBSOLETE. Previously media state\r
hidBuffer[27] = scsiDev.lastSenseASC >> 8;\r
hidBuffer[28] = scsiDev.lastSenseASC;\r
hidBuffer[29] = scsiReadDBxPins();\r
hidBuffer[30] = LastTrace;\r
\r
- hidBuffer[58] = sdDev.capacity >> 24;\r
- hidBuffer[59] = sdDev.capacity >> 16;\r
- hidBuffer[60] = sdDev.capacity >> 8;\r
- hidBuffer[61] = sdDev.capacity;\r
+ hidBuffer[58] = sdCard.capacity >> 24;\r
+ hidBuffer[59] = sdCard.capacity >> 16;\r
+ hidBuffer[60] = sdCard.capacity >> 8;\r
+ hidBuffer[61] = sdCard.capacity;\r
\r
hidBuffer[62] = FIRMWARE_VERSION >> 8;\r
hidBuffer[63] = FIRMWARE_VERSION;\r
// Nowhere to store this data!\r
// Shouldn't happen - our buffer should be many magnitudes larger\r
// than the required size for diagnostic parameters.\r
- scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
- scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;\r
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;\r
+ scsiDev.target->state.sense.asc = INVALID_FIELD_IN_CDB;\r
scsiDev.status = CHECK_CONDITION;\r
scsiDev.phase = STATUS;\r
}\r
// 64bit linear address, then convert back again.\r
uint64 fromByteAddr =\r
scsiByteAddress(\r
- scsiDev.target->liveCfg.bytesPerSector,\r
+ scsiDev.target->state.bytesPerSector,\r
scsiDev.target->cfg->headsPerCylinder,\r
scsiDev.target->cfg->sectorsPerTrack,\r
suppliedFmt,\r
&scsiDev.data[6]);\r
\r
scsiSaveByteAddress(\r
- scsiDev.target->liveCfg.bytesPerSector,\r
+ scsiDev.target->state.bytesPerSector,\r
scsiDev.target->cfg->headsPerCylinder,\r
scsiDev.target->cfg->sectorsPerTrack,\r
translateFmt,\r
{\r
// error.\r
scsiDev.status = CHECK_CONDITION;\r
- scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
- scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;\r
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;\r
+ scsiDev.target->state.sense.asc = INVALID_FIELD_IN_CDB;\r
scsiDev.phase = STATUS;\r
}\r
\r
{\r
// error.\r
scsiDev.status = CHECK_CONDITION;\r
- scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
- scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;\r
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;\r
+ scsiDev.target->state.sense.asc = INVALID_FIELD_IN_CDB;\r
scsiDev.phase = STATUS;\r
}\r
}\r
{\r
// error.\r
scsiDev.status = CHECK_CONDITION;\r
- scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
- scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;\r
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;\r
+ scsiDev.target->state.sense.asc = INVALID_FIELD_IN_CDB;\r
scsiDev.phase = STATUS;\r
}\r
}\r
// Section 4.3.14\r
void scsiWriteSectorBuffer()\r
{\r
- scsiDev.dataLen = scsiDev.target->liveCfg.bytesPerSector;\r
+ scsiDev.dataLen = scsiDev.target->state.bytesPerSector;\r
scsiDev.phase = DATA_OUT;\r
scsiDev.postDataOutHook = doWriteBuffer;\r
}\r
#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
- result = sdInit();\r
-\r
- if (result)\r
- {\r
- blockDev.state = blockDev.state | DISK_INITIALISED;\r
- }\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
// Save the "MODE SELECT savable parameters"\r
configSave(\r
scsiDev.target->targetId,\r
- scsiDev.target->liveCfg.bytesPerSector);\r
+ scsiDev.target->state.bytesPerSector);\r
}\r
\r
if (IP)\r
int pmi = scsiDev.cdb[8] & 1;\r
\r
uint32_t capacity = getScsiCapacity(\r
+ scsiDev.target->device,\r
+ scsiDev.device,\r
scsiDev.target->cfg->sdSectorStart,\r
- scsiDev.target->liveCfg.bytesPerSector,\r
+ scsiDev.target->state.bytesPerSector,\r
scsiDev.target->cfg->scsiSectors);\r
\r
if (!pmi && lba)\r
// assume that delays are constant across each block. But the spec\r
// says we must return this error if pmi is specified incorrectly.\r
scsiDev.status = CHECK_CONDITION;\r
- scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
- scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;\r
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;\r
+ scsiDev.target->state.sense.asc = INVALID_FIELD_IN_CDB;\r
scsiDev.phase = STATUS;\r
}\r
else if (capacity > 0)\r
scsiDev.data[2] = highestBlock >> 8;\r
scsiDev.data[3] = highestBlock;\r
\r
- uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;\r
+ uint32_t bytesPerSector = scsiDev.target->state.bytesPerSector;\r
scsiDev.data[4] = bytesPerSector >> 24;\r
scsiDev.data[5] = bytesPerSector >> 16;\r
scsiDev.data[6] = bytesPerSector >> 8;\r
else\r
{\r
scsiDev.status = CHECK_CONDITION;\r
- scsiDev.target->sense.code = NOT_READY;\r
- scsiDev.target->sense.asc = MEDIUM_NOT_PRESENT;\r
+ scsiDev.target->state.sense.code = NOT_READY;\r
+ scsiDev.target->state.sense.asc = MEDIUM_NOT_PRESENT;\r
scsiDev.phase = STATUS;\r
}\r
}\r
CyDelay(10);\r
}\r
\r
- uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;\r
+ uint32_t bytesPerSector = scsiDev.target->state.bytesPerSector;\r
+ MEDIA_STATE* mediaState = &(scsiDev.target->device->mediaState);\r
\r
- if (unlikely(blockDev.state & DISK_WP) ||\r
+ if (unlikely(*mediaState & MEDIA_WP) ||\r
unlikely(scsiDev.target->cfg->deviceType == CONFIG_OPTICAL))\r
\r
{\r
scsiDev.status = CHECK_CONDITION;\r
- scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
- scsiDev.target->sense.asc = WRITE_PROTECTED;\r
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;\r
+ scsiDev.target->state.sense.asc = WRITE_PROTECTED;\r
scsiDev.phase = STATUS;\r
}\r
else if (unlikely(((uint64) lba) + blocks >\r
getScsiCapacity(\r
+ scsiDev->device,\r
scsiDev.target->cfg->sdSectorStart,\r
bytesPerSector,\r
scsiDev.target->cfg->scsiSectors\r
))\r
{\r
scsiDev.status = CHECK_CONDITION;\r
- scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
- scsiDev.target->sense.asc = LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;\r
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;\r
+ scsiDev.target->state.sense.asc = LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;\r
scsiDev.phase = STATUS;\r
}\r
else\r
\r
uint32_t capacity = getScsiCapacity(\r
scsiDev.target->cfg->sdSectorStart,\r
- scsiDev.target->liveCfg.bytesPerSector,\r
+ scsiDev.target->state.bytesPerSector,\r
scsiDev.target->cfg->scsiSectors);\r
if (unlikely(((uint64) lba) + blocks > capacity))\r
{\r
scsiDev.status = CHECK_CONDITION;\r
- scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
- scsiDev.target->sense.asc = LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;\r
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;\r
+ scsiDev.target->state.sense.asc = LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;\r
scsiDev.phase = STATUS;\r
}\r
else\r
scsiDev.phase = DATA_IN;\r
scsiDev.dataLen = 0; // No data yet\r
\r
- uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;\r
+ uint32_t bytesPerSector = scsiDev.target->state.bytesPerSector;\r
uint32_t sdSectorPerSCSISector = SDSectorsPerSCSISector(bytesPerSector);\r
uint32_t sdSectors =\r
blocks * sdSectorPerSCSISector;\r
if (lba >=\r
getScsiCapacity(\r
scsiDev.target->cfg->sdSectorStart,\r
- scsiDev.target->liveCfg.bytesPerSector,\r
+ scsiDev.target->state.bytesPerSector,\r
scsiDev.target->cfg->scsiSectors)\r
)\r
{\r
scsiDev.status = CHECK_CONDITION;\r
- scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
- scsiDev.target->sense.asc = LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;\r
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;\r
+ scsiDev.target->state.sense.asc = LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;\r
scsiDev.phase = STATUS;\r
}\r
else\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->sense.code = NOT_READY;\r
- scsiDev.target->sense.asc = LOGICAL_UNIT_NOT_READY_INITIALIZING_COMMAND_REQUIRED;\r
+ scsiDev.target->state.sense.code = NOT_READY;\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->sense.code = NOT_READY;\r
- scsiDev.target->sense.asc = MEDIUM_NOT_PRESENT;\r
+ scsiDev.target->state.sense.code = NOT_READY;\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
- scsiDev.target->sense.code = NOT_READY;\r
- scsiDev.target->sense.asc = LOGICAL_UNIT_NOT_READY_CAUSE_NOT_REPORTABLE;\r
+ scsiDev.target->state.sense.code = NOT_READY;\r
+ scsiDev.target->state.sense.asc = LOGICAL_UNIT_NOT_READY_CAUSE_NOT_REPORTABLE;\r
scsiDev.phase = STATUS;\r
}\r
return ready;\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
// TODO. This means they are supplying data to verify against.\r
// Technically we should probably grab the data and compare it.\r
scsiDev.status = CHECK_CONDITION;\r
- scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
- scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;\r
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;\r
+ scsiDev.target->state.sense.asc = INVALID_FIELD_IN_CDB;\r
scsiDev.phase = STATUS;\r
}\r
}\r
\r
void scsiDiskPoll()\r
{\r
- uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;\r
+ uint32_t bytesPerSector = scsiDev.target->state.bytesPerSector;\r
\r
if (scsiDev.phase == DATA_IN &&\r
transfer.currentBlock != transfer.blocks)\r
(scsiDev.boardCfg.flags & CONFIG_ENABLE_PARITY) &&\r
(scsiDev.compatMode >= COMPAT_SCSI2))\r
{\r
- scsiDev.target->sense.code = ABORTED_COMMAND;\r
- scsiDev.target->sense.asc = SCSI_PARITY_ERROR;\r
+ scsiDev.target->state.sense.code = ABORTED_COMMAND;\r
+ scsiDev.target->state.sense.asc = SCSI_PARITY_ERROR;\r
scsiDev.status = CHECK_CONDITION;;\r
}\r
scsiDev.phase = STATUS;\r
{\r
scsiDiskReset();\r
\r
- // Don't require the host to send us a START STOP UNIT command\r
- blockDev.state = DISK_STARTED;\r
// WP pin not available for micro-sd\r
// TODO read card WP register\r
#if 0\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 currentBlock;
} Transfer;
-extern BlockDevice blockDev;
extern Transfer transfer;
void scsiDiskInit(void);
#include "device.h"
#include "config.h"
-#include "sd.h"
+#include "storedevice.h"
typedef enum
{
}
uint32_t getScsiCapacity(
+ S2S_Device* device,
uint32_t sdSectorStart,
uint16_t bytesPerSector,
uint32_t scsiSectors);
{
// error.
scsiDev.status = CHECK_CONDITION;
- scsiDev.target->sense.code = ILLEGAL_REQUEST;
- scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;
+ scsiDev.target->state.sense.asc = INVALID_FIELD_IN_CDB;
scsiDev.phase = STATUS;
}
}
{
// error.
scsiDev.status = CHECK_CONDITION;
- scsiDev.target->sense.code = ILLEGAL_REQUEST;
- scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;
+ scsiDev.target->state.sense.asc = INVALID_FIELD_IN_CDB;
scsiDev.phase = STATUS;
}
else
{
// error.
scsiDev.status = CHECK_CONDITION;
- scsiDev.target->sense.code = ILLEGAL_REQUEST;
- scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;
+ scsiDev.target->state.sense.asc = INVALID_FIELD_IN_CDB;
scsiDev.phase = STATUS;
}
{\r
timeInit();\r
ledInit();\r
+ s2s_deviceEarlyInit();\r
traceInit();\r
\r
// Enable global interrupts.\r
configInit(&scsiDev.boardCfg);\r
debugInit();\r
\r
+\r
scsiPhyConfig();\r
\r
scsiInit();\r
++delaySeconds;\r
}\r
\r
- uint32_t lastSDPoll = getTime_ms();\r
sdCheckPresent();\r
\r
while (1)\r
\r
if (unlikely(scsiDev.phase == BUS_FREE))\r
{\r
- if (unlikely(elapsedTime_ms(lastSDPoll) > 200))\r
+ if (s2s_pollMediaChange())\r
{\r
- lastSDPoll = getTime_ms();\r
- sdCheckPresent();\r
+ scsiPhyConfig();\r
+ scsiInit();\r
}\r
else\r
{\r
CyExitCriticalSection(interruptState);\r
}\r
}\r
- else if ((scsiDev.phase >= 0) && (blockDev.state & DISK_PRESENT))\r
+ else if ((scsiDev.phase >= 0) &&\r
+ scsiDev.target &&\r
+ (scsiDev.target->device->mediaState & MEDIA_PRESENT))\r
{\r
- // don't waste time scanning SD cards while we're doing disk IO\r
- lastSDPoll = getTime_ms();\r
+ scsiDev.target->device->pollMediaBusy();\r
}\r
}\r
return 0;\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 CONFIG_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 CONFIG_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 CONFIG_MO:\r
- mediumType = 0x03; // Optical reversible or erasable medium\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.data[idx++] = 0; // reserved\r
\r
// Block length\r
- uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;\r
+ uint32_t bytesPerSector = scsiDev.target->state.bytesPerSector;\r
scsiDev.data[idx++] = bytesPerSector >> 16;\r
scsiDev.data[idx++] = bytesPerSector >> 8;\r
scsiDev.data[idx++] = bytesPerSector & 0xFF;\r
scsiDev.data[idx+11] = sectorsPerTrack & 0xFF;\r
\r
// Fill out the configured bytes-per-sector\r
- uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;\r
+ uint32_t bytesPerSector = scsiDev.target->state.bytesPerSector;\r
scsiDev.data[idx+12] = bytesPerSector >> 8;\r
scsiDev.data[idx+13] = bytesPerSector & 0xFF;\r
}\r
uint32 sector;\r
LBA2CHS(\r
getScsiCapacity(\r
+ scsiDev.target->device,\r
scsiDev.target->cfg->sdSectorStart,\r
- scsiDev.target->liveCfg.bytesPerSector,\r
+ scsiDev.target->state.bytesPerSector,\r
scsiDev.target->cfg->scsiSectors),\r
&cyl,\r
&head,\r
// Unknown Page Code\r
pageFound = 0;\r
scsiDev.status = CHECK_CONDITION;\r
- scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
- scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;\r
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;\r
+ scsiDev.target->state.sense.asc = INVALID_FIELD_IN_CDB;\r
scsiDev.phase = STATUS;\r
}\r
else\r
}\r
else\r
{\r
- scsiDev.target->liveCfg.bytesPerSector = bytesPerSector;\r
+ scsiDev.target->state.bytesPerSector = bytesPerSector;\r
if (bytesPerSector != scsiDev.target->cfg->bytesPerSector)\r
{\r
configSave(scsiDev.target->targetId, bytesPerSector);\r
goto bad;\r
}\r
\r
- scsiDev.target->liveCfg.bytesPerSector = bytesPerSector;\r
+ scsiDev.target->state.bytesPerSector = bytesPerSector;\r
if (scsiDev.cdb[1] & 1) // SP Save Pages flag\r
{\r
configSave(scsiDev.target->targetId, bytesPerSector);\r
goto out;\r
bad:\r
scsiDev.status = CHECK_CONDITION;\r
- scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
- scsiDev.target->sense.asc = INVALID_FIELD_IN_PARAMETER_LIST;\r
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;\r
+ scsiDev.target->state.sense.asc = INVALID_FIELD_IN_PARAMETER_LIST;\r
\r
out:\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) 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
scsiDev.phase = STATUS;\r
\r
scsiDev.lastStatus = scsiDev.status;\r
- scsiDev.lastSense = scsiDev.target->sense.code;\r
- scsiDev.lastSenseASC = scsiDev.target->sense.asc;\r
+ scsiDev.lastSense = scsiDev.target->state.sense.code;\r
+ scsiDev.lastSenseASC = scsiDev.target->state.sense.asc;\r
}\r
\r
void process_Status()\r
}\r
else if (scsiDev.target->cfg->quirks == CONFIG_QUIRKS_OMTI)\r
{\r
- scsiDev.status |= (scsiDev.target->targetId & 0x03) << 5;\r
+ scsiDev.status |= (scsiDev.target->cfg->scsiId & 0x03) << 5;\r
scsiWriteByte(scsiDev.status);\r
}\r
else\r
}\r
\r
scsiDev.lastStatus = scsiDev.status;\r
- scsiDev.lastSense = scsiDev.target->sense.code;\r
- scsiDev.lastSenseASC = scsiDev.target->sense.asc;\r
+ scsiDev.lastSense = scsiDev.target->state.sense.code;\r
+ scsiDev.lastSenseASC = scsiDev.target->state.sense.asc;\r
\r
\r
// Command Complete occurs AFTER a valid status has been\r
(scsiDev.boardCfg.flags & CONFIG_ENABLE_PARITY) &&\r
(scsiDev.compatMode >= COMPAT_SCSI2))\r
{\r
- scsiDev.target->sense.code = ABORTED_COMMAND;\r
- scsiDev.target->sense.asc = SCSI_PARITY_ERROR;\r
+ scsiDev.target->state.sense.code = ABORTED_COMMAND;\r
+ scsiDev.target->state.sense.asc = SCSI_PARITY_ERROR;\r
enter_Status(CHECK_CONDITION);\r
}\r
}\r
// http://bitsavers.trailing-edge.com/pdf/xebec/104524C_S1410Man_Aug83.pdf\r
if ((scsiDev.lun > 0) && (scsiDev.boardCfg.flags & CONFIG_MAP_LUNS_TO_IDS))\r
{\r
- int tgtIndex;\r
- for (tgtIndex = 0; tgtIndex < MAX_SCSI_TARGETS; ++tgtIndex)\r
+ S2S_Target* lunTarget = s2s_DeviceFindByScsiId(scsiDev.lun);\r
+ if (lunTarget! = NULL)\r
{\r
- if (scsiDev.targets[tgtIndex].targetId == scsiDev.lun)\r
- {\r
- scsiDev.target = &scsiDev.targets[tgtIndex];\r
- scsiDev.lun = 0;\r
- break;\r
- }\r
+ scsiDev.target = lunTarget;\r
+ scsiDev.lun = 0;\r
}\r
}\r
\r
(scsiDev.boardCfg.flags & CONFIG_ENABLE_PARITY) &&\r
(scsiDev.compatMode >= COMPAT_SCSI2))\r
{\r
- scsiDev.target->sense.code = ABORTED_COMMAND;\r
- scsiDev.target->sense.asc = SCSI_PARITY_ERROR;\r
+ scsiDev.target->state.sense.code = ABORTED_COMMAND;\r
+ scsiDev.target->state.sense.asc = SCSI_PARITY_ERROR;\r
enter_Status(CHECK_CONDITION);\r
}\r
else if ((control & 0x02) && ((control & 0x01) == 0) &&\r
likely(scsiDev.target->cfg->quirks != CONFIG_QUIRKS_XEBEC))\r
{\r
// FLAG set without LINK flag.\r
- scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
- scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;\r
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;\r
+ scsiDev.target->state.sense.asc = INVALID_FIELD_IN_CDB;\r
enter_Status(CHECK_CONDITION);\r
}\r
else if (command == 0x12)\r
{\r
// Completely non-standard\r
allocLength = 4;\r
- if (scsiDev.target->sense.code == NO_SENSE)\r
+ if (scsiDev.target->state.sense.code == NO_SENSE)\r
scsiDev.data[0] = 0;\r
- else if (scsiDev.target->sense.code == ILLEGAL_REQUEST)\r
+ else if (scsiDev.target->state.sense.code == ILLEGAL_REQUEST)\r
scsiDev.data[0] = 0x20; // Illegal command\r
- else if (scsiDev.target->sense.code == NOT_READY)\r
+ else if (scsiDev.target->state.sense.code == NOT_READY)\r
scsiDev.data[0] = 0x04; // Drive not ready\r
else\r
scsiDev.data[0] = 0x11; // Uncorrectable data error\r
\r
memset(scsiDev.data, 0, 256); // Max possible alloc length\r
scsiDev.data[0] = 0xF0;\r
- scsiDev.data[2] = scsiDev.target->sense.code & 0x0F;\r
+ scsiDev.data[2] = scsiDev.target->state.sense.code & 0x0F;\r
\r
scsiDev.data[3] = transfer.lba >> 24;\r
scsiDev.data[4] = transfer.lba >> 16;\r
\r
// Additional bytes if there are errors to report\r
scsiDev.data[7] = 10; // additional length\r
- scsiDev.data[12] = scsiDev.target->sense.asc >> 8;\r
- scsiDev.data[13] = scsiDev.target->sense.asc;\r
+ scsiDev.data[12] = scsiDev.target->state.sense.asc >> 8;\r
+ scsiDev.data[13] = scsiDev.target->state.sense.asc;\r
}\r
\r
// Silently truncate results. SCSI-2 spec 8.2.14.\r
enter_DataIn(allocLength);\r
\r
// This is a good time to clear out old sense information.\r
- scsiDev.target->sense.code = NO_SENSE;\r
- scsiDev.target->sense.asc = NO_ADDITIONAL_SENSE_INFORMATION;\r
+ scsiDev.target->state.sense.code = NO_SENSE;\r
+ scsiDev.target->state.sense.asc = NO_ADDITIONAL_SENSE_INFORMATION;\r
}\r
// Some old SCSI drivers do NOT properly support\r
// unitAttention. eg. the Mac Plus would trigger a SCSI reset\r
// on receiving the unit attention response on boot, thus\r
// triggering another unit attention condition.\r
- else if (scsiDev.target->unitAttention &&\r
+ else if (scsiDev.target->state.unitAttention &&\r
(scsiDev.boardCfg.flags & CONFIG_ENABLE_UNIT_ATTENTION))\r
{\r
- scsiDev.target->sense.code = UNIT_ATTENTION;\r
- scsiDev.target->sense.asc = scsiDev.target->unitAttention;\r
+ scsiDev.target->state.sense.code = UNIT_ATTENTION;\r
+ scsiDev.target->state.sense.asc = scsiDev.target->state.unitAttention;\r
\r
// If initiator doesn't do REQUEST SENSE for the next command, then\r
// data is lost.\r
- scsiDev.target->unitAttention = 0;\r
+ scsiDev.target->state.unitAttention = 0;\r
\r
enter_Status(CHECK_CONDITION);\r
}\r
else if (scsiDev.lun)\r
{\r
- scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
- scsiDev.target->sense.asc = LOGICAL_UNIT_NOT_SUPPORTED;\r
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;\r
+ scsiDev.target->state.sense.asc = LOGICAL_UNIT_NOT_SUPPORTED;\r
enter_Status(CHECK_CONDITION);\r
}\r
else if (command == 0x17 || command == 0x16)\r
{\r
doReserveRelease();\r
}\r
- else if ((scsiDev.target->reservedId >= 0) &&\r
- (scsiDev.target->reservedId != scsiDev.initiatorId))\r
+ else if ((scsiDev.target->state.reservedId >= 0) &&\r
+ (scsiDev.target->state.reservedId != scsiDev.initiatorId))\r
{\r
enter_Status(CONFLICT);\r
}\r
{\r
scsiReadBuffer();\r
}\r
- else if (!scsiModeCommand() && !scsiVendorCommand())\r
+ else if (!scsiModeCommand(scsiDev.target->device) && !scsiVendorCommand())\r
{\r
- scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
- scsiDev.target->sense.asc = INVALID_COMMAND_OPERATION_CODE;\r
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;\r
+ scsiDev.target->state.sense.asc = INVALID_COMMAND_OPERATION_CODE;\r
enter_Status(CHECK_CONDITION);\r
}\r
\r
uint8 command = scsiDev.cdb[0];\r
\r
int canRelease =\r
- (!thirdPty && (scsiDev.initiatorId == scsiDev.target->reservedId)) ||\r
+ (!thirdPty && (scsiDev.initiatorId == scsiDev.target->state.reservedId)) ||\r
(thirdPty &&\r
- (scsiDev.target->reserverId == scsiDev.initiatorId) &&\r
- (scsiDev.target->reservedId == thirdPtyId)\r
+ (scsiDev.target->state.reserverId == scsiDev.initiatorId) &&\r
+ (scsiDev.target->state.reservedId == thirdPtyId)\r
);\r
\r
if (extentReservation)\r
{\r
// Not supported.\r
- scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
- scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;\r
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;\r
+ scsiDev.target->state.sense.asc = INVALID_FIELD_IN_CDB;\r
enter_Status(CHECK_CONDITION);\r
}\r
else if (command == 0x17) // release\r
{\r
- if ((scsiDev.target->reservedId < 0) || canRelease)\r
+ if ((scsiDev.target->state.reservedId < 0) || canRelease)\r
{\r
- scsiDev.target->reservedId = -1;\r
- scsiDev.target->reserverId = -1;\r
+ scsiDev.target->state.reservedId = -1;\r
+ scsiDev.target->state.reserverId = -1;\r
}\r
else\r
{\r
}\r
else // assume reserve.\r
{\r
- if ((scsiDev.target->reservedId < 0) || canRelease)\r
+ if ((scsiDev.target->state.reservedId < 0) || canRelease)\r
{\r
- scsiDev.target->reserverId = scsiDev.initiatorId;\r
+ scsiDev.target->state.reserverId = scsiDev.initiatorId;\r
if (thirdPty)\r
{\r
- scsiDev.target->reservedId = thirdPtyId;\r
+ scsiDev.target->state.reservedId = thirdPtyId;\r
}\r
else\r
{\r
- scsiDev.target->reservedId = scsiDev.initiatorId;\r
+ scsiDev.target->state.reservedId = scsiDev.initiatorId;\r
}\r
}\r
else\r
\r
if (scsiDev.target)\r
{\r
- if (scsiDev.target->unitAttention != POWER_ON_RESET)\r
+ if (scsiDev.target->state.unitAttention != POWER_ON_RESET)\r
{\r
- scsiDev.target->unitAttention = SCSI_BUS_RESET;\r
+ scsiDev.target->state.unitAttention = SCSI_BUS_RESET;\r
}\r
- scsiDev.target->reservedId = -1;\r
- scsiDev.target->reserverId = -1;\r
- scsiDev.target->sense.code = NO_SENSE;\r
- scsiDev.target->sense.asc = NO_ADDITIONAL_SENSE_INFORMATION;\r
+ scsiDev.target->state.reservedId = -1;\r
+ scsiDev.target->state.reserverId = -1;\r
+ scsiDev.target->state.sense.code = NO_SENSE;\r
+ scsiDev.target->state.sense.asc = NO_ADDITIONAL_SENSE_INFORMATION;\r
}\r
scsiDev.target = NULL;\r
scsiDiskReset();\r
int goodParity = (Lookup_OddParity[mask] == SCSI_ReadPin(SCSI_In_DBP));\r
int atnFlag = SCSI_ReadFilt(SCSI_Filt_ATN);\r
\r
- int tgtIndex;\r
- TargetState* target = NULL;\r
- for (tgtIndex = 0; tgtIndex < MAX_SCSI_TARGETS; ++tgtIndex)\r
+ S2S_Target* target = NULL;\r
+ for (int testIdx = 0; testtIndex < 8; ++testtIndex)\r
{\r
- if (mask & (1 << scsiDev.targets[tgtIndex].targetId))\r
+ target = s2s_DeviceFindByScsiId(1 << testIdx);\r
+ if (target)\r
{\r
- target = &scsiDev.targets[tgtIndex];\r
break;\r
}\r
}\r
+\r
sel &= (selLatchCfg && scsiDev.selFlag) || SCSI_ReadFilt(SCSI_Filt_SEL);\r
bsy |= SCSI_ReadFilt(SCSI_Filt_BSY);\r
#ifdef SCSI_In_IO\r
// controllers don't generate parity bits.\r
if (!scsiDev.atnFlag)\r
{\r
- target->unitAttention = 0;\r
+ target->state.unitAttention = 0;\r
scsiDev.compatMode = COMPAT_SCSI1;\r
}\r
else if (!(scsiDev.boardCfg.flags & CONFIG_ENABLE_SCSI2))\r
\r
scsiDiskReset();\r
\r
- scsiDev.target->unitAttention = SCSI_BUS_RESET;\r
+ scsiDev.target->state.unitAttention = SCSI_BUS_RESET;\r
\r
// ANY initiator can reset the reservation state via this message.\r
- scsiDev.target->reservedId = -1;\r
- scsiDev.target->reserverId = -1;\r
+ scsiDev.target->state.reservedId = -1;\r
+ scsiDev.target->state.reserverId = -1;\r
enter_BusFree();\r
}\r
else if (scsiDev.msgOut == 0x05)\r
scsiDev.target = NULL;\r
scsiDev.compatMode = COMPAT_UNKNOWN;\r
\r
- int i;\r
- for (i = 0; i < MAX_SCSI_TARGETS; ++i)\r
+ int deviceCount;\r
+ S2S_Device* allDevices = s2s_GetDevices(&deviceCount);\r
+ for (int devIdx = 0; devIdx < deviceCount; ++devIdx)\r
{\r
- const TargetConfig* cfg = getConfigByIndex(i);\r
- if (cfg && (cfg->scsiId & CONFIG_TARGET_ENABLED))\r
- {\r
- scsiDev.targets[i].targetId = cfg->scsiId & CONFIG_TARGET_ID_BITS;\r
- scsiDev.targets[i].cfg = cfg;\r
+ int targetCount;\r
+ S2S_Target* targets = devices[deviceIdx].getTargets(devices + deviceIdx, &targetCount);\r
\r
- scsiDev.targets[i].liveCfg.bytesPerSector = cfg->bytesPerSector;\r
- }\r
- else\r
+ for (int i = 0; i < targetCount; ++i)\r
{\r
- scsiDev.targets[i].targetId = 0xff;\r
- scsiDev.targets[i].cfg = NULL;\r
+ S2S_TargetState* state = &(targets[i].state);\r
+\r
+ scsiDev.targets[i].state.reservedId = -1;\r
+ scsiDev.targets[i].state.reserverId = -1;\r
+ scsiDev.targets[i].state.unitAttention = POWER_ON_RESET;\r
+ scsiDev.targets[i].state.sense.code = NO_SENSE;\r
+ scsiDev.targets[i].state.sense.asc = NO_ADDITIONAL_SENSE_INFORMATION;\r
+\r
+ state->bytesPerSector = targets[i].cfg->bytesPerSector;\r
}\r
- scsiDev.targets[i].reservedId = -1;\r
- scsiDev.targets[i].reserverId = -1;\r
- scsiDev.targets[i].unitAttention = POWER_ON_RESET;\r
- scsiDev.targets[i].sense.code = NO_SENSE;\r
- scsiDev.targets[i].sense.asc = NO_ADDITIONAL_SENSE_INFORMATION;\r
}\r
}\r
\r
#ifndef SCSI_H
#define SCSI_H
+#include "storedevice.h"
#include "geometry.h"
-#include "sense.h"
typedef enum
{
#define MAX_SECTOR_SIZE 8192
#define MIN_SECTOR_SIZE 64
-// Shadow parameters, possibly not saved to flash yet.
-// Set via Mode Select
typedef struct
{
- uint16_t bytesPerSector;
-} LiveCfg;
-
-typedef struct
-{
- uint8_t targetId;
-
- const TargetConfig* cfg;
-
- LiveCfg liveCfg;
-
- ScsiSense sense;
-
- uint16 unitAttention; // Set to the sense qualifier key to be returned.
-
- // Only let the reserved initiator talk to us.
- // A 3rd party may be sending the RESERVE/RELEASE commands
- int reservedId; // 0 -> 7 if reserved. -1 if not reserved.
- int reserverId; // 0 -> 7 if reserved. -1 if not reserved.
-} TargetState;
-
-typedef struct
-{
- TargetState targets[MAX_SCSI_TARGETS];
- TargetState* target;
- BoardConfig boardCfg;
-
+ S2S_Target* target;
// Set to true (1) if the ATN flag was set, and we need to
// enter the MESSAGE_OUT phase.
\r
#include <string.h>\r
\r
+static void sd_earlyInit(S2S_Device* dev);\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_pollMediaBusy(S2S_Device* dev);\r
+\r
// Global\r
-SdDevice sdDev;\r
+SdCard sdCard S2S_DMA_ALIGN = {\r
+ {\r
+ sd_earlyInit,\r
+ sd_getTargets,\r
+ sd_getCapacity,\r
+ sd_pollMediaChange,\r
+ sd_pollMediaBusy\r
+ }\r
+};\r
+S2S_Device* sdDevice = &(sdCard.dev);\r
\r
enum SD_CMD_STATE { CMD_STATE_IDLE, CMD_STATE_READ, CMD_STATE_WRITE };\r
static int sdCmdState = CMD_STATE_IDLE;\r
{\r
uint32_t tmpNextLBA = sdLBA + sdSectors;\r
\r
- if (!sdDev.ccs)\r
+ if (!sdCard.ccs)\r
{\r
sdLBA = sdLBA * SD_SECTOR_SIZE;\r
tmpNextLBA = tmpNextLBA * SD_SECTOR_SIZE;\r
sdClearStatus();\r
\r
scsiDev.status = CHECK_CONDITION;\r
- scsiDev.target->sense.code = HARDWARE_ERROR;\r
- scsiDev.target->sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;\r
+ scsiDev.target->state.sense.code = HARDWARE_ERROR;\r
+ scsiDev.target->state.sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;\r
scsiDev.phase = STATUS;\r
}\r
else\r
if (scsiDev.status != CHECK_CONDITION)\r
{\r
scsiDev.status = CHECK_CONDITION;\r
- scsiDev.target->sense.code = HARDWARE_ERROR;\r
- scsiDev.target->sense.asc = UNRECOVERED_READ_ERROR;\r
+ scsiDev.target->state.sense.code = HARDWARE_ERROR;\r
+ scsiDev.target->state.sense.asc = UNRECOVERED_READ_ERROR;\r
scsiDev.phase = STATUS;\r
}\r
sdClearStatus();\r
sdPreCmdState(CMD_STATE_READ);\r
\r
uint8 v;\r
- if (!sdDev.ccs)\r
+ if (!sdCard.ccs)\r
{\r
lba = lba * SD_SECTOR_SIZE;\r
}\r
sdClearStatus();\r
\r
scsiDev.status = CHECK_CONDITION;\r
- scsiDev.target->sense.code = HARDWARE_ERROR;\r
- scsiDev.target->sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;\r
+ scsiDev.target->state.sense.code = HARDWARE_ERROR;\r
+ scsiDev.target->state.sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;\r
scsiDev.phase = STATUS;\r
}\r
else\r
if (unlikely(r1b) && (scsiDev.phase == DATA_IN))\r
{\r
scsiDev.status = CHECK_CONDITION;\r
- scsiDev.target->sense.code = HARDWARE_ERROR;\r
- scsiDev.target->sense.asc = UNRECOVERED_READ_ERROR;\r
+ scsiDev.target->state.sense.code = HARDWARE_ERROR;\r
+ scsiDev.target->state.sense.asc = UNRECOVERED_READ_ERROR;\r
scsiDev.phase = STATUS;\r
}\r
}\r
sdClearStatus();\r
\r
scsiDev.status = CHECK_CONDITION;\r
- scsiDev.target->sense.code = HARDWARE_ERROR;\r
- scsiDev.target->sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;\r
+ scsiDev.target->state.sense.code = HARDWARE_ERROR;\r
+ scsiDev.target->state.sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;\r
scsiDev.phase = STATUS;\r
}\r
else\r
{\r
sdClearStatus();\r
scsiDev.status = CHECK_CONDITION;\r
- scsiDev.target->sense.code = HARDWARE_ERROR;\r
- scsiDev.target->sense.asc = WRITE_ERROR_AUTO_REALLOCATION_FAILED;\r
+ scsiDev.target->state.sense.code = HARDWARE_ERROR;\r
+ scsiDev.target->state.sense.asc = WRITE_ERROR_AUTO_REALLOCATION_FAILED;\r
scsiDev.phase = STATUS;\r
}\r
}\r
if (status == SD_R1_IDLE)\r
{\r
// Version 2 card.\r
- sdDev.version = 2;\r
+ sdCard.version = 2;\r
// Read 32bit response. Should contain the same bytes that\r
// we sent in the command parameter.\r
sdSpiByte(0xFF);\r
else if (status & SD_R1_ILLEGAL)\r
{\r
// Version 1 card.\r
- sdDev.version = 1;\r
+ sdCard.version = 1;\r
sdClearStatus();\r
break;\r
}\r
buf[i] = sdSpiByte(0xFF);\r
}\r
\r
- sdDev.ccs = (buf[0] & 0x40) ? 1 : 0;\r
+ sdCard.ccs = (buf[0] & 0x40) ? 1 : 0;\r
complete = (buf[0] & 0x80);\r
\r
} while (!status &&\r
\r
for (i = 0; i < 16; ++i)\r
{\r
- sdDev.cid[i] = sdSpiByte(0xFF);\r
+ sdCard.cid[i] = sdSpiByte(0xFF);\r
}\r
sdSpiByte(0xFF); // CRC\r
sdSpiByte(0xFF); // CRC\r
\r
for (i = 0; i < 16; ++i)\r
{\r
- sdDev.csd[i] = sdSpiByte(0xFF);\r
+ sdCard.csd[i] = sdSpiByte(0xFF);\r
}\r
sdSpiByte(0xFF); // CRC\r
sdSpiByte(0xFF); // CRC\r
\r
- if ((sdDev.csd[0] >> 6) == 0x00)\r
+ if ((sdCard.csd[0] >> 6) == 0x00)\r
{\r
// CSD version 1\r
// C_SIZE in bits [73:62]\r
- uint32 c_size = (((((uint32)sdDev.csd[6]) & 0x3) << 16) | (((uint32)sdDev.csd[7]) << 8) | sdDev.csd[8]) >> 6;\r
- uint32 c_mult = (((((uint32)sdDev.csd[9]) & 0x3) << 8) | ((uint32)sdDev.csd[0xa])) >> 7;\r
- uint32 sectorSize = sdDev.csd[5] & 0x0F;\r
- sdDev.capacity = ((c_size+1) * ((uint64)1 << (c_mult+2)) * ((uint64)1 << sectorSize)) / SD_SECTOR_SIZE;\r
+ uint32 c_size = (((((uint32)sdCard.csd[6]) & 0x3) << 16) | (((uint32)sdCard.csd[7]) << 8) | sdCard.csd[8]) >> 6;\r
+ uint32 c_mult = (((((uint32)sdCard.csd[9]) & 0x3) << 8) | ((uint32)sdCard.csd[0xa])) >> 7;\r
+ uint32 sectorSize = sdCard.csd[5] & 0x0F;\r
+ sdCard.capacity = ((c_size+1) * ((uint64)1 << (c_mult+2)) * ((uint64)1 << sectorSize)) / SD_SECTOR_SIZE;\r
}\r
- else if ((sdDev.csd[0] >> 6) == 0x01)\r
+ else if ((sdCard.csd[0] >> 6) == 0x01)\r
{\r
// CSD version 2\r
// C_SIZE in bits [69:48]\r
\r
uint32 c_size =\r
- ((((uint32)sdDev.csd[7]) & 0x3F) << 16) |\r
- (((uint32)sdDev.csd[8]) << 8) |\r
- ((uint32)sdDev.csd[7]);\r
- sdDev.capacity = (c_size + 1) * 1024;\r
+ ((((uint32)sdCard.csd[7]) & 0x3F) << 16) |\r
+ (((uint32)sdCard.csd[8]) << 8) |\r
+ ((uint32)sdCard.csd[7]);\r
+ sdCard.capacity = (c_size + 1) * 1024;\r
}\r
else\r
{\r
uint8 v;\r
\r
sdCmdState = CMD_STATE_IDLE;\r
- sdDev.version = 0;\r
- sdDev.ccs = 0;\r
- sdDev.capacity = 0;\r
- memset(sdDev.csd, 0, sizeof(sdDev.csd));\r
- memset(sdDev.cid, 0, sizeof(sdDev.cid));\r
+ sdCard.version = 0;\r
+ sdCard.ccs = 0;\r
+ sdCard.capacity = 0;\r
+ memset(sdCard.csd, 0, sizeof(sdCard.csd));\r
+ memset(sdCard.cid, 0, sizeof(sdCard.cid));\r
\r
sdInitDMA();\r
\r
if (!sdOpCond()) goto bad; // ACMD41. Wait for init completes.\r
if (!sdReadOCR()) goto bad; // CMD58. Get CCS flag. Only valid after init.\r
\r
- // This command will be ignored if sdDev.ccs is set.\r
+ // This command will be ignored if sdCard.ccs is set.\r
// SDHC and SDXC are always 512bytes.\r
v = sdCRCCommandAndResponse(SD_SET_BLOCKLEN, SD_SECTOR_SIZE); //Force sector size\r
if(v){goto bad;}\r
\r
bad:\r
SD_Data_Clk_SetDivider(clkDiv25MHz); // Restore the clock for our next retry\r
- sdDev.capacity = 0;\r
+ sdCard.capacity = 0;\r
\r
out:\r
sdClearStatus();\r
{\r
uint32_t tmpNextLBA = sdLBA + sdSectors;\r
\r
- if (!sdDev.ccs)\r
+ if (!sdCard.ccs)\r
{\r
sdLBA = sdLBA * SD_SECTOR_SIZE;\r
tmpNextLBA = tmpNextLBA * SD_SECTOR_SIZE;\r
scsiDiskReset();\r
sdClearStatus();\r
scsiDev.status = CHECK_CONDITION;\r
- scsiDev.target->sense.code = HARDWARE_ERROR;\r
- scsiDev.target->sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;\r
+ scsiDev.target->state.sense.code = HARDWARE_ERROR;\r
+ scsiDev.target->state.sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;\r
scsiDev.phase = STATUS;\r
}\r
else\r
uint8_t cs = SD_CS_Read();\r
SD_CS_SetDriveMode(SD_CS_DM_STRONG) ;\r
\r
- if (cs && !(blockDev.state & DISK_PRESENT))\r
+ if (cs && !(sdCard.dev.mediaState & MEDIA_PRESENT))\r
{\r
static int firstInit = 1;\r
\r
\r
if (sdInit())\r
{\r
- blockDev.state |= DISK_PRESENT | DISK_INITIALISED;\r
+ sdCard.dev.mediaState |= MEDIA_PRESENT | MEDIA_INITIALISED;\r
\r
// Always "start" the device. Many systems (eg. Apple System 7)\r
// won't respond properly to\r
firstInit = 0;\r
}\r
}\r
- else if (!cs && (blockDev.state & DISK_PRESENT))\r
+ else if (!cs && (sdCard.dev.mediaState & MEDIA_PRESENT))\r
{\r
- sdDev.capacity = 0;\r
- blockDev.state &= ~DISK_PRESENT;\r
- blockDev.state &= ~DISK_INITIALISED;\r
+ sdCard.capacity = 0;\r
+ sdCard.dev.mediaState &= ~MEDIA_PRESENT;\r
+ sdCard.dev.mediaState &= ~MEDIA_INITIALISED;\r
int i;\r
for (i = 0; i < MAX_SCSI_TARGETS; ++i)\r
{\r
- scsiDev.targets[i].unitAttention = PARAMETERS_CHANGED;\r
+ sdCard.targets[i].state.unitAttention = PARAMETERS_CHANGED;\r
}\r
}\r
}\r
firstCheck = 0;\r
}\r
\r
+static void sd_earlyInit(S2S_Device* dev)\r
+{\r
+ SdCard* sdCardDevice = (SdCard*)dev;\r
+\r
+ for (int i = 0; i < MAX_TARGETS; ++i)\r
+ {\r
+ sdCardDevice->targets[i].device = dev;\r
+ sdCardDevice->targets[i].cfg = getConfigByIndex(i);\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 S2S_Target* sd_getTargets(S2S_Device* dev, int* count)\r
+{\r
+ SdCard* sdCardDevice = (SdCard*)dev;\r
+ *count = MAX_TARGETS;\r
+ return sdCardDevice->targets;\r
+}\r
+\r
+static uint32_t sd_getCapacity(S2S_Device* dev)\r
+{\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
+ sdCheckPresent();\r
+ return 0;\r
+ }\r
+ else\r
+ {\r
+ return 0;\r
+ }\r
+}\r
+\r
+static void sd_pollMediaBusy(S2S_Device* dev)\r
+{\r
+ SdCard* sdCardDevice = (SdCard*)dev;\r
+ sdCardDevice->lastPollMediaTime = s2s_getTime_ms();\r
+}\r
+\r
#ifndef SD_H
#define SD_H
+#include "storedevice.h"
+
#define SD_SECTOR_SIZE 512
typedef enum
typedef struct
{
+ S2S_Device dev;
+
+ S2S_Target targets[MAX_TARGETS];
+
int version; // SDHC = version 2.
int ccs; // Card Capacity Status. 1 = SDHC or SDXC
uint32 capacity; // in 512 byte blocks
uint8_t csd[16]; // Unparsed CSD
uint8_t cid[16]; // Unparsed CID
-} SdDevice;
-extern SdDevice sdDev;
+ uint32_t lastPollMediaTime;
+} SdCard;
+
+extern SdCard sdCard;
+extern S2S_Device* sdDevice;
+
extern volatile uint8_t sdRxDMAComplete;
extern volatile uint8_t sdTxDMAComplete;
--- /dev/null
+// Copyright (C) 2020 Michael McMaster <michael@codesrc.com>
+//
+// This file is part of SCSI2SD.
+//
+// SCSI2SD is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// SCSI2SD is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with SCSI2SD. If not, see <http://www.gnu.org/licenses/>.
+#include "storedevice.h"
+
+#include "sd.h"
+
+#include <stddef.h>
+#include <string.h>
+
+S2S_Target* s2s_DeviceFindByScsiId(int scsiId)
+{
+ int deviceCount;
+ S2S_Device* devices = s2s_GetDevices(&deviceCount);
+ for (int deviceIdx = 0; deviceIdx < deviceCount; ++deviceIdx)
+ {
+ int targetCount;
+ S2S_Target* targets = devices[deviceIdx].getTargets(devices + deviceIdx, &targetCount);
+ for (int targetIdx = 0; targetIdx < targetCount; ++targetIdx)
+ {
+ S2S_Target* target = targets + targetIdx;
+ if (target &&
+ (target->cfg->scsiId & S2S_CFG_TARGET_ENABLED) &&
+ ((target->cfg->scsiId & S2S_CFG_TARGET_ID_BITS) == scsiId))
+ {
+ return target;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+S2S_Device* s2s_GetDevices(int* count)
+{
+ *count = 1;
+ 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;
+}
--- /dev/null
+// Copyright (C) 2020 Michael McMaster <michael@codesrc.com>
+//
+// This file is part of SCSI2SD.
+//
+// SCSI2SD is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// SCSI2SD is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with SCSI2SD. If not, see <http://www.gnu.org/licenses/>.
+#ifndef S2S_DEVICE_H
+#define S2S_DEVICE_H
+
+#include "scsi2sd.h"
+#include "sense.h"
+
+#include <stdint.h>
+
+struct S2S_DeviceStruct;
+typedef struct S2S_DeviceStruct S2S_Device;
+
+struct S2S_TargetStruct;
+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;
+
+ uint16_t unitAttention; // Set to the sense qualifier key to be returned.
+
+ // Only let the reserved initiator talk to us.
+ // A 3rd party may be sending the RESERVE/RELEASE commands
+ int reservedId; // 0 -> 7 if reserved. -1 if not reserved.
+ int reserverId; // 0 -> 7 if reserved. -1 if not reserved.
+
+ // Shadow parameters, possibly not saved to flash yet.
+ // Set via Mode Select
+ uint16_t bytesPerSector;
+};
+
+struct S2S_TargetStruct
+{
+ S2S_Device* device;
+ S2S_TargetCfg* cfg;
+
+ S2S_TargetState state;
+};
+
+struct S2S_DeviceStruct
+{
+ void (*earlyInit)(S2S_Device* dev);
+
+ 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 (*pollMediaBusy)(S2S_Device* dev);
+
+ MEDIA_STATE mediaState;
+};
+
+S2S_Target* s2s_DeviceFindByScsiId(int scsiId);
+
+S2S_Device* s2s_GetDevices(int* count);
+
+void s2s_deviceEarlyInit();
+int s2s_pollMediaChange();
+#endif
+
+