Small compatibility improvements, and added scsi2sd-monitor test program

This commit is contained in:
Michael McMaster 2015-04-20 16:09:51 +10:00
parent 95b519789b
commit 9ad7cc15d0
32 changed files with 759 additions and 248 deletions

View File

@ -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.

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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,
&sector);
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,
&sector);
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)
{

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -88,4 +88,6 @@ uint8_t scsiReadDBxPins(void);
void scsiEnterPhase(int phase);
int scsiSelfTest(void);
#endif

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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>

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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>

View File

@ -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

View File

@ -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)
{
}
*/

View File

@ -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 $@

View File

@ -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,

View File

@ -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);

View 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);

View File

@ -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);