RAW disk support and LittleFS support

This commit is contained in:
David Kuder 2023-05-13 02:49:13 -04:00
parent c5c4c51667
commit d420244da9
7 changed files with 594 additions and 21 deletions

View File

@ -24,6 +24,7 @@ int scriptlevel = -1;
char cmd_prefix[256] = "/";
extern uint8_t mbr_bin[];
uint8_t zero[512];
void cmdDisplay() {
if(cmd_prefix[0] != 0) {
@ -723,7 +724,7 @@ void changeDirectory(int argc, char **argv) {
goto e_invalidpath;
}
if(!strcmp(new_prefix, "/") || !strcmp(new_prefix, "/tgts") || !strcmp(new_prefix, "/vdevs")
if(!strcmp(new_prefix, "/") || !strcmp(new_prefix, "/tgts") || !strcmp(new_prefix, "/vdevs") || !strcmp(new_prefix, "/nv") || !strcmp(new_prefix, "/raw")
|| !strcmp(new_prefix, "/sd") || !strcmp(new_prefix, "/diag")|| !strcmp(new_prefix, "/diag/sd")
) {
strcpy(cmd_prefix, new_prefix);
@ -863,6 +864,7 @@ void showDirectory(int argc, char **argv) {
printDirectory(0, 0, "/ ", " [...]");
printDirectory(1, 0, "diag/ ", " [...]");
printDirectory(1, 0, "sd/ ", " [...]");
printDirectory(1, 0, "raw/ ", " [...]");
sprintf(tmp_right, " [%d Target%s]", NUM_SCSIID, (NUM_SCSIID != 1) ? "s" : "");
printDirectory(1, 0, "tgts/ ", tmp_right);
sprintf(tmp_right, " [%d Storage Object%s]", m_vdevcnt, (m_vdevcnt != 1) ? "s" : "");
@ -874,6 +876,33 @@ void showDirectory(int argc, char **argv) {
printDirectory(1, 0, "sd/ ", " [...]");
return;
}
if(!strcmp(local_prefix, "/raw")) {
mbr_t *mbr = (mbr_t *)cardMBR;
printDirectory(0, 0, "/raw/ ", " [...]");
sd.card()->readSector(0, cardMBR);
for(uint8_t partIndex = 0; partIndex < 4; partIndex++) {
sprintf(tmp_left, "part%d", partIndex);
switch(mbr->part[partIndex].type) {
case 0x04:
case 0x06:
case 0x0B:
case 0x0C:
case 0x0E:
printDirectory(1, 0, tmp_left, "[FAT Filesystem]");
break;
case 0x07:
printDirectory(1, 0, tmp_left, "[EXFAT/NTFS Filesystem]");
break;
case 0x87:
sprintf(tmp_right, "[Emulated %dMB Drive]", (int)(mbr->part[partIndex].totalSectors / 2048));
printDirectory(1, 0, tmp_left, tmp_right);
break;
}
}
return;
}
if(!strcmp(local_prefix, "/diag/sd")) {
printDirectory(0, 0, "/diag/sd/ ", " [...]");
@ -996,6 +1025,31 @@ void showDirectory(int argc, char **argv) {
return;
}
}
if(!strcmp(local_prefix, "/nv") || !strncmp(local_prefix, "/nv/", 4)) {
File root = lfs.open("/");
while(true) {
File entry = root.openNextFile();
if(! entry) {
break;
}
if(!entry.isDirectory()) {
sprintf(tmp_left, "%s ", entry.name());
if(entry.size() >= 8192) {
sprintf(tmp_right, " [%llu KB]", entry.size() >> 10);
} else {
sprintf(tmp_right, " [%llu Bytes]", entry.size());
}
printDirectory(1, 0, tmp_left, tmp_right);
}
entry.close();
}
root.close();
}
if(!strcmp(local_prefix, "/sd") || !strncmp(local_prefix, "/sd/", 4)) {
char name[MAX_FILE_PATH+1];
SdFile root;
@ -1217,15 +1271,15 @@ void makeimagecmd(int argc, char **argv) {
memset(zero, 0, 512);
while(fileSize) {
if((fileSize & 0x7FFF) == 0)
if((fileSize & 0x1FFF) == 0)
Serial.printf(".");
if((fileSize & 0x3FFFFF) == 0)
if((fileSize & 0x7FFFF) == 0)
Serial.printf("\r\n");
file.write(zero, 512);
fileSize -= 512;
}
Serial.printf("\r\n");
file.close();
return;
@ -1250,7 +1304,9 @@ void catcmd(int argc, char **argv) {
}
fixupPath(tmp_path, argv[1]);
if(!strncmp(filename, "/sd/", 4)) {
if(!strncmp(filename, "/nv/", 4)) {
filename += 3;
} else if(!strncmp(filename, "/sd/", 4)) {
filename += 3;
} else {
errorlevel = -1;
@ -1394,6 +1450,14 @@ void setcmd(int argc, char **argv) {
if((param_name) && !strcasecmp(param_name, "/quirks")) {
if(argc<3) {
Serial.printf("0x%02x\r\n", h->m_quirks);
} if(!strcasecmp(argv[2], "SASI") || !strcasecmp(argv[2], "+SASI")) {
h->m_quirks |= QUIRKS_SASI;
} if(!strcasecmp(argv[2], "-SASI")) {
h->m_quirks &= ~QUIRKS_SASI;
} if(!strcasecmp(argv[2], "APPLE") || !strcasecmp(argv[2], "+APPLE")) {
h->m_quirks |= QUIRKS_APPLE;
} if(!strcasecmp(argv[2], "-APPLE")) {
h->m_quirks &= ~QUIRKS_APPLE;
} else {
h->m_quirks = strtol(argv[2], NULL, 0);
}
@ -1593,6 +1657,14 @@ void mountcmd(int argc, char **argv) {
return;
}
}
if(!strncmp(tmp_path, "/raw/", 5)) {
if(OpenDiskImage(h, tmp_path, 512)) {
strcpy(h->m_filename, tmp_path);
h->m_enabled = true;
return;
}
}
h->m_fileSize = 0;
h->m_blocksize = 0;
@ -1770,6 +1842,14 @@ void saveconfig(int argc, char **argv) {
config_file.close();
}
char helponSelfTest[] =
"\r\n"
"selftest\r\n"
"\r\n"
" Use the selftest command to check for miswired boards and shorts.\r\n"
"\r\n"
;
char helponSave[] =
"\r\n"
"saveconfig\r\n"
@ -1907,6 +1987,7 @@ char helponHelp[] =
Commands_t GlobalCommands[] = {
// Command Valid From Path Req. Params Short Help Long Help Handler Dispatch
{ "selftest", "/", 0, "Execute Self Test.", helponSelfTest, SelfTest, NULL },
{ "cd", "/", 1, "change current directory", NULL, changeDirectory, NULL },
{ "sl", "/", 0, NULL, NULL, slcmd, NULL },
{ "dir", "/", 0, NULL, NULL, punishDirectory, NULL },

View File

@ -14,7 +14,7 @@
// SCSI config
#define NUM_SCSIID 8 // Maximum number of supported SCSI-IDs (The minimum is 1)
#define NUM_SCSILUN 8 // Maximum number of LUNs supported (The minimum is 1)
#define NUM_VDEV 8 // Maximum number of VDEVs supported (The minimum is 1)
#define NUM_VDEV 16 // Maximum number of VDEVs supported (The minimum is 1)
#define READ_PARITY_CHECK 0 // Perform read parity check (unverified)

View File

@ -10,7 +10,7 @@ byte checkBlockCommand(uint32_t adds, uint32_t len)
if(!m_sel) {
return STATUS_CHECK;
}
if(!m_sel->m_file.isOpen()) {
if(!m_sel->m_rawPart && !m_sel->m_file.isOpen()) {
m_sel->m_sense.m_key = NOT_READY; // Not ready
m_sel->m_sense.m_code = LUN_NOT_READY; // Logical Unit Not Ready, Manual Intervention Required
m_sel->m_sense.m_key_specific[0] = 0x03;
@ -53,7 +53,7 @@ void ReadCapacityCommandHandler() {
m_phase = PHASE_STATUSIN;
return;
}
if(!m_sel->m_file.isOpen()) {
if(!m_sel->m_rawPart && !m_sel->m_file.isOpen()) {
m_sts |= STATUS_CHECK;
m_sel->m_sense.m_key = NOT_READY; // Not ready
m_sel->m_sense.m_code = LUN_NOT_READY; // Logical Unit Not Ready, Manual Intervention Required
@ -111,7 +111,11 @@ uint8_t onReadCommand(uint32_t adds, uint32_t len)
if(sts) return sts;
LED_ON();
writeDataPhaseSD(adds, len);
if(m_sel->m_rawPart) {
writeDataPhaseRaw(adds, len);
} else {
writeDataPhaseSD(adds, len);
}
LED_OFF();
return 0x00; //sts
}
@ -132,7 +136,11 @@ uint8_t onWriteCommand(uint32_t adds, uint32_t len)
if(sts) return sts;
LED_ON();
readDataPhaseSD(adds, len);
if(m_sel->m_rawPart) {
readDataPhaseRaw(adds, len);
} else {
readDataPhaseSD(adds, len);
}
LED_OFF();
return 0; //sts
}
@ -153,7 +161,11 @@ uint8_t onVerifyCommand(uint32_t adds, uint32_t len)
if(sts) return sts;
LED_ON();
verifyDataPhaseSD(adds, len);
if(m_sel->m_rawPart) {
verifyDataPhaseRaw(adds, len);
} else {
verifyDataPhaseSD(adds, len);
}
LED_OFF();
return 0; //sts
}

View File

@ -40,15 +40,16 @@ void RequestSenseCommandHandler() {
};
if(!m_sel) {
// Image file absent
buf[2] = 0x02; // NOT_READY
buf[12] = 0x25; // Logical Unit Not Supported
buf[2] = 2; // Not ready
buf[12] = LUN_NOT_READY; // Logical Unit Not Ready, Manual Intervention Required
buf[13] = 0x03;
} else {
buf[2] = m_sel->m_sense.m_key;
buf[12] = m_sel->m_sense.m_code;
buf[13] = m_sel->m_sense.m_key_specific[0];
buf[14] = m_sel->m_sense.m_key_specific[1];
buf[15] = m_sel->m_sense.m_key_specific[2];
m_sel->m_sense.m_key = 0;
m_sel->m_sense.m_code = 0;
m_sel->m_sense.m_key_specific[0] = 0;
@ -66,7 +67,7 @@ void TestUnitCommandHandler() {
m_sts |= STATUS_CHECK;
return;
}
if(!m_sel->m_file.isOpen()) {
if(!m_sel->m_rawPart && !m_sel->m_file.isOpen()) {
m_sts |= STATUS_CHECK;
m_sel->m_sense.m_key = NOT_READY; // Not ready
m_sel->m_sense.m_code = LUN_NOT_READY; // Logical Unit Not Ready, Manual Intervention Required
@ -83,13 +84,14 @@ void RezeroUnitCommandHandler() {
m_sts |= STATUS_CHECK;
return;
}
if(!m_sel->m_file.isOpen()) {
if(!m_sel->m_rawPart && !m_sel->m_file.isOpen()) {
m_sts |= STATUS_CHECK;
m_sel->m_sense.m_key = NOT_READY; // Not ready
m_sel->m_sense.m_code = LUN_NOT_READY; // Logical Unit Not Ready, Manual Intervention Required
m_sel->m_sense.m_key_specific[0] = 0x03;
return;
}
m_phase = PHASE_STATUSIN;
}
@ -99,7 +101,7 @@ void FormatUnitCommandHandler() {
m_sts |= STATUS_CHECK;
return;
}
if(!m_sel->m_file.isOpen()) {
if(!m_sel->m_rawPart && !m_sel->m_file.isOpen()) {
m_sts |= STATUS_CHECK;
m_sel->m_sense.m_key = NOT_READY; // Not ready
m_sel->m_sense.m_code = LUN_NOT_READY; // Logical Unit Not Ready, Manual Intervention Required
@ -116,7 +118,7 @@ void ReassignBlocksCommandHandler() {
m_sts |= STATUS_CHECK;
return;
}
if(!m_sel->m_file.isOpen()) {
if(!m_sel->m_rawPart && !m_sel->m_file.isOpen()) {
m_sts |= STATUS_CHECK;
m_sel->m_sense.m_key = NOT_READY; // Not ready
m_sel->m_sense.m_code = LUN_NOT_READY; // Logical Unit Not Ready, Manual Intervention Required
@ -165,7 +167,7 @@ void ModeSenseCommandHandler()
m_phase = PHASE_STATUSIN;
return;
}
if(!m_sel->m_file.isOpen()) {
if(!m_sel->m_rawPart && !m_sel->m_file.isOpen()) {
m_sts |= STATUS_CHECK;
m_sel->m_sense.m_key = NOT_READY; // Not ready
m_sel->m_sense.m_code = LUN_NOT_READY; // Logical Unit Not Ready, Manual Intervention Required

View File

@ -40,6 +40,7 @@
#include <Arduino.h> // For Platform.IO
#include <SPI.h>
#include <LittleFS.h>
#include <SdFat.h>
#include "sdios.h"
#include "config.h"
@ -48,6 +49,25 @@
// SDFAT
SdFs sd;
LittleFS_Program lfs;
struct part_s {
uint8_t boot;
uint8_t beginCHS[3];
uint8_t type;
uint8_t endCHS[3];
uint32_t firstSector;
uint32_t totalSectors;
} __attribute__((packed));
typedef struct part_s part_t;
//-----------------------------------------------------------------------------
struct mbr_s {
uint8_t bootCode[446];
part_t part[4];
uint8_t signature[2];
} __attribute__((packed));
typedef struct mbr_s mbr_t;
boolean debuglog = 0;
@ -194,6 +214,8 @@ typedef struct VirtualDevice_s
FsFile m_file; // File object
uint64_t m_fileSize; // File size
size_t m_blocksize; // SCSI BLOCK size
uint32_t m_firstSector; // First sector for partition
boolean m_rawPart; // Raw Partition (True) or Image File (False)
#if SUPPORT_TAPE
size_t m_filemarks; // Tape position counter (file marks since BOM)
#endif
@ -225,6 +247,8 @@ uint16_t default_quirks = (SUPPORT_SASI_DEFAULT ? QUIRKS_SASI : 0) | (SUPPO
uint16_t ledbits = 0;
uint8_t ledbit = 0;
uint8_t cardMBR[512];
typedef enum {
PHASE_BUSFREE = 0,
PHASE_SELECTION,
@ -236,7 +260,7 @@ typedef enum {
phase_t m_phase = PHASE_BUSFREE;
// Log File
#define VERSION "1.2-20211204"
#define VERSION "1.4-20230513"
#if DEBUG == 2
#define LOG_FILENAME "LOG.txt"
FsFile LOG_FILE;
@ -280,6 +304,59 @@ boolean OpenImage(VirtualDevice_t *h, const char *image_name)
*/
boolean OpenDiskImage(VirtualDevice_t *h, const char *image_name, int blocksize)
{
if(!strncmp(image_name, "/tgts/", 6)) {
LOGN("/tgts/ path is not supported for disk images.");
return false;
}
if(!strncmp(image_name, "/vdevs/", 7)) {
LOGN("/vdevs/ path is not supported for disk images.");
return false;
}
if(!strncmp(image_name, "/diag/", 6)) {
LOGN("/diag/ path is not supported for disk images.");
return false;
}
if(!strncmp(image_name, "/nv/", 4)) {
LOGN("/nv/ path is not supported for disk images.");
return false;
}
h->m_rawPart = false;
if(!strncmp(image_name, "/raw/part", 9)) {
int partIndex = image_name[9] - '0';
mbr_t *mbr = (mbr_t *)cardMBR;
if((partIndex < 0) || (partIndex > 3)) {
LOGN("partition index is outside the allowed range.");
return false;
}
sd.card()->readSector(0, cardMBR);
if(mbr->part[partIndex].type != 0x87) {
LOGN("partition is of the wrong type.");
return false;
}
h->m_blocksize = blocksize;
h->m_fileSize = ((uint64_t)mbr->part[partIndex].totalSectors) * ((uint64_t)512);
h->m_rawPart = true;
h->m_firstSector = mbr->part[partIndex].firstSector;
LOG(" Imagefile: ");
LOG(image_name);
LOG(" / ");
LOG(h->m_fileSize / h->m_blocksize);
LOG(" sectors / ");
LOG(h->m_fileSize / 1024);
LOG(" KiB / ");
LOG(h->m_fileSize / 1024 / 1024);
LOGN(" MiB");
return true; // File opened
}
if(!strncmp(image_name, "/sd/", 4))
image_name += 3;
@ -320,6 +397,29 @@ boolean OpenDiskImage(VirtualDevice_t *h, const char *image_name, int blocksize)
*/
boolean OpenTapeImage(VirtualDevice_t *h, const char *image_name)
{
if(!strncmp(image_name, "/tgts/", 6)) {
LOGN("/tgts/ path is not supported for tape images.");
return false;
}
if(!strncmp(image_name, "/vdevs/", 7)) {
LOGN("/vdevs/ path is not supported for tape images.");
return false;
}
if(!strncmp(image_name, "/diag/", 6)) {
LOGN("/diag/ path is not supported for tape images.");
return false;
}
if(!strncmp(image_name, "/nv/", 4)) {
LOGN("/nv/ path is not supported for tape images.");
return false;
}
if(!strncmp(image_name, "/sd/", 4))
image_name += 3;
h->m_fileSize = 0;
h->m_blocksize = 0;
h->m_filemarks = 0;
@ -406,6 +506,9 @@ void setup()
LED_ON();
// Filesystems
lfs.begin(256 * 1024); // 256KB of program memory to be used as nonvolatile storage
if(!sd.begin(SdioConfig(FIFO_SDIO))) {
#if DEBUG > 0
Serial.println("SD initialization failed!");
@ -420,10 +523,14 @@ void setup()
//HD image file open
scsi_id_mask = 0x00;
// If greenscsi.cfg exists, run it
// If greenscsi.cfg exists, run it (try first from SD, otherwise from flash)
if(sd.exists("/greenscsi.cfg")) {
execscript((char*)"/sd/greenscsi.cfg");
execLoop();
} else
if(lfs.exists("/greenscsi.cfg")) {
execscript((char*)"/nv/greenscsi.cfg");
execLoop();
}
// Scan for images if we haven't defined any targets yet.
@ -911,3 +1018,235 @@ void BusFreePhaseHandler() {
// Reset back to waiting for selection phase.
m_phase = PHASE_SELECTION;
}
typedef struct SelfTestPins_s {
int A;
int B;
int pA;
int pB;
char nA[4];
char nB[4];
} SelfTestPins_t;
SelfTestPins_t SelfTestPins[] = {
{ IO, DB0, 50, 2, "I/O", "DB0" },
{ IO, DB0, 48, 4, "REQ", "DB1" },
{ IO, DB0, 46, 6, "C/D", "DB2" },
{ IO, DB0, 44, 8, "SEL", "DB3" },
{ IO, DB0, 42, 10, "MSG", "DB4" },
{ IO, DB0, 50, 12, "RST", "DB5" },
{ IO, DB0, 38, 14, "ACK", "DB6" },
{ IO, DB0, 36, 16, "BSY", "DB7" },
{ IO, DB0, 32, 18, "ATN", "DBP" },
};
void SelfTest(int argc, char **argv) {
int i, x;
char c;
Serial.printf("Are you sure you wish to run the self test? ");
for(;;) {
if (Serial.available()) {
c = Serial.read();
switch(c) {
default:
return;
case 'y': case 'Y':
goto ConnectHarness;
}
}
}
ConnectHarness:
// Clear any extra characters
while (Serial.available()) {
c = Serial.read();
}
// Disable normal operation and prepare the self test.
detachInterrupt(RST);
detachInterrupt(SEL);
Serial.printf("Self Test starting...\r\n");
// Delay for 3 seconds
delay(3000);
while (Serial.available()) {
c = Serial.read();
}
Serial.printf("Connect the Loopback test adapter and press Enter.");
for(;;) {
if (Serial.available()) {
c = Serial.read();
switch(c) {
case 0xA: case 0xD:
goto ExecuteSelfTest;
}
}
}
ExecuteSelfTest:
// Clear any extra characters
while (Serial.available()) {
c = Serial.read();
}
// All pins input
for(i = 0; i < 9; i++) {
pinMode(SelfTestPins[i].A, INPUT_PULLUP);
pinMode(SelfTestPins[i].B, INPUT_PULLUP);
}
for(i = 0; i < 9; i++) {
// Test A -> B
pinMode(SelfTestPins[i].A, OUTPUT_OPENDRAIN);
digitalWrite(SelfTestPins[i].A, LOW);
delay(10);
if(digitalRead(SelfTestPins[i].B) != LOW) {
Serial.printf("Self Test Failed. Pin %d (%s) was unable to pull Pin %d (%s) LOW.\r\n", SelfTestPins[i].pA, SelfTestPins[i].nA, SelfTestPins[i].pB, SelfTestPins[i].nB);
pinMode(SelfTestPins[i].A, INPUT_PULLUP);
return;
}
for(x = 0; x < 9; x++) {
if(x != i) {
if(digitalRead(SelfTestPins[x].A) == LOW) {
Serial.printf("Self Test Failed. Pin %d (%s) is shorted to Pin %d (%s).\r\n", SelfTestPins[i].pA, SelfTestPins[i].nA, SelfTestPins[x].pA, SelfTestPins[x].nA);
pinMode(SelfTestPins[i].A, INPUT_PULLUP);
return;
}
if(digitalRead(SelfTestPins[x].B) == LOW) {
Serial.printf("Self Test Failed. Pin %d (%s) is shorted to Pin %d (%s).\r\n", SelfTestPins[i].pA, SelfTestPins[i].nA, SelfTestPins[x].pB, SelfTestPins[x].nB);
pinMode(SelfTestPins[i].A, INPUT_PULLUP);
return;
}
}
}
pinMode(SelfTestPins[i].A, INPUT_PULLUP);
delay(10);
// Test B -> A
pinMode(SelfTestPins[i].B, OUTPUT_OPENDRAIN);
digitalWrite(SelfTestPins[i].B, LOW);
delay(10);
if(digitalRead(SelfTestPins[i].A) != LOW) {
Serial.printf("Self Test Failed. Pin %d (%s) was unable to pull Pin %d (%s) LOW.\r\n", SelfTestPins[i].pB, SelfTestPins[i].nB, SelfTestPins[i].pA, SelfTestPins[i].nA);
pinMode(SelfTestPins[i].B, INPUT_PULLUP);
return;
}
for(x = 0; x < 9; x++) {
if(x != i) {
if(digitalRead(SelfTestPins[x].A) == LOW) {
Serial.printf("Self Test Failed. Pin %d (%s) is shorted to Pin %d (%s).\r\n", SelfTestPins[i].pB, SelfTestPins[i].nB, SelfTestPins[x].pA, SelfTestPins[x].nA);
pinMode(SelfTestPins[i].B, INPUT_PULLUP);
return;
}
if(digitalRead(SelfTestPins[x].B) == LOW) {
Serial.printf("Self Test Failed. Pin %d (%s) is shorted to Pin %d (%s).\r\n", SelfTestPins[i].pB, SelfTestPins[i].nB, SelfTestPins[x].pB, SelfTestPins[x].nB);
pinMode(SelfTestPins[i].B, INPUT_PULLUP);
return;
}
}
}
pinMode(SelfTestPins[i].B, INPUT_PULLUP);
delay(10);
}
while (Serial.available()) {
c = Serial.read();
}
Serial.printf("Disconnect the Loopback test adapter and press Enter.");
for(;;) {
if (Serial.available()) {
c = Serial.read();
switch(c) {
case 0xA: case 0xD:
goto DisconnectHarness;
}
}
}
DisconnectHarness:
// Clear any extra characters
while (Serial.available()) {
c = Serial.read();
}
for(i = 0; i < 9; i++) {
// Test A -> B
pinMode(SelfTestPins[i].A, OUTPUT_OPENDRAIN);
digitalWrite(SelfTestPins[i].A, LOW);
delay(10);
if(digitalRead(SelfTestPins[i].B) == LOW) {
Serial.printf("Self Test Failed. Pin %d (%s) is shorted to Pin %d (%s).\r\n", SelfTestPins[i].pA, SelfTestPins[i].nA, SelfTestPins[i].pB, SelfTestPins[i].nB);
pinMode(SelfTestPins[i].A, INPUT_PULLUP);
return;
}
// Test B -> A
pinMode(SelfTestPins[i].B, OUTPUT_OPENDRAIN);
digitalWrite(SelfTestPins[i].B, LOW);
delay(10);
if(digitalRead(SelfTestPins[i].A) == LOW) {
Serial.printf("Self Test Failed. Pin %d (%s) is shorted to Pin %d (%s).\r\n", SelfTestPins[i].pB, SelfTestPins[i].nB, SelfTestPins[i].pA, SelfTestPins[i].nA);
pinMode(SelfTestPins[i].B, INPUT_PULLUP);
return;
}
}
//SelfTestComplete:
// Clear any extra characters
while (Serial.available()) {
c = Serial.read();
}
Serial.printf("Self Test Passed.\r\n");
// On success, restore normal operation
// Input port
pinMode(ATN, INPUT_PULLUP);
pinMode(ACK, INPUT_PULLUP);
pinMode(RST, INPUT_PULLUP);
pinMode(SEL, INPUT_PULLUP);
// Output port
pinModeFastSlew(BSY, OUTPUT_OPENDRAIN);
pinModeFastSlew(MSG, OUTPUT_OPENDRAIN);
pinModeFastSlew(CD, OUTPUT_OPENDRAIN);
pinModeFastSlew(IO, OUTPUT_OPENDRAIN);
pinModeFastSlew(REQ, OUTPUT_OPENDRAIN);
pinModeFastSlew(DB0, OUTPUT_OPENDRAIN);
pinModeFastSlew(DB1, OUTPUT_OPENDRAIN);
pinModeFastSlew(DB2, OUTPUT_OPENDRAIN);
pinModeFastSlew(DB3, OUTPUT_OPENDRAIN);
pinModeFastSlew(DB4, OUTPUT_OPENDRAIN);
pinModeFastSlew(DB5, OUTPUT_OPENDRAIN);
pinModeFastSlew(DB6, OUTPUT_OPENDRAIN);
pinModeFastSlew(DB7, OUTPUT_OPENDRAIN);
pinModeFastSlew(DB8, OUTPUT_OPENDRAIN);
// Turn off the output port
SCSI_TARGET_INACTIVE();
attachInterrupt(RST, onBusReset, FALLING);
attachInterrupt(SEL, SelectionPhaseISR, FALLING);
LED_OFF();
}

View File

@ -497,6 +497,10 @@ void OpticalReadCapacityCommandHandler() {
LOGN("[ReadCapacity]");
if(!m_sel) {
m_sts |= STATUS_CHECK; // Image file absent
m_sel->m_sense.m_key_specific[0] = 0x04;
m_sel->m_sense.m_key_specific[1] = 0x03;
m_sel->m_sense.m_key_specific[2] = 0x00;
m_sel->m_sense.m_key_specific[3] = 0x00;
m_phase = PHASE_STATUSIN;
return;
}

View File

@ -211,6 +211,55 @@ void writeDataPhaseSD(uint32_t adds, uint32_t len)
}
}
/*
* Data in phase.
* Send len block while reading from SD card.
*/
void writeDataPhaseRaw(uint32_t adds, uint32_t len)
{
#if READ_SPEED_OPTIMIZE_RAW
uint32_t bigread = (MAX_BLOCKSIZE / m_sel->m_blocksize);
#endif
uint32_t i = 0;
//LOGN("DATAIN PHASE(RAW)");
uint32_t pos = ((adds * m_sel->m_blocksize) / 512) + m_sel->m_firstSector;
SET_MSG_INACTIVE();
SET_CD_INACTIVE();
SET_IO_ACTIVE();
while(i < len) {
// Asynchronous reads will make it faster ...
#if READ_SPEED_OPTIMIZE_RAW
if((len-i) >= bigread) {
sd.card()->readSectors(pos, m_buf, (MAX_BLOCKSIZE / 512));
writeHandshakeBlock(m_buf, MAX_BLOCKSIZE);
i += bigread;
pos += (MAX_BLOCKSIZE / 512);
} else {
sd.card()->readSectors(pos, m_buf, ((m_sel->m_blocksize * (len-i)) / 512));
writeHandshakeBlock(m_buf, m_sel->m_blocksize * (len-i));
i = len;
}
#else
sd.card()->readSectors(pos, m_buf, (m_sel->m_blocksize / 512));
pos++;
for(unsigned int j = 0; j < m_sel->m_blocksize; j++) {
if(m_isBusReset) {
m_phase = PHASE_BUSFREE;
return;
}
writeHandshake(m_buf[j]);
}
#endif
if(m_isBusReset) {
m_phase = PHASE_BUSFREE;
return;
}
}
}
/*
* Data out phase.
* len block read
@ -275,6 +324,50 @@ void readDataPhaseSD(uint32_t adds, uint32_t len)
m_sel->m_file.flush();
}
/*
* Data out phase.
* Write to SD card while reading len block.
*/
void readDataPhaseRaw(uint32_t adds, uint32_t len)
{
#if WRITE_SPEED_OPTIMIZE
uint32_t bigread = (MAX_BLOCKSIZE / m_sel->m_blocksize);
#endif
uint32_t i = 0;
//LOGN("DATAOUT PHASE(RAW)");
uint32_t pos = ((adds * m_sel->m_blocksize) / 512) + m_sel->m_firstSector;
SET_MSG_INACTIVE();
SET_CD_INACTIVE();
SET_IO_INACTIVE();
while(i < len) {
#if WRITE_SPEED_OPTIMIZE
if((len-i) >= bigread) {
readHandshakeBlock(m_buf, MAX_BLOCKSIZE);
sd.card()->writeSectors(pos, m_buf, (MAX_BLOCKSIZE / 512));
i += bigread;
pos += (MAX_BLOCKSIZE / 512);
} else {
readHandshakeBlock(m_buf, m_sel->m_blocksize * (len-i));
sd.card()->writeSectors(pos, m_buf, ((m_sel->m_blocksize * (len-i)) / 512));
i = len;
}
#else
for(unsigned int j = 0; j < m_sel->m_blocksize; j++) {
if(m_isBusReset) {
return;
}
m_buf[j] = readHandshake();
}
sd.card()->writeSectors(pos, m_buf, (m_sel->m_blocksize / 512));
i++;
pos += (m_sel->m_blocksize / 512);
#endif
}
m_sel->m_file.flush();
}
/*
* Data out phase.
@ -287,12 +380,54 @@ void verifyDataPhaseSD(uint32_t adds, uint32_t len)
#endif
uint32_t i = 0;
//LOGN("DATAOUT PHASE(SD)");
uint32_t pos = adds * m_sel->m_blocksize;
m_sel->m_file.seek(pos);
SET_MSG_INACTIVE();
SET_CD_INACTIVE();
SET_IO_INACTIVE();
while(i < len) {
#if WRITE_SPEED_OPTIMIZE
if((len-i) >= bigread) {
readHandshakeBlock(m_buf, MAX_BLOCKSIZE);
//m_sel->m_file.verify(m_buf, MAX_BLOCKSIZE);
i += bigread;
} else {
readHandshakeBlock(m_buf, m_sel->m_blocksize * (len-i));
//m_sel->m_file.verify(m_buf, m_sel->m_blocksize * (len-i));
i = len;
}
#else
for(unsigned int j = 0; j < m_sel->m_blocksize; j++) {
if(m_isBusReset) {
return;
}
m_buf[j] = readHandshake();
}
//m_sel->m_file.verify(m_buf, m_sel->m_blocksize);
#endif
}
}
/*
* Data out phase.
* Verify SD card while reading len block.
*/
void verifyDataPhaseRaw(uint32_t adds, uint32_t len)
{
#if WRITE_SPEED_OPTIMIZE
uint32_t bigread = (MAX_BLOCKSIZE / m_sel->m_blocksize);
#endif
uint32_t i = 0;
//LOGN("DATAOUT PHASE(RAW)");
uint32_t pos = ((adds * m_sel->m_blocksize) / 512) + m_sel->m_firstSector;
SET_MSG_INACTIVE();
SET_CD_INACTIVE();
SET_IO_INACTIVE();
while(i < len) {
#if WRITE_SPEED_OPTIMIZE
if((len-i) >= bigread) {