mirror of
https://github.com/fhgwright/SCSI2SD.git
synced 2024-12-26 22:30:54 +00:00
Untested port of V6 multidev branch commit 3dc7c11acb55b16fd0a8a033f9fe877d7b18f269
This commit is contained in:
parent
c59a94a16b
commit
35dec8a9fe
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static const uint16_t FIRMWARE_VERSION = 0x0484;
|
||||
static const uint16_t FIRMWARE_VERSION = 0x0485;
|
||||
|
||||
// 1 flash row
|
||||
static const uint8_t DEFAULT_CONFIG[256] =
|
||||
@ -175,9 +175,9 @@ pingCommand()
|
||||
static void
|
||||
sdInfoCommand()
|
||||
{
|
||||
uint8_t response[sizeof(sdDev.csd) + sizeof(sdDev.cid)];
|
||||
memcpy(response, sdDev.csd, sizeof(sdDev.csd));
|
||||
memcpy(response + sizeof(sdDev.csd), sdDev.cid, sizeof(sdDev.cid));
|
||||
uint8_t response[sizeof(sdCard.csd) + sizeof(sdCard.cid)];
|
||||
memcpy(response, sdCard.csd, sizeof(sdCard.csd));
|
||||
memcpy(response + sizeof(sdCard.csd), sdCard.cid, sizeof(sdCard.cid));
|
||||
|
||||
hidPacket_send(response, sizeof(response));
|
||||
}
|
||||
@ -340,16 +340,16 @@ void debugPoll()
|
||||
hidBuffer[23] = scsiDev.msgCount;
|
||||
hidBuffer[24] = scsiDev.cmdCount;
|
||||
hidBuffer[25] = scsiDev.watchdogTick;
|
||||
hidBuffer[26] = blockDev.state;
|
||||
hidBuffer[26] = 0; // OBSOLETE. Previously media state
|
||||
hidBuffer[27] = scsiDev.lastSenseASC >> 8;
|
||||
hidBuffer[28] = scsiDev.lastSenseASC;
|
||||
hidBuffer[29] = scsiReadDBxPins();
|
||||
hidBuffer[30] = LastTrace;
|
||||
|
||||
hidBuffer[58] = sdDev.capacity >> 24;
|
||||
hidBuffer[59] = sdDev.capacity >> 16;
|
||||
hidBuffer[60] = sdDev.capacity >> 8;
|
||||
hidBuffer[61] = sdDev.capacity;
|
||||
hidBuffer[58] = sdCard.capacity >> 24;
|
||||
hidBuffer[59] = sdCard.capacity >> 16;
|
||||
hidBuffer[60] = sdCard.capacity >> 8;
|
||||
hidBuffer[61] = sdCard.capacity;
|
||||
|
||||
hidBuffer[62] = FIRMWARE_VERSION >> 8;
|
||||
hidBuffer[63] = FIRMWARE_VERSION;
|
||||
|
@ -50,8 +50,8 @@ void scsiSendDiagnostic()
|
||||
// Nowhere to store this data!
|
||||
// Shouldn't happen - our buffer should be many magnitudes larger
|
||||
// than the required size for diagnostic parameters.
|
||||
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.status = CHECK_CONDITION;
|
||||
scsiDev.phase = STATUS;
|
||||
}
|
||||
@ -95,14 +95,14 @@ void scsiReceiveDiagnostic()
|
||||
// 64bit linear address, then convert back again.
|
||||
uint64 fromByteAddr =
|
||||
scsiByteAddress(
|
||||
scsiDev.target->liveCfg.bytesPerSector,
|
||||
scsiDev.target->state.bytesPerSector,
|
||||
scsiDev.target->cfg->headsPerCylinder,
|
||||
scsiDev.target->cfg->sectorsPerTrack,
|
||||
suppliedFmt,
|
||||
&scsiDev.data[6]);
|
||||
|
||||
scsiSaveByteAddress(
|
||||
scsiDev.target->liveCfg.bytesPerSector,
|
||||
scsiDev.target->state.bytesPerSector,
|
||||
scsiDev.target->cfg->headsPerCylinder,
|
||||
scsiDev.target->cfg->sectorsPerTrack,
|
||||
translateFmt,
|
||||
@ -121,8 +121,8 @@ void scsiReceiveDiagnostic()
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
||||
@ -169,8 +169,8 @@ void scsiReadBuffer()
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
@ -208,8 +208,8 @@ void scsiWriteBuffer()
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
@ -219,7 +219,7 @@ void scsiWriteBuffer()
|
||||
// Section 4.3.14
|
||||
void scsiWriteSectorBuffer()
|
||||
{
|
||||
scsiDev.dataLen = scsiDev.target->liveCfg.bytesPerSector;
|
||||
scsiDev.dataLen = scsiDev.target->state.bytesPerSector;
|
||||
scsiDev.phase = DATA_OUT;
|
||||
scsiDev.postDataOutHook = doWriteBuffer;
|
||||
}
|
||||
|
@ -28,24 +28,8 @@
|
||||
#include <string.h>
|
||||
|
||||
// Global
|
||||
BlockDevice blockDev;
|
||||
Transfer transfer;
|
||||
|
||||
static int doSdInit()
|
||||
{
|
||||
int result = 0;
|
||||
if (blockDev.state & DISK_PRESENT)
|
||||
{
|
||||
result = sdInit();
|
||||
|
||||
if (result)
|
||||
{
|
||||
blockDev.state = blockDev.state | DISK_INITIALISED;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Callback once all data has been read in the data out phase.
|
||||
static void doFormatUnitComplete(void)
|
||||
{
|
||||
@ -93,7 +77,7 @@ static void doFormatUnitHeader(void)
|
||||
// Save the "MODE SELECT savable parameters"
|
||||
configSave(
|
||||
scsiDev.target->targetId,
|
||||
scsiDev.target->liveCfg.bytesPerSector);
|
||||
scsiDev.target->state.bytesPerSector);
|
||||
}
|
||||
|
||||
if (IP)
|
||||
@ -123,8 +107,10 @@ static void doReadCapacity()
|
||||
int pmi = scsiDev.cdb[8] & 1;
|
||||
|
||||
uint32_t capacity = getScsiCapacity(
|
||||
scsiDev.target->device,
|
||||
scsiDev.device,
|
||||
scsiDev.target->cfg->sdSectorStart,
|
||||
scsiDev.target->liveCfg.bytesPerSector,
|
||||
scsiDev.target->state.bytesPerSector,
|
||||
scsiDev.target->cfg->scsiSectors);
|
||||
|
||||
if (!pmi && lba)
|
||||
@ -134,8 +120,8 @@ static void doReadCapacity()
|
||||
// assume that delays are constant across each block. But the spec
|
||||
// says we must return this error if pmi is specified incorrectly.
|
||||
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 if (capacity > 0)
|
||||
@ -147,7 +133,7 @@ static void doReadCapacity()
|
||||
scsiDev.data[2] = highestBlock >> 8;
|
||||
scsiDev.data[3] = highestBlock;
|
||||
|
||||
uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;
|
||||
uint32_t bytesPerSector = scsiDev.target->state.bytesPerSector;
|
||||
scsiDev.data[4] = bytesPerSector >> 24;
|
||||
scsiDev.data[5] = bytesPerSector >> 16;
|
||||
scsiDev.data[6] = bytesPerSector >> 8;
|
||||
@ -158,8 +144,8 @@ static void doReadCapacity()
|
||||
else
|
||||
{
|
||||
scsiDev.status = CHECK_CONDITION;
|
||||
scsiDev.target->sense.code = NOT_READY;
|
||||
scsiDev.target->sense.asc = MEDIUM_NOT_PRESENT;
|
||||
scsiDev.target->state.sense.code = NOT_READY;
|
||||
scsiDev.target->state.sense.asc = MEDIUM_NOT_PRESENT;
|
||||
scsiDev.phase = STATUS;
|
||||
}
|
||||
}
|
||||
@ -172,19 +158,21 @@ static void doWrite(uint32 lba, uint32 blocks)
|
||||
CyDelay(10);
|
||||
}
|
||||
|
||||
uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;
|
||||
uint32_t bytesPerSector = scsiDev.target->state.bytesPerSector;
|
||||
MEDIA_STATE* mediaState = &(scsiDev.target->device->mediaState);
|
||||
|
||||
if (unlikely(blockDev.state & DISK_WP) ||
|
||||
if (unlikely(*mediaState & MEDIA_WP) ||
|
||||
unlikely(scsiDev.target->cfg->deviceType == CONFIG_OPTICAL))
|
||||
|
||||
{
|
||||
scsiDev.status = CHECK_CONDITION;
|
||||
scsiDev.target->sense.code = ILLEGAL_REQUEST;
|
||||
scsiDev.target->sense.asc = WRITE_PROTECTED;
|
||||
scsiDev.target->state.sense.code = ILLEGAL_REQUEST;
|
||||
scsiDev.target->state.sense.asc = WRITE_PROTECTED;
|
||||
scsiDev.phase = STATUS;
|
||||
}
|
||||
else if (unlikely(((uint64) lba) + blocks >
|
||||
getScsiCapacity(
|
||||
scsiDev->device,
|
||||
scsiDev.target->cfg->sdSectorStart,
|
||||
bytesPerSector,
|
||||
scsiDev.target->cfg->scsiSectors
|
||||
@ -192,8 +180,8 @@ static void doWrite(uint32 lba, uint32 blocks)
|
||||
))
|
||||
{
|
||||
scsiDev.status = CHECK_CONDITION;
|
||||
scsiDev.target->sense.code = ILLEGAL_REQUEST;
|
||||
scsiDev.target->sense.asc = LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
|
||||
scsiDev.target->state.sense.code = ILLEGAL_REQUEST;
|
||||
scsiDev.target->state.sense.asc = LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
|
||||
scsiDev.phase = STATUS;
|
||||
}
|
||||
else
|
||||
@ -231,13 +219,13 @@ static void doRead(uint32 lba, uint32 blocks)
|
||||
|
||||
uint32_t capacity = getScsiCapacity(
|
||||
scsiDev.target->cfg->sdSectorStart,
|
||||
scsiDev.target->liveCfg.bytesPerSector,
|
||||
scsiDev.target->state.bytesPerSector,
|
||||
scsiDev.target->cfg->scsiSectors);
|
||||
if (unlikely(((uint64) lba) + blocks > capacity))
|
||||
{
|
||||
scsiDev.status = CHECK_CONDITION;
|
||||
scsiDev.target->sense.code = ILLEGAL_REQUEST;
|
||||
scsiDev.target->sense.asc = LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
|
||||
scsiDev.target->state.sense.code = ILLEGAL_REQUEST;
|
||||
scsiDev.target->state.sense.asc = LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
|
||||
scsiDev.phase = STATUS;
|
||||
}
|
||||
else
|
||||
@ -248,7 +236,7 @@ static void doRead(uint32 lba, uint32 blocks)
|
||||
scsiDev.phase = DATA_IN;
|
||||
scsiDev.dataLen = 0; // No data yet
|
||||
|
||||
uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;
|
||||
uint32_t bytesPerSector = scsiDev.target->state.bytesPerSector;
|
||||
uint32_t sdSectorPerSCSISector = SDSectorsPerSCSISector(bytesPerSector);
|
||||
uint32_t sdSectors =
|
||||
blocks * sdSectorPerSCSISector;
|
||||
@ -284,13 +272,13 @@ static void doSeek(uint32 lba)
|
||||
if (lba >=
|
||||
getScsiCapacity(
|
||||
scsiDev.target->cfg->sdSectorStart,
|
||||
scsiDev.target->liveCfg.bytesPerSector,
|
||||
scsiDev.target->state.bytesPerSector,
|
||||
scsiDev.target->cfg->scsiSectors)
|
||||
)
|
||||
{
|
||||
scsiDev.status = CHECK_CONDITION;
|
||||
scsiDev.target->sense.code = ILLEGAL_REQUEST;
|
||||
scsiDev.target->sense.asc = LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
|
||||
scsiDev.target->state.sense.code = ILLEGAL_REQUEST;
|
||||
scsiDev.target->state.sense.asc = LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
|
||||
scsiDev.phase = STATUS;
|
||||
}
|
||||
else
|
||||
@ -301,33 +289,35 @@ static void doSeek(uint32 lba)
|
||||
|
||||
static int doTestUnitReady()
|
||||
{
|
||||
MEDIA_STATE* mediaState = &(scsiDev.target->device->mediaState);
|
||||
|
||||
int ready = 1;
|
||||
if (likely(blockDev.state == (DISK_STARTED | DISK_PRESENT | DISK_INITIALISED)))
|
||||
if (likely(*mediaState == (MEDIA_STARTED | MEDIA_PRESENT | MEDIA_INITIALISED)))
|
||||
{
|
||||
// nothing to do.
|
||||
}
|
||||
else if (unlikely(!(blockDev.state & DISK_STARTED)))
|
||||
else if (unlikely(!(*mediaState & MEDIA_STARTED)))
|
||||
{
|
||||
ready = 0;
|
||||
scsiDev.status = CHECK_CONDITION;
|
||||
scsiDev.target->sense.code = NOT_READY;
|
||||
scsiDev.target->sense.asc = LOGICAL_UNIT_NOT_READY_INITIALIZING_COMMAND_REQUIRED;
|
||||
scsiDev.target->state.sense.code = NOT_READY;
|
||||
scsiDev.target->state.sense.asc = LOGICAL_UNIT_NOT_READY_INITIALIZING_COMMAND_REQUIRED;
|
||||
scsiDev.phase = STATUS;
|
||||
}
|
||||
else if (unlikely(!(blockDev.state & DISK_PRESENT)))
|
||||
else if (unlikely(!(*mediaState & MEDIA_PRESENT)))
|
||||
{
|
||||
ready = 0;
|
||||
scsiDev.status = CHECK_CONDITION;
|
||||
scsiDev.target->sense.code = NOT_READY;
|
||||
scsiDev.target->sense.asc = MEDIUM_NOT_PRESENT;
|
||||
scsiDev.target->state.sense.code = NOT_READY;
|
||||
scsiDev.target->state.sense.asc = MEDIUM_NOT_PRESENT;
|
||||
scsiDev.phase = STATUS;
|
||||
}
|
||||
else if (unlikely(!(blockDev.state & DISK_INITIALISED)))
|
||||
else if (unlikely(!(*mediaState & MEDIA_INITIALISED)))
|
||||
{
|
||||
ready = 0;
|
||||
scsiDev.status = CHECK_CONDITION;
|
||||
scsiDev.target->sense.code = NOT_READY;
|
||||
scsiDev.target->sense.asc = LOGICAL_UNIT_NOT_READY_CAUSE_NOT_REPORTABLE;
|
||||
scsiDev.target->state.sense.code = NOT_READY;
|
||||
scsiDev.target->state.sense.asc = LOGICAL_UNIT_NOT_READY_CAUSE_NOT_REPORTABLE;
|
||||
scsiDev.phase = STATUS;
|
||||
}
|
||||
return ready;
|
||||
@ -347,17 +337,21 @@ int scsiDiskCommand()
|
||||
//int immed = scsiDev.cdb[1] & 1;
|
||||
int start = scsiDev.cdb[4] & 1;
|
||||
|
||||
MEDIA_STATE* mediaState = &(scsiDev.target->device->mediaState);
|
||||
if (start)
|
||||
{
|
||||
blockDev.state = blockDev.state | DISK_STARTED;
|
||||
if (!(blockDev.state & DISK_INITIALISED))
|
||||
*mediaState = *mediaState | MEDIA_STARTED;
|
||||
if (!(*mediaState & MEDIA_INITIALISED))
|
||||
{
|
||||
doSdInit();
|
||||
if (*mediaState & MEDIA_PRESENT)
|
||||
{
|
||||
*mediaState = *mediaState | MEDIA_INITIALISED;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
blockDev.state &= ~DISK_STARTED;
|
||||
*mediaState &= ~MEDIA_STARTED;
|
||||
}
|
||||
}
|
||||
else if (unlikely(command == 0x00))
|
||||
@ -514,8 +508,8 @@ int scsiDiskCommand()
|
||||
// TODO. This means they are supplying data to verify against.
|
||||
// Technically we should probably grab the data and compare it.
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -548,7 +542,7 @@ int scsiDiskCommand()
|
||||
|
||||
void scsiDiskPoll()
|
||||
{
|
||||
uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;
|
||||
uint32_t bytesPerSector = scsiDev.target->state.bytesPerSector;
|
||||
|
||||
if (scsiDev.phase == DATA_IN &&
|
||||
transfer.currentBlock != transfer.blocks)
|
||||
@ -799,8 +793,8 @@ void scsiDiskPoll()
|
||||
(scsiDev.boardCfg.flags & CONFIG_ENABLE_PARITY) &&
|
||||
(scsiDev.compatMode >= COMPAT_SCSI2))
|
||||
{
|
||||
scsiDev.target->sense.code = ABORTED_COMMAND;
|
||||
scsiDev.target->sense.asc = SCSI_PARITY_ERROR;
|
||||
scsiDev.target->state.sense.code = ABORTED_COMMAND;
|
||||
scsiDev.target->state.sense.asc = SCSI_PARITY_ERROR;
|
||||
scsiDev.status = CHECK_CONDITION;;
|
||||
}
|
||||
scsiDev.phase = STATUS;
|
||||
@ -834,8 +828,6 @@ void scsiDiskInit()
|
||||
{
|
||||
scsiDiskReset();
|
||||
|
||||
// Don't require the host to send us a START STOP UNIT command
|
||||
blockDev.state = DISK_STARTED;
|
||||
// WP pin not available for micro-sd
|
||||
// TODO read card WP register
|
||||
#if 0
|
||||
|
@ -17,25 +17,12 @@
|
||||
#ifndef DISK_H
|
||||
#define DISK_H
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DISK_STARTED = 1, // Controlled via START STOP UNIT
|
||||
DISK_PRESENT = 2, // SD card is physically present
|
||||
DISK_INITIALISED = 4, // SD card responded to init sequence
|
||||
DISK_WP = 8 // Write-protect.
|
||||
} DISK_STATE;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TRANSFER_READ,
|
||||
TRANSFER_WRITE
|
||||
} TRANSFER_DIR;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int state;
|
||||
} BlockDevice;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int multiBlock; // True if we're using a multi-block SPI transfer.
|
||||
@ -45,7 +32,6 @@ typedef struct
|
||||
uint32 currentBlock;
|
||||
} Transfer;
|
||||
|
||||
extern BlockDevice blockDev;
|
||||
extern Transfer transfer;
|
||||
|
||||
void scsiDiskInit(void);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@ int main()
|
||||
{
|
||||
timeInit();
|
||||
ledInit();
|
||||
s2s_deviceEarlyInit();
|
||||
traceInit();
|
||||
|
||||
// Enable global interrupts.
|
||||
@ -41,6 +42,7 @@ int main()
|
||||
configInit(&scsiDev.boardCfg);
|
||||
debugInit();
|
||||
|
||||
|
||||
scsiPhyConfig();
|
||||
|
||||
scsiInit();
|
||||
@ -60,7 +62,6 @@ int main()
|
||||
++delaySeconds;
|
||||
}
|
||||
|
||||
uint32_t lastSDPoll = getTime_ms();
|
||||
sdCheckPresent();
|
||||
|
||||
while (1)
|
||||
@ -74,10 +75,10 @@ int main()
|
||||
|
||||
if (unlikely(scsiDev.phase == BUS_FREE))
|
||||
{
|
||||
if (unlikely(elapsedTime_ms(lastSDPoll) > 200))
|
||||
if (s2s_pollMediaChange())
|
||||
{
|
||||
lastSDPoll = getTime_ms();
|
||||
sdCheckPresent();
|
||||
scsiPhyConfig();
|
||||
scsiInit();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -94,10 +95,11 @@ int main()
|
||||
CyExitCriticalSection(interruptState);
|
||||
}
|
||||
}
|
||||
else if ((scsiDev.phase >= 0) && (blockDev.state & DISK_PRESENT))
|
||||
else if ((scsiDev.phase >= 0) &&
|
||||
scsiDev.target &&
|
||||
(scsiDev.target->device->mediaState & MEDIA_PRESENT))
|
||||
{
|
||||
// don't waste time scanning SD cards while we're doing disk IO
|
||||
lastSDPoll = getTime_ms();
|
||||
scsiDev.target->device->pollMediaBusy();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
@ -269,7 +269,12 @@ static int useCustomPages(const TargetConfig* cfg, int pc, int pageCode, int* id
|
||||
}
|
||||
|
||||
static void doModeSense(
|
||||
int sixByteCmd, int dbd, int pc, int pageCode, int allocLength)
|
||||
S2S_Device* dev,
|
||||
int sixByteCmd,
|
||||
int dbd,
|
||||
int pc,
|
||||
int pageCode,
|
||||
int allocLength)
|
||||
{
|
||||
////////////// Mode Parameter Header
|
||||
////////////////////////////////////
|
||||
@ -288,14 +293,14 @@ static void doModeSense(
|
||||
mediumType = 0; // We should support various floppy types here!
|
||||
// Contains cache bits (0) and a Write-Protect bit.
|
||||
deviceSpecificParam =
|
||||
(blockDev.state & DISK_WP) ? 0x80 : 0;
|
||||
(dev->mediaState & MEDIA_WP) ? 0x80 : 0;
|
||||
density = 0; // reserved for direct access
|
||||
break;
|
||||
|
||||
case CONFIG_FLOPPY_14MB:
|
||||
mediumType = 0x1E; // 90mm/3.5"
|
||||
deviceSpecificParam =
|
||||
(blockDev.state & DISK_WP) ? 0x80 : 0;
|
||||
(dev->mediaState & MEDIA_WP) ? 0x80 : 0;
|
||||
density = 0; // reserved for direct access
|
||||
break;
|
||||
|
||||
@ -308,14 +313,14 @@ static void doModeSense(
|
||||
case CONFIG_SEQUENTIAL:
|
||||
mediumType = 0; // reserved
|
||||
deviceSpecificParam =
|
||||
(blockDev.state & DISK_WP) ? 0x80 : 0;
|
||||
density = 0x13; // DAT Data Storage, X3B5/88-185A
|
||||
(dev->mediaState & MEDIA_WP) ? 0x80 : 0;
|
||||
density = 0x13; // DAT Data Storage, X3B5/88-185A
|
||||
break;
|
||||
|
||||
case CONFIG_MO:
|
||||
mediumType = 0x03; // Optical reversible or erasable medium
|
||||
mediumType = 0x03; // Optical reversible or erasable medium
|
||||
deviceSpecificParam =
|
||||
(blockDev.state & DISK_WP) ? 0x80 : 0;
|
||||
(dev->mediaState & MEDIA_WP) ? 0x80 : 0;
|
||||
density = 0x00; // Default
|
||||
break;
|
||||
|
||||
@ -368,7 +373,7 @@ static void doModeSense(
|
||||
scsiDev.data[idx++] = 0; // reserved
|
||||
|
||||
// Block length
|
||||
uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;
|
||||
uint32_t bytesPerSector = scsiDev.target->state.bytesPerSector;
|
||||
scsiDev.data[idx++] = bytesPerSector >> 16;
|
||||
scsiDev.data[idx++] = bytesPerSector >> 8;
|
||||
scsiDev.data[idx++] = bytesPerSector & 0xFF;
|
||||
@ -423,7 +428,7 @@ static void doModeSense(
|
||||
scsiDev.data[idx+11] = sectorsPerTrack & 0xFF;
|
||||
|
||||
// Fill out the configured bytes-per-sector
|
||||
uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;
|
||||
uint32_t bytesPerSector = scsiDev.target->state.bytesPerSector;
|
||||
scsiDev.data[idx+12] = bytesPerSector >> 8;
|
||||
scsiDev.data[idx+13] = bytesPerSector & 0xFF;
|
||||
}
|
||||
@ -457,8 +462,9 @@ static void doModeSense(
|
||||
uint32 sector;
|
||||
LBA2CHS(
|
||||
getScsiCapacity(
|
||||
scsiDev.target->device,
|
||||
scsiDev.target->cfg->sdSectorStart,
|
||||
scsiDev.target->liveCfg.bytesPerSector,
|
||||
scsiDev.target->state.bytesPerSector,
|
||||
scsiDev.target->cfg->scsiSectors),
|
||||
&cyl,
|
||||
&head,
|
||||
@ -557,8 +563,8 @@ static void doModeSense(
|
||||
// Unknown Page Code
|
||||
pageFound = 0;
|
||||
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
|
||||
@ -617,7 +623,7 @@ static void doModeSelect(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
scsiDev.target->liveCfg.bytesPerSector = bytesPerSector;
|
||||
scsiDev.target->state.bytesPerSector = bytesPerSector;
|
||||
if (bytesPerSector != scsiDev.target->cfg->bytesPerSector)
|
||||
{
|
||||
configSave(scsiDev.target->targetId, bytesPerSector);
|
||||
@ -650,7 +656,7 @@ static void doModeSelect(void)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
scsiDev.target->liveCfg.bytesPerSector = bytesPerSector;
|
||||
scsiDev.target->state.bytesPerSector = bytesPerSector;
|
||||
if (scsiDev.cdb[1] & 1) // SP Save Pages flag
|
||||
{
|
||||
configSave(scsiDev.target->targetId, bytesPerSector);
|
||||
@ -669,14 +675,14 @@ static void doModeSelect(void)
|
||||
goto out;
|
||||
bad:
|
||||
scsiDev.status = CHECK_CONDITION;
|
||||
scsiDev.target->sense.code = ILLEGAL_REQUEST;
|
||||
scsiDev.target->sense.asc = INVALID_FIELD_IN_PARAMETER_LIST;
|
||||
scsiDev.target->state.sense.code = ILLEGAL_REQUEST;
|
||||
scsiDev.target->state.sense.asc = INVALID_FIELD_IN_PARAMETER_LIST;
|
||||
|
||||
out:
|
||||
scsiDev.phase = STATUS;
|
||||
}
|
||||
|
||||
int scsiModeCommand()
|
||||
int scsiModeCommand(S2S_Device* dev)
|
||||
{
|
||||
int commandHandled = 1;
|
||||
|
||||
@ -696,7 +702,7 @@ int scsiModeCommand()
|
||||
// SCSI1 standard: (CCS X3T9.2/86-52)
|
||||
// "An Allocation Length of zero indicates that no MODE SENSE data shall
|
||||
// be transferred. This condition shall not be considered as an error."
|
||||
doModeSense(1, dbd, pc, pageCode, allocLength);
|
||||
doModeSense(dev, 1, dbd, pc, pageCode, allocLength);
|
||||
}
|
||||
else if (command == 0x5A)
|
||||
{
|
||||
@ -707,7 +713,7 @@ int scsiModeCommand()
|
||||
int allocLength =
|
||||
(((uint16) scsiDev.cdb[7]) << 8) +
|
||||
scsiDev.cdb[8];
|
||||
doModeSense(0, dbd, pc, pageCode, allocLength);
|
||||
doModeSense(dev, 0, dbd, pc, pageCode, allocLength);
|
||||
}
|
||||
else if (command == 0x15)
|
||||
{
|
||||
|
@ -17,6 +17,6 @@
|
||||
#ifndef MODE_H
|
||||
#define MODE_H
|
||||
|
||||
int scsiModeCommand(void);
|
||||
int scsiModeCommand(S2S_Device* dev);
|
||||
|
||||
#endif
|
||||
|
@ -132,8 +132,8 @@ static void enter_Status(uint8 status)
|
||||
scsiDev.phase = STATUS;
|
||||
|
||||
scsiDev.lastStatus = scsiDev.status;
|
||||
scsiDev.lastSense = scsiDev.target->sense.code;
|
||||
scsiDev.lastSenseASC = scsiDev.target->sense.asc;
|
||||
scsiDev.lastSense = scsiDev.target->state.sense.code;
|
||||
scsiDev.lastSenseASC = scsiDev.target->state.sense.asc;
|
||||
}
|
||||
|
||||
void process_Status()
|
||||
@ -192,7 +192,7 @@ void process_Status()
|
||||
}
|
||||
else if (scsiDev.target->cfg->quirks == CONFIG_QUIRKS_OMTI)
|
||||
{
|
||||
scsiDev.status |= (scsiDev.target->targetId & 0x03) << 5;
|
||||
scsiDev.status |= (scsiDev.target->cfg->scsiId & 0x03) << 5;
|
||||
scsiWriteByte(scsiDev.status);
|
||||
}
|
||||
else
|
||||
@ -201,8 +201,8 @@ void process_Status()
|
||||
}
|
||||
|
||||
scsiDev.lastStatus = scsiDev.status;
|
||||
scsiDev.lastSense = scsiDev.target->sense.code;
|
||||
scsiDev.lastSenseASC = scsiDev.target->sense.asc;
|
||||
scsiDev.lastSense = scsiDev.target->state.sense.code;
|
||||
scsiDev.lastSenseASC = scsiDev.target->state.sense.asc;
|
||||
|
||||
|
||||
// Command Complete occurs AFTER a valid status has been
|
||||
@ -262,8 +262,8 @@ static void process_DataOut()
|
||||
(scsiDev.boardCfg.flags & CONFIG_ENABLE_PARITY) &&
|
||||
(scsiDev.compatMode >= COMPAT_SCSI2))
|
||||
{
|
||||
scsiDev.target->sense.code = ABORTED_COMMAND;
|
||||
scsiDev.target->sense.asc = SCSI_PARITY_ERROR;
|
||||
scsiDev.target->state.sense.code = ABORTED_COMMAND;
|
||||
scsiDev.target->state.sense.asc = SCSI_PARITY_ERROR;
|
||||
enter_Status(CHECK_CONDITION);
|
||||
}
|
||||
}
|
||||
@ -318,15 +318,11 @@ static void process_Command()
|
||||
// http://bitsavers.trailing-edge.com/pdf/xebec/104524C_S1410Man_Aug83.pdf
|
||||
if ((scsiDev.lun > 0) && (scsiDev.boardCfg.flags & CONFIG_MAP_LUNS_TO_IDS))
|
||||
{
|
||||
int tgtIndex;
|
||||
for (tgtIndex = 0; tgtIndex < MAX_SCSI_TARGETS; ++tgtIndex)
|
||||
S2S_Target* lunTarget = s2s_DeviceFindByScsiId(scsiDev.lun);
|
||||
if (lunTarget! = NULL)
|
||||
{
|
||||
if (scsiDev.targets[tgtIndex].targetId == scsiDev.lun)
|
||||
{
|
||||
scsiDev.target = &scsiDev.targets[tgtIndex];
|
||||
scsiDev.lun = 0;
|
||||
break;
|
||||
}
|
||||
scsiDev.target = lunTarget;
|
||||
scsiDev.lun = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -347,8 +343,8 @@ static void process_Command()
|
||||
(scsiDev.boardCfg.flags & CONFIG_ENABLE_PARITY) &&
|
||||
(scsiDev.compatMode >= COMPAT_SCSI2))
|
||||
{
|
||||
scsiDev.target->sense.code = ABORTED_COMMAND;
|
||||
scsiDev.target->sense.asc = SCSI_PARITY_ERROR;
|
||||
scsiDev.target->state.sense.code = ABORTED_COMMAND;
|
||||
scsiDev.target->state.sense.asc = SCSI_PARITY_ERROR;
|
||||
enter_Status(CHECK_CONDITION);
|
||||
}
|
||||
else if ((control & 0x02) && ((control & 0x01) == 0) &&
|
||||
@ -356,8 +352,8 @@ static void process_Command()
|
||||
likely(scsiDev.target->cfg->quirks != CONFIG_QUIRKS_XEBEC))
|
||||
{
|
||||
// FLAG set without LINK flag.
|
||||
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;
|
||||
enter_Status(CHECK_CONDITION);
|
||||
}
|
||||
else if (command == 0x12)
|
||||
@ -373,11 +369,11 @@ static void process_Command()
|
||||
{
|
||||
// Completely non-standard
|
||||
allocLength = 4;
|
||||
if (scsiDev.target->sense.code == NO_SENSE)
|
||||
if (scsiDev.target->state.sense.code == NO_SENSE)
|
||||
scsiDev.data[0] = 0;
|
||||
else if (scsiDev.target->sense.code == ILLEGAL_REQUEST)
|
||||
else if (scsiDev.target->state.sense.code == ILLEGAL_REQUEST)
|
||||
scsiDev.data[0] = 0x20; // Illegal command
|
||||
else if (scsiDev.target->sense.code == NOT_READY)
|
||||
else if (scsiDev.target->state.sense.code == NOT_READY)
|
||||
scsiDev.data[0] = 0x04; // Drive not ready
|
||||
else
|
||||
scsiDev.data[0] = 0x11; // Uncorrectable data error
|
||||
@ -395,7 +391,7 @@ static void process_Command()
|
||||
|
||||
memset(scsiDev.data, 0, 256); // Max possible alloc length
|
||||
scsiDev.data[0] = 0xF0;
|
||||
scsiDev.data[2] = scsiDev.target->sense.code & 0x0F;
|
||||
scsiDev.data[2] = scsiDev.target->state.sense.code & 0x0F;
|
||||
|
||||
scsiDev.data[3] = transfer.lba >> 24;
|
||||
scsiDev.data[4] = transfer.lba >> 16;
|
||||
@ -404,45 +400,45 @@ static void process_Command()
|
||||
|
||||
// Additional bytes if there are errors to report
|
||||
scsiDev.data[7] = 10; // additional length
|
||||
scsiDev.data[12] = scsiDev.target->sense.asc >> 8;
|
||||
scsiDev.data[13] = scsiDev.target->sense.asc;
|
||||
scsiDev.data[12] = scsiDev.target->state.sense.asc >> 8;
|
||||
scsiDev.data[13] = scsiDev.target->state.sense.asc;
|
||||
}
|
||||
|
||||
// Silently truncate results. SCSI-2 spec 8.2.14.
|
||||
enter_DataIn(allocLength);
|
||||
|
||||
// This is a good time to clear out old sense information.
|
||||
scsiDev.target->sense.code = NO_SENSE;
|
||||
scsiDev.target->sense.asc = NO_ADDITIONAL_SENSE_INFORMATION;
|
||||
scsiDev.target->state.sense.code = NO_SENSE;
|
||||
scsiDev.target->state.sense.asc = NO_ADDITIONAL_SENSE_INFORMATION;
|
||||
}
|
||||
// Some old SCSI drivers do NOT properly support
|
||||
// unitAttention. eg. the Mac Plus would trigger a SCSI reset
|
||||
// on receiving the unit attention response on boot, thus
|
||||
// triggering another unit attention condition.
|
||||
else if (scsiDev.target->unitAttention &&
|
||||
else if (scsiDev.target->state.unitAttention &&
|
||||
(scsiDev.boardCfg.flags & CONFIG_ENABLE_UNIT_ATTENTION))
|
||||
{
|
||||
scsiDev.target->sense.code = UNIT_ATTENTION;
|
||||
scsiDev.target->sense.asc = scsiDev.target->unitAttention;
|
||||
scsiDev.target->state.sense.code = UNIT_ATTENTION;
|
||||
scsiDev.target->state.sense.asc = scsiDev.target->state.unitAttention;
|
||||
|
||||
// If initiator doesn't do REQUEST SENSE for the next command, then
|
||||
// data is lost.
|
||||
scsiDev.target->unitAttention = 0;
|
||||
scsiDev.target->state.unitAttention = 0;
|
||||
|
||||
enter_Status(CHECK_CONDITION);
|
||||
}
|
||||
else if (scsiDev.lun)
|
||||
{
|
||||
scsiDev.target->sense.code = ILLEGAL_REQUEST;
|
||||
scsiDev.target->sense.asc = LOGICAL_UNIT_NOT_SUPPORTED;
|
||||
scsiDev.target->state.sense.code = ILLEGAL_REQUEST;
|
||||
scsiDev.target->state.sense.asc = LOGICAL_UNIT_NOT_SUPPORTED;
|
||||
enter_Status(CHECK_CONDITION);
|
||||
}
|
||||
else if (command == 0x17 || command == 0x16)
|
||||
{
|
||||
doReserveRelease();
|
||||
}
|
||||
else if ((scsiDev.target->reservedId >= 0) &&
|
||||
(scsiDev.target->reservedId != scsiDev.initiatorId))
|
||||
else if ((scsiDev.target->state.reservedId >= 0) &&
|
||||
(scsiDev.target->state.reservedId != scsiDev.initiatorId))
|
||||
{
|
||||
enter_Status(CONFLICT);
|
||||
}
|
||||
@ -481,10 +477,10 @@ static void process_Command()
|
||||
{
|
||||
scsiReadBuffer();
|
||||
}
|
||||
else if (!scsiModeCommand() && !scsiVendorCommand())
|
||||
else if (!scsiModeCommand(scsiDev.target->device) && !scsiVendorCommand())
|
||||
{
|
||||
scsiDev.target->sense.code = ILLEGAL_REQUEST;
|
||||
scsiDev.target->sense.asc = INVALID_COMMAND_OPERATION_CODE;
|
||||
scsiDev.target->state.sense.code = ILLEGAL_REQUEST;
|
||||
scsiDev.target->state.sense.asc = INVALID_COMMAND_OPERATION_CODE;
|
||||
enter_Status(CHECK_CONDITION);
|
||||
}
|
||||
|
||||
@ -504,25 +500,25 @@ static void doReserveRelease()
|
||||
uint8 command = scsiDev.cdb[0];
|
||||
|
||||
int canRelease =
|
||||
(!thirdPty && (scsiDev.initiatorId == scsiDev.target->reservedId)) ||
|
||||
(!thirdPty && (scsiDev.initiatorId == scsiDev.target->state.reservedId)) ||
|
||||
(thirdPty &&
|
||||
(scsiDev.target->reserverId == scsiDev.initiatorId) &&
|
||||
(scsiDev.target->reservedId == thirdPtyId)
|
||||
(scsiDev.target->state.reserverId == scsiDev.initiatorId) &&
|
||||
(scsiDev.target->state.reservedId == thirdPtyId)
|
||||
);
|
||||
|
||||
if (extentReservation)
|
||||
{
|
||||
// Not supported.
|
||||
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;
|
||||
enter_Status(CHECK_CONDITION);
|
||||
}
|
||||
else if (command == 0x17) // release
|
||||
{
|
||||
if ((scsiDev.target->reservedId < 0) || canRelease)
|
||||
if ((scsiDev.target->state.reservedId < 0) || canRelease)
|
||||
{
|
||||
scsiDev.target->reservedId = -1;
|
||||
scsiDev.target->reserverId = -1;
|
||||
scsiDev.target->state.reservedId = -1;
|
||||
scsiDev.target->state.reserverId = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -531,16 +527,16 @@ static void doReserveRelease()
|
||||
}
|
||||
else // assume reserve.
|
||||
{
|
||||
if ((scsiDev.target->reservedId < 0) || canRelease)
|
||||
if ((scsiDev.target->state.reservedId < 0) || canRelease)
|
||||
{
|
||||
scsiDev.target->reserverId = scsiDev.initiatorId;
|
||||
scsiDev.target->state.reserverId = scsiDev.initiatorId;
|
||||
if (thirdPty)
|
||||
{
|
||||
scsiDev.target->reservedId = thirdPtyId;
|
||||
scsiDev.target->state.reservedId = thirdPtyId;
|
||||
}
|
||||
else
|
||||
{
|
||||
scsiDev.target->reservedId = scsiDev.initiatorId;
|
||||
scsiDev.target->state.reservedId = scsiDev.initiatorId;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -569,14 +565,14 @@ static void scsiReset()
|
||||
|
||||
if (scsiDev.target)
|
||||
{
|
||||
if (scsiDev.target->unitAttention != POWER_ON_RESET)
|
||||
if (scsiDev.target->state.unitAttention != POWER_ON_RESET)
|
||||
{
|
||||
scsiDev.target->unitAttention = SCSI_BUS_RESET;
|
||||
scsiDev.target->state.unitAttention = SCSI_BUS_RESET;
|
||||
}
|
||||
scsiDev.target->reservedId = -1;
|
||||
scsiDev.target->reserverId = -1;
|
||||
scsiDev.target->sense.code = NO_SENSE;
|
||||
scsiDev.target->sense.asc = NO_ADDITIONAL_SENSE_INFORMATION;
|
||||
scsiDev.target->state.reservedId = -1;
|
||||
scsiDev.target->state.reserverId = -1;
|
||||
scsiDev.target->state.sense.code = NO_SENSE;
|
||||
scsiDev.target->state.sense.asc = NO_ADDITIONAL_SENSE_INFORMATION;
|
||||
}
|
||||
scsiDev.target = NULL;
|
||||
scsiDiskReset();
|
||||
@ -666,16 +662,16 @@ static void process_SelectionPhase()
|
||||
int goodParity = (Lookup_OddParity[mask] == SCSI_ReadPin(SCSI_In_DBP));
|
||||
int atnFlag = SCSI_ReadFilt(SCSI_Filt_ATN);
|
||||
|
||||
int tgtIndex;
|
||||
TargetState* target = NULL;
|
||||
for (tgtIndex = 0; tgtIndex < MAX_SCSI_TARGETS; ++tgtIndex)
|
||||
S2S_Target* target = NULL;
|
||||
for (int testIdx = 0; testtIndex < 8; ++testtIndex)
|
||||
{
|
||||
if (mask & (1 << scsiDev.targets[tgtIndex].targetId))
|
||||
target = s2s_DeviceFindByScsiId(1 << testIdx);
|
||||
if (target)
|
||||
{
|
||||
target = &scsiDev.targets[tgtIndex];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sel &= (selLatchCfg && scsiDev.selFlag) || SCSI_ReadFilt(SCSI_Filt_SEL);
|
||||
bsy |= SCSI_ReadFilt(SCSI_Filt_BSY);
|
||||
#ifdef SCSI_In_IO
|
||||
@ -709,7 +705,7 @@ static void process_SelectionPhase()
|
||||
// controllers don't generate parity bits.
|
||||
if (!scsiDev.atnFlag)
|
||||
{
|
||||
target->unitAttention = 0;
|
||||
target->state.unitAttention = 0;
|
||||
scsiDev.compatMode = COMPAT_SCSI1;
|
||||
}
|
||||
else if (!(scsiDev.boardCfg.flags & CONFIG_ENABLE_SCSI2))
|
||||
@ -816,11 +812,11 @@ static void process_MessageOut()
|
||||
|
||||
scsiDiskReset();
|
||||
|
||||
scsiDev.target->unitAttention = SCSI_BUS_RESET;
|
||||
scsiDev.target->state.unitAttention = SCSI_BUS_RESET;
|
||||
|
||||
// ANY initiator can reset the reservation state via this message.
|
||||
scsiDev.target->reservedId = -1;
|
||||
scsiDev.target->reserverId = -1;
|
||||
scsiDev.target->state.reservedId = -1;
|
||||
scsiDev.target->state.reserverId = -1;
|
||||
enter_BusFree();
|
||||
}
|
||||
else if (scsiDev.msgOut == 0x05)
|
||||
@ -1055,27 +1051,25 @@ void scsiInit()
|
||||
scsiDev.target = NULL;
|
||||
scsiDev.compatMode = COMPAT_UNKNOWN;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < MAX_SCSI_TARGETS; ++i)
|
||||
int deviceCount;
|
||||
S2S_Device* allDevices = s2s_GetDevices(&deviceCount);
|
||||
for (int devIdx = 0; devIdx < deviceCount; ++devIdx)
|
||||
{
|
||||
const TargetConfig* cfg = getConfigByIndex(i);
|
||||
if (cfg && (cfg->scsiId & CONFIG_TARGET_ENABLED))
|
||||
{
|
||||
scsiDev.targets[i].targetId = cfg->scsiId & CONFIG_TARGET_ID_BITS;
|
||||
scsiDev.targets[i].cfg = cfg;
|
||||
int targetCount;
|
||||
S2S_Target* targets = devices[deviceIdx].getTargets(devices + deviceIdx, &targetCount);
|
||||
|
||||
scsiDev.targets[i].liveCfg.bytesPerSector = cfg->bytesPerSector;
|
||||
}
|
||||
else
|
||||
for (int i = 0; i < targetCount; ++i)
|
||||
{
|
||||
scsiDev.targets[i].targetId = 0xff;
|
||||
scsiDev.targets[i].cfg = NULL;
|
||||
S2S_TargetState* state = &(targets[i].state);
|
||||
|
||||
scsiDev.targets[i].state.reservedId = -1;
|
||||
scsiDev.targets[i].state.reserverId = -1;
|
||||
scsiDev.targets[i].state.unitAttention = POWER_ON_RESET;
|
||||
scsiDev.targets[i].state.sense.code = NO_SENSE;
|
||||
scsiDev.targets[i].state.sense.asc = NO_ADDITIONAL_SENSE_INFORMATION;
|
||||
|
||||
state->bytesPerSector = targets[i].cfg->bytesPerSector;
|
||||
}
|
||||
scsiDev.targets[i].reservedId = -1;
|
||||
scsiDev.targets[i].reserverId = -1;
|
||||
scsiDev.targets[i].unitAttention = POWER_ON_RESET;
|
||||
scsiDev.targets[i].sense.code = NO_SENSE;
|
||||
scsiDev.targets[i].sense.asc = NO_ADDITIONAL_SENSE_INFORMATION;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -28,8 +28,23 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static void sd_earlyInit(S2S_Device* dev);
|
||||
static S2S_Target* sd_getTargets(S2S_Device* dev, int* count);
|
||||
static uint32_t sd_getCapacity(S2S_Device* dev);
|
||||
static int sd_pollMediaChange(S2S_Device* dev);
|
||||
static void sd_pollMediaBusy(S2S_Device* dev);
|
||||
|
||||
// Global
|
||||
SdDevice sdDev;
|
||||
SdCard sdCard S2S_DMA_ALIGN = {
|
||||
{
|
||||
sd_earlyInit,
|
||||
sd_getTargets,
|
||||
sd_getCapacity,
|
||||
sd_pollMediaChange,
|
||||
sd_pollMediaBusy
|
||||
}
|
||||
};
|
||||
S2S_Device* sdDevice = &(sdCard.dev);
|
||||
|
||||
enum SD_CMD_STATE { CMD_STATE_IDLE, CMD_STATE_READ, CMD_STATE_WRITE };
|
||||
static int sdCmdState = CMD_STATE_IDLE;
|
||||
@ -268,7 +283,7 @@ sdReadMultiSectorPrep(uint32_t sdLBA, uint32_t sdSectors)
|
||||
{
|
||||
uint32_t tmpNextLBA = sdLBA + sdSectors;
|
||||
|
||||
if (!sdDev.ccs)
|
||||
if (!sdCard.ccs)
|
||||
{
|
||||
sdLBA = sdLBA * SD_SECTOR_SIZE;
|
||||
tmpNextLBA = tmpNextLBA * SD_SECTOR_SIZE;
|
||||
@ -291,8 +306,8 @@ sdReadMultiSectorPrep(uint32_t sdLBA, uint32_t sdSectors)
|
||||
sdClearStatus();
|
||||
|
||||
scsiDev.status = CHECK_CONDITION;
|
||||
scsiDev.target->sense.code = HARDWARE_ERROR;
|
||||
scsiDev.target->sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
||||
scsiDev.target->state.sense.code = HARDWARE_ERROR;
|
||||
scsiDev.target->state.sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
||||
scsiDev.phase = STATUS;
|
||||
}
|
||||
else
|
||||
@ -330,8 +345,8 @@ dmaReadSector(uint8_t* outputBuffer)
|
||||
if (scsiDev.status != CHECK_CONDITION)
|
||||
{
|
||||
scsiDev.status = CHECK_CONDITION;
|
||||
scsiDev.target->sense.code = HARDWARE_ERROR;
|
||||
scsiDev.target->sense.asc = UNRECOVERED_READ_ERROR;
|
||||
scsiDev.target->state.sense.code = HARDWARE_ERROR;
|
||||
scsiDev.target->state.sense.asc = UNRECOVERED_READ_ERROR;
|
||||
scsiDev.phase = STATUS;
|
||||
}
|
||||
sdClearStatus();
|
||||
@ -399,7 +414,7 @@ void sdReadSingleSectorDMA(uint32_t lba, uint8_t* outputBuffer)
|
||||
sdPreCmdState(CMD_STATE_READ);
|
||||
|
||||
uint8 v;
|
||||
if (!sdDev.ccs)
|
||||
if (!sdCard.ccs)
|
||||
{
|
||||
lba = lba * SD_SECTOR_SIZE;
|
||||
}
|
||||
@ -410,8 +425,8 @@ void sdReadSingleSectorDMA(uint32_t lba, uint8_t* outputBuffer)
|
||||
sdClearStatus();
|
||||
|
||||
scsiDev.status = CHECK_CONDITION;
|
||||
scsiDev.target->sense.code = HARDWARE_ERROR;
|
||||
scsiDev.target->sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
||||
scsiDev.target->state.sense.code = HARDWARE_ERROR;
|
||||
scsiDev.target->state.sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
||||
scsiDev.phase = STATUS;
|
||||
}
|
||||
else
|
||||
@ -446,8 +461,8 @@ static void sdCompleteRead()
|
||||
if (unlikely(r1b) && (scsiDev.phase == DATA_IN))
|
||||
{
|
||||
scsiDev.status = CHECK_CONDITION;
|
||||
scsiDev.target->sense.code = HARDWARE_ERROR;
|
||||
scsiDev.target->sense.asc = UNRECOVERED_READ_ERROR;
|
||||
scsiDev.target->state.sense.code = HARDWARE_ERROR;
|
||||
scsiDev.target->state.sense.asc = UNRECOVERED_READ_ERROR;
|
||||
scsiDev.phase = STATUS;
|
||||
}
|
||||
}
|
||||
@ -544,8 +559,8 @@ sdWriteSectorDMAPoll()
|
||||
sdClearStatus();
|
||||
|
||||
scsiDev.status = CHECK_CONDITION;
|
||||
scsiDev.target->sense.code = HARDWARE_ERROR;
|
||||
scsiDev.target->sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
||||
scsiDev.target->state.sense.code = HARDWARE_ERROR;
|
||||
scsiDev.target->state.sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
||||
scsiDev.phase = STATUS;
|
||||
}
|
||||
else
|
||||
@ -599,8 +614,8 @@ static void sdCompleteWrite()
|
||||
{
|
||||
sdClearStatus();
|
||||
scsiDev.status = CHECK_CONDITION;
|
||||
scsiDev.target->sense.code = HARDWARE_ERROR;
|
||||
scsiDev.target->sense.asc = WRITE_ERROR_AUTO_REALLOCATION_FAILED;
|
||||
scsiDev.target->state.sense.code = HARDWARE_ERROR;
|
||||
scsiDev.target->state.sense.asc = WRITE_ERROR_AUTO_REALLOCATION_FAILED;
|
||||
scsiDev.phase = STATUS;
|
||||
}
|
||||
}
|
||||
@ -627,7 +642,7 @@ static int sendIfCond()
|
||||
if (status == SD_R1_IDLE)
|
||||
{
|
||||
// Version 2 card.
|
||||
sdDev.version = 2;
|
||||
sdCard.version = 2;
|
||||
// Read 32bit response. Should contain the same bytes that
|
||||
// we sent in the command parameter.
|
||||
sdSpiByte(0xFF);
|
||||
@ -639,7 +654,7 @@ static int sendIfCond()
|
||||
else if (status & SD_R1_ILLEGAL)
|
||||
{
|
||||
// Version 1 card.
|
||||
sdDev.version = 1;
|
||||
sdCard.version = 1;
|
||||
sdClearStatus();
|
||||
break;
|
||||
}
|
||||
@ -688,7 +703,7 @@ static int sdReadOCR()
|
||||
buf[i] = sdSpiByte(0xFF);
|
||||
}
|
||||
|
||||
sdDev.ccs = (buf[0] & 0x40) ? 1 : 0;
|
||||
sdCard.ccs = (buf[0] & 0x40) ? 1 : 0;
|
||||
complete = (buf[0] & 0x80);
|
||||
|
||||
} while (!status &&
|
||||
@ -715,7 +730,7 @@ static void sdReadCID()
|
||||
|
||||
for (i = 0; i < 16; ++i)
|
||||
{
|
||||
sdDev.cid[i] = sdSpiByte(0xFF);
|
||||
sdCard.cid[i] = sdSpiByte(0xFF);
|
||||
}
|
||||
sdSpiByte(0xFF); // CRC
|
||||
sdSpiByte(0xFF); // CRC
|
||||
@ -738,30 +753,30 @@ static int sdReadCSD()
|
||||
|
||||
for (i = 0; i < 16; ++i)
|
||||
{
|
||||
sdDev.csd[i] = sdSpiByte(0xFF);
|
||||
sdCard.csd[i] = sdSpiByte(0xFF);
|
||||
}
|
||||
sdSpiByte(0xFF); // CRC
|
||||
sdSpiByte(0xFF); // CRC
|
||||
|
||||
if ((sdDev.csd[0] >> 6) == 0x00)
|
||||
if ((sdCard.csd[0] >> 6) == 0x00)
|
||||
{
|
||||
// CSD version 1
|
||||
// C_SIZE in bits [73:62]
|
||||
uint32 c_size = (((((uint32)sdDev.csd[6]) & 0x3) << 16) | (((uint32)sdDev.csd[7]) << 8) | sdDev.csd[8]) >> 6;
|
||||
uint32 c_mult = (((((uint32)sdDev.csd[9]) & 0x3) << 8) | ((uint32)sdDev.csd[0xa])) >> 7;
|
||||
uint32 sectorSize = sdDev.csd[5] & 0x0F;
|
||||
sdDev.capacity = ((c_size+1) * ((uint64)1 << (c_mult+2)) * ((uint64)1 << sectorSize)) / SD_SECTOR_SIZE;
|
||||
uint32 c_size = (((((uint32)sdCard.csd[6]) & 0x3) << 16) | (((uint32)sdCard.csd[7]) << 8) | sdCard.csd[8]) >> 6;
|
||||
uint32 c_mult = (((((uint32)sdCard.csd[9]) & 0x3) << 8) | ((uint32)sdCard.csd[0xa])) >> 7;
|
||||
uint32 sectorSize = sdCard.csd[5] & 0x0F;
|
||||
sdCard.capacity = ((c_size+1) * ((uint64)1 << (c_mult+2)) * ((uint64)1 << sectorSize)) / SD_SECTOR_SIZE;
|
||||
}
|
||||
else if ((sdDev.csd[0] >> 6) == 0x01)
|
||||
else if ((sdCard.csd[0] >> 6) == 0x01)
|
||||
{
|
||||
// CSD version 2
|
||||
// C_SIZE in bits [69:48]
|
||||
|
||||
uint32 c_size =
|
||||
((((uint32)sdDev.csd[7]) & 0x3F) << 16) |
|
||||
(((uint32)sdDev.csd[8]) << 8) |
|
||||
((uint32)sdDev.csd[7]);
|
||||
sdDev.capacity = (c_size + 1) * 1024;
|
||||
((((uint32)sdCard.csd[7]) & 0x3F) << 16) |
|
||||
(((uint32)sdCard.csd[8]) << 8) |
|
||||
((uint32)sdCard.csd[7]);
|
||||
sdCard.capacity = (c_size + 1) * 1024;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -809,11 +824,11 @@ int sdInit()
|
||||
uint8 v;
|
||||
|
||||
sdCmdState = CMD_STATE_IDLE;
|
||||
sdDev.version = 0;
|
||||
sdDev.ccs = 0;
|
||||
sdDev.capacity = 0;
|
||||
memset(sdDev.csd, 0, sizeof(sdDev.csd));
|
||||
memset(sdDev.cid, 0, sizeof(sdDev.cid));
|
||||
sdCard.version = 0;
|
||||
sdCard.ccs = 0;
|
||||
sdCard.capacity = 0;
|
||||
memset(sdCard.csd, 0, sizeof(sdCard.csd));
|
||||
memset(sdCard.cid, 0, sizeof(sdCard.cid));
|
||||
|
||||
sdInitDMA();
|
||||
|
||||
@ -848,7 +863,7 @@ int sdInit()
|
||||
if (!sdOpCond()) goto bad; // ACMD41. Wait for init completes.
|
||||
if (!sdReadOCR()) goto bad; // CMD58. Get CCS flag. Only valid after init.
|
||||
|
||||
// This command will be ignored if sdDev.ccs is set.
|
||||
// This command will be ignored if sdCard.ccs is set.
|
||||
// SDHC and SDXC are always 512bytes.
|
||||
v = sdCRCCommandAndResponse(SD_SET_BLOCKLEN, SD_SECTOR_SIZE); //Force sector size
|
||||
if(v){goto bad;}
|
||||
@ -882,7 +897,7 @@ int sdInit()
|
||||
|
||||
bad:
|
||||
SD_Data_Clk_SetDivider(clkDiv25MHz); // Restore the clock for our next retry
|
||||
sdDev.capacity = 0;
|
||||
sdCard.capacity = 0;
|
||||
|
||||
out:
|
||||
sdClearStatus();
|
||||
@ -895,7 +910,7 @@ void sdWriteMultiSectorPrep(uint32_t sdLBA, uint32_t sdSectors)
|
||||
{
|
||||
uint32_t tmpNextLBA = sdLBA + sdSectors;
|
||||
|
||||
if (!sdDev.ccs)
|
||||
if (!sdCard.ccs)
|
||||
{
|
||||
sdLBA = sdLBA * SD_SECTOR_SIZE;
|
||||
tmpNextLBA = tmpNextLBA * SD_SECTOR_SIZE;
|
||||
@ -924,8 +939,8 @@ void sdWriteMultiSectorPrep(uint32_t sdLBA, uint32_t sdSectors)
|
||||
scsiDiskReset();
|
||||
sdClearStatus();
|
||||
scsiDev.status = CHECK_CONDITION;
|
||||
scsiDev.target->sense.code = HARDWARE_ERROR;
|
||||
scsiDev.target->sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
||||
scsiDev.target->state.sense.code = HARDWARE_ERROR;
|
||||
scsiDev.target->state.sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
||||
scsiDev.phase = STATUS;
|
||||
}
|
||||
else
|
||||
@ -968,7 +983,7 @@ void sdCheckPresent()
|
||||
uint8_t cs = SD_CS_Read();
|
||||
SD_CS_SetDriveMode(SD_CS_DM_STRONG) ;
|
||||
|
||||
if (cs && !(blockDev.state & DISK_PRESENT))
|
||||
if (cs && !(sdCard.dev.mediaState & MEDIA_PRESENT))
|
||||
{
|
||||
static int firstInit = 1;
|
||||
|
||||
@ -981,7 +996,7 @@ void sdCheckPresent()
|
||||
|
||||
if (sdInit())
|
||||
{
|
||||
blockDev.state |= DISK_PRESENT | DISK_INITIALISED;
|
||||
sdCard.dev.mediaState |= MEDIA_PRESENT | MEDIA_INITIALISED;
|
||||
|
||||
// Always "start" the device. Many systems (eg. Apple System 7)
|
||||
// won't respond properly to
|
||||
@ -1001,18 +1016,68 @@ void sdCheckPresent()
|
||||
firstInit = 0;
|
||||
}
|
||||
}
|
||||
else if (!cs && (blockDev.state & DISK_PRESENT))
|
||||
else if (!cs && (sdCard.dev.mediaState & MEDIA_PRESENT))
|
||||
{
|
||||
sdDev.capacity = 0;
|
||||
blockDev.state &= ~DISK_PRESENT;
|
||||
blockDev.state &= ~DISK_INITIALISED;
|
||||
sdCard.capacity = 0;
|
||||
sdCard.dev.mediaState &= ~MEDIA_PRESENT;
|
||||
sdCard.dev.mediaState &= ~MEDIA_INITIALISED;
|
||||
int i;
|
||||
for (i = 0; i < MAX_SCSI_TARGETS; ++i)
|
||||
{
|
||||
scsiDev.targets[i].unitAttention = PARAMETERS_CHANGED;
|
||||
sdCard.targets[i].state.unitAttention = PARAMETERS_CHANGED;
|
||||
}
|
||||
}
|
||||
}
|
||||
firstCheck = 0;
|
||||
}
|
||||
|
||||
static void sd_earlyInit(S2S_Device* dev)
|
||||
{
|
||||
SdCard* sdCardDevice = (SdCard*)dev;
|
||||
|
||||
for (int i = 0; i < MAX_TARGETS; ++i)
|
||||
{
|
||||
sdCardDevice->targets[i].device = dev;
|
||||
sdCardDevice->targets[i].cfg = getConfigByIndex(i);
|
||||
}
|
||||
sdCardDevice->lastPollMediaTime = s2s_getTime_ms();
|
||||
|
||||
// Don't require the host to send us a START STOP UNIT command
|
||||
sdCardDevice->dev.mediaState = MEDIA_STARTED;
|
||||
|
||||
}
|
||||
|
||||
static S2S_Target* sd_getTargets(S2S_Device* dev, int* count)
|
||||
{
|
||||
SdCard* sdCardDevice = (SdCard*)dev;
|
||||
*count = MAX_TARGETS;
|
||||
return sdCardDevice->targets;
|
||||
}
|
||||
|
||||
static uint32_t sd_getCapacity(S2S_Device* dev)
|
||||
{
|
||||
SdCard* sdCardDevice = (SdCard*)dev;
|
||||
return sdCardDevice->capacity;
|
||||
}
|
||||
|
||||
static int sd_pollMediaChange(S2S_Device* dev)
|
||||
{
|
||||
SdCard* sdCardDevice = (SdCard*)dev;
|
||||
if (s2s_elapsedTime_ms(sdCardDevice->lastPollMediaTime) > 200)
|
||||
{
|
||||
sdCardDevice->lastPollMediaTime = s2s_getTime_ms();
|
||||
sdCheckPresent();
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void sd_pollMediaBusy(S2S_Device* dev)
|
||||
{
|
||||
SdCard* sdCardDevice = (SdCard*)dev;
|
||||
sdCardDevice->lastPollMediaTime = s2s_getTime_ms();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
74
software/SCSI2SD/src/storedevice.c
Normal file
74
software/SCSI2SD/src/storedevice.c
Normal file
@ -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;
|
||||
}
|
89
software/SCSI2SD/src/storedevice.h
Normal file
89
software/SCSI2SD/src/storedevice.h
Normal file
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user