]> localhost Git - SCSI2SD.git/commitdiff
Untested port of V6 multidev branch commit 3dc7c11acb55b16fd0a8a033f9fe877d7b18f269
authorMichael McMaster <michael@codesrc.com>
Sat, 2 Jan 2021 12:51:19 +0000 (22:51 +1000)
committerMichael McMaster <michael@codesrc.com>
Sat, 2 Jan 2021 12:51:19 +0000 (22:51 +1000)
16 files changed:
software/SCSI2SD/src/cdrom.c
software/SCSI2SD/src/config.c
software/SCSI2SD/src/diagnostic.c
software/SCSI2SD/src/disk.c
software/SCSI2SD/src/disk.h
software/SCSI2SD/src/geometry.h
software/SCSI2SD/src/inquiry.c
software/SCSI2SD/src/main.c
software/SCSI2SD/src/mode.c
software/SCSI2SD/src/mode.h
software/SCSI2SD/src/scsi.c
software/SCSI2SD/src/scsi.h
software/SCSI2SD/src/sd.c
software/SCSI2SD/src/sd.h
software/SCSI2SD/src/storedevice.c [new file with mode: 0644]
software/SCSI2SD/src/storedevice.h [new file with mode: 0644]

index 9b40859f97846886d22de52c4289a5af35d20495..7f93948ebf9332f240cceb7b572917413dc0b147 100755 (executable)
@@ -152,8 +152,8 @@ static void doReadTOC(int MSF, uint8_t track, uint16_t allocationLength)
        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
@@ -162,8 +162,9 @@ static void doReadTOC(int MSF, uint8_t track, uint16_t allocationLength)
                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
@@ -213,8 +214,8 @@ static void doReadFullTOC(int convertBCD, uint8_t session, uint16_t allocationLe
        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
@@ -297,8 +298,8 @@ int scsiCDRomCommand()
                        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;
                        }
                }
index cc3233e84b34006b21ec1b132598c5bfb4ff2ff3..ada1a472a97b985a8b78e69349a0c89152002c90 100755 (executable)
@@ -31,7 +31,7 @@
 \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
@@ -175,9 +175,9 @@ pingCommand()
 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
@@ -340,16 +340,16 @@ void debugPoll()
                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
index d8f6477b195bb177955b1554037555dd786c7102..a359df35f860af165cdb3ccebd222d535de3d2e0 100755 (executable)
@@ -50,8 +50,8 @@ void scsiSendDiagnostic()
                        // 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
@@ -95,14 +95,14 @@ void scsiReceiveDiagnostic()
                // 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
@@ -121,8 +121,8 @@ void scsiReceiveDiagnostic()
        {\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
@@ -169,8 +169,8 @@ void scsiReadBuffer()
        {\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
@@ -208,8 +208,8 @@ void scsiWriteBuffer()
        {\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
@@ -219,7 +219,7 @@ void scsiWriteBuffer()
 // 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
index 5c5a1deeaee7763c5f10270153ad86bda9836347..b49923a65bc90ddd6859d3e562cda1f95ebdf998 100755 (executable)
 #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
@@ -93,7 +77,7 @@ static void doFormatUnitHeader(void)
                // 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
@@ -123,8 +107,10 @@ static void doReadCapacity()
        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
@@ -134,8 +120,8 @@ static void doReadCapacity()
                // 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
@@ -147,7 +133,7 @@ static void doReadCapacity()
                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
@@ -158,8 +144,8 @@ static void doReadCapacity()
        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
@@ -172,19 +158,21 @@ static void doWrite(uint32 lba, uint32 blocks)
                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
@@ -192,8 +180,8 @@ static void doWrite(uint32 lba, uint32 blocks)
                ))\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
@@ -231,13 +219,13 @@ static void doRead(uint32 lba, uint32 blocks)
 \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
@@ -248,7 +236,7 @@ static void doRead(uint32 lba, uint32 blocks)
                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
@@ -284,13 +272,13 @@ static void doSeek(uint32 lba)
        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
@@ -301,33 +289,35 @@ static void doSeek(uint32 lba)
 \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
@@ -347,17 +337,21 @@ int scsiDiskCommand()
                //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
@@ -514,8 +508,8 @@ int scsiDiskCommand()
                        // 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
@@ -548,7 +542,7 @@ int scsiDiskCommand()
 \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
@@ -799,8 +793,8 @@ void scsiDiskPoll()
                                (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
@@ -834,8 +828,6 @@ void scsiDiskInit()
 {\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
index df197d7737cb732e3c14e322347878f1c41956fa..f78b0329878b11919b8bd5feae4f3a197ab3b258 100755 (executable)
 #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 currentBlock;
 } Transfer;
 
-extern BlockDevice blockDev;
 extern Transfer transfer;
 
 void scsiDiskInit(void);
index 8df3d4c97230d1e6cbd581e73360a8159e6cd4fc..76da6e133adccdcbe9c0a2c41da2e8e2b5ed30bb 100755 (executable)
@@ -20,7 +20,7 @@
 #include "device.h"
 
 #include "config.h"
-#include "sd.h"
+#include "storedevice.h"
 
 typedef enum
 {
@@ -35,6 +35,7 @@ static inline int SDSectorsPerSCSISector(uint16_t bytesPerSector)
 }
 
 uint32_t getScsiCapacity(
+       S2S_Device* device,
        uint32_t sdSectorStart,
        uint16_t bytesPerSector,
        uint32_t scsiSectors);
index 3b84c524adcec38879983e458765bee2e7635442..b51069d6931a4a395ef3c6a53f69a62a89195607 100755 (executable)
@@ -116,8 +116,8 @@ static void useCustomVPD(const TargetConfig* cfg, int pageCode)
        {
                // 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;
        }
 }
@@ -141,8 +141,8 @@ void scsiInquiry()
                {
                        // 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
@@ -206,8 +206,8 @@ void scsiInquiry()
        {
                // 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;
        }
 
index aa144bde2c676cc8256d4196d6ce9f3ca1dc588d..f552923a65bbc3108089aab3f381e7679fd8af92 100755 (executable)
@@ -29,6 +29,7 @@ int main()
 {\r
        timeInit();\r
        ledInit();\r
+       s2s_deviceEarlyInit();\r
        traceInit();\r
 \r
        // Enable global interrupts.\r
@@ -41,6 +42,7 @@ int main()
        configInit(&scsiDev.boardCfg);\r
        debugInit();\r
 \r
+\r
        scsiPhyConfig();\r
 \r
        scsiInit();\r
@@ -60,7 +62,6 @@ int main()
                ++delaySeconds;\r
        }\r
 \r
-       uint32_t lastSDPoll = getTime_ms();\r
        sdCheckPresent();\r
 \r
        while (1)\r
@@ -74,10 +75,10 @@ int main()
 \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
@@ -94,10 +95,11 @@ int main()
                                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
index bb16cf71df92da63a3d6b765ce67361875a30622..5c2e4dc61f3c8a26887887a7b5231fc8ec74506c 100755 (executable)
@@ -269,7 +269,12 @@ static int useCustomPages(const TargetConfig* cfg, int pc, int pageCode, int* id
 }\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
@@ -288,14 +293,14 @@ static void doModeSense(
                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
@@ -308,14 +313,14 @@ static void doModeSense(
        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
@@ -368,7 +373,7 @@ static void doModeSense(
                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
@@ -423,7 +428,7 @@ static void doModeSense(
                        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
@@ -457,8 +462,9 @@ static void doModeSense(
                        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
@@ -557,8 +563,8 @@ static void doModeSense(
                // 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
@@ -617,7 +623,7 @@ static void doModeSelect(void)
                        }\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
@@ -650,7 +656,7 @@ static void doModeSelect(void)
                                        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
@@ -669,14 +675,14 @@ static void doModeSelect(void)
        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
@@ -696,7 +702,7 @@ int scsiModeCommand()
                // 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
@@ -707,7 +713,7 @@ int scsiModeCommand()
                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
index 819b1f531803c8fa5ab580a339a880331e7cdeb4..887e91ab6029058bed512dda782b4c2e71bd8284 100755 (executable)
@@ -17,6 +17,6 @@
 #ifndef MODE_H
 #define MODE_H
 
-int scsiModeCommand(void);
+int scsiModeCommand(S2S_Device* dev);
 
 #endif
index dc39968c6738aba2ab8e7595c1bf8d65889b28a4..a4d59f055740a80a0090d4182e9a90811de09d3a 100755 (executable)
@@ -132,8 +132,8 @@ static void enter_Status(uint8 status)
        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
@@ -192,7 +192,7 @@ void process_Status()
        }\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
@@ -201,8 +201,8 @@ void process_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
        // Command Complete occurs AFTER a valid status has been\r
@@ -262,8 +262,8 @@ static void process_DataOut()
                        (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
@@ -318,15 +318,11 @@ static void process_Command()
        // 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
@@ -347,8 +343,8 @@ static void process_Command()
                (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
@@ -356,8 +352,8 @@ static void process_Command()
                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
@@ -373,11 +369,11 @@ static void process_Command()
                {\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
@@ -395,7 +391,7 @@ static void process_Command()
 \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
@@ -404,45 +400,45 @@ static void process_Command()
 \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
@@ -481,10 +477,10 @@ static void process_Command()
        {\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
@@ -504,25 +500,25 @@ static void doReserveRelease()
        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
@@ -531,16 +527,16 @@ static void doReserveRelease()
        }\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
@@ -569,14 +565,14 @@ static void scsiReset()
 \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
@@ -666,16 +662,16 @@ static void process_SelectionPhase()
        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
@@ -709,7 +705,7 @@ static void process_SelectionPhase()
                // 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
@@ -816,11 +812,11 @@ static void process_MessageOut()
 \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
@@ -1055,27 +1051,25 @@ void scsiInit()
        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
index d1a9f54c25e11391e0a7a14a69201209d25858ac..a259105a94c417d0dbef0d335b9ee49e254f58d6 100755 (executable)
@@ -17,8 +17,8 @@
 #ifndef SCSI_H
 #define SCSI_H
 
+#include "storedevice.h"
 #include "geometry.h"
-#include "sense.h"
 
 typedef enum
 {
@@ -73,37 +73,9 @@ 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.
index 6cd9029c857b61e1b63ded6df03af3d2e58a5f4e..3014e706d22eb72db6cc5785e29bf97e4acfb6cc 100755 (executable)
 \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
@@ -268,7 +283,7 @@ sdReadMultiSectorPrep(uint32_t sdLBA, uint32_t sdSectors)
 {\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
@@ -291,8 +306,8 @@ sdReadMultiSectorPrep(uint32_t sdLBA, uint32_t sdSectors)
                        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
@@ -330,8 +345,8 @@ dmaReadSector(uint8_t* outputBuffer)
                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
@@ -399,7 +414,7 @@ void sdReadSingleSectorDMA(uint32_t lba, uint8_t* outputBuffer)
        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
@@ -410,8 +425,8 @@ void sdReadSingleSectorDMA(uint32_t lba, uint8_t* outputBuffer)
                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
@@ -446,8 +461,8 @@ static void sdCompleteRead()
                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
@@ -544,8 +559,8 @@ sdWriteSectorDMAPoll()
                                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
@@ -599,8 +614,8 @@ static void sdCompleteWrite()
                {\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
@@ -627,7 +642,7 @@ static int sendIfCond()
                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
@@ -639,7 +654,7 @@ static int sendIfCond()
                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
@@ -688,7 +703,7 @@ static int sdReadOCR()
                        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
@@ -715,7 +730,7 @@ static void sdReadCID()
 \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
@@ -738,30 +753,30 @@ static int sdReadCSD()
 \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
@@ -809,11 +824,11 @@ int sdInit()
        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
@@ -848,7 +863,7 @@ int sdInit()
        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
@@ -882,7 +897,7 @@ int sdInit()
 \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
@@ -895,7 +910,7 @@ void sdWriteMultiSectorPrep(uint32_t sdLBA, uint32_t sdSectors)
 {\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
@@ -924,8 +939,8 @@ void sdWriteMultiSectorPrep(uint32_t sdLBA, uint32_t sdSectors)
                        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
@@ -968,7 +983,7 @@ void sdCheckPresent()
                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
@@ -981,7 +996,7 @@ void sdCheckPresent()
 \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
@@ -1001,18 +1016,68 @@ void sdCheckPresent()
                                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
index 8ffcee7d26efd35b4b0320f2ce8ef20c9e06b68e..d6e2ec8cc2fc16c0a518280181f52209d6972813 100755 (executable)
@@ -17,6 +17,8 @@
 #ifndef SD_H
 #define SD_H
 
+#include "storedevice.h"
+
 #define SD_SECTOR_SIZE 512
 
 typedef enum
@@ -52,15 +54,23 @@ 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;
 
diff --git a/software/SCSI2SD/src/storedevice.c b/software/SCSI2SD/src/storedevice.c
new file mode 100644 (file)
index 0000000..261f461
--- /dev/null
@@ -0,0 +1,74 @@
+//     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;
+}
diff --git a/software/SCSI2SD/src/storedevice.h b/software/SCSI2SD/src/storedevice.h
new file mode 100644 (file)
index 0000000..8d39cbd
--- /dev/null
@@ -0,0 +1,89 @@
+//     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
+
+