bluescsi.ini support enabled for some features

MegaSTE Mode
Per SCSI device Product/Vendor/Revision

bunch of text refactoring for brievity and byteshaving
some reorg of the SD card info printed in the log
other little bits here and there
This commit is contained in:
Troy 2022-12-22 17:45:20 -05:00
parent c2c4b83925
commit 5bad53008a
2 changed files with 166 additions and 140 deletions

View File

@ -52,6 +52,7 @@
#include "scsi_sense.h" #include "scsi_sense.h"
#include "scsi_status.h" #include "scsi_status.h"
#include "scsi_mode.h" #include "scsi_mode.h"
#include <minIni.h>
#ifdef USE_STM32_DMA #ifdef USE_STM32_DMA
#warning "warning USE_STM32_DMA" #warning "warning USE_STM32_DMA"
@ -64,16 +65,10 @@ FsFile LOG_FILE;
volatile bool m_isBusReset = false; // Bus reset volatile bool m_isBusReset = false; // Bus reset
volatile bool m_resetJmp = false; // Call longjmp on reset volatile bool m_resetJmp = false; // Call longjmp on reset
jmp_buf m_resetJmpBuf; jmp_buf m_resetJmpBuf;
byte scsi_id_mask; // Mask list of responding SCSI IDs byte scsi_id_mask; // Mask list of responding SCSI IDs
byte m_id; // Currently responding SCSI-ID
byte m_lun; // Logical unit number currently responding
byte m_sts; // Status byte
byte m_msg; // Message bytes
byte m_buf[MAX_BLOCKSIZE]; // General purpose buffer byte m_buf[MAX_BLOCKSIZE]; // General purpose buffer
byte m_scsi_buf[SCSI_BUF_SIZE]; // Buffer for SCSI READ/WRITE Buffer byte m_scsi_buf[SCSI_BUF_SIZE]; // Buffer for SCSI READ/WRITE Buffer
unsigned m_scsi_buf_size = 0;
byte m_msb[256]; // Command storage bytes
SCSI_DEVICE scsi_device_list[NUM_SCSIID][NUM_SCSILUN]; // Maximum number SCSI_DEVICE scsi_device_list[NUM_SCSIID][NUM_SCSILUN]; // Maximum number
SCSI_INQUIRY_DATA default_hdd, default_optical; SCSI_INQUIRY_DATA default_hdd, default_optical;
@ -112,7 +107,7 @@ static void LBAtoMSF(const uint32_t lba, byte *msf);
static void flashError(const unsigned error); static void flashError(const unsigned error);
void onBusReset(void); void onBusReset(void);
void initFileLog(int); void initFileLog(void);
void finalizeFileLog(void); void finalizeFileLog(void);
void findDriveImages(FsFile root); void findDriveImages(FsFile root);
@ -132,67 +127,106 @@ inline byte readIO(void)
return bret; return bret;
} }
// If config file exists, read the first three lines and copy the contents. // Read config file for per device settings
// File must be well formed or you will get junk in the SCSI Vendor fields. void readSCSIDeviceConfig(uint8_t scsi_id, SCSI_DEVICE *dev) {
void readSCSIDeviceConfig(SCSI_DEVICE *dev) { SCSI_INQUIRY_DATA *iq = &dev->inquiry_block;
FsFile config_file = SD.open("scsi-config.txt", O_RDONLY); char section[6] = {'S', 'C', 'S', 'I', 0, 0};
if (!config_file.isOpen()) { FsFile config_file;
char *buf = (char *)&m_scsi_buf;
// check for bluescsi.ini
if(!SD.exists(BLUESCSI_INI)) {
return; return;
} }
SCSI_INQUIRY_DATA *iq = dev->inquiry_block;
char vendor[9]; // create section name from id
memset(vendor, 0, sizeof(vendor)); section[4] = INT_TO_CHAR(scsi_id);
config_file.readBytes(vendor, sizeof(vendor));
LOG_FILE.print("SCSI VENDOR: ");
LOG_FILE.println(vendor);
memcpy(&iq->vendor, vendor, 8);
char product[17]; switch(ini_getl(section, "type", 99, BLUESCSI_INI))
memset(product, 0, sizeof(product)); {
config_file.readBytes(product, sizeof(product)); case 0:
LOG_FILE.print("SCSI PRODUCT: "); dev->m_type = SCSI_DEVICE_HDD;
LOG_FILE.println(product); memcpy(iq, &default_hdd, sizeof(default_hdd));
memcpy(&iq->product, product, 16); LOG_FILE.println("Forced HDD");
break;
char version[5]; case 2:
memset(version, 0, sizeof(version)); dev->m_type = SCSI_DEVICE_OPTICAL;
config_file.readBytes(version, sizeof(version)); memcpy(iq, &default_optical, sizeof(default_optical));
LOG_FILE.print("SCSI VERSION: "); LOG_FILE.println("Forced Optical");
LOG_FILE.println(version); break;
memcpy(&iq->revision, version, 4);
config_file.close(); case 99:
// default, do nothing at all
break;
default:
LOG_FILE.println("Unsupported override type");
}
if(ini_gets(section, "vendor", NULL, buf, SCSI_BUF_SIZE, BLUESCSI_INI)) {
memcpy(iq->vendor, buf, SCSI_VENDOR_LENGTH);
LOG_FILE.print("vendor:");
LOG_FILE.println(buf);
}
if(ini_gets(section, "product", NULL, buf, SCSI_BUF_SIZE, BLUESCSI_INI)) {
memcpy(iq->product, buf, SCSI_PRODUCT_LENGTH);
LOG_FILE.print("product:");
LOG_FILE.println(buf);
}
if(ini_gets(section, "revision", NULL, buf, SCSI_BUF_SIZE, BLUESCSI_INI)) {
memcpy(iq->revision, buf, SCSI_REVISION_LENGTH);
LOG_FILE.print("revision:");
LOG_FILE.println(buf);
}
} }
// read SD information and print to logfile // read SD information and print to logfile
void readSDCardInfo() void readSDCardInfo(int success_mhz)
{ {
cid_t sd_cid; cid_t sd_cid;
LOG_FILE.println("SDCard Info:");
LOG_FILE.print(" Format:");
switch(SD.vol()->fatType()) {
case FAT_TYPE_EXFAT:
LOG_FILE.println("exFAT");
break;
default:
LOG_FILE.print("FAT32/16/12 - exFAT may improve performance");
}
LOG_FILE.print("SPI speed: ");
LOG_FILE.print(success_mhz);
LOG_FILE.println("Mhz");
LOG_FILE.print(" Max Filename Length:");
LOG_FILE.println(MAX_FILE_PATH);
if(SD.card()->readCID(&sd_cid)) if(SD.card()->readCID(&sd_cid))
{ {
LOG_FILE.print("Sd MID:"); LOG_FILE.print(" MID:");
LOG_FILE.print(sd_cid.mid, 16); LOG_FILE.print(sd_cid.mid, 16);
LOG_FILE.print(" OID:"); LOG_FILE.print(" OID:");
LOG_FILE.print(sd_cid.oid[0]); LOG_FILE.print(sd_cid.oid[0]);
LOG_FILE.println(sd_cid.oid[1]); LOG_FILE.println(sd_cid.oid[1]);
LOG_FILE.print("Sd Name:"); LOG_FILE.print(" Name:");
LOG_FILE.print(sd_cid.pnm[0]); LOG_FILE.print(sd_cid.pnm[0]);
LOG_FILE.print(sd_cid.pnm[1]); LOG_FILE.print(sd_cid.pnm[1]);
LOG_FILE.print(sd_cid.pnm[2]); LOG_FILE.print(sd_cid.pnm[2]);
LOG_FILE.print(sd_cid.pnm[3]); LOG_FILE.print(sd_cid.pnm[3]);
LOG_FILE.println(sd_cid.pnm[4]); LOG_FILE.print(sd_cid.pnm[4]);
LOG_FILE.print("Sd Date:"); LOG_FILE.print(" Date:");
LOG_FILE.print(sd_cid.mdtMonth()); LOG_FILE.print(sd_cid.mdtMonth());
LOG_FILE.print("/"); LOG_FILE.print("/");
LOG_FILE.println(sd_cid.mdtYear()); LOG_FILE.println(sd_cid.mdtYear());
LOG_FILE.print("Sd Serial:"); LOG_FILE.print(" Serial:");
LOG_FILE.println(sd_cid.psn()); LOG_FILE.println(sd_cid.psn());
LOG_FILE.sync();
} }
LOG_FILE.sync();
} }
bool VerifyISOPVD(SCSI_DEVICE *dev, unsigned sector_size, bool mode2) bool VerifyISOPVD(SCSI_DEVICE *dev, unsigned sector_size, bool mode2)
@ -202,13 +236,13 @@ bool VerifyISOPVD(SCSI_DEVICE *dev, unsigned sector_size, bool mode2)
if(mode2) seek += 8; if(mode2) seek += 8;
bool ret = false; bool ret = false;
dev->m_file->seekSet(seek); dev->m_file.seekSet(seek);
dev->m_file->read(m_buf, 2048); dev->m_file.read(m_buf, 2048);
ret = ((m_buf[0] == 1 && !strncmp((char *)&m_buf[1], "CD001", 5) && m_buf[6] == 1) || ret = ((m_buf[0] == 1 && !strncmp((char *)&m_buf[1], "CD001", 5) && m_buf[6] == 1) ||
(m_buf[8] == 1 && !strncmp((char *)&m_buf[9], "CDROM", 5) && m_buf[14] == 1)); (m_buf[8] == 1 && !strncmp((char *)&m_buf[9], "CDROM", 5) && m_buf[14] == 1));
dev->m_file->rewind(); dev->m_file.rewind();
return ret; return ret;
} }
@ -220,18 +254,19 @@ bool hddimageOpen(SCSI_DEVICE *dev, FsFile *file,int id,int lun,int blocksize)
{ {
dev->m_fileSize= 0; dev->m_fileSize= 0;
dev->m_sector_offset = 0; dev->m_sector_offset = 0;
dev->flags = 0;
dev->m_blocksize = blocksize; dev->m_blocksize = blocksize;
dev->m_rawblocksize = blocksize; dev->m_rawblocksize = blocksize;
dev->m_file = file; dev->m_file = *file;
if(!dev->m_file->isOpen()) { goto failed; } if(!dev->m_file.isOpen()) { goto failed; }
dev->m_fileSize = dev->m_file->size(); dev->m_fileSize = dev->m_file.size();
if(dev->m_fileSize < 1) { if(dev->m_fileSize < 1) {
LOG_FILE.println(" - file is 0 bytes, can not use."); LOG_FILE.println(" - file is 0 bytes, can not use.");
goto failed; goto failed;
} }
if(!dev->m_file->isContiguous()) if(!dev->m_file.isContiguous())
{ {
LOG_FILE.println(" - file is fragmented, see https://github.com/erichelgeson/BlueSCSI/wiki/Image-File-Fragmentation"); LOG_FILE.println(" - file is fragmented, see https://github.com/erichelgeson/BlueSCSI/wiki/Image-File-Fragmentation");
} }
@ -243,19 +278,18 @@ bool hddimageOpen(SCSI_DEVICE *dev, FsFile *file,int id,int lun,int blocksize)
// Borrowed from PCEM // Borrowed from PCEM
if(VerifyISOPVD(dev, CDROM_COMMON_SECTORSIZE, false)) { if(VerifyISOPVD(dev, CDROM_COMMON_SECTORSIZE, false)) {
dev->m_rawblocksize = CDROM_COMMON_SECTORSIZE; dev->m_rawblocksize = CDROM_COMMON_SECTORSIZE;
dev->m_mode2 = false; SET_DEVICE_FLAG(dev->flags, SCSI_DEVICE_FLAG_OPTICAL_MODE2);
} else if(VerifyISOPVD(dev, CDROM_RAW_SECTORSIZE, false)) { } else if(VerifyISOPVD(dev, CDROM_RAW_SECTORSIZE, false)) {
dev->m_rawblocksize = CDROM_RAW_SECTORSIZE; dev->m_rawblocksize = CDROM_RAW_SECTORSIZE;
dev->m_mode2 = false; SET_DEVICE_FLAG(dev->flags, SCSI_DEVICE_FLAG_OPTICAL_RAW);
dev->m_raw = true;
dev->m_sector_offset = 16; dev->m_sector_offset = 16;
} else if(VerifyISOPVD(dev, 2336, true)) { } else if(VerifyISOPVD(dev, 2336, true)) {
dev->m_rawblocksize = 2336; dev->m_rawblocksize = 2336;
dev->m_mode2 = true; SET_DEVICE_FLAG(dev->flags, SCSI_DEVICE_FLAG_OPTICAL_MODE2);
} else if(VerifyISOPVD(dev, CDROM_RAW_SECTORSIZE, true)) { } else if(VerifyISOPVD(dev, CDROM_RAW_SECTORSIZE, true)) {
dev->m_rawblocksize = CDROM_RAW_SECTORSIZE; dev->m_rawblocksize = CDROM_RAW_SECTORSIZE;
dev->m_mode2 = true; SET_DEVICE_FLAG(dev->flags, SCSI_DEVICE_FLAG_OPTICAL_MODE2);
dev->m_raw = true; SET_DEVICE_FLAG(dev->flags, SCSI_DEVICE_FLAG_OPTICAL_RAW);
dev->m_sector_offset = 24; dev->m_sector_offset = 24;
} else { } else {
// Last ditch effort // Last ditch effort
@ -264,7 +298,7 @@ bool hddimageOpen(SCSI_DEVICE *dev, FsFile *file,int id,int lun,int blocksize)
goto failed; goto failed;
} }
dev->m_raw = true; SET_DEVICE_FLAG(dev->flags, SCSI_DEVICE_FLAG_OPTICAL_RAW);
if(!(dev->m_fileSize % CDROM_COMMON_SECTORSIZE)) { if(!(dev->m_fileSize % CDROM_COMMON_SECTORSIZE)) {
// try a multiple of 2048 // try a multiple of 2048
@ -291,17 +325,17 @@ bool hddimageOpen(SCSI_DEVICE *dev, FsFile *file,int id,int lun,int blocksize)
LOG_FILE.println("MiB"); LOG_FILE.println("MiB");
if(dev->m_type == SCSI_DEVICE_OPTICAL) { if(dev->m_type == SCSI_DEVICE_OPTICAL) {
LOG_FILE.print(" MODE2:");LOG_FILE.print(dev->m_mode2); LOG_FILE.print(" MODE2:");LOG_FILE.print(IS_MODE2(dev->flags));
LOG_FILE.print(" BlockSize:");LOG_FILE.println(dev->m_rawblocksize); LOG_FILE.print(" BlockSize:");LOG_FILE.println(IS_RAW(dev->flags));
} }
return true; // File opened return true; // File opened
failed: failed:
dev->m_file->close(); dev->m_file.close();
dev->m_fileSize = dev->m_blocksize = 0; // no file dev->m_fileSize = dev->m_blocksize = 0; // no file
delete dev->m_file; //delete dev->m_file;
dev->m_file = NULL; //dev->m_file = NULL;
return false; return false;
} }
@ -326,15 +360,6 @@ void setup()
scsi_command_table[i] = onUnimplemented; scsi_command_table[i] = onUnimplemented;
} }
// zero all SCSI device structs
for(unsigned id = 0; id < NUM_SCSIID; id++)
{
for(unsigned lun = 0; lun < NUM_SCSILUN; lun++)
{
memset(&scsi_device_list[id][lun], 0, sizeof(SCSI_DEVICE));
}
}
// SCSI commands that just need to return ok // SCSI commands that just need to return ok
scsi_command_table[SCSI_FORMAT_UNIT4] = onNOP; scsi_command_table[SCSI_FORMAT_UNIT4] = onNOP;
scsi_command_table[SCSI_FORMAT_UNIT6] = onNOP; scsi_command_table[SCSI_FORMAT_UNIT6] = onNOP;
@ -483,22 +508,26 @@ void setup()
if(!sd_ready) { if(!sd_ready) {
#if DEBUG > 0 #if DEBUG > 0
Serial.println("SD initialization failed!"); Serial.println("SD Init failed!");
#endif #endif
flashError(ERROR_NO_SDCARD); flashError(ERROR_NO_SDCARD);
} }
initFileLog(mhz); initFileLog();
readSDCardInfo(); readSDCardInfo(mhz);
//HD image file open //HD image file open
scsi_id_mask = 0x00; scsi_id_mask = 0x00;
// Look for this file to enable MSTE_MODE if(ini_getl("SCSI", "megastemode", 0, BLUESCSI_INI))
if(SD.exists("MSTE_MODE")) { {
LOG_FILE.println("MSTE_MODE - IDs treated as LUNs"); LOG_FILE.println("MSTE_MODE - IDs treated as LUNs");
megaste_mode = true; megaste_mode = true;
} }
if(SD.exists("scsi-config.txt")) {
LOG_FILE.println("scsi-config.txt is deprecated, use bluescsi.ini");
}
// Iterate over the root path in the SD card looking for candidate image files. // Iterate over the root path in the SD card looking for candidate image files.
FsFile root; FsFile root;
@ -540,7 +569,7 @@ void setup()
void findDriveImages(FsFile root) { void findDriveImages(FsFile root) {
bool image_ready; bool image_ready;
FsFile *file = NULL; FsFile file;
char path_name[MAX_FILE_PATH+1]; char path_name[MAX_FILE_PATH+1];
root.getName(path_name, sizeof(path_name)); root.getName(path_name, sizeof(path_name));
SD.chdir(path_name); SD.chdir(path_name);
@ -564,14 +593,11 @@ void findDriveImages(FsFile root) {
} }
// Valid file, open for reading/writing. // Valid file, open for reading/writing.
file = new FsFile(SD.open(name, O_RDWR)); file = SD.open(name, O_RDWR);
if(file && file->isFile()) { if(file && file.isFile()) {
SCSI_DEVICE_TYPE device_type; SCSI_DEVICE_TYPE device_type;
if(tolower(name[1]) != 'd') { if(tolower(name[1]) != 'd') {
file->close(); file.close();
delete file;
LOG_FILE.print("Not an image: ");
LOG_FILE.println(name);
continue; continue;
} }
@ -581,10 +607,7 @@ void findDriveImages(FsFile root) {
case 'c': device_type = SCSI_DEVICE_OPTICAL; case 'c': device_type = SCSI_DEVICE_OPTICAL;
break; break;
default: default:
file->close(); file.close();
delete file;
LOG_FILE.print("Not an image: ");
LOG_FILE.println(name);
continue; continue;
} }
@ -597,7 +620,7 @@ void findDriveImages(FsFile root) {
// We only require the minimum and read in the next if provided. // We only require the minimum and read in the next if provided.
int file_name_length = strlen(name); int file_name_length = strlen(name);
if(file_name_length > 2) { // HD[N] if(file_name_length > 2) { // HD[N]
int tmp_id = name[HDIMG_ID_POS] - '0'; int tmp_id = CHAR_TO_INT(name[HDIMG_ID_POS]);
// If valid id, set it, else use default // If valid id, set it, else use default
if(tmp_id > -1 && tmp_id < 8) { if(tmp_id > -1 && tmp_id < 8) {
@ -609,7 +632,7 @@ void findDriveImages(FsFile root) {
} }
if(file_name_length > 3) { // HDN[N] if(file_name_length > 3) { // HDN[N]
int tmp_lun = name[HDIMG_LUN_POS] - '0'; int tmp_lun = CHAR_TO_INT(name[HDIMG_LUN_POS]);
// If valid lun, set it, else use default // If valid lun, set it, else use default
if(tmp_lun == 0 || tmp_lun == 1) { if(tmp_lun == 0 || tmp_lun == 1) {
@ -622,11 +645,11 @@ void findDriveImages(FsFile root) {
int blk1 = 0, blk2, blk3, blk4 = 0; int blk1 = 0, blk2, blk3, blk4 = 0;
if(file_name_length > 8) { // HD00_[111] if(file_name_length > 8) { // HD00_[111]
blk1 = name[HDIMG_BLK_POS] - '0'; blk1 = CHAR_TO_INT(name[HDIMG_BLK_POS]);
blk2 = name[HDIMG_BLK_POS+1] - '0'; blk2 = CHAR_TO_INT(name[HDIMG_BLK_POS+1]);
blk3 = name[HDIMG_BLK_POS+2] - '0'; blk3 = CHAR_TO_INT(name[HDIMG_BLK_POS+2]);
if(file_name_length > 9) // HD00_NNN[1] if(file_name_length > 9) // HD00_NNN[1]
blk4 = name[HDIMG_BLK_POS+3] - '0'; blk4 = CHAR_TO_INT(name[HDIMG_BLK_POS+3]);
} }
if(blk1 == 2 && blk2 == 5 && blk3 == 6) { if(blk1 == 2 && blk2 == 5 && blk3 == 6) {
blk = 256; blk = 256;
@ -641,7 +664,7 @@ void findDriveImages(FsFile root) {
LOG_FILE.print(" - "); LOG_FILE.print(" - ");
LOG_FILE.print(name); LOG_FILE.print(name);
dev->m_type = device_type; dev->m_type = device_type;
image_ready = hddimageOpen(dev, file, id, lun, blk); image_ready = hddimageOpen(dev, &file, id, lun, blk);
if(image_ready) { // Marked as a responsive ID if(image_ready) { // Marked as a responsive ID
scsi_id_mask |= 1<<id; scsi_id_mask |= 1<<id;
@ -649,16 +672,16 @@ void findDriveImages(FsFile root) {
{ {
case SCSI_DEVICE_HDD: case SCSI_DEVICE_HDD:
// default SCSI HDD // default SCSI HDD
dev->inquiry_block = &default_hdd; dev->inquiry_block = default_hdd;
break; break;
case SCSI_DEVICE_OPTICAL: case SCSI_DEVICE_OPTICAL:
// default SCSI CDROM // default SCSI CDROM
dev->inquiry_block = &default_optical; dev->inquiry_block = default_optical;
break; break;
} }
readSCSIDeviceConfig(dev); readSCSIDeviceConfig(id, dev);
} }
} }
} }
@ -671,32 +694,14 @@ void findDriveImages(FsFile root) {
/* /*
* Setup initialization logfile * Setup initialization logfile
*/ */
void initFileLog(int success_mhz) { void initFileLog() {
LOG_FILE = SD.open(LOG_FILENAME, O_WRONLY | O_CREAT | O_TRUNC); LOG_FILE = SD.open(LOG_FILENAME, O_WRONLY | O_CREAT | O_TRUNC);
LOG_FILE.println("BlueSCSI <-> SD - https://github.com/erichelgeson/BlueSCSI"); LOG_FILE.println("BlueSCSI https://github.com/erichelgeson/BlueSCSI");
LOG_FILE.print("VER: "); LOG_FILE.print("VER: ");
LOG_FILE.print(VERSION); LOG_FILE.print(VERSION);
LOG_FILE.println(BUILD_TAGS); LOG_FILE.println(BUILD_TAGS);
LOG_FILE.print("DEBUG:"); LOG_FILE.print("DEBUG:");
LOG_FILE.print(DEBUG); LOG_FILE.println(DEBUG);
LOG_FILE.print(" SDFAT_FILE_TYPE:");
LOG_FILE.println(SDFAT_FILE_TYPE);
LOG_FILE.print("SdFat version: ");
LOG_FILE.println(SD_FAT_VERSION_STR);
LOG_FILE.print("Sd Format: ");
switch(SD.vol()->fatType()) {
case FAT_TYPE_EXFAT:
LOG_FILE.println("exFAT");
break;
default:
LOG_FILE.print("FAT 32/16/12 - Consider formatting the SD Card with exFAT for improved performance.");
}
LOG_FILE.print("SPI speed: ");
LOG_FILE.print(success_mhz);
LOG_FILE.println("Mhz");
LOG_FILE.print("SdFat Max FileName Length: ");
LOG_FILE.println(MAX_FILE_PATH);
LOG_FILE.println("Initialized SD Card - let's go!");
LOG_FILE.sync(); LOG_FILE.sync();
} }
@ -730,7 +735,7 @@ void finalizeFileLog() {
} }
LOG_FILE.println(":"); LOG_FILE.println(":");
} }
LOG_FILE.println("Finished initialization of SCSI Devices - Entering main loop."); LOG_FILE.println("Finished configuration - Starting BlueSCSI");
LOG_FILE.sync(); LOG_FILE.sync();
#if DEBUG < 2 #if DEBUG < 2
LOG_FILE.close(); LOG_FILE.close();
@ -948,7 +953,7 @@ void writeDataPhaseSD(SCSI_DEVICE *dev, uint32_t adds, uint32_t len)
SCSI_PHASE_CHANGE(SCSI_PHASE_DATAIN); SCSI_PHASE_CHANGE(SCSI_PHASE_DATAIN);
//Bus settle delay 400ns, file.seek() measured at over 1000ns. //Bus settle delay 400ns, file.seek() measured at over 1000ns.
uint64_t pos = (uint64_t)adds * dev->m_rawblocksize; uint64_t pos = (uint64_t)adds * dev->m_rawblocksize;
dev->m_file->seekSet(pos); dev->m_file.seekSet(pos);
#ifdef XCVR #ifdef XCVR
TRANSCEIVER_IO_SET(vTR_DBP,TR_OUTPUT) TRANSCEIVER_IO_SET(vTR_DBP,TR_OUTPUT)
#endif #endif
@ -957,7 +962,7 @@ void writeDataPhaseSD(SCSI_DEVICE *dev, uint32_t adds, uint32_t len)
for(uint32_t i = 0; i < len; i++) { for(uint32_t i = 0; i < len; i++) {
// Asynchronous reads will make it faster ... // Asynchronous reads will make it faster ...
m_resetJmp = false; m_resetJmp = false;
dev->m_file->read(m_buf, dev->m_rawblocksize); dev->m_file.read(m_buf, dev->m_rawblocksize);
enableResetJmp(); enableResetJmp();
writeDataLoop(dev->m_blocksize, &m_buf[dev->m_sector_offset]); writeDataLoop(dev->m_blocksize, &m_buf[dev->m_sector_offset]);
@ -1029,18 +1034,18 @@ void readDataPhaseSD(SCSI_DEVICE *dev, uint32_t adds, uint32_t len)
//Bus settle delay 400ns, file.seek() measured at over 1000ns. //Bus settle delay 400ns, file.seek() measured at over 1000ns.
uint64_t pos = (uint64_t)adds * dev->m_blocksize; uint64_t pos = (uint64_t)adds * dev->m_blocksize;
dev->m_file->seekSet(pos); dev->m_file.seekSet(pos);
for(uint32_t i = 0; i < len; i++) { for(uint32_t i = 0; i < len; i++) {
m_resetJmp = true; m_resetJmp = true;
readDataLoop(dev->m_blocksize, m_buf); readDataLoop(dev->m_blocksize, m_buf);
m_resetJmp = false; m_resetJmp = false;
dev->m_file->write(m_buf, dev->m_blocksize); dev->m_file.write(m_buf, dev->m_blocksize);
// If a reset happened while writing, break and let the flush happen before it is handled. // If a reset happened while writing, break and let the flush happen before it is handled.
if (m_isBusReset) { if (m_isBusReset) {
break; break;
} }
} }
dev->m_file->flush(); dev->m_file.flush();
enableResetJmp(); enableResetJmp();
} }
@ -1055,7 +1060,7 @@ void verifyDataPhaseSD(SCSI_DEVICE *dev, uint32_t adds, uint32_t len)
//Bus settle delay 400ns, file.seek() measured at over 1000ns. //Bus settle delay 400ns, file.seek() measured at over 1000ns.
uint64_t pos = (uint64_t)adds * dev->m_blocksize; uint64_t pos = (uint64_t)adds * dev->m_blocksize;
dev->m_file->seekSet(pos); dev->m_file.seekSet(pos);
for(uint32_t i = 0; i < len; i++) { for(uint32_t i = 0; i < len; i++) {
readDataLoop(dev->m_blocksize, m_buf); readDataLoop(dev->m_blocksize, m_buf);
// This has just gone through the transfer to make things work, a compare would go here. // This has just gone through the transfer to make things work, a compare would go here.
@ -1079,6 +1084,12 @@ void MsgIn2(int msg)
*/ */
void loop() void loop()
{ {
byte m_id = 0; // Currently responding SCSI-ID
byte m_lun = 0xff; // Logical unit number currently responding
byte m_sts = 0; // Status byte
byte m_msg = 0; // Message bytes
byte m_msb[256]; // Command storage bytes
#ifdef XCVR #ifdef XCVR
// Reset all DB and Target pins, switch transceivers to input // Reset all DB and Target pins, switch transceivers to input
// Precaution against bugs or jumps which don't clean up properly // Precaution against bugs or jumps which don't clean up properly
@ -1088,9 +1099,6 @@ void loop()
TRANSCEIVER_IO_SET(vTR_INITIATOR,TR_INPUT) TRANSCEIVER_IO_SET(vTR_INITIATOR,TR_INPUT)
#endif #endif
//int msg = 0;
m_msg = 0;
m_lun = 0xff;
SCSI_DEVICE *dev = (SCSI_DEVICE *)0; // HDD image for current SCSI-ID, LUN SCSI_DEVICE *dev = (SCSI_DEVICE *)0; // HDD image for current SCSI-ID, LUN
do {} while( SCSI_IN(vBSY) || !SCSI_IN(vSEL) || SCSI_IN(vRST)); do {} while( SCSI_IN(vBSY) || !SCSI_IN(vSEL) || SCSI_IN(vRST));
@ -1255,16 +1263,16 @@ void loop()
LOGN("onInquiry - InvalidLUN"); LOGN("onInquiry - InvalidLUN");
dev = &(scsi_device_list[m_id][0]); dev = &(scsi_device_list[m_id][0]);
byte temp = dev->inquiry_block->raw[0]; byte temp = dev->inquiry_block.raw[0];
// If the LUN is invalid byte 0 of inquiry block needs to be 7fh // If the LUN is invalid byte 0 of inquiry block needs to be 7fh
dev->inquiry_block->raw[0] = 0x7f; dev->inquiry_block.raw[0] = 0x7f;
// only write back what was asked for // only write back what was asked for
writeDataPhase(cmd[4], dev->inquiry_block->raw); writeDataPhase(cmd[4], dev->inquiry_block.raw);
// return it back to normal if it was altered // return it back to normal if it was altered
dev->inquiry_block->raw[0] = temp; dev->inquiry_block.raw[0] = temp;
} }
else if(cmd[0] == SCSI_REQUEST_SENSE) else if(cmd[0] == SCSI_REQUEST_SENSE)
{ {
@ -1290,7 +1298,7 @@ void loop()
} }
dev = &(scsi_device_list[m_id][m_lun]); dev = &(scsi_device_list[m_id][m_lun]);
if(!dev->m_file) if(!dev->m_file.isOpen())
{ {
dev->m_senseKey = SCSI_SENSE_ILLEGAL_REQUEST; dev->m_senseKey = SCSI_SENSE_ILLEGAL_REQUEST;
dev->m_additional_sense_code = SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED; dev->m_additional_sense_code = SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED;
@ -1359,7 +1367,7 @@ static byte onNOP(SCSI_DEVICE *dev, const byte *cdb)
*/ */
byte onInquiry(SCSI_DEVICE *dev, const byte *cdb) byte onInquiry(SCSI_DEVICE *dev, const byte *cdb)
{ {
writeDataPhase(cdb[4] < 47 ? cdb[4] : 47, dev->inquiry_block->raw); writeDataPhase(cdb[4] < 47 ? cdb[4] : 47, dev->inquiry_block.raw);
return SCSI_STATUS_GOOD; return SCSI_STATUS_GOOD;
} }
@ -1891,7 +1899,7 @@ byte onWriteBuffer(SCSI_DEVICE *dev, const byte *cdb)
byte onReadBuffer(SCSI_DEVICE *dev, const byte *cdb) byte onReadBuffer(SCSI_DEVICE *dev, const byte *cdb)
{ {
byte mode = cdb[1] & 7; byte mode = cdb[1] & 7;
uint32_t allocLength = ((uint32_t)cdb[6] << 16) | ((uint32_t)cdb[7] << 8) | cdb[8]; unsigned m_scsi_buf_size = 0;
LOGN("-ReadBuffer"); LOGN("-ReadBuffer");
LOGHEXN(mode); LOGHEXN(mode);
@ -1911,6 +1919,7 @@ byte onReadBuffer(SCSI_DEVICE *dev, const byte *cdb)
writeDataPhase(4 + m_scsi_buf_size, m_buf); writeDataPhase(4 + m_scsi_buf_size, m_buf);
#if DEBUG > 0 #if DEBUG > 0
uint32_t allocLength = ((uint32_t)cdb[6] << 16) | ((uint32_t)cdb[7] << 8) | cdb[8];
for (unsigned i = 0; i < allocLength; i++) { for (unsigned i = 0; i < allocLength; i++) {
LOGHEX(m_scsi_buf[i]);LOG(" "); LOGHEX(m_scsi_buf[i]);LOG(" ");
} }

View File

@ -15,6 +15,11 @@
#define SCSI_BUF_SIZE 512 // Size of the SCSI Buffer #define SCSI_BUF_SIZE 512 // Size of the SCSI Buffer
#define HDD_BLOCK_SIZE 512 #define HDD_BLOCK_SIZE 512
#define OPTICAL_BLOCK_SIZE 2048 #define OPTICAL_BLOCK_SIZE 2048
#define BLUESCSI_INI "bluescsi.ini"
#define SCSI_VENDOR_LENGTH 8
#define SCSI_PRODUCT_LENGTH 16
#define SCSI_REVISION_LENGTH 4
// HDD format // HDD format
#define MAX_BLOCKSIZE 4096 // Maximum BLOCK size #define MAX_BLOCKSIZE 4096 // Maximum BLOCK size
@ -32,6 +37,18 @@ enum SCSI_DEVICE_TYPE
SCSI_DEVICE_OPTICAL, SCSI_DEVICE_OPTICAL,
}; };
#define SCSI_DEVICE_FLAG_OPTICAL_MODE2 0x1
#define SCSI_DEVICE_FLAG_OPTICAL_RAW 0x2
#define SET_DEVICE_FLAG(var, flag) (var |= flag)
#define UNSET_DEVICE_FLAG(var, flag) (var &= ~flag)
#define IS_DEVICE_FLAG_SET(var, flag) ((var & flag) == flag)
#define IS_RAW(var) IS_DEVICE_FLAG_SET(var, SCSI_DEVICE_FLAG_OPTICAL_RAW)
#define IS_MODE2(var) IS_DEVICE_FLAG_SET(var, SCSI_DEVICE_FLAG_OPTICAL_MODE2)
#define INT_TO_CHAR(var) var+'0'
#define CHAR_TO_INT(var) var-'0'
#define CDROM_RAW_SECTORSIZE 2352 #define CDROM_RAW_SECTORSIZE 2352
#define CDROM_COMMON_SECTORSIZE 2048 #define CDROM_COMMON_SECTORSIZE 2048
@ -124,7 +141,7 @@ enum SCSI_DEVICE_TYPE
// SCSI output pin control: opendrain active LOW (direct pin drive) // SCSI output pin control: opendrain active LOW (direct pin drive)
#define SCSI_OUT(VPIN,ACTIVE) { GPIOREG(VPIN)->BSRR = BITMASK(VPIN)<<((ACTIVE)?16:0); } #define SCSI_OUT(VPIN,ACTIVE) { GPIOREG(VPIN)->BSRR = BITMASK(VPIN)<<((ACTIVE)?16:0); }
// SCSI input pin check (inactive=0,avtive=1) // SCSI input pin check (inactive=0,active=1)
#define SCSI_IN(VPIN) ((~GPIOREG(VPIN)->IDR>>(VPIN&15))&1) #define SCSI_IN(VPIN) ((~GPIOREG(VPIN)->IDR>>(VPIN&15))&1)
#define NOP(x) for(unsigned _nopcount = x; _nopcount; _nopcount--) { asm("NOP"); } #define NOP(x) for(unsigned _nopcount = x; _nopcount; _nopcount--) { asm("NOP"); }
@ -231,7 +248,8 @@ enum SCSI_DEVICE_TYPE
*/ */
// Parity bit generation // Parity bit generation
#define PTY(V) (1^((V)^((V)>>1)^((V)>>2)^((V)>>3)^((V)>>4)^((V)>>5)^((V)>>6)^((V)>>7))&1) //#define PTY(V) (1^((V)^((V)>>1)^((V)>>2)^((V)>>3)^((V)>>4)^((V)>>5)^((V)>>6)^((V)>>7))&1)
#define PTY(n) ((1 ^ (n) ^ ((n)>>1) ^ ((n)>>2) ^ ((n)>>3) ^ ((n)>>4) ^ ((n)>>5) ^ ((n)>>6) ^ ((n)>>7)) & 1)
// Data byte to BSRR register setting value conversion table // Data byte to BSRR register setting value conversion table
// BSRR[31:24] = DB[7:0] // BSRR[31:24] = DB[7:0]
@ -263,7 +281,7 @@ uint32_t db_bsrr[256];
struct SCSI_INQUIRY_DATA typedef struct _SCSI_INQUIRY_DATA
{ {
union union
{ {
@ -306,23 +324,22 @@ struct SCSI_INQUIRY_DATA
// raw bytes // raw bytes
byte raw[64]; byte raw[64];
}; };
}; } SCSI_INQUIRY_DATA;
// HDD image // HDD image
typedef __attribute__((aligned(4))) struct _SCSI_DEVICE typedef __attribute__((aligned(4))) struct _SCSI_DEVICE
{ {
FsFile *m_file; // File object FsFile m_file; // File object
uint64_t m_fileSize; // File size uint64_t m_fileSize; // File size
uint16_t m_blocksize; // SCSI BLOCK size uint16_t m_blocksize; // SCSI BLOCK size
uint16_t m_rawblocksize; // OPTICAL raw sector size uint16_t m_rawblocksize; // OPTICAL raw sector size
uint8_t m_type; // SCSI device type uint8_t m_type; // SCSI device type
uint32_t m_blockcount; // blockcount uint32_t m_blockcount; // blockcount
bool m_raw; // Raw disk SCSI_INQUIRY_DATA inquiry_block; // SCSI information
SCSI_INQUIRY_DATA *inquiry_block; // SCSI information
uint8_t m_senseKey; // Sense key uint8_t m_senseKey; // Sense key
uint16_t m_additional_sense_code; // ASC/ASCQ uint16_t m_additional_sense_code; // ASC/ASCQ
bool m_mode2; // MODE2 CDROM
uint8_t m_sector_offset; // optical sector offset for missing sync header uint8_t m_sector_offset; // optical sector offset for missing sync header
uint8_t flags; // various device flags
} SCSI_DEVICE; } SCSI_DEVICE;
static byte cdb_len_lookup[] = { static byte cdb_len_lookup[] = {