src/firmware/bsp.c \
src/firmware/cdrom.c \
src/firmware/config.c \
+ src/firmware/device.c \
src/firmware/disk.c \
src/firmware/diagnostic.c \
src/firmware/fpga.c \
if (track > 1)
{
scsiDev.status = CHECK_CONDITION;
- scsiDev.target->sense.code = ILLEGAL_REQUEST;
- scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;
+ scsiDev.target->state.sense.asc = INVALID_FIELD_IN_CDB;
scsiDev.phase = STATUS;
}
else
memcpy(scsiDev.data, SimpleTOC, len);
uint32_t capacity = getScsiCapacity(
+ scsiDev.target->device,
scsiDev.target->cfg->sdSectorStart,
- scsiDev.target->liveCfg.bytesPerSector,
+ scsiDev.target->state.bytesPerSector,
scsiDev.target->cfg->scsiSectors);
// Replace start of leadout track
if (session > 1)
{
scsiDev.status = CHECK_CONDITION;
- scsiDev.target->sense.code = ILLEGAL_REQUEST;
- scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;
+ scsiDev.target->state.sense.asc = INVALID_FIELD_IN_CDB;
scsiDev.phase = STATUS;
}
else
default:
{
scsiDev.status = CHECK_CONDITION;
- scsiDev.target->sense.code = ILLEGAL_REQUEST;
- scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;
+ scsiDev.target->state.sense.asc = INVALID_FIELD_IN_CDB;
scsiDev.phase = STATUS;
}
}
memcpy(config, s2s_cfg, sizeof(S2S_BoardCfg));\r
}\r
\r
- else if ((blockDev.state & DISK_PRESENT) && sdDev.capacity)\r
+ else if ((blockDev.state & DISK_PRESENT) && sdCard.capacity)\r
{\r
int cfgSectors = (S2S_CFG_SIZE + 511) / 512;\r
BSP_SD_ReadBlocks_DMA(\r
(uint32_t*) &s2s_cfg[0],\r
- (sdDev.capacity - cfgSectors) * 512ll,\r
+ (sdCard.capacity - cfgSectors) * 512ll,\r
512,\r
cfgSectors);\r
\r
static void\r
sdInfoCommand()\r
{\r
- uint8_t response[sizeof(sdDev.csd) + sizeof(sdDev.cid)];\r
- memcpy(response, sdDev.csd, sizeof(sdDev.csd));\r
- memcpy(response + sizeof(sdDev.csd), sdDev.cid, sizeof(sdDev.cid));\r
+ uint8_t response[sizeof(sdCard.csd) + sizeof(sdCard.cid)];\r
+ memcpy(response, sdCard.csd, sizeof(sdCard.csd));\r
+ memcpy(response + sizeof(sdCard.csd), sdCard.cid, sizeof(sdCard.cid));\r
\r
hidPacket_send(response, sizeof(response));\r
}\r
{\r
FIRMWARE_VERSION >> 8,\r
FIRMWARE_VERSION & 0xff,\r
- sdDev.capacity >> 24,\r
- sdDev.capacity >> 16,\r
- sdDev.capacity >> 8,\r
- sdDev.capacity,\r
+ sdCard.capacity >> 24,\r
+ sdCard.capacity >> 16,\r
+ sdCard.capacity >> 8,\r
+ sdCard.capacity,\r
1 // useSdConfig, always true for V6.\r
};\r
hidPacket_send(response, sizeof(response));\r
response[15] = scsiDev.lastSense;\r
response[16] = scsiDev.phase;\r
response[17] = *SCSI_STS_SCSI;\r
- response[18] = scsiDev.target != NULL ? scsiDev.target->syncOffset : 0;\r
- response[19] = scsiDev.target != NULL ? scsiDev.target->syncPeriod : 0;\r
+ response[18] = scsiDev.target != NULL ? scsiDev.target->state.syncOffset : 0;\r
+ response[19] = scsiDev.target != NULL ? scsiDev.target->state.syncPeriod : 0;\r
response[20] = scsiDev.minSyncPeriod;\r
response[21] = scsiDev.rstCount;\r
response[22] = scsiDev.selCount;\r
\r
BSP_SD_WriteBlocks_DMA(\r
(uint32_t*) &s2s_cfg[0],\r
- (sdDev.capacity - S2S_CFG_SIZE) * 512ll,\r
+ (sdCard.capacity - S2S_CFG_SIZE) * 512ll,\r
512,\r
(S2S_CFG_SIZE + 511) / 512);\r
}\r
--- /dev/null
+// Copyright (C) 2020 Michael McMaster <michael@codesrc.com>
+//
+// This file is part of SCSI2SD.
+//
+// SCSI2SD is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// SCSI2SD is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with SCSI2SD. If not, see <http://www.gnu.org/licenses/>.
+#include "device.h"
+
+#include "sd.h"
+
+#include <stddef.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 & 7) == scsiId))
+ {
+ return target;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+S2S_Device* s2s_GetDevices(int* count)
+{
+ *count = 1;
+ return sdDevice;
+}
+
--- /dev/null
+// Copyright (C) 2020 Michael McMaster <michael@codesrc.com>
+//
+// This file is part of SCSI2SD.
+//
+// SCSI2SD is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// SCSI2SD is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with SCSI2SD. If not, see <http://www.gnu.org/licenses/>.
+#ifndef S2S_DEVICE_H
+#define S2S_DEVICE_H
+
+#include "scsi2sd.h"
+#include "sense.h"
+
+#include <stdint.h>
+
+struct S2S_DeviceStruct;
+typedef struct S2S_DeviceStruct S2S_Device;
+
+struct S2S_TargetStruct;
+typedef struct S2S_TargetStruct S2S_Target;
+
+struct S2S_TargetStateStruct;
+typedef struct S2S_TargetStateStruct S2S_TargetState;
+
+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.
+
+ uint8_t syncOffset;
+ uint8_t syncPeriod;
+
+ // Shadow parameters, possibly not saved to flash yet.
+ // Set via Mode Select
+ uint16_t bytesPerSector;
+};
+
+struct S2S_TargetStruct
+{
+ uint8_t id;
+
+ S2S_Device* device;
+ S2S_TargetCfg* cfg;
+
+ S2S_TargetState state;
+};
+
+struct S2S_DeviceStruct
+{
+ const S2S_BoardCfg* (*getBoardConfig)(S2S_Device* dev);
+ //const S2S_Target* (*findByScsiId)(S2S_Device* dev, int scsiId);
+ S2S_Target* (*getTargets)(S2S_Device* dev, int* count);
+
+ // Get the number of 512 byte blocks
+ uint32_t (*getCapacity)(S2S_Device* dev);
+
+};
+
+void s2s_DeviceGetBoardConfig(S2S_BoardCfg* config);
+S2S_Target* s2s_DeviceFindByScsiId(int scsiId);
+
+S2S_Device* s2s_GetDevices(int* count);
+
+#endif
+
+
// Nowhere to store this data!\r
// Shouldn't happen - our buffer should be many magnitudes larger\r
// than the required size for diagnostic parameters.\r
- scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
- scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;\r
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;\r
+ scsiDev.target->state.sense.asc = INVALID_FIELD_IN_CDB;\r
scsiDev.status = CHECK_CONDITION;\r
scsiDev.phase = STATUS;\r
}\r
// 64bit linear address, then convert back again.\r
uint64_t fromByteAddr =\r
scsiByteAddress(\r
- scsiDev.target->liveCfg.bytesPerSector,\r
+ scsiDev.target->state.bytesPerSector,\r
scsiDev.target->cfg->headsPerCylinder,\r
scsiDev.target->cfg->sectorsPerTrack,\r
suppliedFmt,\r
&scsiDev.data[6]);\r
\r
scsiSaveByteAddress(\r
- scsiDev.target->liveCfg.bytesPerSector,\r
+ scsiDev.target->state.bytesPerSector,\r
scsiDev.target->cfg->headsPerCylinder,\r
scsiDev.target->cfg->sectorsPerTrack,\r
translateFmt,\r
{\r
// error.\r
scsiDev.status = CHECK_CONDITION;\r
- scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
- scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;\r
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;\r
+ scsiDev.target->state.sense.asc = INVALID_FIELD_IN_CDB;\r
scsiDev.phase = STATUS;\r
}\r
\r
{\r
// error.\r
scsiDev.status = CHECK_CONDITION;\r
- scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
- scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;\r
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;\r
+ scsiDev.target->state.sense.asc = INVALID_FIELD_IN_CDB;\r
scsiDev.phase = STATUS;\r
}\r
}\r
{\r
// error.\r
scsiDev.status = CHECK_CONDITION;\r
- scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
- scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;\r
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;\r
+ scsiDev.target->state.sense.asc = INVALID_FIELD_IN_CDB;\r
scsiDev.phase = STATUS;\r
}\r
}\r
// Section 4.3.14\r
void scsiWriteSectorBuffer()\r
{\r
- scsiDev.dataLen = scsiDev.target->liveCfg.bytesPerSector;\r
+ scsiDev.dataLen = scsiDev.target->state.bytesPerSector;\r
scsiDev.phase = DATA_OUT;\r
scsiDev.postDataOutHook = doWriteBuffer;\r
}\r
{\r
// Save the "MODE SELECT savable parameters"\r
s2s_configSave(\r
- scsiDev.target->targetId,\r
- scsiDev.target->liveCfg.bytesPerSector);\r
+ scsiDev.target->id,\r
+ scsiDev.target->state.bytesPerSector);\r
}\r
\r
if (IP)\r
int pmi = scsiDev.cdb[8] & 1;\r
\r
uint32_t capacity = getScsiCapacity(\r
+ scsiDev.target->device,\r
scsiDev.target->cfg->sdSectorStart,\r
- scsiDev.target->liveCfg.bytesPerSector,\r
+ scsiDev.target->state.bytesPerSector,\r
scsiDev.target->cfg->scsiSectors);\r
\r
if (!pmi && lba)\r
// assume that delays are constant across each block. But the spec\r
// says we must return this error if pmi is specified incorrectly.\r
scsiDev.status = CHECK_CONDITION;\r
- scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
- scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;\r
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;\r
+ scsiDev.target->state.sense.asc = INVALID_FIELD_IN_CDB;\r
scsiDev.phase = STATUS;\r
}\r
else if (capacity > 0)\r
scsiDev.data[2] = highestBlock >> 8;\r
scsiDev.data[3] = highestBlock;\r
\r
- uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;\r
+ uint32_t bytesPerSector = scsiDev.target->state.bytesPerSector;\r
scsiDev.data[4] = bytesPerSector >> 24;\r
scsiDev.data[5] = bytesPerSector >> 16;\r
scsiDev.data[6] = bytesPerSector >> 8;\r
else\r
{\r
scsiDev.status = CHECK_CONDITION;\r
- scsiDev.target->sense.code = NOT_READY;\r
- scsiDev.target->sense.asc = MEDIUM_NOT_PRESENT;\r
+ scsiDev.target->state.sense.code = NOT_READY;\r
+ scsiDev.target->state.sense.asc = MEDIUM_NOT_PRESENT;\r
scsiDev.phase = STATUS;\r
}\r
}\r
s2s_delay_ms(10);\r
}\r
\r
- uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;\r
+ uint32_t bytesPerSector = scsiDev.target->state.bytesPerSector;\r
\r
if (unlikely(blockDev.state & DISK_WP) ||\r
unlikely(scsiDev.target->cfg->deviceType == S2S_CFG_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_t) lba) + blocks >\r
getScsiCapacity(\r
+ scsiDev.target->device,\r
scsiDev.target->cfg->sdSectorStart,\r
bytesPerSector,\r
scsiDev.target->cfg->scsiSectors\r
))\r
{\r
scsiDev.status = CHECK_CONDITION;\r
- scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
- scsiDev.target->sense.asc = LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;\r
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;\r
+ scsiDev.target->state.sense.asc = LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;\r
scsiDev.phase = STATUS;\r
}\r
else\r
}\r
\r
uint32_t capacity = 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
if (unlikely(((uint64_t) lba) + blocks > capacity))\r
{\r
scsiDev.status = CHECK_CONDITION;\r
- scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
- scsiDev.target->sense.asc = LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;\r
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;\r
+ scsiDev.target->state.sense.asc = LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;\r
scsiDev.phase = STATUS;\r
}\r
else\r
scsiDev.phase = DATA_IN;\r
scsiDev.dataLen = 0; // No data yet\r
\r
- uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;\r
+ uint32_t bytesPerSector = scsiDev.target->state.bytesPerSector;\r
uint32_t sdSectorPerSCSISector = SDSectorsPerSCSISector(bytesPerSector);\r
uint32_t sdSectors =\r
blocks * sdSectorPerSCSISector;\r
{\r
if (lba >=\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
)\r
{\r
scsiDev.status = CHECK_CONDITION;\r
- scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
- scsiDev.target->sense.asc = LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;\r
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;\r
+ scsiDev.target->state.sense.asc = LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;\r
scsiDev.phase = STATUS;\r
}\r
else\r
{\r
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
{\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
{\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
// TODO. This means they are supplying data to verify against.\r
// Technically we should probably grab the data and compare it.\r
scsiDev.status = CHECK_CONDITION;\r
- scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
- scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;\r
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;\r
+ scsiDev.target->state.sense.asc = INVALID_FIELD_IN_CDB;\r
scsiDev.phase = STATUS;\r
}\r
}\r
\r
void scsiDiskPoll()\r
{\r
- uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;\r
+ uint32_t bytesPerSector = scsiDev.target->state.bytesPerSector;\r
\r
if (scsiDev.phase == DATA_IN &&\r
transfer.currentBlock != transfer.blocks)\r
if (parityError &&\r
(scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY))\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
#include <string.h>\r
\r
uint32_t getScsiCapacity(\r
+ S2S_Device* device,\r
uint32_t sdSectorStart,\r
uint16_t bytesPerSector,\r
uint32_t scsiSectors)\r
{\r
+ uint32_t devCapacity = device->getCapacity(device);\r
+\r
uint32_t capacity =\r
- (sdDev.capacity - sdSectorStart - S2S_CFG_SIZE) /\r
+ (devCapacity - sdSectorStart - S2S_CFG_SIZE) /\r
SDSectorsPerSCSISector(bytesPerSector);\r
\r
-\r
- if (sdDev.capacity == 0)\r
+ if (devCapacity == 0)\r
{\r
capacity = 0;\r
}\r
- else if (sdSectorStart >= (sdDev.capacity - S2S_CFG_SIZE))\r
+ else if (sdSectorStart >= (devCapacity - S2S_CFG_SIZE))\r
{\r
capacity = 0;\r
}\r
#define GEOMETRY_H
#include "config.h"
-// TODO #include "sd.h"
+#include "device.h"
#define SD_SECTOR_SIZE 512
typedef enum
}
uint32_t getScsiCapacity(
+ S2S_Device* device,
uint32_t sdSectorStart,
uint16_t bytesPerSector,
uint32_t scsiSectors);
// Values for STM32F401RE
const size_t OTP_SIZE = 512;
const size_t OTP_BLOCKS = 16;
-const size_t OTP_BLOCK_SIZE = OTP_SIZE / OTP_BLOCKS;
+const size_t OTP_BLOCK_SIZE = 32;//OTP_SIZE / OTP_BLOCKS;
const size_t OTP_BLOCK_NUM = 0;
-// Define some pointers for writing, but also to allow easy reading back values
#define FLASH_OTP_BASE 0x1FFF7800
-const uint8_t *otp = (uint8_t*)(FLASH_OTP_BASE + OTP_BLOCK_NUM * OTP_BLOCK_SIZE);
-const uint32_t *otp32 = (uint32_t*)(FLASH_OTP_BASE + OTP_BLOCK_NUM * OTP_BLOCK_SIZE);
-const uint8_t *lock = (uint8_t*)(FLASH_OTP_BASE + OTP_SIZE + OTP_BLOCK_NUM);
const uint32_t marker = 0x06002020;
{
checkHwSensePins();
+ // Define some pointers for writing, but also to allow easy reading back values
+ const uint8_t *otp = (uint8_t*)(FLASH_OTP_BASE + OTP_BLOCK_NUM * OTP_BLOCK_SIZE);
+ const uint32_t *otp32 = (uint32_t*)(FLASH_OTP_BASE + OTP_BLOCK_NUM * OTP_BLOCK_SIZE);
+ const uint8_t *lock = (uint8_t*)(FLASH_OTP_BASE + OTP_SIZE + OTP_BLOCK_NUM);
+
// Write a marker to flash that can be read by dfu-util now that we know
// the version is correct.
if (*otp32 != marker)
{\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
else\r
{\r
// error.\r
scsiDev.status = CHECK_CONDITION;\r
- scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
- scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;\r
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;\r
+ scsiDev.target->state.sense.asc = INVALID_FIELD_IN_CDB;\r
scsiDev.phase = STATUS;\r
}\r
\r
scsiDev.data[idx++] = 0; // reserved\r
\r
// Block length\r
- uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;\r
+ uint32_t bytesPerSector = scsiDev.target->state.bytesPerSector;\r
scsiDev.data[idx++] = bytesPerSector >> 16;\r
scsiDev.data[idx++] = bytesPerSector >> 8;\r
scsiDev.data[idx++] = bytesPerSector & 0xFF;\r
scsiDev.data[idx+11] = sectorsPerTrack & 0xFF;\r
\r
// Fill out the configured bytes-per-sector\r
- uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;\r
+ uint32_t bytesPerSector = scsiDev.target->state.bytesPerSector;\r
scsiDev.data[idx+12] = bytesPerSector >> 8;\r
scsiDev.data[idx+13] = bytesPerSector & 0xFF;\r
}\r
uint32_t sector;\r
LBA2CHS(\r
getScsiCapacity(\r
+ scsiDev.target->device,\r
scsiDev.target->cfg->sdSectorStart,\r
- scsiDev.target->liveCfg.bytesPerSector,\r
+ scsiDev.target->state.bytesPerSector,\r
scsiDev.target->cfg->scsiSectors),\r
&cyl,\r
&head,\r
// Unknown Page Code\r
pageFound = 0;\r
scsiDev.status = CHECK_CONDITION;\r
- scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
- scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;\r
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;\r
+ scsiDev.target->state.sense.asc = INVALID_FIELD_IN_CDB;\r
scsiDev.phase = STATUS;\r
}\r
else\r
}\r
else\r
{\r
- scsiDev.target->liveCfg.bytesPerSector = bytesPerSector;\r
+ scsiDev.target->state.bytesPerSector = bytesPerSector;\r
if (bytesPerSector != scsiDev.target->cfg->bytesPerSector)\r
{\r
- s2s_configSave(scsiDev.target->targetId, bytesPerSector);\r
+ s2s_configSave(scsiDev.target->id, bytesPerSector);\r
}\r
}\r
}\r
goto bad;\r
}\r
\r
- scsiDev.target->liveCfg.bytesPerSector = bytesPerSector;\r
+ scsiDev.target->state.bytesPerSector = bytesPerSector;\r
if (scsiDev.cdb[1] & 1) // SP Save Pages flag\r
{\r
- s2s_configSave(scsiDev.target->targetId, bytesPerSector);\r
+ s2s_configSave(scsiDev.target->id, bytesPerSector);\r
}\r
}\r
break;\r
goto out;\r
bad:\r
scsiDev.status = CHECK_CONDITION;\r
- scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
- scsiDev.target->sense.asc = INVALID_FIELD_IN_PARAMETER_LIST;\r
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;\r
+ scsiDev.target->state.sense.asc = INVALID_FIELD_IN_PARAMETER_LIST;\r
\r
out:\r
scsiDev.phase = STATUS;\r
scsiDev.phase = STATUS;\r
\r
scsiDev.lastStatus = scsiDev.status;\r
- scsiDev.lastSense = scsiDev.target->sense.code;\r
- scsiDev.lastSenseASC = scsiDev.target->sense.asc;\r
+ scsiDev.lastSense = scsiDev.target->state.sense.code;\r
+ scsiDev.lastSenseASC = scsiDev.target->state.sense.asc;\r
}\r
\r
void process_Status()\r
}\r
else if (scsiDev.target->cfg->quirks == S2S_CFG_QUIRKS_OMTI)\r
{\r
- scsiDev.status |= (scsiDev.target->targetId & 0x03) << 5;\r
+ scsiDev.status |= (scsiDev.target->id & 0x03) << 5;\r
scsiWriteByte(scsiDev.status);\r
}\r
else\r
}\r
\r
scsiDev.lastStatus = scsiDev.status;\r
- scsiDev.lastSense = scsiDev.target->sense.code;\r
- scsiDev.lastSenseASC = scsiDev.target->sense.asc;\r
+ scsiDev.lastSense = scsiDev.target->state.sense.code;\r
+ scsiDev.lastSenseASC = scsiDev.target->state.sense.asc;\r
\r
// Command Complete occurs AFTER a valid status has been\r
// sent. then we go bus-free.\r
if (parityError &&\r
(scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY))\r
{\r
- scsiDev.target->sense.code = ABORTED_COMMAND;\r
- scsiDev.target->sense.asc = SCSI_PARITY_ERROR;\r
+ scsiDev.target->state.sense.code = ABORTED_COMMAND;\r
+ scsiDev.target->state.sense.asc = SCSI_PARITY_ERROR;\r
enter_Status(CHECK_CONDITION);\r
}\r
}\r
// http://bitsavers.trailing-edge.com/pdf/xebec/104524C_S1410Man_Aug83.pdf\r
if ((scsiDev.lun > 0) && (scsiDev.boardCfg.flags & S2S_CFG_MAP_LUNS_TO_IDS))\r
{\r
- int tgtIndex;\r
- for (tgtIndex = 0; tgtIndex < S2S_MAX_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
else if (parityError &&\r
(scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY))\r
{\r
- scsiDev.target->sense.code = ABORTED_COMMAND;\r
- scsiDev.target->sense.asc = SCSI_PARITY_ERROR;\r
+ scsiDev.target->state.sense.code = ABORTED_COMMAND;\r
+ scsiDev.target->state.sense.asc = SCSI_PARITY_ERROR;\r
enter_Status(CHECK_CONDITION);\r
}\r
else if ((control & 0x02) && ((control & 0x01) == 0) &&\r
likely(scsiDev.target->cfg->quirks != S2S_CFG_QUIRKS_XEBEC))\r
{\r
// FLAG set without LINK flag.\r
- scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
- scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;\r
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;\r
+ scsiDev.target->state.sense.asc = INVALID_FIELD_IN_CDB;\r
enter_Status(CHECK_CONDITION);\r
}\r
else if (command == 0x12)\r
{\r
// Completely non-standard\r
allocLength = 4;\r
- if (scsiDev.target->sense.code == NO_SENSE)\r
+ if (scsiDev.target->state.sense.code == NO_SENSE)\r
scsiDev.data[0] = 0;\r
- else if (scsiDev.target->sense.code == ILLEGAL_REQUEST)\r
+ else if (scsiDev.target->state.sense.code == ILLEGAL_REQUEST)\r
scsiDev.data[0] = 0x20; // Illegal command\r
- else if (scsiDev.target->sense.code == NOT_READY)\r
+ else if (scsiDev.target->state.sense.code == NOT_READY)\r
scsiDev.data[0] = 0x04; // Drive not ready\r
else\r
scsiDev.data[0] = 0x11; // Uncorrectable data error\r
\r
memset(scsiDev.data, 0, 256); // Max possible alloc length\r
scsiDev.data[0] = 0xF0;\r
- scsiDev.data[2] = scsiDev.target->sense.code & 0x0F;\r
+ scsiDev.data[2] = scsiDev.target->state.sense.code & 0x0F;\r
\r
scsiDev.data[3] = transfer.lba >> 24;\r
scsiDev.data[4] = transfer.lba >> 16;\r
\r
// Additional bytes if there are errors to report\r
scsiDev.data[7] = 10; // additional length\r
- scsiDev.data[12] = scsiDev.target->sense.asc >> 8;\r
- scsiDev.data[13] = scsiDev.target->sense.asc;\r
+ scsiDev.data[12] = scsiDev.target->state.sense.asc >> 8;\r
+ scsiDev.data[13] = scsiDev.target->state.sense.asc;\r
}\r
\r
// Silently truncate results. SCSI-2 spec 8.2.14.\r
enter_DataIn(allocLength);\r
\r
// This is a good time to clear out old sense information.\r
- scsiDev.target->sense.code = NO_SENSE;\r
- scsiDev.target->sense.asc = NO_ADDITIONAL_SENSE_INFORMATION;\r
+ scsiDev.target->state.sense.code = NO_SENSE;\r
+ scsiDev.target->state.sense.asc = NO_ADDITIONAL_SENSE_INFORMATION;\r
}\r
// Some old SCSI drivers do NOT properly support\r
// unitAttention. eg. the Mac Plus would trigger a SCSI reset\r
// on receiving the unit attention response on boot, thus\r
// triggering another unit attention condition.\r
- else if (scsiDev.target->unitAttention &&\r
+ else if (scsiDev.target->state.unitAttention &&\r
(scsiDev.boardCfg.flags & S2S_CFG_ENABLE_UNIT_ATTENTION))\r
{\r
- scsiDev.target->sense.code = UNIT_ATTENTION;\r
- scsiDev.target->sense.asc = scsiDev.target->unitAttention;\r
+ scsiDev.target->state.sense.code = UNIT_ATTENTION;\r
+ scsiDev.target->state.sense.asc = scsiDev.target->state.unitAttention;\r
\r
// If initiator doesn't do REQUEST SENSE for the next command, then\r
// data is lost.\r
- scsiDev.target->unitAttention = 0;\r
+ scsiDev.target->state.unitAttention = 0;\r
\r
enter_Status(CHECK_CONDITION);\r
}\r
else if (scsiDev.lun)\r
{\r
- scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
- scsiDev.target->sense.asc = LOGICAL_UNIT_NOT_SUPPORTED;\r
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;\r
+ scsiDev.target->state.sense.asc = LOGICAL_UNIT_NOT_SUPPORTED;\r
enter_Status(CHECK_CONDITION);\r
}\r
else if (command == 0x17 || command == 0x16)\r
{\r
doReserveRelease();\r
}\r
- else if ((scsiDev.target->reservedId >= 0) &&\r
- (scsiDev.target->reservedId != scsiDev.initiatorId))\r
+ else if ((scsiDev.target->state.reservedId >= 0) &&\r
+ (scsiDev.target->state.reservedId != scsiDev.initiatorId))\r
{\r
enter_Status(CONFLICT);\r
}\r
}\r
else if (!scsiModeCommand() && !scsiVendorCommand())\r
{\r
- scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
- scsiDev.target->sense.asc = INVALID_COMMAND_OPERATION_CODE;\r
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;\r
+ scsiDev.target->state.sense.asc = INVALID_COMMAND_OPERATION_CODE;\r
enter_Status(CHECK_CONDITION);\r
}\r
\r
uint8_t command = scsiDev.cdb[0];\r
\r
int canRelease =\r
- (!thirdPty && (scsiDev.initiatorId == scsiDev.target->reservedId)) ||\r
+ (!thirdPty && (scsiDev.initiatorId == scsiDev.target->state.reservedId)) ||\r
(thirdPty &&\r
- (scsiDev.target->reserverId == scsiDev.initiatorId) &&\r
- (scsiDev.target->reservedId == thirdPtyId)\r
+ (scsiDev.target->state.reserverId == scsiDev.initiatorId) &&\r
+ (scsiDev.target->state.reservedId == thirdPtyId)\r
);\r
\r
if (extentReservation)\r
{\r
// Not supported.\r
- scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
- scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;\r
+ scsiDev.target->state.sense.code = ILLEGAL_REQUEST;\r
+ scsiDev.target->state.sense.asc = INVALID_FIELD_IN_CDB;\r
enter_Status(CHECK_CONDITION);\r
}\r
else if (command == 0x17) // release\r
{\r
- if ((scsiDev.target->reservedId < 0) || canRelease)\r
+ if ((scsiDev.target->state.reservedId < 0) || canRelease)\r
{\r
- scsiDev.target->reservedId = -1;\r
- scsiDev.target->reserverId = -1;\r
+ scsiDev.target->state.reservedId = -1;\r
+ scsiDev.target->state.reserverId = -1;\r
}\r
else\r
{\r
}\r
else // assume reserve.\r
{\r
- if ((scsiDev.target->reservedId < 0) || canRelease)\r
+ if ((scsiDev.target->state.reservedId < 0) || canRelease)\r
{\r
- scsiDev.target->reserverId = scsiDev.initiatorId;\r
+ scsiDev.target->state.reserverId = scsiDev.initiatorId;\r
if (thirdPty)\r
{\r
- scsiDev.target->reservedId = thirdPtyId;\r
+ scsiDev.target->state.reservedId = thirdPtyId;\r
}\r
else\r
{\r
- scsiDev.target->reservedId = scsiDev.initiatorId;\r
+ scsiDev.target->state.reservedId = scsiDev.initiatorId;\r
}\r
}\r
else\r
\r
if (scsiDev.target)\r
{\r
- if (scsiDev.target->unitAttention != POWER_ON_RESET)\r
+ if (scsiDev.target->state.unitAttention != POWER_ON_RESET)\r
{\r
- scsiDev.target->unitAttention = SCSI_BUS_RESET;\r
+ scsiDev.target->state.unitAttention = SCSI_BUS_RESET;\r
}\r
- scsiDev.target->reservedId = -1;\r
- scsiDev.target->reserverId = -1;\r
- scsiDev.target->sense.code = NO_SENSE;\r
- scsiDev.target->sense.asc = NO_ADDITIONAL_SENSE_INFORMATION;\r
+ scsiDev.target->state.reservedId = -1;\r
+ scsiDev.target->state.reserverId = -1;\r
+ scsiDev.target->state.sense.code = NO_SENSE;\r
+ scsiDev.target->state.sense.asc = NO_ADDITIONAL_SENSE_INFORMATION;\r
}\r
scsiDev.target = NULL;\r
\r
- for (int i = 0; i < S2S_MAX_TARGETS; ++i)\r
+ int deviceCount;\r
+ S2S_Device* allDevices = s2s_GetDevices(&deviceCount);\r
+ for (int devIdx = 0; devIdx < deviceCount; ++devIdx)\r
{\r
- scsiDev.targets[i].syncOffset = 0;\r
- scsiDev.targets[i].syncPeriod = 0;\r
+ int targetCount;\r
+ S2S_Target* allTargets = allDevices[devIdx].getTargets(allDevices + devIdx, &targetCount);\r
+ for (int i = 0; i < targetCount; ++i)\r
+ {\r
+ allTargets[i].state.syncOffset = 0;\r
+ allTargets[i].state.syncPeriod = 0;\r
+ }\r
}\r
scsiDev.minSyncPeriod = 0;\r
\r
selStatus = scsiDev.selFlag;\r
}\r
\r
- int tgtIndex;\r
- TargetState* target = NULL;\r
- for (tgtIndex = 0; tgtIndex < S2S_MAX_TARGETS; ++tgtIndex)\r
- {\r
- if (scsiDev.targets[tgtIndex].targetId == (selStatus & 7))\r
- {\r
- target = &scsiDev.targets[tgtIndex];\r
- break;\r
- }\r
- }\r
+ S2S_Target* target = s2s_DeviceFindByScsiId(selStatus & 7);\r
if ((target != NULL) && (selStatus & 0x40))\r
{\r
// We've been selected!\r
// controllers don't generate parity bits.\r
if (!scsiDev.atnFlag)\r
{\r
- target->unitAttention = 0;\r
+ target->state.unitAttention = 0;\r
scsiDev.compatMode = COMPAT_SCSI1;\r
}\r
else if (!(scsiDev.boardCfg.flags & S2S_CFG_ENABLE_SCSI2))\r
\r
scsiDiskReset();\r
\r
- scsiDev.target->unitAttention = SCSI_BUS_RESET;\r
+ scsiDev.target->state.unitAttention = SCSI_BUS_RESET;\r
\r
// ANY initiator can reset the reservation state via this message.\r
- scsiDev.target->reservedId = -1;\r
- scsiDev.target->reserverId = -1;\r
+ scsiDev.target->state.reservedId = -1;\r
+ scsiDev.target->state.reserverId = -1;\r
\r
// Cancel any sync negotiation\r
- scsiDev.target->syncOffset = 0;\r
- scsiDev.target->syncPeriod = 0;\r
+ scsiDev.target->state.syncOffset = 0;\r
+ scsiDev.target->state.syncPeriod = 0;\r
\r
enter_BusFree();\r
}\r
\r
if (wasNeedSyncNegotiationAck)\r
{\r
- scsiDev.target->syncOffset = 0;\r
- scsiDev.target->syncPeriod = 0;\r
+ scsiDev.target->state.syncOffset = 0;\r
+ scsiDev.target->state.syncPeriod = 0;\r
}\r
}\r
else if (scsiDev.msgOut == 0x08)\r
\r
if (wasNeedSyncNegotiationAck)\r
{\r
- scsiDev.target->syncOffset = 0;\r
- scsiDev.target->syncPeriod = 0;\r
+ scsiDev.target->state.syncOffset = 0;\r
+ scsiDev.target->state.syncPeriod = 0;\r
}\r
}\r
else if (scsiDev.msgOut & 0x80) // 0x80 -> 0xFF\r
scsiWrite(WDTR, sizeof(WDTR));\r
\r
// SDTR becomes invalidated.\r
- scsiDev.target->syncOffset = 0;\r
- scsiDev.target->syncPeriod = 0;\r
+ scsiDev.target->state.syncOffset = 0;\r
+ scsiDev.target->state.syncPeriod = 0;\r
}\r
else if (extmsg[0] == 1 && msgLen == 3) // Synchronous data request\r
{\r
- int oldPeriod = scsiDev.target->syncPeriod;\r
- int oldOffset = scsiDev.target->syncOffset;\r
+ int oldPeriod = scsiDev.target->state.syncPeriod;\r
+ int oldOffset = scsiDev.target->state.syncOffset;\r
\r
int transferPeriod = extmsg[1];\r
int offset = extmsg[2];\r
((scsiDev.boardCfg.scsiSpeed != S2S_CFG_SPEED_NoLimit) &&\r
(scsiDev.boardCfg.scsiSpeed <= S2S_CFG_SPEED_ASYNC_50)))\r
{\r
- scsiDev.target->syncOffset = 0;\r
- scsiDev.target->syncPeriod = 0;\r
+ scsiDev.target->state.syncOffset = 0;\r
+ scsiDev.target->state.syncPeriod = 0;\r
} else {\r
- scsiDev.target->syncOffset = offset <= 15 ? offset : 15;\r
+ scsiDev.target->state.syncOffset = offset <= 15 ? offset : 15;\r
// FAST20 / 50ns / 20MHz is disabled for now due to\r
// data corruption while reading data. We can count the\r
// ACK's correctly, but can't save the data to a register\r
if ((scsiDev.boardCfg.scsiSpeed == S2S_CFG_SPEED_TURBO) &&\r
(transferPeriod <= 16))\r
{\r
- scsiDev.target->syncPeriod = 16; // 15.6MB/s\r
+ scsiDev.target->state.syncPeriod = 16; // 15.6MB/s\r
}\r
else if (scsiDev.boardCfg.scsiSpeed == S2S_CFG_SPEED_TURBO)\r
{\r
- scsiDev.target->syncPeriod = transferPeriod;\r
+ scsiDev.target->state.syncPeriod = transferPeriod;\r
}\r
else if (transferPeriod <= 25 &&\r
((scsiDev.boardCfg.scsiSpeed == S2S_CFG_SPEED_NoLimit) ||\r
(scsiDev.boardCfg.scsiSpeed >= S2S_CFG_SPEED_SYNC_10)))\r
{\r
- scsiDev.target->syncPeriod = 25; // 100ns, 10MB/s\r
+ scsiDev.target->state.syncPeriod = 25; // 100ns, 10MB/s\r
\r
} else if (transferPeriod < 50 &&\r
((scsiDev.boardCfg.scsiSpeed == S2S_CFG_SPEED_NoLimit) ||\r
(scsiDev.boardCfg.scsiSpeed >= S2S_CFG_SPEED_SYNC_10)))\r
{\r
- scsiDev.target->syncPeriod = transferPeriod;\r
+ scsiDev.target->state.syncPeriod = transferPeriod;\r
} else if (transferPeriod >= 50)\r
{\r
- scsiDev.target->syncPeriod = transferPeriod;\r
+ scsiDev.target->state.syncPeriod = transferPeriod;\r
} else {\r
- scsiDev.target->syncPeriod = 50;\r
+ scsiDev.target->state.syncPeriod = 50;\r
}\r
}\r
\r
if (transferPeriod != oldPeriod ||\r
- scsiDev.target->syncPeriod != oldPeriod ||\r
+ scsiDev.target->state.syncPeriod != oldPeriod ||\r
offset != oldOffset ||\r
- scsiDev.target->syncOffset != oldOffset ||\r
+ scsiDev.target->state.syncOffset != oldOffset ||\r
!wasNeedSyncNegotiationAck) // Don't get into infinite loops negotiating.\r
{\r
scsiEnterPhase(MESSAGE_IN);\r
- uint8_t SDTR[] = {0x01, 0x03, 0x01, scsiDev.target->syncPeriod, scsiDev.target->syncOffset};\r
+ uint8_t SDTR[] = {0x01, 0x03, 0x01, scsiDev.target->state.syncPeriod, scsiDev.target->state.syncOffset};\r
scsiWrite(SDTR, sizeof(SDTR));\r
scsiDev.needSyncNegotiationAck = 1; // Check if this message is rejected.\r
scsiDev.sdUnderrunCount = 0; // reset counter, may work now.\r
scsiDev.hostSpeedKBs = 0;\r
scsiDev.hostSpeedMeasured = 0;\r
\r
- int i;\r
- for (i = 0; i < S2S_MAX_TARGETS; ++i)\r
+ int deviceCount;\r
+ S2S_Device* devices = s2s_GetDevices(&deviceCount);\r
+ for (int deviceIdx = 0; deviceIdx < deviceCount; ++deviceIdx)\r
{\r
- const S2S_TargetCfg* cfg = s2s_getConfigByIndex(i);\r
- if (cfg && (cfg->scsiId & S2S_CFG_TARGET_ENABLED))\r
- {\r
- scsiDev.targets[i].targetId = cfg->scsiId & S2S_CFG_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
- }\r
- scsiDev.targets[i].reservedId = -1;\r
- scsiDev.targets[i].reserverId = -1;\r
- if (firstInit)\r
- {\r
- scsiDev.targets[i].unitAttention = POWER_ON_RESET;\r
- }\r
- else\r
- {\r
- scsiDev.targets[i].unitAttention = PARAMETERS_CHANGED;\r
- }\r
- scsiDev.targets[i].sense.code = NO_SENSE;\r
- scsiDev.targets[i].sense.asc = NO_ADDITIONAL_SENSE_INFORMATION;\r
-\r
- scsiDev.targets[i].syncOffset = 0;\r
- scsiDev.targets[i].syncPeriod = 0;\r
- }\r
- firstInit = 0;\r
-}\r
-\r
-/* TODO REENABLE\r
-void scsiDisconnect()\r
-{\r
- scsiEnterPhase(MESSAGE_IN);\r
- scsiWriteByte(0x02); // save data pointer\r
- scsiWriteByte(0x04); // disconnect msg.\r
-\r
- // For now, the caller is responsible for tracking the disconnected\r
- // state, and calling scsiReconnect.\r
- // Ideally the client would exit their loop and we'd implement this\r
- // as part of scsiPoll\r
- int phase = scsiDev.phase;\r
- enter_BusFree();\r
- scsiDev.phase = phase;\r
-}\r
-*/\r
-\r
-/* TODO REENABLE\r
-int scsiReconnect()\r
-{\r
- int reconnected = 0;\r
-\r
- int sel = SCSI_ReadFilt(SCSI_Filt_SEL);\r
- int bsy = SCSI_ReadFilt(SCSI_Filt_BSY);\r
- if (!sel && !bsy)\r
- {\r
- s2s_delay_us(1);\r
- sel = SCSI_ReadFilt(SCSI_Filt_SEL);\r
- bsy = SCSI_ReadFilt(SCSI_Filt_BSY);\r
- }\r
-\r
- if (!sel && !bsy)\r
- {\r
- // Arbitrate.\r
- s2s_ledOn();\r
- uint8_t scsiIdMask = 1 << scsiDev.target->targetId;\r
- SCSI_Out_Bits_Write(scsiIdMask);\r
- SCSI_Out_Ctl_Write(1); // Write bits manually.\r
- SCSI_SetPin(SCSI_Out_BSY);\r
-\r
- s2s_delay_us(3); // arbitrate delay. 2.4us.\r
-\r
- uint8_t dbx = scsiReadDBxPins();\r
- sel = SCSI_ReadFilt(SCSI_Filt_SEL);\r
- if (sel || ((dbx ^ scsiIdMask) > scsiIdMask))\r
- {\r
- // Lost arbitration.\r
- SCSI_Out_Ctl_Write(0);\r
- SCSI_ClearPin(SCSI_Out_BSY);\r
- s2s_ledOff();\r
- }\r
- else\r
- {\r
- // Won arbitration\r
- SCSI_SetPin(SCSI_Out_SEL);\r
- s2s_delay_us(1); // Bus clear + Bus settle.\r
-\r
- // Reselection phase\r
- SCSI_CTL_PHASE_Write(__scsiphase_io);\r
- SCSI_Out_Bits_Write(scsiIdMask | (1 << scsiDev.initiatorId));\r
- scsiDeskewDelay(); // 2 deskew delays\r
- scsiDeskewDelay(); // 2 deskew delays\r
- SCSI_ClearPin(SCSI_Out_BSY);\r
- s2s_delay_us(1); // Bus Settle Delay\r
-\r
- uint32_t waitStart_ms = getTime_ms();\r
- bsy = SCSI_ReadFilt(SCSI_Filt_BSY);\r
- // Wait for initiator.\r
- while (\r
- !bsy &&\r
- !scsiDev.resetFlag &&\r
- (elapsedTime_ms(waitStart_ms) < 250))\r
- {\r
- bsy = SCSI_ReadFilt(SCSI_Filt_BSY);\r
- }\r
-\r
- if (bsy)\r
+ S2S_TargetState* state = &(targets[i].state);\r
+ state->reservedId = -1;\r
+ state->reserverId = -1;\r
+ if (firstInit)\r
{\r
- SCSI_SetPin(SCSI_Out_BSY);\r
- scsiDeskewDelay(); // 2 deskew delays\r
- scsiDeskewDelay(); // 2 deskew delays\r
- SCSI_ClearPin(SCSI_Out_SEL);\r
-\r
- // Prepare for the initial IDENTIFY message.\r
- SCSI_Out_Ctl_Write(0);\r
- scsiEnterPhase(MESSAGE_IN);\r
-\r
- // Send identify command\r
- scsiWriteByte(0x80);\r
-\r
- scsiEnterPhase(scsiDev.phase);\r
- reconnected = 1;\r
+ state->unitAttention = POWER_ON_RESET;\r
}\r
else\r
{\r
- // reselect timeout.\r
- SCSI_Out_Ctl_Write(0);\r
- SCSI_ClearPin(SCSI_Out_SEL);\r
- SCSI_CTL_PHASE_Write(0);\r
- s2s_ledOff();\r
+ state->unitAttention = PARAMETERS_CHANGED;\r
}\r
+ state->sense.code = NO_SENSE;\r
+ state->sense.asc = NO_ADDITIONAL_SENSE_INFORMATION;\r
+\r
+ state->syncOffset = 0;\r
+ state->syncPeriod = 0;\r
}\r
}\r
- return reconnected;\r
+ firstInit = 0;\r
}\r
-*/\r
+\r
\r
#ifndef SCSI_H
#define SCSI_H
+#include "device.h"
#include "geometry.h"
-#include "sense.h"
#include <stdint.h>
#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 S2S_TargetCfg* cfg;
-
- LiveCfg liveCfg;
-
- 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.
-
- uint8_t syncOffset;
- uint8_t syncPeriod;
-} TargetState;
typedef struct
{
// 65536 bytes is the DMA limit
uint8_t data[MAX_SECTOR_SIZE * 8];
- TargetState targets[S2S_MAX_TARGETS];
- TargetState* target;
- S2S_BoardCfg boardCfg;
-
+ S2S_Target* target;
+ S2S_BoardCfg boardCfg; // TODO remove
// Set to true (1) if the ATN flag was set, and we need to
// enter the MESSAGE_OUT phase.
while (likely(!scsiDev.resetFlag) && scsiStatusACK()) {}\r
\r
int oldPhase = *SCSI_CTRL_PHASE;\r
+ uint8_t syncOffset = scsiDev.target->state.syncOffset;\r
+ uint8_t syncPeriod = scsiDev.target->state.syncPeriod;\r
\r
if (newPhase != oldPhase)\r
{\r
- if ((newPhase == DATA_IN || newPhase == DATA_OUT) &&\r
- scsiDev.target->syncOffset)\r
+ if ((newPhase == DATA_IN || newPhase == DATA_OUT) && syncOffset)\r
{\r
- if (scsiDev.target->syncPeriod < 23)\r
+ if (syncPeriod < 23)\r
{\r
scsiSetTiming(SCSI_FAST20_ASSERT, SCSI_FAST20_DESKEW, SCSI_FAST20_HOLD, 1);\r
}\r
- else if (scsiDev.target->syncPeriod <= 25)\r
+ else if (syncPeriod <= 25)\r
{\r
if (newPhase == DATA_IN)\r
{\r
// Amiga A3000 OS3.9 sets period to 35 and fails with\r
// glitch == 1.\r
int glitch =\r
- scsiDev.target->syncPeriod < 35 ? 1 :\r
- (scsiDev.target->syncPeriod < 45 ? 2 : 5);\r
- int deskew = syncDeskew(scsiDev.target->syncPeriod);\r
+ syncPeriod < 35 ? 1 : (syncPeriod < 45 ? 2 : 5);\r
+ int deskew = syncDeskew(syncPeriod);\r
int assertion;\r
if (newPhase == DATA_IN)\r
{\r
- assertion = syncAssertionWrite(scsiDev.target->syncPeriod, deskew);\r
+ assertion = syncAssertionWrite(syncPeriod, deskew);\r
}\r
else\r
{\r
- assertion = syncAssertionRead(scsiDev.target->syncPeriod);\r
+ assertion = syncAssertionRead(syncPeriod);\r
}\r
scsiSetTiming(\r
assertion,\r
deskew,\r
- syncHold(scsiDev.target->syncPeriod),\r
+ syncHold(syncPeriod),\r
glitch);\r
}\r
\r
- *SCSI_CTRL_SYNC_OFFSET = scsiDev.target->syncOffset;\r
+ *SCSI_CTRL_SYNC_OFFSET = syncOffset;\r
}\r
else if (newPhase >= 0)\r
{\r
// theoretical speed / 2\r
uint32_t s2s_getScsiRateKBs()\r
{\r
- if (scsiDev.target->syncOffset)\r
+ if (scsiDev.target->state.syncOffset)\r
{\r
- if (scsiDev.target->syncPeriod < 23)\r
+ if (scsiDev.target->state.syncPeriod < 23)\r
{\r
return 20 / 2;\r
}\r
- else if (scsiDev.target->syncPeriod <= 25)\r
+ else if (scsiDev.target->state.syncPeriod <= 25)\r
{\r
return 10 / 2;\r
}\r
{\r
// 1000000000 / (scsiDev.target->syncPeriod * 4) bytes per second\r
// (1000000000 / (scsiDev.target->syncPeriod * 4)) / 1000 kB/s\r
- return (1000000 / (scsiDev.target->syncPeriod * 4)) / 2;\r
+ return (1000000 / (scsiDev.target->state.syncPeriod * 4)) / 2;\r
}\r
}\r
else\r
\r
#include <string.h>\r
\r
+static const S2S_BoardCfg* sd_getBoardConfig(S2S_Device* dev);\r
+//static const S2S_TargetCfg* sd_findByScsiId(S2S_Device* dev, int scsiId);\r
+static S2S_Target* sd_getTargets(S2S_Device* dev, int* count);\r
+static uint32_t sd_getCapacity(S2S_Device* dev);\r
+\r
// Global\r
-SdDevice sdDev;\r
+SdCard sdCard S2S_DMA_ALIGN = {\r
+ {\r
+ sd_getBoardConfig,\r
+ //sd_findByScsiId,\r
+ sd_getTargets,\r
+ sd_getCapacity\r
+ }\r
+};\r
+\r
+S2S_Device* sdDevice = &(sdCard.dev);\r
\r
static int sdCmdActive = 0;\r
\r
scsiDiskReset();\r
\r
scsiDev.status = CHECK_CONDITION;\r
- scsiDev.target->sense.code = HARDWARE_ERROR;\r
- scsiDev.target->sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;\r
+ scsiDev.target->state.sense.code = HARDWARE_ERROR;\r
+ scsiDev.target->state.sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;\r
scsiDev.phase = STATUS;\r
}\r
else\r
\r
static void sdClear()\r
{\r
- sdDev.version = 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.capacity = 0;\r
+ memset(sdCard.csd, 0, sizeof(sdCard.csd));\r
+ memset(sdCard.cid, 0, sizeof(sdCard.cid));\r
}\r
\r
static int sdDoInit()\r
int8_t error = BSP_SD_Init();\r
if (error == MSD_OK)\r
{\r
- memcpy(sdDev.csd, &SDCardInfo.SD_csd, sizeof(sdDev.csd));\r
- memcpy(sdDev.cid, &SDCardInfo.SD_cid, sizeof(sdDev.cid));\r
- sdDev.capacity = SDCardInfo.CardCapacity / SD_SECTOR_SIZE;\r
+ memcpy(sdCard.csd, &SDCardInfo.SD_csd, sizeof(sdCard.csd));\r
+ memcpy(sdCard.cid, &SDCardInfo.SD_cid, sizeof(sdCard.cid));\r
+ sdCard.capacity = SDCardInfo.CardCapacity / SD_SECTOR_SIZE;\r
blockDev.state |= DISK_PRESENT | DISK_INITIALISED;\r
result = 1;\r
\r
//bad:\r
blockDev.state &= ~(DISK_PRESENT | DISK_INITIALISED);\r
\r
- sdDev.capacity = 0;\r
+ sdCard.capacity = 0;\r
\r
out:\r
s2s_ledOff();\r
}\r
else if (!cs && (blockDev.state & DISK_PRESENT))\r
{\r
- sdDev.capacity = 0;\r
+ sdCard.capacity = 0;\r
blockDev.state &= ~DISK_PRESENT;\r
blockDev.state &= ~DISK_INITIALISED;\r
int i;\r
for (i = 0; i < S2S_MAX_TARGETS; ++i)\r
{\r
- scsiDev.targets[i].unitAttention = PARAMETERS_CHANGED;\r
+ sdCard.targets[i].state.unitAttention = PARAMETERS_CHANGED;\r
}\r
\r
HAL_SD_DeInit(&hsd);\r
return result;\r
}\r
\r
+static const S2S_BoardCfg* sd_getBoardConfig(S2S_Device* dev)\r
+{\r
+ SdCard* sdCardDevice = (SdCard*)dev;\r
+\r
+ if ((blockDev.state & DISK_PRESENT) && sdCardDevice->capacity)\r
+ {\r
+ int cfgSectors = (S2S_CFG_SIZE + 511) / 512;\r
+ BSP_SD_ReadBlocks_DMA(\r
+ (uint32_t*) &(sdCardDevice->boardCfg[0]),\r
+ (sdCardDevice->capacity - cfgSectors) * 512ll,\r
+ 512,\r
+ cfgSectors);\r
+\r
+ S2S_BoardCfg* cfg = (S2S_BoardCfg*) &(sdCardDevice->boardCfg[0]);\r
+ if (memcmp(cfg->magic, "BCFG", 4))\r
+ {\r
+ return NULL;\r
+ }\r
+ else\r
+ {\r
+ return cfg;\r
+ }\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+//static const S2S_TargetCfg* sd_findByScsiId(S2S_Device* dev, int scsiId)\r
+static S2S_Target* sd_getTargets(S2S_Device* dev, int* count)\r
+{\r
+ SdCard* sdCardDevice = (SdCard*)dev;\r
+ *count = S2S_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
#define S2S_SD_H
#include <stdint.h>
+#include "bsp.h"
+#include "device.h"
#define SD_SECTOR_SIZE 512
typedef struct
{
+ S2S_Device dev;
+
+ uint8_t boardCfg[S2S_CFG_SIZE] S2S_DMA_ALIGN;
+
+ S2S_Target targets[S2S_MAX_TARGETS];
+
int version; // SDHC = version 2.
uint32_t capacity; // in 512 byte blocks
uint8_t csd[16]; // Unparsed CSD
uint8_t cid[16]; // Unparsed CID
-} SdDevice;
+} SdCard;
+
+extern SdCard sdCard; // TODO move to .c file
-extern SdDevice sdDev;
+extern S2S_Device* sdDevice;
int sdInit(void);
// along with SCSI2SD. If not, see <http://www.gnu.org/licenses/>.
-#include "usbd_msc_storage_sd.h"
-#include "stm32f2xx.h"
#include "../bsp_driver_sd.h"
#include "../bsp.h"
#include "../disk.h"
#include "../config.h"
#include "../geometry.h"
#include "../inquiry.h"
-#include "usb_device.h"
+#include "usbd_msc_storage_sd.h"
+#include "stm32f2xx.h"
+#include "usb_device.h"
static int8_t s2s_usbd_storage_Init(uint8_t lun);
s2s_usbd_storage_Inquiry
};
-static const S2S_TargetCfg* getUsbConfig(uint8_t lun) {
+static const S2S_Target* getUsbTarget(uint8_t lun) {
int count = 0;
- for (int i = 0; i < S2S_MAX_TARGETS; ++i)
+ int deviceCount;
+ S2S_Device* devices = s2s_GetDevices(&deviceCount);
+ for (int deviceIdx = 0; deviceIdx < deviceCount; ++deviceIdx)
{
- const S2S_TargetCfg* cfg = s2s_getConfigByIndex(i);
- if (cfg && (cfg->scsiId & S2S_CFG_TARGET_ENABLED))
+ int targetCount;
+ S2S_Target* targets = devices[deviceIdx].getTargets(devices + deviceIdx, &targetCount);
+ for (int targetIdx = 0; targetIdx < targetCount; ++targetIdx)
{
- if (count == lun)
- {
- return cfg;
- }
- else
+ S2S_Target* target = targets + targetIdx;
+ if (target && (target->cfg->scsiId & S2S_CFG_TARGET_ENABLED))
{
- count++;
+ if (count == lun)
+ {
+ return target;
+ }
+ else
+ {
+ count++;
+ }
}
}
}
- return s2s_getConfigByIndex(0); // Fallback, try not to crash
+ int dummy;
+ return devices[0].getTargets(devices, &dummy); // Fallback, try not to crash
}
int8_t s2s_usbd_storage_Init(uint8_t lun)
int8_t s2s_usbd_storage_GetCapacity (uint8_t lun, uint32_t *block_num, uint16_t *block_size)
{
- const S2S_TargetCfg* cfg = getUsbConfig(lun);
+ const S2S_Target* target = getUsbTarget(lun);
uint32_t capacity = getScsiCapacity(
- cfg->sdSectorStart,
- cfg->bytesPerSector,
- cfg->scsiSectors);
+ target->device,
+ target->cfg->sdSectorStart,
+ target->state.bytesPerSector,
+ target->cfg->scsiSectors);
*block_num = capacity;
- *block_size = cfg->bytesPerSector;
+ *block_size = target->state.bytesPerSector;
return (0);
}
uint32_t s2s_usbd_storage_Inquiry (uint8_t lun, uint8_t* buf, uint8_t maxlen)
{
- const S2S_TargetCfg* cfg = getUsbConfig(lun);
+ const S2S_Target* target = getUsbTarget(lun);
- return s2s_getStandardInquiry(cfg, buf, maxlen);
+ return s2s_getStandardInquiry(target->cfg, buf, maxlen);
}
int8_t s2s_usbd_storage_IsReady (uint8_t lun)
{
- const S2S_TargetCfg* cfg = getUsbConfig(lun);
+ const S2S_Target* target = getUsbTarget(lun);
return (
- cfg &&
+ target &&
(blockDev.state & DISK_PRESENT) &&
(blockDev.state & DISK_INITIALISED)
) ? 0 : 1; // inverse logic
uint16_t blk_len)
{
s2s_ledOn();
- const S2S_TargetCfg* cfg = getUsbConfig(lun);
+ const S2S_Target* target = getUsbTarget(lun);
- if (cfg->bytesPerSector == 512)
+ if (target->state.bytesPerSector == 512)
{
BSP_SD_ReadBlocks_DMA(
(uint32_t*) buf,
- (cfg->sdSectorStart + blk_addr) * 512ll,
+ (target->cfg->sdSectorStart + blk_addr) * 512ll,
512,
blk_len);
}
else
{
- int sdPerScsi = SDSectorsPerSCSISector(cfg->bytesPerSector);
- int sdSectorNum = cfg->sdSectorStart + (blk_addr * sdPerScsi);
+ int sdPerScsi = SDSectorsPerSCSISector(target->state.bytesPerSector);
+ int sdSectorNum = target->cfg->sdSectorStart + (blk_addr * sdPerScsi);
for (int blk = 0; blk < blk_len; ++blk)
{
- for (int i = 0; i < SDSectorsPerSCSISector(cfg->bytesPerSector); ++i)
+ for (int i = 0; i < SDSectorsPerSCSISector(target->state.bytesPerSector); ++i)
{
uint8_t partial[512] S2S_DMA_ALIGN;
BSP_SD_ReadBlocks_DMA(
1);
sdSectorNum++;
- int validBytes = cfg->bytesPerSector % SD_SECTOR_SIZE;
+ int validBytes = target->state.bytesPerSector % SD_SECTOR_SIZE;
if (validBytes == 0) validBytes = SD_SECTOR_SIZE;
memcpy(buf, partial, validBytes);
buf += validBytes;
}
-
}
-
}
s2s_ledOff();
return 0;
uint16_t blk_len)
{
s2s_ledOn();
- const S2S_TargetCfg* cfg = getUsbConfig(lun);
+ const S2S_Target* target = getUsbTarget(lun);
- if (cfg->bytesPerSector == 512)
+ if (target->state.bytesPerSector == 512)
{
BSP_SD_WriteBlocks_DMA(
(uint32_t*) buf,
- (cfg->sdSectorStart + blk_addr) * 512ll,
+ (target->cfg->sdSectorStart + blk_addr) * 512ll,
512,
blk_len);
}
else
{
- int sdPerScsi = SDSectorsPerSCSISector(cfg->bytesPerSector);
- int sdSectorNum = cfg->sdSectorStart + (blk_addr * sdPerScsi);
+ int sdPerScsi = SDSectorsPerSCSISector(target->state.bytesPerSector);
+ int sdSectorNum = target->cfg->sdSectorStart + (blk_addr * sdPerScsi);
for (int blk = 0; blk < blk_len; ++blk)
{
- for (int i = 0; i < SDSectorsPerSCSISector(cfg->bytesPerSector); ++i)
+ for (int i = 0; i < SDSectorsPerSCSISector(target->state.bytesPerSector); ++i)
{
uint8_t partial[512] S2S_DMA_ALIGN;
memcpy(partial, buf, 512);
1);
sdSectorNum++;
- int validBytes = cfg->bytesPerSector % SD_SECTOR_SIZE;
+ int validBytes = target->state.bytesPerSector % SD_SECTOR_SIZE;
if (validBytes == 0) validBytes = SD_SECTOR_SIZE;
buf += validBytes;
int8_t s2s_usbd_storage_GetMaxLun (void)
{
int count = 0;
- for (int i = 0; i < S2S_MAX_TARGETS; ++i)
+ int deviceCount;
+ S2S_Device* devices = s2s_GetDevices(&deviceCount);
+ for (int deviceIdx = 0; deviceIdx < deviceCount; ++deviceIdx)
{
- const S2S_TargetCfg* cfg = s2s_getConfigByIndex(i);
- if (cfg && (cfg->scsiId & S2S_CFG_TARGET_ENABLED))
+ int targetCount;
+ S2S_Target* targets = devices[deviceIdx].getTargets(devices + deviceIdx, &targetCount);
+ for (int targetIdx = 0; targetIdx < targetCount; ++targetIdx)
{
- count++;
+ S2S_Target* target = targets + targetIdx;
+ if (target && (target->cfg->scsiId & S2S_CFG_TARGET_ENABLED))
+ {
+ count++;
+ }
}
}
return count - 1 < 0 ? 0 : count - 1;