mirror of
https://github.com/dkgrizzly/GreenSCSI.git
synced 2024-06-13 17:29:35 +00:00
RAW disk support and LittleFS support
This commit is contained in:
parent
c5c4c51667
commit
d420244da9
91
src/cmd.ino
91
src/cmd.ino
|
@ -24,6 +24,7 @@ int scriptlevel = -1;
|
||||||
char cmd_prefix[256] = "/";
|
char cmd_prefix[256] = "/";
|
||||||
|
|
||||||
extern uint8_t mbr_bin[];
|
extern uint8_t mbr_bin[];
|
||||||
|
uint8_t zero[512];
|
||||||
|
|
||||||
void cmdDisplay() {
|
void cmdDisplay() {
|
||||||
if(cmd_prefix[0] != 0) {
|
if(cmd_prefix[0] != 0) {
|
||||||
|
@ -723,7 +724,7 @@ void changeDirectory(int argc, char **argv) {
|
||||||
goto e_invalidpath;
|
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")
|
|| !strcmp(new_prefix, "/sd") || !strcmp(new_prefix, "/diag")|| !strcmp(new_prefix, "/diag/sd")
|
||||||
) {
|
) {
|
||||||
strcpy(cmd_prefix, new_prefix);
|
strcpy(cmd_prefix, new_prefix);
|
||||||
|
@ -863,6 +864,7 @@ void showDirectory(int argc, char **argv) {
|
||||||
printDirectory(0, 0, "/ ", " [...]");
|
printDirectory(0, 0, "/ ", " [...]");
|
||||||
printDirectory(1, 0, "diag/ ", " [...]");
|
printDirectory(1, 0, "diag/ ", " [...]");
|
||||||
printDirectory(1, 0, "sd/ ", " [...]");
|
printDirectory(1, 0, "sd/ ", " [...]");
|
||||||
|
printDirectory(1, 0, "raw/ ", " [...]");
|
||||||
sprintf(tmp_right, " [%d Target%s]", NUM_SCSIID, (NUM_SCSIID != 1) ? "s" : "");
|
sprintf(tmp_right, " [%d Target%s]", NUM_SCSIID, (NUM_SCSIID != 1) ? "s" : "");
|
||||||
printDirectory(1, 0, "tgts/ ", tmp_right);
|
printDirectory(1, 0, "tgts/ ", tmp_right);
|
||||||
sprintf(tmp_right, " [%d Storage Object%s]", m_vdevcnt, (m_vdevcnt != 1) ? "s" : "");
|
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/ ", " [...]");
|
printDirectory(1, 0, "sd/ ", " [...]");
|
||||||
return;
|
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")) {
|
if(!strcmp(local_prefix, "/diag/sd")) {
|
||||||
printDirectory(0, 0, "/diag/sd/ ", " [...]");
|
printDirectory(0, 0, "/diag/sd/ ", " [...]");
|
||||||
|
|
||||||
|
@ -996,6 +1025,31 @@ void showDirectory(int argc, char **argv) {
|
||||||
return;
|
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)) {
|
if(!strcmp(local_prefix, "/sd") || !strncmp(local_prefix, "/sd/", 4)) {
|
||||||
char name[MAX_FILE_PATH+1];
|
char name[MAX_FILE_PATH+1];
|
||||||
SdFile root;
|
SdFile root;
|
||||||
|
@ -1217,15 +1271,15 @@ void makeimagecmd(int argc, char **argv) {
|
||||||
memset(zero, 0, 512);
|
memset(zero, 0, 512);
|
||||||
|
|
||||||
while(fileSize) {
|
while(fileSize) {
|
||||||
if((fileSize & 0x7FFF) == 0)
|
if((fileSize & 0x1FFF) == 0)
|
||||||
Serial.printf(".");
|
Serial.printf(".");
|
||||||
if((fileSize & 0x3FFFFF) == 0)
|
if((fileSize & 0x7FFFF) == 0)
|
||||||
Serial.printf("\r\n");
|
Serial.printf("\r\n");
|
||||||
file.write(zero, 512);
|
file.write(zero, 512);
|
||||||
fileSize -= 512;
|
fileSize -= 512;
|
||||||
}
|
}
|
||||||
Serial.printf("\r\n");
|
Serial.printf("\r\n");
|
||||||
|
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -1250,7 +1304,9 @@ void catcmd(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fixupPath(tmp_path, argv[1]);
|
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;
|
filename += 3;
|
||||||
} else {
|
} else {
|
||||||
errorlevel = -1;
|
errorlevel = -1;
|
||||||
|
@ -1394,6 +1450,14 @@ void setcmd(int argc, char **argv) {
|
||||||
if((param_name) && !strcasecmp(param_name, "/quirks")) {
|
if((param_name) && !strcasecmp(param_name, "/quirks")) {
|
||||||
if(argc<3) {
|
if(argc<3) {
|
||||||
Serial.printf("0x%02x\r\n", h->m_quirks);
|
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 {
|
} else {
|
||||||
h->m_quirks = strtol(argv[2], NULL, 0);
|
h->m_quirks = strtol(argv[2], NULL, 0);
|
||||||
}
|
}
|
||||||
|
@ -1593,6 +1657,14 @@ void mountcmd(int argc, char **argv) {
|
||||||
return;
|
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_fileSize = 0;
|
||||||
h->m_blocksize = 0;
|
h->m_blocksize = 0;
|
||||||
|
@ -1770,6 +1842,14 @@ void saveconfig(int argc, char **argv) {
|
||||||
config_file.close();
|
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[] =
|
char helponSave[] =
|
||||||
"\r\n"
|
"\r\n"
|
||||||
"saveconfig\r\n"
|
"saveconfig\r\n"
|
||||||
|
@ -1907,6 +1987,7 @@ char helponHelp[] =
|
||||||
|
|
||||||
Commands_t GlobalCommands[] = {
|
Commands_t GlobalCommands[] = {
|
||||||
// Command Valid From Path Req. Params Short Help Long Help Handler Dispatch
|
// 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 },
|
{ "cd", "/", 1, "change current directory", NULL, changeDirectory, NULL },
|
||||||
{ "sl", "/", 0, NULL, NULL, slcmd, NULL },
|
{ "sl", "/", 0, NULL, NULL, slcmd, NULL },
|
||||||
{ "dir", "/", 0, NULL, NULL, punishDirectory, NULL },
|
{ "dir", "/", 0, NULL, NULL, punishDirectory, NULL },
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
// SCSI config
|
// SCSI config
|
||||||
#define NUM_SCSIID 8 // Maximum number of supported SCSI-IDs (The minimum is 1)
|
#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_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)
|
#define READ_PARITY_CHECK 0 // Perform read parity check (unverified)
|
||||||
|
|
||||||
|
|
22
src/disk.ino
22
src/disk.ino
|
@ -10,7 +10,7 @@ byte checkBlockCommand(uint32_t adds, uint32_t len)
|
||||||
if(!m_sel) {
|
if(!m_sel) {
|
||||||
return STATUS_CHECK;
|
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_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_code = LUN_NOT_READY; // Logical Unit Not Ready, Manual Intervention Required
|
||||||
m_sel->m_sense.m_key_specific[0] = 0x03;
|
m_sel->m_sense.m_key_specific[0] = 0x03;
|
||||||
|
@ -53,7 +53,7 @@ void ReadCapacityCommandHandler() {
|
||||||
m_phase = PHASE_STATUSIN;
|
m_phase = PHASE_STATUSIN;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(!m_sel->m_file.isOpen()) {
|
if(!m_sel->m_rawPart && !m_sel->m_file.isOpen()) {
|
||||||
m_sts |= STATUS_CHECK;
|
m_sts |= STATUS_CHECK;
|
||||||
m_sel->m_sense.m_key = NOT_READY; // Not ready
|
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_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;
|
if(sts) return sts;
|
||||||
|
|
||||||
LED_ON();
|
LED_ON();
|
||||||
writeDataPhaseSD(adds, len);
|
if(m_sel->m_rawPart) {
|
||||||
|
writeDataPhaseRaw(adds, len);
|
||||||
|
} else {
|
||||||
|
writeDataPhaseSD(adds, len);
|
||||||
|
}
|
||||||
LED_OFF();
|
LED_OFF();
|
||||||
return 0x00; //sts
|
return 0x00; //sts
|
||||||
}
|
}
|
||||||
|
@ -132,7 +136,11 @@ uint8_t onWriteCommand(uint32_t adds, uint32_t len)
|
||||||
if(sts) return sts;
|
if(sts) return sts;
|
||||||
|
|
||||||
LED_ON();
|
LED_ON();
|
||||||
readDataPhaseSD(adds, len);
|
if(m_sel->m_rawPart) {
|
||||||
|
readDataPhaseRaw(adds, len);
|
||||||
|
} else {
|
||||||
|
readDataPhaseSD(adds, len);
|
||||||
|
}
|
||||||
LED_OFF();
|
LED_OFF();
|
||||||
return 0; //sts
|
return 0; //sts
|
||||||
}
|
}
|
||||||
|
@ -153,7 +161,11 @@ uint8_t onVerifyCommand(uint32_t adds, uint32_t len)
|
||||||
if(sts) return sts;
|
if(sts) return sts;
|
||||||
|
|
||||||
LED_ON();
|
LED_ON();
|
||||||
verifyDataPhaseSD(adds, len);
|
if(m_sel->m_rawPart) {
|
||||||
|
verifyDataPhaseRaw(adds, len);
|
||||||
|
} else {
|
||||||
|
verifyDataPhaseSD(adds, len);
|
||||||
|
}
|
||||||
LED_OFF();
|
LED_OFF();
|
||||||
return 0; //sts
|
return 0; //sts
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,15 +40,16 @@ void RequestSenseCommandHandler() {
|
||||||
};
|
};
|
||||||
|
|
||||||
if(!m_sel) {
|
if(!m_sel) {
|
||||||
// Image file absent
|
buf[2] = 2; // Not ready
|
||||||
buf[2] = 0x02; // NOT_READY
|
buf[12] = LUN_NOT_READY; // Logical Unit Not Ready, Manual Intervention Required
|
||||||
buf[12] = 0x25; // Logical Unit Not Supported
|
buf[13] = 0x03;
|
||||||
} else {
|
} else {
|
||||||
buf[2] = m_sel->m_sense.m_key;
|
buf[2] = m_sel->m_sense.m_key;
|
||||||
buf[12] = m_sel->m_sense.m_code;
|
buf[12] = m_sel->m_sense.m_code;
|
||||||
buf[13] = m_sel->m_sense.m_key_specific[0];
|
buf[13] = m_sel->m_sense.m_key_specific[0];
|
||||||
buf[14] = m_sel->m_sense.m_key_specific[1];
|
buf[14] = m_sel->m_sense.m_key_specific[1];
|
||||||
buf[15] = m_sel->m_sense.m_key_specific[2];
|
buf[15] = m_sel->m_sense.m_key_specific[2];
|
||||||
|
|
||||||
m_sel->m_sense.m_key = 0;
|
m_sel->m_sense.m_key = 0;
|
||||||
m_sel->m_sense.m_code = 0;
|
m_sel->m_sense.m_code = 0;
|
||||||
m_sel->m_sense.m_key_specific[0] = 0;
|
m_sel->m_sense.m_key_specific[0] = 0;
|
||||||
|
@ -66,7 +67,7 @@ void TestUnitCommandHandler() {
|
||||||
m_sts |= STATUS_CHECK;
|
m_sts |= STATUS_CHECK;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(!m_sel->m_file.isOpen()) {
|
if(!m_sel->m_rawPart && !m_sel->m_file.isOpen()) {
|
||||||
m_sts |= STATUS_CHECK;
|
m_sts |= STATUS_CHECK;
|
||||||
m_sel->m_sense.m_key = NOT_READY; // Not ready
|
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_code = LUN_NOT_READY; // Logical Unit Not Ready, Manual Intervention Required
|
||||||
|
@ -83,13 +84,14 @@ void RezeroUnitCommandHandler() {
|
||||||
m_sts |= STATUS_CHECK;
|
m_sts |= STATUS_CHECK;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(!m_sel->m_file.isOpen()) {
|
if(!m_sel->m_rawPart && !m_sel->m_file.isOpen()) {
|
||||||
m_sts |= STATUS_CHECK;
|
m_sts |= STATUS_CHECK;
|
||||||
m_sel->m_sense.m_key = NOT_READY; // Not ready
|
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_code = LUN_NOT_READY; // Logical Unit Not Ready, Manual Intervention Required
|
||||||
m_sel->m_sense.m_key_specific[0] = 0x03;
|
m_sel->m_sense.m_key_specific[0] = 0x03;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_phase = PHASE_STATUSIN;
|
m_phase = PHASE_STATUSIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +101,7 @@ void FormatUnitCommandHandler() {
|
||||||
m_sts |= STATUS_CHECK;
|
m_sts |= STATUS_CHECK;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(!m_sel->m_file.isOpen()) {
|
if(!m_sel->m_rawPart && !m_sel->m_file.isOpen()) {
|
||||||
m_sts |= STATUS_CHECK;
|
m_sts |= STATUS_CHECK;
|
||||||
m_sel->m_sense.m_key = NOT_READY; // Not ready
|
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_code = LUN_NOT_READY; // Logical Unit Not Ready, Manual Intervention Required
|
||||||
|
@ -116,7 +118,7 @@ void ReassignBlocksCommandHandler() {
|
||||||
m_sts |= STATUS_CHECK;
|
m_sts |= STATUS_CHECK;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(!m_sel->m_file.isOpen()) {
|
if(!m_sel->m_rawPart && !m_sel->m_file.isOpen()) {
|
||||||
m_sts |= STATUS_CHECK;
|
m_sts |= STATUS_CHECK;
|
||||||
m_sel->m_sense.m_key = NOT_READY; // Not ready
|
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_code = LUN_NOT_READY; // Logical Unit Not Ready, Manual Intervention Required
|
||||||
|
@ -165,7 +167,7 @@ void ModeSenseCommandHandler()
|
||||||
m_phase = PHASE_STATUSIN;
|
m_phase = PHASE_STATUSIN;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(!m_sel->m_file.isOpen()) {
|
if(!m_sel->m_rawPart && !m_sel->m_file.isOpen()) {
|
||||||
m_sts |= STATUS_CHECK;
|
m_sts |= STATUS_CHECK;
|
||||||
m_sel->m_sense.m_key = NOT_READY; // Not ready
|
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_code = LUN_NOT_READY; // Logical Unit Not Ready, Manual Intervention Required
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
|
|
||||||
#include <Arduino.h> // For Platform.IO
|
#include <Arduino.h> // For Platform.IO
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
|
#include <LittleFS.h>
|
||||||
#include <SdFat.h>
|
#include <SdFat.h>
|
||||||
#include "sdios.h"
|
#include "sdios.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
@ -48,6 +49,25 @@
|
||||||
|
|
||||||
// SDFAT
|
// SDFAT
|
||||||
SdFs sd;
|
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;
|
boolean debuglog = 0;
|
||||||
|
|
||||||
|
@ -194,6 +214,8 @@ typedef struct VirtualDevice_s
|
||||||
FsFile m_file; // File object
|
FsFile m_file; // File object
|
||||||
uint64_t m_fileSize; // File size
|
uint64_t m_fileSize; // File size
|
||||||
size_t m_blocksize; // SCSI BLOCK 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
|
#if SUPPORT_TAPE
|
||||||
size_t m_filemarks; // Tape position counter (file marks since BOM)
|
size_t m_filemarks; // Tape position counter (file marks since BOM)
|
||||||
#endif
|
#endif
|
||||||
|
@ -225,6 +247,8 @@ uint16_t default_quirks = (SUPPORT_SASI_DEFAULT ? QUIRKS_SASI : 0) | (SUPPO
|
||||||
uint16_t ledbits = 0;
|
uint16_t ledbits = 0;
|
||||||
uint8_t ledbit = 0;
|
uint8_t ledbit = 0;
|
||||||
|
|
||||||
|
uint8_t cardMBR[512];
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
PHASE_BUSFREE = 0,
|
PHASE_BUSFREE = 0,
|
||||||
PHASE_SELECTION,
|
PHASE_SELECTION,
|
||||||
|
@ -236,7 +260,7 @@ typedef enum {
|
||||||
phase_t m_phase = PHASE_BUSFREE;
|
phase_t m_phase = PHASE_BUSFREE;
|
||||||
|
|
||||||
// Log File
|
// Log File
|
||||||
#define VERSION "1.2-20211204"
|
#define VERSION "1.4-20230513"
|
||||||
#if DEBUG == 2
|
#if DEBUG == 2
|
||||||
#define LOG_FILENAME "LOG.txt"
|
#define LOG_FILENAME "LOG.txt"
|
||||||
FsFile LOG_FILE;
|
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)
|
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))
|
if(!strncmp(image_name, "/sd/", 4))
|
||||||
image_name += 3;
|
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)
|
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_fileSize = 0;
|
||||||
h->m_blocksize = 0;
|
h->m_blocksize = 0;
|
||||||
h->m_filemarks = 0;
|
h->m_filemarks = 0;
|
||||||
|
@ -406,6 +506,9 @@ void setup()
|
||||||
|
|
||||||
LED_ON();
|
LED_ON();
|
||||||
|
|
||||||
|
// Filesystems
|
||||||
|
lfs.begin(256 * 1024); // 256KB of program memory to be used as nonvolatile storage
|
||||||
|
|
||||||
if(!sd.begin(SdioConfig(FIFO_SDIO))) {
|
if(!sd.begin(SdioConfig(FIFO_SDIO))) {
|
||||||
#if DEBUG > 0
|
#if DEBUG > 0
|
||||||
Serial.println("SD initialization failed!");
|
Serial.println("SD initialization failed!");
|
||||||
|
@ -420,10 +523,14 @@ void setup()
|
||||||
//HD image file open
|
//HD image file open
|
||||||
scsi_id_mask = 0x00;
|
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")) {
|
if(sd.exists("/greenscsi.cfg")) {
|
||||||
execscript((char*)"/sd/greenscsi.cfg");
|
execscript((char*)"/sd/greenscsi.cfg");
|
||||||
execLoop();
|
execLoop();
|
||||||
|
} else
|
||||||
|
if(lfs.exists("/greenscsi.cfg")) {
|
||||||
|
execscript((char*)"/nv/greenscsi.cfg");
|
||||||
|
execLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan for images if we haven't defined any targets yet.
|
// Scan for images if we haven't defined any targets yet.
|
||||||
|
@ -911,3 +1018,235 @@ void BusFreePhaseHandler() {
|
||||||
// Reset back to waiting for selection phase.
|
// Reset back to waiting for selection phase.
|
||||||
m_phase = PHASE_SELECTION;
|
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();
|
||||||
|
}
|
|
@ -497,6 +497,10 @@ void OpticalReadCapacityCommandHandler() {
|
||||||
LOGN("[ReadCapacity]");
|
LOGN("[ReadCapacity]");
|
||||||
if(!m_sel) {
|
if(!m_sel) {
|
||||||
m_sts |= STATUS_CHECK; // Image file absent
|
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;
|
m_phase = PHASE_STATUSIN;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
135
src/scsibus.ino
135
src/scsibus.ino
|
@ -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.
|
* Data out phase.
|
||||||
* len block read
|
* len block read
|
||||||
|
@ -275,6 +324,50 @@ void readDataPhaseSD(uint32_t adds, uint32_t len)
|
||||||
m_sel->m_file.flush();
|
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.
|
* Data out phase.
|
||||||
|
@ -287,12 +380,54 @@ void verifyDataPhaseSD(uint32_t adds, uint32_t len)
|
||||||
#endif
|
#endif
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
|
|
||||||
|
//LOGN("DATAOUT PHASE(SD)");
|
||||||
uint32_t pos = adds * m_sel->m_blocksize;
|
uint32_t pos = adds * m_sel->m_blocksize;
|
||||||
m_sel->m_file.seek(pos);
|
m_sel->m_file.seek(pos);
|
||||||
SET_MSG_INACTIVE();
|
SET_MSG_INACTIVE();
|
||||||
SET_CD_INACTIVE();
|
SET_CD_INACTIVE();
|
||||||
SET_IO_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) {
|
while(i < len) {
|
||||||
#if WRITE_SPEED_OPTIMIZE
|
#if WRITE_SPEED_OPTIMIZE
|
||||||
if((len-i) >= bigread) {
|
if((len-i) >= bigread) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user