mirror of
https://github.com/fhgwright/SCSI2SD.git
synced 2025-04-10 01:37:07 +00:00
Small compatibility improvements, and added scsi2sd-monitor test program
This commit is contained in:
parent
95b519789b
commit
9ad7cc15d0
@ -1,4 +1,7 @@
|
||||
201501?? 4.1.1
|
||||
20150420 4.2.2
|
||||
- Improved compatibility with older SCSI1 hosts.
|
||||
|
||||
20150123 4.1.1
|
||||
- Fix MODE SENSE bug when the allocation length is less than the
|
||||
page size.
|
||||
- Add WRITE BUFFER and WRITE AND VERIFY support.
|
||||
|
@ -13,7 +13,6 @@ computer and a modern PC (who still has access to a working floppy drive ?)
|
||||
Features
|
||||
|
||||
In-built active terminator.
|
||||
Can optional supply terminator power back to the SCSI bus
|
||||
Emulates up to 4 SCSI devices
|
||||
Supports sector sizes from 64 bytes to 8192 bytes
|
||||
Firmware updatable over USB
|
||||
@ -95,6 +94,8 @@ Samplers
|
||||
SCSI cable reversed on S3200
|
||||
There are compatibility problems with the Akai MPC3000. It works (slowly) with the alternate Vailixi OS with multi-sector transfers disabled.
|
||||
EMU Emulator E4X with EOS 3.00b and E6400 (classic) with Eos 4.01
|
||||
EMU E6400 w/ EOS2.80f
|
||||
EMU Emax2
|
||||
Ensoniq ASR-X, ASR-10 (from v3.4, 2GB size limit)
|
||||
ASR-20 Requires TERMPWR jumper.
|
||||
ASR-X resets when writing to devices > 2Gb.
|
||||
@ -113,3 +114,5 @@ Other
|
||||
Reftek RT-72A Seismic datalogger.
|
||||
http://www.iris.iris.edu/passcal/Reftek/72A-R-005-00.1.pdf
|
||||
http://www.iris.iris.edu/passcal/Manual/rtfm.s3a.13.html
|
||||
Konami Simpson's Bowling arcade machine
|
||||
http://forums.arcade-museum.com/showthread.php?p=3027446
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static const uint16_t FIRMWARE_VERSION = 0x0411;
|
||||
static const uint16_t FIRMWARE_VERSION = 0x0422;
|
||||
|
||||
enum USB_ENDPOINTS
|
||||
{
|
||||
@ -53,8 +53,30 @@ static int usbInEpState;
|
||||
static int usbDebugEpState;
|
||||
static int usbReady;
|
||||
|
||||
uint8_t DEFAULT_CONFIG[256]
|
||||
__attribute__ ((section(".DEFAULT_CONFIG"))) =
|
||||
{
|
||||
CONFIG_TARGET_ENABLED,
|
||||
CONFIG_FIXED,
|
||||
0,
|
||||
0,
|
||||
0, 0, 0, 0,
|
||||
0xff, 0xff, 0x3f, 0x00, // 4194303, 2GB - 1 sector
|
||||
0x00, 0x02, //512
|
||||
63, 0,
|
||||
255, 0,
|
||||
' ', 'c', 'o', 'd', 'e', 's', 'r', 'c',
|
||||
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'S', 'C', 'S', 'I', '2', 'S', 'D',
|
||||
' ', '4', '.', '2',
|
||||
'1','2','3','4','5','6','7','8','1','2','3','4','5','6','7','8'
|
||||
};
|
||||
// otherwise linker removes unused section.
|
||||
volatile uint8_t trickLinker;
|
||||
|
||||
void configInit()
|
||||
{
|
||||
trickLinker = DEFAULT_CONFIG[0];
|
||||
|
||||
// The USB block will be powered by an internal 3.3V regulator.
|
||||
// The PSoC must be operating between 4.6V and 5V for the regulator
|
||||
// to work.
|
||||
@ -132,6 +154,20 @@ sdInfoCommand()
|
||||
|
||||
hidPacket_send(response, sizeof(response));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scsiTestCommand()
|
||||
{
|
||||
int resultCode = scsiSelfTest();
|
||||
uint8_t response[] =
|
||||
{
|
||||
resultCode == 0 ? CONFIG_STATUS_GOOD : CONFIG_STATUS_ERR,
|
||||
resultCode
|
||||
};
|
||||
hidPacket_send(response, sizeof(response));
|
||||
}
|
||||
|
||||
static void
|
||||
processCommand(const uint8_t* cmd, size_t cmdSize)
|
||||
{
|
||||
@ -157,6 +193,10 @@ processCommand(const uint8_t* cmd, size_t cmdSize)
|
||||
sdInfoCommand();
|
||||
break;
|
||||
|
||||
case CONFIG_SCSITEST:
|
||||
scsiTestCommand();
|
||||
break;
|
||||
|
||||
case CONFIG_NONE: // invalid
|
||||
default:
|
||||
break;
|
||||
|
@ -728,7 +728,7 @@ void scsiDiskPoll()
|
||||
{
|
||||
if (scsiDev.parityError &&
|
||||
(scsiDev.target->cfg->flags & CONFIG_ENABLE_PARITY) &&
|
||||
!scsiDev.compatMode)
|
||||
(scsiDev.compatMode >= COMPAT_SCSI2))
|
||||
{
|
||||
scsiDev.target->sense.code = ABORTED_COMMAND;
|
||||
scsiDev.target->sense.asc = SCSI_PARITY_ERROR;
|
||||
|
@ -145,231 +145,224 @@ static void pageIn(int pc, int dataIdx, const uint8* pageData, int pageLen)
|
||||
static void doModeSense(
|
||||
int sixByteCmd, int dbd, int pc, int pageCode, int allocLength)
|
||||
{
|
||||
if (pc == 0x03) // Saved Values not supported.
|
||||
////////////// Mode Parameter Header
|
||||
////////////////////////////////////
|
||||
|
||||
// Skip the Mode Data Length, we set that last.
|
||||
int idx = 1;
|
||||
if (!sixByteCmd) ++idx;
|
||||
|
||||
uint8_t mediumType = 0;
|
||||
uint8_t deviceSpecificParam = 0;
|
||||
uint8_t density = 0;
|
||||
switch (scsiDev.target->cfg->deviceType == CONFIG_OPTICAL)
|
||||
{
|
||||
case CONFIG_FIXED:
|
||||
case CONFIG_REMOVEABLE:
|
||||
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;
|
||||
density = 0; // reserved for direct access
|
||||
break;
|
||||
|
||||
case CONFIG_FLOPPY_14MB:
|
||||
mediumType = 0x1E; // 90mm/3.5"
|
||||
deviceSpecificParam =
|
||||
(blockDev.state & DISK_WP) ? 0x80 : 0;
|
||||
density = 0; // reserved for direct access
|
||||
break;
|
||||
|
||||
case CONFIG_OPTICAL:
|
||||
mediumType = 0x02; // 120mm CDROM, data only.
|
||||
deviceSpecificParam = 0;
|
||||
density = 0x01; // User data only, 2048bytes per sector.
|
||||
break;
|
||||
|
||||
};
|
||||
|
||||
scsiDev.data[idx++] = mediumType;
|
||||
scsiDev.data[idx++] = deviceSpecificParam;
|
||||
|
||||
if (sixByteCmd)
|
||||
{
|
||||
if (dbd)
|
||||
{
|
||||
scsiDev.data[idx++] = 0; // No block descriptor
|
||||
}
|
||||
else
|
||||
{
|
||||
// One block descriptor of length 8 bytes.
|
||||
scsiDev.data[idx++] = 8;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
scsiDev.data[idx++] = 0; // Reserved
|
||||
scsiDev.data[idx++] = 0; // Reserved
|
||||
if (dbd)
|
||||
{
|
||||
scsiDev.data[idx++] = 0; // No block descriptor
|
||||
scsiDev.data[idx++] = 0; // No block descriptor
|
||||
}
|
||||
else
|
||||
{
|
||||
// One block descriptor of length 8 bytes.
|
||||
scsiDev.data[idx++] = 0;
|
||||
scsiDev.data[idx++] = 8;
|
||||
}
|
||||
}
|
||||
|
||||
////////////// Block Descriptor
|
||||
////////////////////////////////////
|
||||
if (!dbd)
|
||||
{
|
||||
scsiDev.data[idx++] = density;
|
||||
// Number of blocks
|
||||
// Zero == all remaining blocks shall have the medium
|
||||
// characteristics specified.
|
||||
scsiDev.data[idx++] = 0;
|
||||
scsiDev.data[idx++] = 0;
|
||||
scsiDev.data[idx++] = 0;
|
||||
|
||||
scsiDev.data[idx++] = 0; // reserved
|
||||
|
||||
// Block length
|
||||
uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;
|
||||
scsiDev.data[idx++] = bytesPerSector >> 16;
|
||||
scsiDev.data[idx++] = bytesPerSector >> 8;
|
||||
scsiDev.data[idx++] = bytesPerSector & 0xFF;
|
||||
}
|
||||
|
||||
int pageFound = 0;
|
||||
|
||||
if (pageCode == 0x01 || pageCode == 0x3F)
|
||||
{
|
||||
pageFound = 1;
|
||||
pageIn(pc, idx, ReadWriteErrorRecoveryPage, sizeof(ReadWriteErrorRecoveryPage));
|
||||
idx += sizeof(ReadWriteErrorRecoveryPage);
|
||||
}
|
||||
|
||||
if (pageCode == 0x02 || pageCode == 0x3F)
|
||||
{
|
||||
pageFound = 1;
|
||||
pageIn(pc, idx, DisconnectReconnectPage, sizeof(DisconnectReconnectPage));
|
||||
idx += sizeof(DisconnectReconnectPage);
|
||||
}
|
||||
|
||||
if (pageCode == 0x03 || pageCode == 0x3F)
|
||||
{
|
||||
pageFound = 1;
|
||||
pageIn(pc, idx, FormatDevicePage, sizeof(FormatDevicePage));
|
||||
if (pc != 0x01)
|
||||
{
|
||||
// Fill out the configured bytes-per-sector
|
||||
uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;
|
||||
scsiDev.data[idx+12] = bytesPerSector >> 8;
|
||||
scsiDev.data[idx+13] = bytesPerSector & 0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set a mask for the changeable values.
|
||||
scsiDev.data[idx+12] = 0xFF;
|
||||
scsiDev.data[idx+13] = 0xFF;
|
||||
}
|
||||
|
||||
idx += sizeof(FormatDevicePage);
|
||||
}
|
||||
|
||||
if (pageCode == 0x04 || pageCode == 0x3F)
|
||||
{
|
||||
pageFound = 1;
|
||||
pageIn(pc, idx, RigidDiskDriveGeometry, sizeof(RigidDiskDriveGeometry));
|
||||
|
||||
if (pc != 0x01)
|
||||
{
|
||||
// Need to fill out the number of cylinders.
|
||||
uint32 cyl;
|
||||
uint8 head;
|
||||
uint32 sector;
|
||||
LBA2CHS(
|
||||
getScsiCapacity(
|
||||
scsiDev.target->cfg->sdSectorStart,
|
||||
scsiDev.target->liveCfg.bytesPerSector,
|
||||
scsiDev.target->cfg->scsiSectors),
|
||||
&cyl,
|
||||
&head,
|
||||
§or);
|
||||
|
||||
scsiDev.data[idx+2] = cyl >> 16;
|
||||
scsiDev.data[idx+3] = cyl >> 8;
|
||||
scsiDev.data[idx+4] = cyl;
|
||||
|
||||
memcpy(&scsiDev.data[idx+6], &scsiDev.data[idx+2], 3);
|
||||
memcpy(&scsiDev.data[idx+9], &scsiDev.data[idx+2], 3);
|
||||
}
|
||||
|
||||
idx += sizeof(RigidDiskDriveGeometry);
|
||||
}
|
||||
|
||||
// DON'T output the following pages for SCSI1 hosts. They get upset when
|
||||
// we have more data to send than the allocation length provided.
|
||||
// (ie. Try not to output any more pages below this comment)
|
||||
|
||||
|
||||
if ((scsiDev.compatMode >= COMPAT_SCSI2) &&
|
||||
(pageCode == 0x08 || pageCode == 0x3F))
|
||||
{
|
||||
pageFound = 1;
|
||||
pageIn(pc, idx, CachingPage, sizeof(CachingPage));
|
||||
idx += sizeof(CachingPage);
|
||||
}
|
||||
|
||||
if ((scsiDev.compatMode >= COMPAT_SCSI2)
|
||||
&& (pageCode == 0x0A || pageCode == 0x3F))
|
||||
{
|
||||
pageFound = 1;
|
||||
pageIn(pc, idx, ControlModePage, sizeof(ControlModePage));
|
||||
idx += sizeof(ControlModePage);
|
||||
}
|
||||
|
||||
if ((
|
||||
(scsiDev.target->cfg->quirks == CONFIG_QUIRKS_APPLE) ||
|
||||
(idx + sizeof(AppleVendorPage) <= allocLength)
|
||||
) &&
|
||||
(pageCode == 0x30 || pageCode == 0x3F))
|
||||
{
|
||||
pageFound = 1;
|
||||
pageIn(pc, idx, AppleVendorPage, sizeof(AppleVendorPage));
|
||||
idx += sizeof(AppleVendorPage);
|
||||
}
|
||||
|
||||
if (!pageFound)
|
||||
{
|
||||
// Unknown Page Code
|
||||
pageFound = 0;
|
||||
scsiDev.status = CHECK_CONDITION;
|
||||
scsiDev.target->sense.code = ILLEGAL_REQUEST;
|
||||
scsiDev.target->sense.asc = SAVING_PARAMETERS_NOT_SUPPORTED;
|
||||
scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
|
||||
scsiDev.phase = STATUS;
|
||||
}
|
||||
else
|
||||
{
|
||||
////////////// Mode Parameter Header
|
||||
////////////////////////////////////
|
||||
|
||||
// Skip the Mode Data Length, we set that last.
|
||||
int idx = 1;
|
||||
if (!sixByteCmd) ++idx;
|
||||
|
||||
uint8_t mediumType = 0;
|
||||
uint8_t deviceSpecificParam = 0;
|
||||
uint8_t density = 0;
|
||||
switch (scsiDev.target->cfg->deviceType == CONFIG_OPTICAL)
|
||||
{
|
||||
case CONFIG_FIXED:
|
||||
case CONFIG_REMOVEABLE:
|
||||
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;
|
||||
density = 0; // reserved for direct access
|
||||
break;
|
||||
|
||||
case CONFIG_FLOPPY_14MB:
|
||||
mediumType = 0x1E; // 90mm/3.5"
|
||||
deviceSpecificParam =
|
||||
(blockDev.state & DISK_WP) ? 0x80 : 0;
|
||||
density = 0; // reserved for direct access
|
||||
break;
|
||||
|
||||
case CONFIG_OPTICAL:
|
||||
mediumType = 0x02; // 120mm CDROM, data only.
|
||||
deviceSpecificParam = 0;
|
||||
density = 0x01; // User data only, 2048bytes per sector.
|
||||
break;
|
||||
|
||||
};
|
||||
|
||||
scsiDev.data[idx++] = mediumType;
|
||||
scsiDev.data[idx++] = deviceSpecificParam;
|
||||
|
||||
// Go back and fill out the mode data length
|
||||
if (sixByteCmd)
|
||||
{
|
||||
if (dbd)
|
||||
{
|
||||
scsiDev.data[idx++] = 0; // No block descriptor
|
||||
}
|
||||
else
|
||||
{
|
||||
// One block descriptor of length 8 bytes.
|
||||
scsiDev.data[idx++] = 8;
|
||||
}
|
||||
// Cannot currently exceed limits. yay
|
||||
scsiDev.data[0] = idx - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
scsiDev.data[idx++] = 0; // Reserved
|
||||
scsiDev.data[idx++] = 0; // Reserved
|
||||
if (dbd)
|
||||
{
|
||||
scsiDev.data[idx++] = 0; // No block descriptor
|
||||
scsiDev.data[idx++] = 0; // No block descriptor
|
||||
}
|
||||
else
|
||||
{
|
||||
// One block descriptor of length 8 bytes.
|
||||
scsiDev.data[idx++] = 0;
|
||||
scsiDev.data[idx++] = 8;
|
||||
}
|
||||
scsiDev.data[0] = ((idx - 2) >> 8);
|
||||
scsiDev.data[1] = (idx - 2);
|
||||
}
|
||||
|
||||
////////////// Block Descriptor
|
||||
////////////////////////////////////
|
||||
if (!dbd)
|
||||
{
|
||||
scsiDev.data[idx++] = density;
|
||||
// Number of blocks
|
||||
// Zero == all remaining blocks shall have the medium
|
||||
// characteristics specified.
|
||||
scsiDev.data[idx++] = 0;
|
||||
scsiDev.data[idx++] = 0;
|
||||
scsiDev.data[idx++] = 0;
|
||||
|
||||
scsiDev.data[idx++] = 0; // reserved
|
||||
|
||||
// Block length
|
||||
uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;
|
||||
scsiDev.data[idx++] = bytesPerSector >> 16;
|
||||
scsiDev.data[idx++] = bytesPerSector >> 8;
|
||||
scsiDev.data[idx++] = bytesPerSector & 0xFF;
|
||||
}
|
||||
|
||||
int pageFound = 0;
|
||||
|
||||
if (pageCode == 0x01 || pageCode == 0x3F)
|
||||
{
|
||||
pageFound = 1;
|
||||
pageIn(pc, idx, ReadWriteErrorRecoveryPage, sizeof(ReadWriteErrorRecoveryPage));
|
||||
idx += sizeof(ReadWriteErrorRecoveryPage);
|
||||
}
|
||||
|
||||
if (pageCode == 0x02 || pageCode == 0x3F)
|
||||
{
|
||||
pageFound = 1;
|
||||
pageIn(pc, idx, DisconnectReconnectPage, sizeof(DisconnectReconnectPage));
|
||||
idx += sizeof(DisconnectReconnectPage);
|
||||
}
|
||||
|
||||
if (pageCode == 0x03 || pageCode == 0x3F)
|
||||
{
|
||||
pageFound = 1;
|
||||
pageIn(pc, idx, FormatDevicePage, sizeof(FormatDevicePage));
|
||||
if (pc != 0x01)
|
||||
{
|
||||
// Fill out the configured bytes-per-sector
|
||||
uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;
|
||||
scsiDev.data[idx+12] = bytesPerSector >> 8;
|
||||
scsiDev.data[idx+13] = bytesPerSector & 0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set a mask for the changeable values.
|
||||
scsiDev.data[idx+12] = 0xFF;
|
||||
scsiDev.data[idx+13] = 0xFF;
|
||||
}
|
||||
|
||||
idx += sizeof(FormatDevicePage);
|
||||
}
|
||||
|
||||
if (pageCode == 0x04 || pageCode == 0x3F)
|
||||
{
|
||||
pageFound = 1;
|
||||
pageIn(pc, idx, RigidDiskDriveGeometry, sizeof(RigidDiskDriveGeometry));
|
||||
|
||||
if (pc != 0x01)
|
||||
{
|
||||
// Need to fill out the number of cylinders.
|
||||
uint32 cyl;
|
||||
uint8 head;
|
||||
uint32 sector;
|
||||
LBA2CHS(
|
||||
getScsiCapacity(
|
||||
scsiDev.target->cfg->sdSectorStart,
|
||||
scsiDev.target->liveCfg.bytesPerSector,
|
||||
scsiDev.target->cfg->scsiSectors),
|
||||
&cyl,
|
||||
&head,
|
||||
§or);
|
||||
|
||||
scsiDev.data[idx+2] = cyl >> 16;
|
||||
scsiDev.data[idx+3] = cyl >> 8;
|
||||
scsiDev.data[idx+4] = cyl;
|
||||
|
||||
memcpy(&scsiDev.data[idx+6], &scsiDev.data[idx+2], 3);
|
||||
memcpy(&scsiDev.data[idx+9], &scsiDev.data[idx+2], 3);
|
||||
}
|
||||
|
||||
idx += sizeof(RigidDiskDriveGeometry);
|
||||
}
|
||||
|
||||
// DON'T output the following pages for SCSI1 hosts. They get upset when
|
||||
// we have more data to send than the allocation length provided.
|
||||
// (ie. Try not to output any more pages below this comment)
|
||||
|
||||
|
||||
if (!scsiDev.compatMode && (pageCode == 0x08 || pageCode == 0x3F))
|
||||
{
|
||||
pageFound = 1;
|
||||
pageIn(pc, idx, CachingPage, sizeof(CachingPage));
|
||||
idx += sizeof(CachingPage);
|
||||
}
|
||||
|
||||
if (!scsiDev.compatMode && (pageCode == 0x0A || pageCode == 0x3F))
|
||||
{
|
||||
pageFound = 1;
|
||||
pageIn(pc, idx, ControlModePage, sizeof(ControlModePage));
|
||||
idx += sizeof(ControlModePage);
|
||||
}
|
||||
|
||||
if ((
|
||||
(scsiDev.target->cfg->quirks == CONFIG_QUIRKS_APPLE) ||
|
||||
(idx + sizeof(AppleVendorPage) <= allocLength)
|
||||
) &&
|
||||
(pageCode == 0x30 || pageCode == 0x3F))
|
||||
{
|
||||
pageFound = 1;
|
||||
pageIn(pc, idx, AppleVendorPage, sizeof(AppleVendorPage));
|
||||
idx += sizeof(AppleVendorPage);
|
||||
}
|
||||
|
||||
if (!pageFound)
|
||||
{
|
||||
// Unknown Page Code
|
||||
pageFound = 0;
|
||||
scsiDev.status = CHECK_CONDITION;
|
||||
scsiDev.target->sense.code = ILLEGAL_REQUEST;
|
||||
scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
|
||||
scsiDev.phase = STATUS;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Go back and fill out the mode data length
|
||||
if (sixByteCmd)
|
||||
{
|
||||
// Cannot currently exceed limits. yay
|
||||
scsiDev.data[0] = idx - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
scsiDev.data[0] = ((idx - 2) >> 8);
|
||||
scsiDev.data[1] = (idx - 2);
|
||||
}
|
||||
|
||||
scsiDev.dataLen = idx > allocLength ? allocLength : idx;
|
||||
scsiDev.phase = DATA_IN;
|
||||
}
|
||||
scsiDev.dataLen = idx > allocLength ? allocLength : idx;
|
||||
scsiDev.phase = DATA_IN;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Callback after the DATA OUT phase is complete.
|
||||
static void doModeSelect(void)
|
||||
{
|
||||
|
@ -53,7 +53,7 @@ static void enter_BusFree()
|
||||
{
|
||||
// This delay probably isn't needed for most SCSI hosts, but it won't
|
||||
// hurt either. It's possible some of the samplers needed this delay.
|
||||
if (scsiDev.compatMode)
|
||||
if (scsiDev.compatMode < COMPAT_SCSI2)
|
||||
{
|
||||
CyDelayUs(2);
|
||||
}
|
||||
@ -214,7 +214,7 @@ static void process_DataOut()
|
||||
|
||||
if (scsiDev.parityError &&
|
||||
(scsiDev.target->cfg->flags & CONFIG_ENABLE_PARITY) &&
|
||||
!scsiDev.compatMode)
|
||||
(scsiDev.compatMode >= COMPAT_SCSI2))
|
||||
{
|
||||
scsiDev.target->sense.code = ABORTED_COMMAND;
|
||||
scsiDev.target->sense.asc = SCSI_PARITY_ERROR;
|
||||
@ -274,7 +274,7 @@ static void process_Command()
|
||||
}
|
||||
else if (scsiDev.parityError &&
|
||||
(scsiDev.target->cfg->flags & CONFIG_ENABLE_PARITY) &&
|
||||
!scsiDev.compatMode)
|
||||
(scsiDev.compatMode >= COMPAT_SCSI2))
|
||||
{
|
||||
scsiDev.target->sense.code = ABORTED_COMMAND;
|
||||
scsiDev.target->sense.asc = SCSI_PARITY_ERROR;
|
||||
@ -459,6 +459,7 @@ static void scsiReset()
|
||||
scsiDev.atnFlag = 0;
|
||||
scsiDev.resetFlag = 0;
|
||||
scsiDev.lun = -1;
|
||||
scsiDev.compatMode = COMPAT_UNKNOWN;
|
||||
|
||||
if (scsiDev.target)
|
||||
{
|
||||
@ -500,7 +501,6 @@ static void enter_SelectionPhase()
|
||||
scsiDev.phase = SELECTION;
|
||||
scsiDev.lun = -1;
|
||||
scsiDev.discPriv = 0;
|
||||
scsiDev.compatMode = 0;
|
||||
|
||||
scsiDev.initiatorId = -1;
|
||||
scsiDev.target = NULL;
|
||||
@ -513,6 +513,12 @@ static void enter_SelectionPhase()
|
||||
|
||||
static void process_SelectionPhase()
|
||||
{
|
||||
if (scsiDev.compatMode < COMPAT_SCSI2)
|
||||
{
|
||||
// Required for some older SCSI1 devices using a 5380 chip.
|
||||
CyDelayUs(100);
|
||||
}
|
||||
|
||||
int sel = SCSI_ReadFilt(SCSI_Filt_SEL);
|
||||
int bsy = SCSI_ReadFilt(SCSI_Filt_BSY);
|
||||
|
||||
@ -552,7 +558,11 @@ static void process_SelectionPhase()
|
||||
if (!scsiDev.atnFlag)
|
||||
{
|
||||
target->unitAttention = 0;
|
||||
scsiDev.compatMode = 1;
|
||||
scsiDev.compatMode = COMPAT_SCSI1;
|
||||
}
|
||||
else if (scsiDev.compatMode == COMPAT_UNKNOWN)
|
||||
{
|
||||
scsiDev.compatMode = COMPAT_SCSI2;
|
||||
}
|
||||
|
||||
// We've been selected!
|
||||
@ -611,7 +621,7 @@ static void process_MessageOut()
|
||||
|
||||
if (scsiDev.parityError &&
|
||||
(scsiDev.target->cfg->flags & CONFIG_ENABLE_PARITY) &&
|
||||
!scsiDev.compatMode)
|
||||
(scsiDev.compatMode >= COMPAT_SCSI2))
|
||||
{
|
||||
// Skip the remaining message bytes, and then start the MESSAGE_OUT
|
||||
// phase again from the start. The initiator will re-send the
|
||||
@ -872,6 +882,7 @@ void scsiInit()
|
||||
scsiDev.resetFlag = 1;
|
||||
scsiDev.phase = BUS_FREE;
|
||||
scsiDev.target = NULL;
|
||||
scsiDev.compatMode = COMPAT_UNKNOWN;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < MAX_SCSI_TARGETS; ++i)
|
||||
|
@ -57,6 +57,13 @@ typedef enum
|
||||
MSG_LINKED_COMMAND_COMPLETE_WITH_FLAG = 0x0B
|
||||
} SCSI_MESSAGE;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
COMPAT_UNKNOWN,
|
||||
COMPAT_SCSI1,
|
||||
COMPAT_SCSI2
|
||||
} SCSI_COMPAT_MODE;
|
||||
|
||||
// Maximum value for bytes-per-sector.
|
||||
#define MAX_SECTOR_SIZE 8192
|
||||
#define MIN_SECTOR_SIZE 64
|
||||
@ -112,7 +119,7 @@ typedef struct
|
||||
uint8 cdbLen; // 6, 10, or 12 byte message.
|
||||
int8 lun; // Target lun, set by IDENTIFY message.
|
||||
uint8 discPriv; // Disconnect priviledge.
|
||||
uint8_t compatMode; // true for SCSI1 and SASI hosts.
|
||||
uint8_t compatMode; // SCSI_COMPAT_MODE
|
||||
|
||||
// Only let the reserved initiator talk to us.
|
||||
// A 3rd party may be sending the RESERVE/RELEASE commands
|
||||
|
@ -447,4 +447,87 @@ void scsiPhyInit()
|
||||
|
||||
SCSI_RST_ISR_StartEx(scsiResetISR);
|
||||
}
|
||||
|
||||
// 1 = DBx error
|
||||
// 2 = Parity error
|
||||
// 4 = MSG error
|
||||
// 8 = CD error
|
||||
// 16 = IO error
|
||||
// 32 = other error
|
||||
int scsiSelfTest()
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
// TEST DBx and DBp
|
||||
int i;
|
||||
SCSI_Out_Ctl_Write(1); // Write bits manually.
|
||||
SCSI_CTL_PHASE_Write(__scsiphase_io); // Needed for parity generation
|
||||
for (i = 0; i < 256; ++i)
|
||||
{
|
||||
SCSI_Out_Bits_Write(i);
|
||||
scsiDeskewDelay();
|
||||
if (scsiReadDBxPins() != (i & 0xff))
|
||||
{
|
||||
result |= 1;
|
||||
}
|
||||
if (Lookup_OddParity[i & 0xff] != SCSI_ReadPin(SCSI_In_DBP))
|
||||
{
|
||||
result |= 2;
|
||||
}
|
||||
}
|
||||
SCSI_Out_Ctl_Write(0); // Write bits normally.
|
||||
|
||||
// TEST MSG, CD, IO
|
||||
for (i = 0; i < 8; ++i)
|
||||
{
|
||||
SCSI_CTL_PHASE_Write(i);
|
||||
scsiDeskewDelay();
|
||||
|
||||
if (SCSI_ReadPin(SCSI_In_MSG) != !!(i & __scsiphase_msg))
|
||||
{
|
||||
result |= 4;
|
||||
}
|
||||
if (SCSI_ReadPin(SCSI_In_CD) != !!(i & __scsiphase_cd))
|
||||
{
|
||||
result |= 8;
|
||||
}
|
||||
if (SCSI_ReadPin(SCSI_In_IO) != !!(i & __scsiphase_io))
|
||||
{
|
||||
result |= 16;
|
||||
}
|
||||
}
|
||||
SCSI_CTL_PHASE_Write(0);
|
||||
|
||||
uint32_t signalsOut[] = { SCSI_Out_ATN, SCSI_Out_BSY, SCSI_Out_RST, SCSI_Out_SEL };
|
||||
uint32_t signalsIn[] = { SCSI_Filt_ATN, SCSI_Filt_BSY, SCSI_Filt_RST, SCSI_Filt_SEL };
|
||||
|
||||
for (i = 0; i < 4; ++i)
|
||||
{
|
||||
SCSI_SetPin(signalsOut[i]);
|
||||
scsiDeskewDelay();
|
||||
|
||||
int j;
|
||||
for (j = 0; j < 4; ++j)
|
||||
{
|
||||
if (i == j)
|
||||
{
|
||||
if (! SCSI_ReadFilt(signalsIn[j]))
|
||||
{
|
||||
result |= 32;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (SCSI_ReadFilt(signalsIn[j]))
|
||||
{
|
||||
result |= 32;
|
||||
}
|
||||
}
|
||||
}
|
||||
SCSI_ClearPin(signalsOut[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
#pragma GCC pop_options
|
||||
|
@ -88,4 +88,6 @@ uint8_t scsiReadDBxPins(void);
|
||||
|
||||
void scsiEnterPhase(int phase);
|
||||
|
||||
int scsiSelfTest(void);
|
||||
|
||||
#endif
|
||||
|
@ -103,7 +103,7 @@
|
||||
#define USBFS_arb_int__INTC_CLR_PD_REG CYREG_NVIC_CLRPEND0
|
||||
#define USBFS_arb_int__INTC_MASK 0x400000u
|
||||
#define USBFS_arb_int__INTC_NUMBER 22u
|
||||
#define USBFS_arb_int__INTC_PRIOR_NUM 7u
|
||||
#define USBFS_arb_int__INTC_PRIOR_NUM 6u
|
||||
#define USBFS_arb_int__INTC_PRIOR_REG CYREG_NVIC_PRI_22
|
||||
#define USBFS_arb_int__INTC_SET_EN_REG CYREG_NVIC_SETENA0
|
||||
#define USBFS_arb_int__INTC_SET_PD_REG CYREG_NVIC_SETPEND0
|
||||
|
@ -103,7 +103,7 @@
|
||||
.set USBFS_arb_int__INTC_CLR_PD_REG, CYREG_NVIC_CLRPEND0
|
||||
.set USBFS_arb_int__INTC_MASK, 0x400000
|
||||
.set USBFS_arb_int__INTC_NUMBER, 22
|
||||
.set USBFS_arb_int__INTC_PRIOR_NUM, 7
|
||||
.set USBFS_arb_int__INTC_PRIOR_NUM, 6
|
||||
.set USBFS_arb_int__INTC_PRIOR_REG, CYREG_NVIC_PRI_22
|
||||
.set USBFS_arb_int__INTC_SET_EN_REG, CYREG_NVIC_SETENA0
|
||||
.set USBFS_arb_int__INTC_SET_PD_REG, CYREG_NVIC_SETPEND0
|
||||
|
@ -103,7 +103,7 @@ USBFS_arb_int__INTC_CLR_EN_REG EQU CYREG_NVIC_CLRENA0
|
||||
USBFS_arb_int__INTC_CLR_PD_REG EQU CYREG_NVIC_CLRPEND0
|
||||
USBFS_arb_int__INTC_MASK EQU 0x400000
|
||||
USBFS_arb_int__INTC_NUMBER EQU 22
|
||||
USBFS_arb_int__INTC_PRIOR_NUM EQU 7
|
||||
USBFS_arb_int__INTC_PRIOR_NUM EQU 6
|
||||
USBFS_arb_int__INTC_PRIOR_REG EQU CYREG_NVIC_PRI_22
|
||||
USBFS_arb_int__INTC_SET_EN_REG EQU CYREG_NVIC_SETENA0
|
||||
USBFS_arb_int__INTC_SET_PD_REG EQU CYREG_NVIC_SETPEND0
|
||||
|
@ -103,7 +103,7 @@ USBFS_arb_int__INTC_CLR_EN_REG EQU CYREG_NVIC_CLRENA0
|
||||
USBFS_arb_int__INTC_CLR_PD_REG EQU CYREG_NVIC_CLRPEND0
|
||||
USBFS_arb_int__INTC_MASK EQU 0x400000
|
||||
USBFS_arb_int__INTC_NUMBER EQU 22
|
||||
USBFS_arb_int__INTC_PRIOR_NUM EQU 7
|
||||
USBFS_arb_int__INTC_PRIOR_NUM EQU 6
|
||||
USBFS_arb_int__INTC_PRIOR_REG EQU CYREG_NVIC_PRI_22
|
||||
USBFS_arb_int__INTC_SET_EN_REG EQU CYREG_NVIC_SETENA0
|
||||
USBFS_arb_int__INTC_SET_PD_REG EQU CYREG_NVIC_SETPEND0
|
||||
|
@ -28,7 +28,7 @@ __attribute__ ((__section__(".cyloadablemeta"), used))
|
||||
const uint8 cy_meta_loadable[] = {
|
||||
0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
|
||||
0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
|
||||
0x00u, 0x00u, 0x00u, 0x00u, 0x5Cu, 0xD1u, 0x20u, 0x04u,
|
||||
0x00u, 0x00u, 0x00u, 0x00u, 0x5Cu, 0xD1u, 0x22u, 0x04u,
|
||||
0x01u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
|
||||
0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
|
||||
0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
|
||||
|
Binary file not shown.
@ -3357,7 +3357,7 @@
|
||||
<name_val_pair name="c9323d49-d323-40b8-9b59-cc008d68a989@Release@CortexM3@Linker@General@Enable printf Float" v="True" />
|
||||
<name_val_pair name="c9323d49-d323-40b8-9b59-cc008d68a989@Release@CortexM3@Linker@Optimization@Optimization Level" v="Size" />
|
||||
<name_val_pair name="c9323d49-d323-40b8-9b59-cc008d68a989@Release@CortexM3@Linker@Optimization@Remove Unused Functions" v="True" />
|
||||
<name_val_pair name="c9323d49-d323-40b8-9b59-cc008d68a989@Release@CortexM3@Linker@Command Line@Command Line" v="" />
|
||||
<name_val_pair name="c9323d49-d323-40b8-9b59-cc008d68a989@Release@CortexM3@Linker@Command Line@Command Line" v="-Wl,--section-start=.DEFAULT_CONFIG=0x0001BC00" />
|
||||
</name>
|
||||
</platform>
|
||||
<platform>
|
||||
|
Binary file not shown.
@ -104,7 +104,7 @@
|
||||
#define USBFS_arb_int__INTC_CLR_PD_REG CYREG_NVIC_CLRPEND0
|
||||
#define USBFS_arb_int__INTC_MASK 0x400000u
|
||||
#define USBFS_arb_int__INTC_NUMBER 22u
|
||||
#define USBFS_arb_int__INTC_PRIOR_NUM 7u
|
||||
#define USBFS_arb_int__INTC_PRIOR_NUM 6u
|
||||
#define USBFS_arb_int__INTC_PRIOR_REG CYREG_NVIC_PRI_22
|
||||
#define USBFS_arb_int__INTC_SET_EN_REG CYREG_NVIC_SETENA0
|
||||
#define USBFS_arb_int__INTC_SET_PD_REG CYREG_NVIC_SETPEND0
|
||||
@ -2322,7 +2322,7 @@
|
||||
#define SD_RX_DMA__DRQ_CTL CYREG_IDMUX_DRQ_CTL0
|
||||
#define SD_RX_DMA__DRQ_NUMBER 2u
|
||||
#define SD_RX_DMA__NUMBEROF_TDS 0u
|
||||
#define SD_RX_DMA__PRIORITY 2u
|
||||
#define SD_RX_DMA__PRIORITY 0u
|
||||
#define SD_RX_DMA__TERMIN_EN 0u
|
||||
#define SD_RX_DMA__TERMIN_SEL 0u
|
||||
#define SD_RX_DMA__TERMOUT0_EN 1u
|
||||
@ -2344,7 +2344,7 @@
|
||||
#define SD_TX_DMA__DRQ_CTL CYREG_IDMUX_DRQ_CTL0
|
||||
#define SD_TX_DMA__DRQ_NUMBER 3u
|
||||
#define SD_TX_DMA__NUMBEROF_TDS 0u
|
||||
#define SD_TX_DMA__PRIORITY 2u
|
||||
#define SD_TX_DMA__PRIORITY 1u
|
||||
#define SD_TX_DMA__TERMIN_EN 0u
|
||||
#define SD_TX_DMA__TERMIN_SEL 0u
|
||||
#define SD_TX_DMA__TERMOUT0_EN 1u
|
||||
|
@ -104,7 +104,7 @@
|
||||
.set USBFS_arb_int__INTC_CLR_PD_REG, CYREG_NVIC_CLRPEND0
|
||||
.set USBFS_arb_int__INTC_MASK, 0x400000
|
||||
.set USBFS_arb_int__INTC_NUMBER, 22
|
||||
.set USBFS_arb_int__INTC_PRIOR_NUM, 7
|
||||
.set USBFS_arb_int__INTC_PRIOR_NUM, 6
|
||||
.set USBFS_arb_int__INTC_PRIOR_REG, CYREG_NVIC_PRI_22
|
||||
.set USBFS_arb_int__INTC_SET_EN_REG, CYREG_NVIC_SETENA0
|
||||
.set USBFS_arb_int__INTC_SET_PD_REG, CYREG_NVIC_SETPEND0
|
||||
@ -2322,7 +2322,7 @@
|
||||
.set SD_RX_DMA__DRQ_CTL, CYREG_IDMUX_DRQ_CTL0
|
||||
.set SD_RX_DMA__DRQ_NUMBER, 2
|
||||
.set SD_RX_DMA__NUMBEROF_TDS, 0
|
||||
.set SD_RX_DMA__PRIORITY, 2
|
||||
.set SD_RX_DMA__PRIORITY, 0
|
||||
.set SD_RX_DMA__TERMIN_EN, 0
|
||||
.set SD_RX_DMA__TERMIN_SEL, 0
|
||||
.set SD_RX_DMA__TERMOUT0_EN, 1
|
||||
@ -2344,7 +2344,7 @@
|
||||
.set SD_TX_DMA__DRQ_CTL, CYREG_IDMUX_DRQ_CTL0
|
||||
.set SD_TX_DMA__DRQ_NUMBER, 3
|
||||
.set SD_TX_DMA__NUMBEROF_TDS, 0
|
||||
.set SD_TX_DMA__PRIORITY, 2
|
||||
.set SD_TX_DMA__PRIORITY, 1
|
||||
.set SD_TX_DMA__TERMIN_EN, 0
|
||||
.set SD_TX_DMA__TERMIN_SEL, 0
|
||||
.set SD_TX_DMA__TERMOUT0_EN, 1
|
||||
|
@ -104,7 +104,7 @@ USBFS_arb_int__INTC_CLR_EN_REG EQU CYREG_NVIC_CLRENA0
|
||||
USBFS_arb_int__INTC_CLR_PD_REG EQU CYREG_NVIC_CLRPEND0
|
||||
USBFS_arb_int__INTC_MASK EQU 0x400000
|
||||
USBFS_arb_int__INTC_NUMBER EQU 22
|
||||
USBFS_arb_int__INTC_PRIOR_NUM EQU 7
|
||||
USBFS_arb_int__INTC_PRIOR_NUM EQU 6
|
||||
USBFS_arb_int__INTC_PRIOR_REG EQU CYREG_NVIC_PRI_22
|
||||
USBFS_arb_int__INTC_SET_EN_REG EQU CYREG_NVIC_SETENA0
|
||||
USBFS_arb_int__INTC_SET_PD_REG EQU CYREG_NVIC_SETPEND0
|
||||
@ -2322,7 +2322,7 @@ SCSI_Out_DBx__DB7__SLW EQU CYREG_PRT2_SLW
|
||||
SD_RX_DMA__DRQ_CTL EQU CYREG_IDMUX_DRQ_CTL0
|
||||
SD_RX_DMA__DRQ_NUMBER EQU 2
|
||||
SD_RX_DMA__NUMBEROF_TDS EQU 0
|
||||
SD_RX_DMA__PRIORITY EQU 2
|
||||
SD_RX_DMA__PRIORITY EQU 0
|
||||
SD_RX_DMA__TERMIN_EN EQU 0
|
||||
SD_RX_DMA__TERMIN_SEL EQU 0
|
||||
SD_RX_DMA__TERMOUT0_EN EQU 1
|
||||
@ -2344,7 +2344,7 @@ SD_RX_DMA_COMPLETE__INTC_SET_PD_REG EQU CYREG_NVIC_SETPEND0
|
||||
SD_TX_DMA__DRQ_CTL EQU CYREG_IDMUX_DRQ_CTL0
|
||||
SD_TX_DMA__DRQ_NUMBER EQU 3
|
||||
SD_TX_DMA__NUMBEROF_TDS EQU 0
|
||||
SD_TX_DMA__PRIORITY EQU 2
|
||||
SD_TX_DMA__PRIORITY EQU 1
|
||||
SD_TX_DMA__TERMIN_EN EQU 0
|
||||
SD_TX_DMA__TERMIN_SEL EQU 0
|
||||
SD_TX_DMA__TERMOUT0_EN EQU 1
|
||||
|
@ -104,7 +104,7 @@ USBFS_arb_int__INTC_CLR_EN_REG EQU CYREG_NVIC_CLRENA0
|
||||
USBFS_arb_int__INTC_CLR_PD_REG EQU CYREG_NVIC_CLRPEND0
|
||||
USBFS_arb_int__INTC_MASK EQU 0x400000
|
||||
USBFS_arb_int__INTC_NUMBER EQU 22
|
||||
USBFS_arb_int__INTC_PRIOR_NUM EQU 7
|
||||
USBFS_arb_int__INTC_PRIOR_NUM EQU 6
|
||||
USBFS_arb_int__INTC_PRIOR_REG EQU CYREG_NVIC_PRI_22
|
||||
USBFS_arb_int__INTC_SET_EN_REG EQU CYREG_NVIC_SETENA0
|
||||
USBFS_arb_int__INTC_SET_PD_REG EQU CYREG_NVIC_SETPEND0
|
||||
@ -2322,7 +2322,7 @@ SCSI_Out_DBx__DB7__SLW EQU CYREG_PRT2_SLW
|
||||
SD_RX_DMA__DRQ_CTL EQU CYREG_IDMUX_DRQ_CTL0
|
||||
SD_RX_DMA__DRQ_NUMBER EQU 2
|
||||
SD_RX_DMA__NUMBEROF_TDS EQU 0
|
||||
SD_RX_DMA__PRIORITY EQU 2
|
||||
SD_RX_DMA__PRIORITY EQU 0
|
||||
SD_RX_DMA__TERMIN_EN EQU 0
|
||||
SD_RX_DMA__TERMIN_SEL EQU 0
|
||||
SD_RX_DMA__TERMOUT0_EN EQU 1
|
||||
@ -2344,7 +2344,7 @@ SD_RX_DMA_COMPLETE__INTC_SET_PD_REG EQU CYREG_NVIC_SETPEND0
|
||||
SD_TX_DMA__DRQ_CTL EQU CYREG_IDMUX_DRQ_CTL0
|
||||
SD_TX_DMA__DRQ_NUMBER EQU 3
|
||||
SD_TX_DMA__NUMBEROF_TDS EQU 0
|
||||
SD_TX_DMA__PRIORITY EQU 2
|
||||
SD_TX_DMA__PRIORITY EQU 1
|
||||
SD_TX_DMA__TERMIN_EN EQU 0
|
||||
SD_TX_DMA__TERMIN_SEL EQU 0
|
||||
SD_TX_DMA__TERMOUT0_EN EQU 1
|
||||
|
@ -28,7 +28,7 @@ __attribute__ ((__section__(".cyloadablemeta"), used))
|
||||
const uint8 cy_meta_loadable[] = {
|
||||
0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
|
||||
0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
|
||||
0x00u, 0x00u, 0x00u, 0x00u, 0x5Cu, 0xD1u, 0x10u, 0x04u,
|
||||
0x00u, 0x00u, 0x00u, 0x00u, 0x5Cu, 0xD1u, 0x22u, 0x04u,
|
||||
0x01u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
|
||||
0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
|
||||
0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
|
||||
|
Binary file not shown.
@ -2499,7 +2499,7 @@
|
||||
<name_val_pair name="c9323d49-d323-40b8-9b59-cc008d68a989@Release@CortexM3@Linker@General@Enable printf Float" v="True" />
|
||||
<name_val_pair name="c9323d49-d323-40b8-9b59-cc008d68a989@Release@CortexM3@Linker@Optimization@Optimization Level" v="Size" />
|
||||
<name_val_pair name="c9323d49-d323-40b8-9b59-cc008d68a989@Release@CortexM3@Linker@Optimization@Remove Unused Functions" v="True" />
|
||||
<name_val_pair name="c9323d49-d323-40b8-9b59-cc008d68a989@Release@CortexM3@Linker@Command Line@Command Line" v="" />
|
||||
<name_val_pair name="c9323d49-d323-40b8-9b59-cc008d68a989@Release@CortexM3@Linker@Command Line@Command Line" v="-Wl,--section-start=.DEFAULT_CONFIG=0x0001BC00" />
|
||||
</name>
|
||||
</platform>
|
||||
<platform>
|
||||
|
Binary file not shown.
@ -181,7 +181,14 @@ typedef enum
|
||||
// Response:
|
||||
// uint8_t[16] CSD
|
||||
// uint8_t[16] CID
|
||||
CONFIG_SDINFO
|
||||
CONFIG_SDINFO,
|
||||
|
||||
// Command content:
|
||||
// uint8_t CONFIG_SCSITEST
|
||||
// Response:
|
||||
// CONFIG_STATUS
|
||||
// uint8_t result code (0 = passed)
|
||||
CONFIG_SCSITEST
|
||||
} CONFIG_COMMAND;
|
||||
|
||||
typedef enum
|
||||
|
@ -24,7 +24,6 @@
|
||||
|
||||
using namespace SCSI2SD;
|
||||
|
||||
ADD QUIRKS MODES
|
||||
namespace
|
||||
{
|
||||
// Endian conversion routines.
|
||||
@ -105,7 +104,7 @@ ConfigUtil::Default(size_t targetIdx)
|
||||
config.headsPerCylinder = 255;
|
||||
memcpy(config.vendor, " codesrc", 8);
|
||||
memcpy(config.prodId, " SCSI2SD", 16);
|
||||
memcpy(config.revision, " 4.0", 4);
|
||||
memcpy(config.revision, " 4.2", 4);
|
||||
memcpy(config.serial, "1234567812345678", 16);
|
||||
|
||||
// Reserved fields, already set to 0
|
||||
@ -146,6 +145,7 @@ ConfigUtil::toBytes(const TargetConfig& _config)
|
||||
return std::vector<uint8_t>(begin, begin + sizeof(config));
|
||||
}
|
||||
|
||||
/*
|
||||
wxXmlNode*
|
||||
ConfigUtil::toXML(const TargetConfig& config)
|
||||
{
|
||||
@ -203,3 +203,4 @@ ConfigUtil::deserialise(const std::string& in)
|
||||
{
|
||||
|
||||
}
|
||||
*/
|
||||
|
@ -51,7 +51,7 @@ endif
|
||||
|
||||
export CC CXX
|
||||
|
||||
all: $(BUILD)/scsi2sd-util$(EXE)
|
||||
all: $(BUILD)/scsi2sd-util$(EXE) $(BUILD)/scsi2sd-monitor$(EXE)
|
||||
|
||||
CYAPI = \
|
||||
$(BUILD)/cybtldr_api2.o \
|
||||
@ -66,7 +66,6 @@ HIDAPI = \
|
||||
|
||||
OBJ = \
|
||||
$(CYAPI) $(HIDAPI) \
|
||||
$(BUILD)/scsi2sd-util.o \
|
||||
$(BUILD)/ConfigUtil.o \
|
||||
$(BUILD)/Firmware.o \
|
||||
$(BUILD)/TargetPanel.o \
|
||||
@ -74,8 +73,14 @@ OBJ = \
|
||||
$(BUILD)/SCSI2SD_HID.o \
|
||||
$(BUILD)/hidpacket.o \
|
||||
|
||||
EXEOBJ = \
|
||||
$(BUILD)/scsi2sd-util.o \
|
||||
$(BUILD)/scsi2sd-monitor.o \
|
||||
|
||||
|
||||
|
||||
$(OBJ): $(BUILD)/zlib/buildstamp
|
||||
$(EXEOBJ): $(BUILD)/zlib/buildstamp
|
||||
$(BUILD)/zlib/buildstamp:
|
||||
mkdir -p $(dir $@)
|
||||
( \
|
||||
@ -87,6 +92,7 @@ $(BUILD)/zlib/buildstamp:
|
||||
touch $@
|
||||
|
||||
$(OBJ): $(BUILD)/wx.buildstamp
|
||||
$(EXEOBJ): $(BUILD)/wx.buildstamp
|
||||
$(BUILD)/wx.buildstamp: $(BUILD)/zlib/buildstamp
|
||||
mkdir -p $(dir $@)
|
||||
( \
|
||||
@ -97,6 +103,7 @@ $(BUILD)/wx.buildstamp: $(BUILD)/zlib/buildstamp
|
||||
touch $@
|
||||
|
||||
$(OBJ): $(BUILD)/libzipper/buildstamp
|
||||
$(EXEOBJ): $(BUILD)/libzipper/buildstamp
|
||||
$(BUILD)/libzipper/buildstamp: $(BUILD)/zlib/buildstamp
|
||||
mkdir -p $(dir $@)
|
||||
( \
|
||||
@ -114,7 +121,11 @@ $(BUILD)/%.o: %.cc
|
||||
mkdir -p $(dir $@)
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) `$(BUILD)/wx-config --cxxflags` $< -c -o $@
|
||||
|
||||
$(BUILD)/scsi2sd-util$(EXE): $(OBJ)
|
||||
$(BUILD)/scsi2sd-util$(EXE): $(OBJ) $(BUILD)/scsi2sd-util.o
|
||||
mkdir -p $(dir $@)
|
||||
$(CXX) $(CXXFLAGS) $^ $(LDFLAGS) `$(BUILD)/wx-config --libs` -o $@
|
||||
|
||||
$(BUILD)/scsi2sd-monitor$(EXE): $(OBJ) $(BUILD)/scsi2sd-monitor.o
|
||||
mkdir -p $(dir $@)
|
||||
$(CXX) $(CXXFLAGS) $^ $(LDFLAGS) `$(BUILD)/wx-config --libs` -o $@
|
||||
|
||||
|
@ -338,7 +338,7 @@ HID::getSD_CSD()
|
||||
std::vector<uint8_t> out;
|
||||
try
|
||||
{
|
||||
sendHIDPacket(cmd, out, 1);
|
||||
sendHIDPacket(cmd, out, 16);
|
||||
}
|
||||
catch (std::runtime_error& e)
|
||||
{
|
||||
@ -356,7 +356,7 @@ HID::getSD_CID()
|
||||
std::vector<uint8_t> out;
|
||||
try
|
||||
{
|
||||
sendHIDPacket(cmd, out, 1);
|
||||
sendHIDPacket(cmd, out, 16);
|
||||
}
|
||||
catch (std::runtime_error& e)
|
||||
{
|
||||
@ -368,6 +368,23 @@ HID::getSD_CID()
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
HID::scsiSelfTest()
|
||||
{
|
||||
std::vector<uint8_t> cmd { CONFIG_SCSITEST };
|
||||
std::vector<uint8_t> out;
|
||||
try
|
||||
{
|
||||
sendHIDPacket(cmd, out, 2);
|
||||
}
|
||||
catch (std::runtime_error& e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return (out.size() >= 1) && (out[0] == CONFIG_STATUS_GOOD);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HID::sendHIDPacket(
|
||||
const std::vector<uint8_t>& cmd,
|
||||
|
@ -58,6 +58,8 @@ public:
|
||||
std::vector<uint8_t> getSD_CSD();
|
||||
std::vector<uint8_t> getSD_CID();
|
||||
|
||||
bool scsiSelfTest();
|
||||
|
||||
void enterBootloader();
|
||||
|
||||
void readFlashRow(int array, int row, std::vector<uint8_t>& out);
|
||||
|
288
software/scsi2sd-util/scsi2sd-monitor.cc
Normal file
288
software/scsi2sd-util/scsi2sd-monitor.cc
Normal file
@ -0,0 +1,288 @@
|
||||
// Copyright (C) 2015 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/>.
|
||||
|
||||
|
||||
// For compilers that support precompilation, includes "wx/wx.h".
|
||||
#include <wx/wxprec.h>
|
||||
#ifndef WX_PRECOMP
|
||||
#include <wx/wx.h>
|
||||
#endif
|
||||
|
||||
#include <wx/filedlg.h>
|
||||
#include <wx/filefn.h>
|
||||
#include <wx/filename.h>
|
||||
#include <wx/log.h>
|
||||
#include <wx/notebook.h>
|
||||
#include <wx/progdlg.h>
|
||||
#include <wx/utils.h>
|
||||
#include <wx/windowptr.h>
|
||||
#include <wx/thread.h>
|
||||
|
||||
#include <zipper.hh>
|
||||
|
||||
#include "ConfigUtil.hh"
|
||||
#include "TargetPanel.hh"
|
||||
#include "SCSI2SD_Bootloader.hh"
|
||||
#include "SCSI2SD_HID.hh"
|
||||
#include "Firmware.hh"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
using std::shared_ptr;
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#include <tr1/memory>
|
||||
using std::tr1::shared_ptr;
|
||||
#endif
|
||||
|
||||
#define MIN_FIRMWARE_VERSION 0x0400
|
||||
|
||||
using namespace SCSI2SD;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
static uint8_t sdCrc7(uint8_t* chr, uint8_t cnt, uint8_t crc)
|
||||
{
|
||||
uint8_t a;
|
||||
for(a = 0; a < cnt; a++)
|
||||
{
|
||||
uint8_t data = chr[a];
|
||||
uint8_t i;
|
||||
for(i = 0; i < 8; i++)
|
||||
{
|
||||
crc <<= 1;
|
||||
if ((data & 0x80) ^ (crc & 0x80))
|
||||
{
|
||||
crc ^= 0x09;
|
||||
}
|
||||
data <<= 1;
|
||||
}
|
||||
}
|
||||
return crc & 0x7F;
|
||||
}
|
||||
|
||||
class TimerLock
|
||||
{
|
||||
public:
|
||||
TimerLock(wxTimer* timer) :
|
||||
myTimer(timer),
|
||||
myInterval(myTimer->GetInterval())
|
||||
{
|
||||
myTimer->Stop();
|
||||
};
|
||||
|
||||
virtual ~TimerLock()
|
||||
{
|
||||
if (myTimer && myInterval > 0)
|
||||
{
|
||||
myTimer->Start(myInterval);
|
||||
}
|
||||
}
|
||||
private:
|
||||
wxTimer* myTimer;
|
||||
int myInterval;
|
||||
};
|
||||
|
||||
class AppFrame : public wxFrame
|
||||
{
|
||||
public:
|
||||
AppFrame() :
|
||||
wxFrame(NULL, wxID_ANY, "scsi2sd-monitor", wxPoint(50, 50), wxSize(250, 150))
|
||||
{
|
||||
wxFlexGridSizer *fgs = new wxFlexGridSizer(3, 2, 9, 25);
|
||||
|
||||
fgs->Add(new wxStaticText(this, wxID_ANY, wxT("SCSI2SD Device:")));
|
||||
myBoardText = new wxStaticText(this, wxID_ANY, wxT(""));
|
||||
fgs->Add(myBoardText);
|
||||
fgs->Add(new wxStaticText(this, wxID_ANY, wxT("SD Test:")));
|
||||
mySDText = new wxStaticText(this, wxID_ANY, wxT(""));
|
||||
fgs->Add(mySDText);
|
||||
fgs->Add(new wxStaticText(this, wxID_ANY, wxT("SCSI Test:")));
|
||||
mySCSIText = new wxStaticText(this, wxID_ANY, wxT(""));
|
||||
fgs->Add(mySCSIText);
|
||||
|
||||
wxBoxSizer* hbox = new wxBoxSizer(wxHORIZONTAL);
|
||||
hbox->Add(fgs, 1, wxALL | wxEXPAND, 15);
|
||||
this->SetSizer(hbox);
|
||||
Centre();
|
||||
|
||||
//Fit(); // Needed to reduce window size on Windows
|
||||
//FitInside(); // Needed on Linux to prevent status bar overlap
|
||||
|
||||
myTimer = new wxTimer(this, ID_Timer);
|
||||
myTimer->Start(1000);
|
||||
}
|
||||
|
||||
private:
|
||||
wxTimer* myTimer;
|
||||
shared_ptr<HID> myHID;
|
||||
shared_ptr<Bootloader> myBootloader;
|
||||
|
||||
wxStaticText* myBoardText;
|
||||
wxStaticText* mySDText;
|
||||
wxStaticText* mySCSIText;
|
||||
|
||||
enum
|
||||
{
|
||||
ID_ConfigDefaults = wxID_HIGHEST + 1,
|
||||
ID_Timer
|
||||
};
|
||||
|
||||
void evaluate()
|
||||
{
|
||||
if (myHID)
|
||||
{
|
||||
std::stringstream msg;
|
||||
msg << "Ready, " <<
|
||||
myHID->getFirmwareVersionStr();
|
||||
myBoardText->SetLabelText(msg.str());
|
||||
|
||||
|
||||
std::vector<uint8_t> csd(myHID->getSD_CSD());
|
||||
std::vector<uint8_t> cid(myHID->getSD_CID());
|
||||
|
||||
bool sdGood = false;
|
||||
for (size_t i = 0; i < 16; ++i)
|
||||
{
|
||||
if (csd[i] != 0)
|
||||
{
|
||||
sdGood = true;
|
||||
//break;
|
||||
}
|
||||
}
|
||||
|
||||
sdGood = sdGood &&
|
||||
(sdCrc7(&csd[0], 15, 0) == (csd[15] >> 1)) &&
|
||||
(sdCrc7(&cid[0], 15, 0) == (cid[15] >> 1));
|
||||
|
||||
if (sdGood)
|
||||
{
|
||||
mySDText->SetLabelText("OK");
|
||||
}
|
||||
else
|
||||
{
|
||||
mySDText->SetLabelText("FAIL");
|
||||
}
|
||||
|
||||
if (myHID->scsiSelfTest())
|
||||
{
|
||||
mySCSIText->SetLabelText("OK");
|
||||
}
|
||||
else
|
||||
{
|
||||
mySCSIText->SetLabelText("FAIL");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (myBootloader)
|
||||
{
|
||||
myBoardText->SetLabelText("Bootloader");
|
||||
}
|
||||
else
|
||||
{
|
||||
myBoardText->SetLabelText("Missing");
|
||||
}
|
||||
mySDText->SetLabelText("-");
|
||||
mySCSIText->SetLabelText("-");
|
||||
}
|
||||
}
|
||||
|
||||
void OnID_Timer(wxTimerEvent& event)
|
||||
{
|
||||
// Check if we are connected to the HID device.
|
||||
// AND/or bootloader device.
|
||||
try
|
||||
{
|
||||
if (myBootloader)
|
||||
{
|
||||
// Verify the USB HID connection is valid
|
||||
if (!myBootloader->ping())
|
||||
{
|
||||
myBootloader.reset();
|
||||
}
|
||||
}
|
||||
|
||||
if (!myBootloader)
|
||||
{
|
||||
myBootloader.reset(Bootloader::Open());
|
||||
}
|
||||
|
||||
if (myHID && !myHID->ping())
|
||||
{
|
||||
// Verify the USB HID connection is valid
|
||||
std::cerr << "RESET!" << std::endl;
|
||||
myHID.reset();
|
||||
}
|
||||
|
||||
if (!myHID)
|
||||
{
|
||||
myHID.reset(HID::Open());
|
||||
|
||||
}
|
||||
}
|
||||
catch (std::runtime_error& e)
|
||||
{
|
||||
std::cerr << e.what() << std::endl;
|
||||
}
|
||||
|
||||
evaluate();
|
||||
}
|
||||
|
||||
// Note: Don't confuse this with the wxApp::OnExit virtual method
|
||||
void OnExitEvt(wxCommandEvent& event)
|
||||
{
|
||||
Close(true);
|
||||
}
|
||||
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
||||
wxBEGIN_EVENT_TABLE(AppFrame, wxFrame)
|
||||
EVT_MENU(wxID_EXIT, AppFrame::OnExitEvt)
|
||||
|
||||
EVT_TIMER(AppFrame::ID_Timer, AppFrame::OnID_Timer)
|
||||
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
|
||||
|
||||
class App : public wxApp
|
||||
{
|
||||
public:
|
||||
virtual bool OnInit()
|
||||
{
|
||||
AppFrame* frame = new AppFrame();
|
||||
frame->Show(true);
|
||||
SetTopWindow(frame);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
// Main Method
|
||||
wxIMPLEMENT_APP(App);
|
||||
|
||||
|
@ -108,6 +108,26 @@ void ProgressUpdate(unsigned char arrayId, unsigned short rowNum)
|
||||
namespace
|
||||
{
|
||||
|
||||
static uint8_t sdCrc7(uint8_t* chr, uint8_t cnt, uint8_t crc)
|
||||
{
|
||||
uint8_t a;
|
||||
for(a = 0; a < cnt; a++)
|
||||
{
|
||||
uint8_t data = chr[a];
|
||||
uint8_t i;
|
||||
for(i = 0; i < 8; i++)
|
||||
{
|
||||
crc <<= 1;
|
||||
if ((data & 0x80) ^ (crc & 0x80))
|
||||
{
|
||||
crc ^= 0x09;
|
||||
}
|
||||
data <<= 1;
|
||||
}
|
||||
}
|
||||
return crc & 0x7F;
|
||||
}
|
||||
|
||||
class TimerLock
|
||||
{
|
||||
public:
|
||||
@ -163,6 +183,11 @@ public:
|
||||
"Log SCSI data",
|
||||
"Log SCSI commands");
|
||||
|
||||
mySelfTestChk = menuDebug->AppendCheckItem(
|
||||
ID_SelfTest,
|
||||
"SCSI Standalone Self-Test",
|
||||
"SCSI Standalone Self-Test");
|
||||
|
||||
wxMenu *menuHelp = new wxMenu();
|
||||
menuHelp->Append(wxID_ABOUT);
|
||||
|
||||
@ -229,6 +254,7 @@ private:
|
||||
wxButton* myLoadButton;
|
||||
wxButton* mySaveButton;
|
||||
wxMenuItem* mySCSILogChk;
|
||||
wxMenuItem* mySelfTestChk;
|
||||
wxTimer* myTimer;
|
||||
shared_ptr<HID> myHID;
|
||||
shared_ptr<Bootloader> myBootloader;
|
||||
@ -329,7 +355,8 @@ private:
|
||||
ID_BtnLoad,
|
||||
ID_BtnSave,
|
||||
ID_LogWindow,
|
||||
ID_SCSILog
|
||||
ID_SCSILog,
|
||||
ID_SelfTest
|
||||
};
|
||||
|
||||
void OnID_ConfigDefaults(wxCommandEvent& event)
|
||||
@ -629,6 +656,10 @@ private:
|
||||
myHID->getSDCapacity() << std::endl;
|
||||
|
||||
sdinfo << "SD CSD Register: ";
|
||||
if (sdCrc7(&csd[0], 15, 0) != (csd[15] >> 1))
|
||||
{
|
||||
sdinfo << "BADCRC ";
|
||||
}
|
||||
for (size_t i = 0; i < csd.size(); ++i)
|
||||
{
|
||||
sdinfo <<
|
||||
@ -637,6 +668,10 @@ private:
|
||||
}
|
||||
sdinfo << std::endl;
|
||||
sdinfo << "SD CID Register: ";
|
||||
if (sdCrc7(&cid[0], 15, 0) != (cid[15] >> 1))
|
||||
{
|
||||
sdinfo << "BADCRC ";
|
||||
}
|
||||
for (size_t i = 0; i < cid.size(); ++i)
|
||||
{
|
||||
sdinfo <<
|
||||
@ -646,6 +681,14 @@ private:
|
||||
|
||||
wxLogMessage(this, "%s", sdinfo.str());
|
||||
|
||||
if (mySelfTestChk->IsChecked())
|
||||
{
|
||||
std::stringstream scsiInfo;
|
||||
scsiInfo << "SCSI Self-Test: " <<
|
||||
(myHID->scsiSelfTest() ? "Passed" : "FAIL");
|
||||
wxLogMessage(this, "%s", scsiInfo.str());
|
||||
}
|
||||
|
||||
if (!myInitialConfig)
|
||||
{
|
||||
wxCommandEvent loadEvent(wxEVT_NULL, ID_BtnLoad);
|
||||
|
Loading…
x
Reference in New Issue
Block a user