mirror of
https://github.com/erichelgeson/BlueSCSI.git
synced 2025-07-17 22:24:02 +00:00
Compare commits
28 Commits
prerelease
...
main
Author | SHA1 | Date | |
---|---|---|---|
|
bf5823468a | ||
|
2baa0155e1 | ||
|
3a9db99723 | ||
|
70eda86484 | ||
|
9d4207ea14 | ||
|
1d49003fe1 | ||
|
0a30396c3b | ||
|
ba06827814 | ||
|
a45af3edec | ||
|
0be37ccde0 | ||
|
e236b5b054 | ||
|
47179c5fd0 | ||
|
59c858332a | ||
|
dddb7bfc1c | ||
|
8b79df00ba | ||
|
7c9428131b | ||
|
e35bae560c | ||
|
13d7b985b7 | ||
|
27b7427301 | ||
|
98162fcd84 | ||
|
2be810e2ca | ||
|
4f7c0fe2c2 | ||
|
458617a827 | ||
|
810eae9be3 | ||
|
d67fa80cf0 | ||
|
9e746ba145 | ||
|
e0d115f33c | ||
|
27d13192b0 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,3 +3,4 @@
|
|||||||
.vscode/
|
.vscode/
|
||||||
workspace.code-workspace
|
workspace.code-workspace
|
||||||
dist/
|
dist/
|
||||||
|
hw/*/*-backups/
|
||||||
|
BIN
3D-Files/1.1/internal-50pin/bluescsi11a_kerosmacmodsv2.stl.zip
Normal file
BIN
3D-Files/1.1/internal-50pin/bluescsi11a_kerosmacmodsv2.stl.zip
Normal file
Binary file not shown.
@@ -11,9 +11,7 @@ upload_protocol = stlink
|
|||||||
; Different gcc versions produce much different binaries in terms of speed.
|
; Different gcc versions produce much different binaries in terms of speed.
|
||||||
platform_packages = platformio/toolchain-gccarmnoneeabi@1.90301.200702
|
platform_packages = platformio/toolchain-gccarmnoneeabi@1.90301.200702
|
||||||
build_flags =
|
build_flags =
|
||||||
-DARDUINO_GENERIC_STM32F103C
|
|
||||||
-DARDUINO_LIB_DISCOVERY_PHASE
|
-DARDUINO_LIB_DISCOVERY_PHASE
|
||||||
-DARDUINO=10813
|
|
||||||
-DARDUINO_ARCH_STM32
|
-DARDUINO_ARCH_STM32
|
||||||
-DDEBUG_LEVEL=DEBUG_NONE
|
-DDEBUG_LEVEL=DEBUG_NONE
|
||||||
-O2
|
-O2
|
||||||
@@ -78,9 +76,7 @@ build_flags =
|
|||||||
-D USB_MANUFACTURER="Unknown"
|
-D USB_MANUFACTURER="Unknown"
|
||||||
-D USB_PRODUCT="\"BLUEPILL_F103C8\""
|
-D USB_PRODUCT="\"BLUEPILL_F103C8\""
|
||||||
-D HAL_PCD_MODULE_ENABLED
|
-D HAL_PCD_MODULE_ENABLED
|
||||||
-DARDUINO_GENERIC_STM32F103C
|
|
||||||
-DARDUINO_LIB_DISCOVERY_PHASE
|
-DARDUINO_LIB_DISCOVERY_PHASE
|
||||||
-DARDUINO=10813
|
|
||||||
-DARDUINO_ARCH_STM32
|
-DARDUINO_ARCH_STM32
|
||||||
-DDEBUG_LEVEL=DEBUG_NONE
|
-DDEBUG_LEVEL=DEBUG_NONE
|
||||||
-O2
|
-O2
|
||||||
|
496
src/BlueSCSI.cpp
496
src/BlueSCSI.cpp
@@ -44,7 +44,7 @@
|
|||||||
// 2: Debug information output to LOG.txt (slow)
|
// 2: Debug information output to LOG.txt (slow)
|
||||||
|
|
||||||
// Log File
|
// Log File
|
||||||
#define VERSION "1.1-20221222-SNAPSHOT"
|
#define VERSION "1.1-20231117-SNAPSHOT"
|
||||||
#define LOG_FILENAME "LOG.txt"
|
#define LOG_FILENAME "LOG.txt"
|
||||||
|
|
||||||
#include "BlueSCSI.h"
|
#include "BlueSCSI.h"
|
||||||
@@ -105,10 +105,18 @@ SCSI_COMMAND_HANDLER(onReadDiscInformation);
|
|||||||
static uint32_t MSFtoLBA(const byte *msf);
|
static uint32_t MSFtoLBA(const byte *msf);
|
||||||
static void LBAtoMSF(const uint32_t lba, byte *msf);
|
static void LBAtoMSF(const uint32_t lba, byte *msf);
|
||||||
|
|
||||||
|
// BlueSCSI Toolbox Vendor Commands
|
||||||
|
SCSI_COMMAND_HANDLER(onCountFiles);
|
||||||
|
SCSI_COMMAND_HANDLER(onGetFile);
|
||||||
|
SCSI_COMMAND_HANDLER(onListFiles);
|
||||||
|
SCSI_COMMAND_HANDLER(onSendFilePrep);
|
||||||
|
SCSI_COMMAND_HANDLER(onSendFile10);
|
||||||
|
SCSI_COMMAND_HANDLER(onSendFileEnd);
|
||||||
|
|
||||||
static void flashError(const unsigned error);
|
static void flashError(const unsigned error);
|
||||||
void onBusReset(void);
|
void onBusReset(void);
|
||||||
void initFileLog(void);
|
void initFileLog(void);
|
||||||
void finalizeFileLog(void);
|
void finalizeDevices(void);
|
||||||
void findDriveImages(FsFile root);
|
void findDriveImages(FsFile root);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -130,7 +138,7 @@ inline byte readIO(void)
|
|||||||
// Read config file for per device settings
|
// Read config file for per device settings
|
||||||
void readSCSIDeviceConfig(uint8_t scsi_id, SCSI_DEVICE *dev) {
|
void readSCSIDeviceConfig(uint8_t scsi_id, SCSI_DEVICE *dev) {
|
||||||
SCSI_INQUIRY_DATA *iq = &dev->inquiry_block;
|
SCSI_INQUIRY_DATA *iq = &dev->inquiry_block;
|
||||||
char section[6] = {'S', 'C', 'S', 'I', 0, 0};
|
char section[] = "SCSI0";
|
||||||
FsFile config_file;
|
FsFile config_file;
|
||||||
char *buf = (char *)&m_scsi_buf;
|
char *buf = (char *)&m_scsi_buf;
|
||||||
|
|
||||||
@@ -139,6 +147,9 @@ void readSCSIDeviceConfig(uint8_t scsi_id, SCSI_DEVICE *dev) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG_FILE.println();
|
||||||
|
LOG_FILE.print("\t\tINI Overrides: ");
|
||||||
|
|
||||||
// create section name from id
|
// create section name from id
|
||||||
section[4] = INT_TO_CHAR(scsi_id);
|
section[4] = INT_TO_CHAR(scsi_id);
|
||||||
|
|
||||||
@@ -147,13 +158,13 @@ void readSCSIDeviceConfig(uint8_t scsi_id, SCSI_DEVICE *dev) {
|
|||||||
case 0:
|
case 0:
|
||||||
dev->m_type = SCSI_DEVICE_HDD;
|
dev->m_type = SCSI_DEVICE_HDD;
|
||||||
memcpy(iq, &default_hdd, sizeof(default_hdd));
|
memcpy(iq, &default_hdd, sizeof(default_hdd));
|
||||||
LOG_FILE.println("Forced HDD");
|
LOG_FILE.print("Forced HDD");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
dev->m_type = SCSI_DEVICE_OPTICAL;
|
dev->m_type = SCSI_DEVICE_OPTICAL;
|
||||||
memcpy(iq, &default_optical, sizeof(default_optical));
|
memcpy(iq, &default_optical, sizeof(default_optical));
|
||||||
LOG_FILE.println("Forced Optical");
|
LOG_FILE.print("Forced CDROM");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 99:
|
case 99:
|
||||||
@@ -161,25 +172,25 @@ void readSCSIDeviceConfig(uint8_t scsi_id, SCSI_DEVICE *dev) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG_FILE.println("Unsupported override type");
|
LOG_FILE.print("Unsupported type override");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ini_gets(section, "vendor", NULL, buf, SCSI_BUF_SIZE, BLUESCSI_INI)) {
|
if(ini_gets(section, "vendor", NULL, buf, SCSI_BUF_SIZE, BLUESCSI_INI)) {
|
||||||
memcpy(iq->vendor, buf, SCSI_VENDOR_LENGTH);
|
memcpy(iq->vendor, buf, SCSI_VENDOR_LENGTH);
|
||||||
LOG_FILE.print("vendor:");
|
LOG_FILE.print(" / Vendor: ");
|
||||||
LOG_FILE.println(buf);
|
LOG_FILE.print(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ini_gets(section, "product", NULL, buf, SCSI_BUF_SIZE, BLUESCSI_INI)) {
|
if(ini_gets(section, "product", NULL, buf, SCSI_BUF_SIZE, BLUESCSI_INI)) {
|
||||||
memcpy(iq->product, buf, SCSI_PRODUCT_LENGTH);
|
memcpy(iq->product, buf, SCSI_PRODUCT_LENGTH);
|
||||||
LOG_FILE.print("product:");
|
LOG_FILE.print(" / Product: ");
|
||||||
LOG_FILE.println(buf);
|
LOG_FILE.print(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ini_gets(section, "revision", NULL, buf, SCSI_BUF_SIZE, BLUESCSI_INI)) {
|
if(ini_gets(section, "revision", NULL, buf, SCSI_BUF_SIZE, BLUESCSI_INI)) {
|
||||||
memcpy(iq->revision, buf, SCSI_REVISION_LENGTH);
|
memcpy(iq->revision, buf, SCSI_REVISION_LENGTH);
|
||||||
LOG_FILE.print("revision:");
|
LOG_FILE.print(" / Revision: ");
|
||||||
LOG_FILE.println(buf);
|
LOG_FILE.print(buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,42 +199,39 @@ void readSDCardInfo(int success_mhz)
|
|||||||
{
|
{
|
||||||
cid_t sd_cid;
|
cid_t sd_cid;
|
||||||
|
|
||||||
LOG_FILE.println("SDCard Info:");
|
LOG_FILE.println("SD Card Info:");
|
||||||
LOG_FILE.print(" Format:");
|
LOG_FILE.print(" SPI Speed: ");
|
||||||
|
LOG_FILE.print(success_mhz);
|
||||||
|
LOG_FILE.println("MHz");
|
||||||
|
LOG_FILE.print(" Format: ");
|
||||||
switch(SD.vol()->fatType()) {
|
switch(SD.vol()->fatType()) {
|
||||||
case FAT_TYPE_EXFAT:
|
case FAT_TYPE_EXFAT:
|
||||||
LOG_FILE.println("exFAT");
|
LOG_FILE.println("exFAT");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG_FILE.print("FAT32/16/12 - exFAT may improve performance");
|
LOG_FILE.println("FAT32/16/12 - exFAT may improve performance");
|
||||||
}
|
}
|
||||||
LOG_FILE.print("SPI speed: ");
|
LOG_FILE.print(" Max Filename Length: ");
|
||||||
LOG_FILE.print(success_mhz);
|
|
||||||
LOG_FILE.println("Mhz");
|
|
||||||
LOG_FILE.print(" Max Filename Length:");
|
|
||||||
LOG_FILE.println(MAX_FILE_PATH);
|
LOG_FILE.println(MAX_FILE_PATH);
|
||||||
|
|
||||||
if(SD.card()->readCID(&sd_cid))
|
if(SD.card()->readCID(&sd_cid))
|
||||||
{
|
{
|
||||||
LOG_FILE.print(" 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(" Name:");
|
LOG_FILE.print(" Name: ");
|
||||||
LOG_FILE.print(sd_cid.pnm[0]);
|
for (uint8_t i = 0; i < 5; i++) {
|
||||||
LOG_FILE.print(sd_cid.pnm[1]);
|
LOG_FILE.print(sd_cid.pnm[i]);
|
||||||
LOG_FILE.print(sd_cid.pnm[2]);
|
}
|
||||||
LOG_FILE.print(sd_cid.pnm[3]);
|
|
||||||
LOG_FILE.print(sd_cid.pnm[4]);
|
|
||||||
|
|
||||||
LOG_FILE.print(" 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(" Serial:");
|
LOG_FILE.print(" Serial: ");
|
||||||
LOG_FILE.println(sd_cid.psn());
|
LOG_FILE.println(sd_cid.psn());
|
||||||
}
|
}
|
||||||
LOG_FILE.sync();
|
LOG_FILE.sync();
|
||||||
@@ -263,16 +271,16 @@ bool hddimageOpen(SCSI_DEVICE *dev, FsFile *file,int id,int lun,int blocksize)
|
|||||||
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(" ERROR: 0 byte file");
|
||||||
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(" WARNING: Fragmented, see https://github.com/erichelgeson/BlueSCSI/wiki/Image-File-Fragmentation");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dev->m_type == SCSI_DEVICE_OPTICAL) {
|
if(dev->m_type == SCSI_DEVICE_OPTICAL) {
|
||||||
LOG_FILE.print(" CDROM");
|
|
||||||
dev->m_blocksize = CDROM_COMMON_SECTORSIZE;
|
dev->m_blocksize = CDROM_COMMON_SECTORSIZE;
|
||||||
|
|
||||||
// Borrowed from PCEM
|
// Borrowed from PCEM
|
||||||
@@ -295,6 +303,7 @@ bool hddimageOpen(SCSI_DEVICE *dev, FsFile *file,int id,int lun,int blocksize)
|
|||||||
// Last ditch effort
|
// Last ditch effort
|
||||||
// size must be less than 700MB
|
// size must be less than 700MB
|
||||||
if(dev->m_fileSize > 912579600) {
|
if(dev->m_fileSize > 912579600) {
|
||||||
|
LOG_FILE.println(" ERROR: ISO too large!");
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,32 +315,29 @@ bool hddimageOpen(SCSI_DEVICE *dev, FsFile *file,int id,int lun,int blocksize)
|
|||||||
dev->m_rawblocksize = CDROM_COMMON_SECTORSIZE;
|
dev->m_rawblocksize = CDROM_COMMON_SECTORSIZE;
|
||||||
} else {
|
} else {
|
||||||
// I give up!
|
// I give up!
|
||||||
LOG_FILE.println(" InvalidISO");
|
LOG_FILE.println(" ERROR: Invalid ISO!");
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
LOG_FILE.print(" HDD");
|
|
||||||
}
|
}
|
||||||
dev->m_blockcount = dev->m_fileSize / dev->m_blocksize;
|
dev->m_blockcount = dev->m_fileSize / dev->m_blocksize;
|
||||||
|
|
||||||
// check blocksize dummy file
|
// check blocksize dummy file
|
||||||
LOG_FILE.print(" / ");
|
LOG_FILE.print(" File size: ");
|
||||||
LOG_FILE.print(dev->m_fileSize);
|
LOG_FILE.print(dev->m_fileSize);
|
||||||
LOG_FILE.print("bytes / ");
|
LOG_FILE.print(" bytes, ");
|
||||||
LOG_FILE.print(dev->m_fileSize / 1024);
|
LOG_FILE.print(dev->m_fileSize / 1024);
|
||||||
LOG_FILE.print("KiB / ");
|
LOG_FILE.print("KiB, ");
|
||||||
LOG_FILE.print(dev->m_fileSize / 1024 / 1024);
|
LOG_FILE.print(dev->m_fileSize / 1024 / 1024);
|
||||||
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(IS_MODE2(dev->flags));
|
LOG_FILE.print(" MODE2: ");LOG_FILE.print(IS_MODE2(dev->flags));
|
||||||
LOG_FILE.print(" BlockSize:");LOG_FILE.println(IS_RAW(dev->flags));
|
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;
|
||||||
@@ -394,6 +400,14 @@ void setup()
|
|||||||
scsi_command_table[SCSI_READ_DVD_STRUCTURE] = onReadDVDStructure;
|
scsi_command_table[SCSI_READ_DVD_STRUCTURE] = onReadDVDStructure;
|
||||||
scsi_command_table[SCSI_READ_DISC_INFORMATION] = onReadDiscInformation;
|
scsi_command_table[SCSI_READ_DISC_INFORMATION] = onReadDiscInformation;
|
||||||
|
|
||||||
|
// BlueSCSI Toolbox Commands
|
||||||
|
scsi_command_table[BLUESCSI_COUNT_FILES] = onCountFiles;
|
||||||
|
scsi_command_table[BLUESCSI_GET_FILE] = onGetFile;
|
||||||
|
scsi_command_table[BLUESCSI_LIST_FILES] = onListFiles;
|
||||||
|
scsi_command_table[BLUESCSI_SEND_PREP] = onSendFilePrep;
|
||||||
|
scsi_command_table[BLUESCSI_SEND] = onSendFile10;
|
||||||
|
scsi_command_table[BLUESCSI_SEND_END] = onSendFileEnd;
|
||||||
|
|
||||||
// clear and initialize default inquiry blocks
|
// clear and initialize default inquiry blocks
|
||||||
// default SCSI HDD
|
// default SCSI HDD
|
||||||
memset(&default_hdd, 0, sizeof(default_hdd));
|
memset(&default_hdd, 0, sizeof(default_hdd));
|
||||||
@@ -426,15 +440,15 @@ void setup()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// PIN initialization
|
// PIN initialization
|
||||||
gpio_mode(LED2, GPIO_OUTPUT_PP);
|
gpio_mode(LED2, LED2_MODE);
|
||||||
gpio_mode(LED, GPIO_OUTPUT_OD);
|
gpio_mode(LED, LED_MODE);
|
||||||
|
|
||||||
// Image Set Select Init
|
// Image Set Select Init
|
||||||
gpio_mode(IMAGE_SELECT1, GPIO_INPUT_PU);
|
gpio_mode(IMAGE_SELECT1, GPIO_INPUT_PU);
|
||||||
gpio_mode(IMAGE_SELECT2, GPIO_INPUT_PU);
|
gpio_mode(IMAGE_SELECT2, GPIO_INPUT_PU);
|
||||||
pinMode(IMAGE_SELECT1, INPUT);
|
// pinMode(IMAGE_SELECT1, INPUT);
|
||||||
pinMode(IMAGE_SELECT2, INPUT);
|
// pinMode(IMAGE_SELECT2, INPUT);
|
||||||
int image_file_set = ((digitalRead(IMAGE_SELECT1) == LOW) ? 1 : 0) | ((digitalRead(IMAGE_SELECT2) == LOW) ? 2 : 0);
|
int image_file_set = (isLow(gpio_read(IMAGE_SELECT1)) ? 1 : 0) | (isLow(gpio_read(IMAGE_SELECT2)) ? 2 : 0);
|
||||||
|
|
||||||
LED_OFF();
|
LED_OFF();
|
||||||
|
|
||||||
@@ -447,12 +461,12 @@ void setup()
|
|||||||
TRANSCEIVER_IO_SET(vTR_INITIATOR,TR_INPUT);
|
TRANSCEIVER_IO_SET(vTR_INITIATOR,TR_INPUT);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//GPIO(SCSI BUS)Initialization
|
// GPIO(SCSI BUS)Initialization
|
||||||
//Port setting register (lower)
|
// Port setting register (lower)
|
||||||
// GPIOB->regs->CRL |= 0x000000008; // SET INPUT W/ PUPD on PAB-PB0
|
// GPIOB->regs->CRL |= 0x000000008; // SET INPUT W/ PUPD on PAB-PB0
|
||||||
//Port setting register (upper)
|
// Port setting register (upper)
|
||||||
//GPIOB->regs->CRH = 0x88888888; // SET INPUT W/ PUPD on PB15-PB8
|
// GPIOB->regs->CRH = 0x88888888; // SET INPUT W/ PUPD on PB15-PB8
|
||||||
// GPIOB->regs->ODR = 0x0000FF00; // SET PULL-UPs on PB15-PB8
|
// GPIOB->regs->ODR = 0x0000FF00; // SET PULL-UPs on PB15-PB8
|
||||||
// DB and DP are input modes
|
// DB and DP are input modes
|
||||||
SCSI_DB_INPUT()
|
SCSI_DB_INPUT()
|
||||||
|
|
||||||
@@ -512,37 +526,40 @@ void setup()
|
|||||||
#endif
|
#endif
|
||||||
flashError(ERROR_NO_SDCARD);
|
flashError(ERROR_NO_SDCARD);
|
||||||
}
|
}
|
||||||
|
|
||||||
initFileLog();
|
initFileLog();
|
||||||
readSDCardInfo(mhz);
|
readSDCardInfo(mhz);
|
||||||
|
|
||||||
//HD image file open
|
// HD image file open
|
||||||
scsi_id_mask = 0x00;
|
scsi_id_mask = 0x00;
|
||||||
|
|
||||||
|
if(SD.exists("scsi-config.txt")) {
|
||||||
|
LOG_FILE.print("scsi-config.txt is deprecated, use ");
|
||||||
|
LOG_FILE.println(BLUESCSI_INI);
|
||||||
|
}
|
||||||
|
|
||||||
if(ini_getl("SCSI", "MapLunsToIDs", 0, BLUESCSI_INI))
|
if(ini_getl("SCSI", "MapLunsToIDs", 0, BLUESCSI_INI))
|
||||||
{
|
{
|
||||||
LOG_FILE.println("IDs treated as LUNs for ID0");
|
|
||||||
ids_as_luns = true;
|
ids_as_luns = true;
|
||||||
}
|
LOG_FILE.println("Treating IDs as LUNs on ID0");
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
char image_set_dir_name[] = "/ImageSetX/";
|
char image_set_dir_name[] = "/ImageSetX/";
|
||||||
image_set_dir_name[9] = char(image_file_set) + 0x30;
|
image_set_dir_name[9] = INT_TO_CHAR(image_file_set);
|
||||||
root.open(image_set_dir_name);
|
root.open(image_set_dir_name);
|
||||||
if (root.isDirectory()) {
|
|
||||||
LOG_FILE.print("Looking for images in: ");
|
LOG_FILE.print("Looking for images in: ");
|
||||||
|
if (root.isDirectory()) {
|
||||||
LOG_FILE.println(image_set_dir_name);
|
LOG_FILE.println(image_set_dir_name);
|
||||||
LOG_FILE.sync();
|
|
||||||
} else {
|
} else {
|
||||||
root.close();
|
root.close();
|
||||||
root.open("/");
|
root.open("/");
|
||||||
|
LOG_FILE.println("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG_FILE.sync();
|
||||||
findDriveImages(root);
|
findDriveImages(root);
|
||||||
root.close();
|
root.close();
|
||||||
|
|
||||||
@@ -561,9 +578,9 @@ void setup()
|
|||||||
flashError(ERROR_FALSE_INIT);
|
flashError(ERROR_FALSE_INIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
finalizeFileLog();
|
finalizeDevices();
|
||||||
LED_OFF();
|
|
||||||
//Occurs when the RST pin state changes from HIGH to LOW
|
// Occurs when the RST pin state changes from HIGH to LOW
|
||||||
attachInterrupt(RST, onBusReset, FALLING);
|
attachInterrupt(RST, onBusReset, FALLING);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -579,10 +596,10 @@ void findDriveImages(FsFile root) {
|
|||||||
// Directories can not be opened RDWR, so it will fail, but fails the same way with no file/dir, so we need to peek at the file first.
|
// Directories can not be opened RDWR, so it will fail, but fails the same way with no file/dir, so we need to peek at the file first.
|
||||||
FsFile file_test = root.openNextFile(O_RDONLY);
|
FsFile file_test = root.openNextFile(O_RDONLY);
|
||||||
char name[MAX_FILE_PATH+1];
|
char name[MAX_FILE_PATH+1];
|
||||||
file_test.getName(name, MAX_FILE_PATH+1);
|
file_test.getName(name, sizeof(name));
|
||||||
|
|
||||||
// Skip directories and already open files.
|
// Skip directories and already open files.
|
||||||
if(file_test.isDir() || strncmp(name, "LOG.txt", 7) == 0) {
|
if(file_test.isDir() || strncmp(name, LOG_FILENAME, (sizeof(LOG_FILENAME) - 1)) == 0) {
|
||||||
file_test.close();
|
file_test.close();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -615,34 +632,36 @@ void findDriveImages(FsFile root) {
|
|||||||
|
|
||||||
if(file && file.isFile()) {
|
if(file && file.isFile()) {
|
||||||
// Defaults for Hard Disks
|
// Defaults for Hard Disks
|
||||||
int id = 1; // 0 and 3 are common in Macs for physical HD and CD, so avoid them.
|
int id = DEFAULT_SCSI_ID; // 0 and 3 are common in Macs for physical HD and CD, so avoid them.
|
||||||
int lun = 0;
|
int lun = DEFAULT_SCSI_LUN;
|
||||||
int blk = 512;
|
int blk = HDD_BLOCK_SIZE;
|
||||||
|
|
||||||
// Positionally read in and coerase the chars to integers.
|
LOG_FILE.print(" "); LOG_FILE.println(name);
|
||||||
|
|
||||||
|
// Positionally read in and coerce the chars to integers.
|
||||||
// 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 > HDIMG_ID_POS) { // HD[N]
|
||||||
int tmp_id = CHAR_TO_INT(name[HDIMG_ID_POS]);
|
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 <= MAX_SCSIID) {
|
||||||
id = tmp_id;
|
id = tmp_id;
|
||||||
} else {
|
} else {
|
||||||
LOG_FILE.print(name);
|
LOG_FILE.print(" WARNING: Bad SCSI ID in filename, using ID ");
|
||||||
LOG_FILE.println(" - bad SCSI id in filename, Using default ID 1");
|
LOG_FILE.println(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(file_name_length > 3) { // HDN[N]
|
if(file_name_length > HDIMG_LUN_POS) { // HDN[N]
|
||||||
int tmp_lun = CHAR_TO_INT(name[HDIMG_LUN_POS]);
|
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 > -1 && tmp_lun <= NUM_SCSILUN) {
|
||||||
lun = tmp_lun;
|
lun = tmp_lun;
|
||||||
} else {
|
} else {
|
||||||
LOG_FILE.print(name);
|
LOG_FILE.print(" WARNING: Bad SCSI LUN in filename, using LUN ");
|
||||||
LOG_FILE.println(" - bad SCSI LUN in filename, Using default LUN ID 0");
|
LOG_FILE.println(lun);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -662,10 +681,23 @@ void findDriveImages(FsFile root) {
|
|||||||
blk = 2048;
|
blk = 2048;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(id < NUM_SCSIID && lun < NUM_SCSILUN) {
|
LOG_FILE.print(" Parsed: ");
|
||||||
|
switch(device_type)
|
||||||
|
{
|
||||||
|
case SCSI_DEVICE_HDD:
|
||||||
|
LOG_FILE.print("HDD");
|
||||||
|
break;
|
||||||
|
case SCSI_DEVICE_OPTICAL:
|
||||||
|
LOG_FILE.print("CDROM");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG_FILE.print("UNKNOWN");
|
||||||
|
}
|
||||||
|
LOG_FILE.print(" ID "); LOG_FILE.print(id);
|
||||||
|
LOG_FILE.print(" LUN "); LOG_FILE.print(lun);
|
||||||
|
LOG_FILE.print(" Blocksize "); LOG_FILE.print(blk); LOG_FILE.println("k");
|
||||||
|
|
||||||
dev = &scsi_device_list[id][lun];
|
dev = &scsi_device_list[id][lun];
|
||||||
LOG_FILE.print(" - ");
|
|
||||||
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
|
||||||
@@ -683,10 +715,8 @@ void findDriveImages(FsFile root) {
|
|||||||
dev->inquiry_block = default_optical;
|
dev->inquiry_block = default_optical;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
readSCSIDeviceConfig(id, dev);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
LOG_FILE.println();
|
||||||
}
|
}
|
||||||
LOG_FILE.sync();
|
LOG_FILE.sync();
|
||||||
}
|
}
|
||||||
@@ -702,46 +732,46 @@ void initFileLog() {
|
|||||||
LOG_FILE.println("BlueSCSI 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.print(BUILD_TAGS);
|
||||||
LOG_FILE.print("DEBUG:");
|
LOG_FILE.print(" DEBUG: ");
|
||||||
LOG_FILE.println(DEBUG);
|
LOG_FILE.println(DEBUG);
|
||||||
LOG_FILE.sync();
|
LOG_FILE.sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Finalize initialization logfile
|
* Check INI file for device overrides and print summary to logfile
|
||||||
*/
|
*/
|
||||||
void finalizeFileLog() {
|
void finalizeDevices() {
|
||||||
// View support drive map
|
// View support drive map
|
||||||
LOG_FILE.print("ID");
|
LOG_FILE.println("SCSI Devices");
|
||||||
for(int lun=0;lun<NUM_SCSILUN;lun++)
|
LOG_FILE.println("ID\tLUN\tName");
|
||||||
{
|
|
||||||
LOG_FILE.print(":LUN");
|
|
||||||
LOG_FILE.print(lun);
|
|
||||||
}
|
|
||||||
LOG_FILE.println(":");
|
|
||||||
//
|
|
||||||
for(int id=0;id<NUM_SCSIID;id++)
|
for(int id=0;id<NUM_SCSIID;id++)
|
||||||
{
|
{
|
||||||
LOG_FILE.print(" ");
|
|
||||||
LOG_FILE.print(id);
|
|
||||||
for(int lun=0;lun<NUM_SCSILUN;lun++)
|
for(int lun=0;lun<NUM_SCSILUN;lun++)
|
||||||
{
|
{
|
||||||
|
LOG_FILE.print(id);
|
||||||
|
LOG_FILE.print("\t");
|
||||||
|
LOG_FILE.print(lun);
|
||||||
|
LOG_FILE.print("\t");
|
||||||
SCSI_DEVICE *dev = &scsi_device_list[id][lun];
|
SCSI_DEVICE *dev = &scsi_device_list[id][lun];
|
||||||
if( (lun<NUM_SCSILUN) && (dev->m_file))
|
if(dev->m_file)
|
||||||
{
|
{
|
||||||
LOG_FILE.print((dev->m_blocksize<1000) ? ": " : ":");
|
char name[MAX_FILE_PATH+1];
|
||||||
LOG_FILE.print(dev->m_blocksize);
|
dev->m_file.getName(name, sizeof(name));
|
||||||
|
LOG_FILE.print(name);
|
||||||
|
readSCSIDeviceConfig(id, dev);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LOG_FILE.print(":----");
|
LOG_FILE.print("-");
|
||||||
|
|
||||||
|
LOG_FILE.println();
|
||||||
}
|
}
|
||||||
LOG_FILE.println(":");
|
|
||||||
}
|
}
|
||||||
LOG_FILE.println("Finished configuration - Starting BlueSCSI");
|
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();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -808,7 +838,7 @@ void onBusReset(void)
|
|||||||
LOGN("BusReset!");
|
LOGN("BusReset!");
|
||||||
if (m_resetJmp) {
|
if (m_resetJmp) {
|
||||||
m_resetJmp = false;
|
m_resetJmp = false;
|
||||||
// Jumping out of the interrupt handler, so need to clear the interupt source.
|
// Jumping out of the interrupt handler, so need to clear the interrupt source.
|
||||||
uint8 exti = PIN_MAP[RST].gpio_bit;
|
uint8 exti = PIN_MAP[RST].gpio_bit;
|
||||||
EXTI_BASE->PR = (1U << exti);
|
EXTI_BASE->PR = (1U << exti);
|
||||||
longjmpFromInterrupt(m_resetJmpBuf, 1);
|
longjmpFromInterrupt(m_resetJmpBuf, 1);
|
||||||
@@ -1234,7 +1264,7 @@ void loop()
|
|||||||
LOG("CMD:");
|
LOG("CMD:");
|
||||||
SCSI_PHASE_CHANGE(SCSI_PHASE_COMMAND);
|
SCSI_PHASE_CHANGE(SCSI_PHASE_COMMAND);
|
||||||
// Bus settle delay 400ns. The following code was measured at 20ns before REQ asserted. Added another 380ns. STM32F103.
|
// Bus settle delay 400ns. The following code was measured at 20ns before REQ asserted. Added another 380ns. STM32F103.
|
||||||
asm("nop;nop;nop;nop;nop;nop;nop;nop");// This asm causes some code reodering, which adds 270ns, plus 8 nop cycles for an additional 110ns. STM32F103
|
asm("nop;nop;nop;nop;nop;nop;nop;nop");// This asm causes some code reordering, which adds 270ns, plus 8 nop cycles for an additional 110ns. STM32F103
|
||||||
int len;
|
int len;
|
||||||
byte cmd[20];
|
byte cmd[20];
|
||||||
|
|
||||||
@@ -1701,7 +1731,7 @@ byte onModeSense(SCSI_DEVICE *dev, const byte *cdb)
|
|||||||
m_buf[a + 0] = SCSI_SENSE_MODE_CACHING;
|
m_buf[a + 0] = SCSI_SENSE_MODE_CACHING;
|
||||||
m_buf[a + 1] = 0x0A; // Page length
|
m_buf[a + 1] = 0x0A; // Page length
|
||||||
if(pageControl != 1) {
|
if(pageControl != 1) {
|
||||||
m_buf[a + 2] = 0x01; // Disalbe Read Cache so no one asks for Cache Stats page.
|
m_buf[a + 2] = 0x01; // Disable Read Cache so no one asks for Cache Stats page.
|
||||||
}
|
}
|
||||||
a += 0x0C;
|
a += 0x0C;
|
||||||
if(pageCode != SCSI_SENSE_MODE_ALL) break;
|
if(pageCode != SCSI_SENSE_MODE_ALL) break;
|
||||||
@@ -1715,8 +1745,19 @@ byte onModeSense(SCSI_DEVICE *dev, const byte *cdb)
|
|||||||
}
|
}
|
||||||
if(pageCode != SCSI_SENSE_MODE_ALL) break;
|
if(pageCode != SCSI_SENSE_MODE_ALL) break;
|
||||||
}
|
}
|
||||||
|
case SCSI_SENSE_MODE_VENDOR_BLUESCSI:
|
||||||
|
{
|
||||||
|
const byte page42[42] = {
|
||||||
|
'B','l','u','e','S','C','S','I',' ','i','s',' ','t','h','e',' ','B','E','S','T',' ',
|
||||||
|
'S','T','O','L','E','N',' ','F','R','O','M',' ','B','L','U','E','S','C','S','I',0x00
|
||||||
|
};
|
||||||
|
m_buf[a + 0] = SCSI_SENSE_MODE_VENDOR_BLUESCSI; // Page code
|
||||||
|
m_buf[a + 1] = sizeof(page42); // Page length
|
||||||
|
memcpy(&m_buf[a + 2], page42, sizeof(page42));
|
||||||
|
a += 2 + sizeof(page42);
|
||||||
|
if(pageCode != SCSI_SENSE_MODE_ALL) break;
|
||||||
|
}
|
||||||
break; // Don't want SCSI_SENSE_MODE_ALL falling through to error condition
|
break; // Don't want SCSI_SENSE_MODE_ALL falling through to error condition
|
||||||
|
|
||||||
default:
|
default:
|
||||||
dev->m_senseKey = SCSI_SENSE_ILLEGAL_REQUEST;
|
dev->m_senseKey = SCSI_SENSE_ILLEGAL_REQUEST;
|
||||||
dev->m_additional_sense_code = SCSI_ASC_INVALID_FIELD_IN_CDB;
|
dev->m_additional_sense_code = SCSI_ASC_INVALID_FIELD_IN_CDB;
|
||||||
@@ -1802,6 +1843,221 @@ byte onModeSense(SCSI_DEVICE *dev, const byte *cdb)
|
|||||||
return SCSI_STATUS_GOOD;
|
return SCSI_STATUS_GOOD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// onListFiles
|
||||||
|
byte onListFiles(SCSI_DEVICE *dev, const byte *cdb) {
|
||||||
|
File dir;
|
||||||
|
File file;
|
||||||
|
|
||||||
|
memset(m_buf, 0, MAC_BLK_SIZE);
|
||||||
|
int ENTRY_SIZE = 40;
|
||||||
|
char name[MAX_MAC_PATH + 1];
|
||||||
|
dir.open("/shared");
|
||||||
|
dir.rewindDirectory();
|
||||||
|
uint8_t index = 0;
|
||||||
|
while (file.openNext(&dir, O_RDONLY))
|
||||||
|
{
|
||||||
|
uint8_t isDir = file.isDirectory() ? 0x00 : 0x01;
|
||||||
|
file.getName(name, MAX_MAC_PATH + 1);
|
||||||
|
uint64_t size = file.fileSize();
|
||||||
|
file.close();
|
||||||
|
if(name[0] == '.')
|
||||||
|
continue;
|
||||||
|
byte file_entry[ENTRY_SIZE] = {0};
|
||||||
|
file_entry[0] = index;
|
||||||
|
file_entry[1] = isDir;
|
||||||
|
int c = 0;
|
||||||
|
for(int i = 2; i < (MAX_MAC_PATH + 1 + 2); i++) { // bytes 2 - 34
|
||||||
|
file_entry[i] = name[c++];
|
||||||
|
}
|
||||||
|
file_entry[35] = 0; //(size >> 32) & 0xff;
|
||||||
|
file_entry[36] = (size >> 24) & 0xff;
|
||||||
|
file_entry[37] = (size >> 16) & 0xff;
|
||||||
|
file_entry[38] = (size >> 8) & 0xff;
|
||||||
|
file_entry[39] = (size) & 0xff;
|
||||||
|
memcpy(&(m_buf[ENTRY_SIZE * index]), file_entry, ENTRY_SIZE);
|
||||||
|
index = index + 1;
|
||||||
|
}
|
||||||
|
dir.close();
|
||||||
|
writeDataPhase(MAC_BLK_SIZE, (const byte *)m_buf);
|
||||||
|
return SCSI_STATUS_GOOD;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns how many files exist in a directory so we know how many times to request list files.
|
||||||
|
byte onCountFiles(SCSI_DEVICE *dev, const byte *cdb) {
|
||||||
|
File dir;
|
||||||
|
File file;
|
||||||
|
char name[MAX_MAC_PATH + 1];
|
||||||
|
|
||||||
|
dir.open("/shared");
|
||||||
|
dir.rewindDirectory();
|
||||||
|
uint16_t index = 0;
|
||||||
|
while (file.openNext(&dir, O_RDONLY))
|
||||||
|
{
|
||||||
|
if(file.getError() > 0)
|
||||||
|
{
|
||||||
|
file.close();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
file.getName(name, MAX_MAC_PATH + 1);
|
||||||
|
file.close();
|
||||||
|
// only count valid files.
|
||||||
|
if(name[0] != '.')
|
||||||
|
index = index + 1;
|
||||||
|
}
|
||||||
|
dir.close();
|
||||||
|
|
||||||
|
if(index > 100) {
|
||||||
|
dev->m_senseKey = SCSI_SENSE_ILLEGAL_REQUEST;
|
||||||
|
dev->m_additional_sense_code = OPEN_RETRO_SCSI_TOO_MANY_FILES;
|
||||||
|
return SCSI_STATUS_CHECK_CONDITION;
|
||||||
|
}
|
||||||
|
writeDataPhase(sizeof(index), (const byte *)&index);
|
||||||
|
return SCSI_STATUS_GOOD;
|
||||||
|
}
|
||||||
|
|
||||||
|
File get_file_from_index(uint8_t index)
|
||||||
|
{
|
||||||
|
File dir;
|
||||||
|
FsFile file_test;
|
||||||
|
char name[MAX_MAC_PATH + 1];
|
||||||
|
|
||||||
|
dir.open("/shared");
|
||||||
|
dir.rewindDirectory(); // Back to the top
|
||||||
|
int count = 0;
|
||||||
|
while (file_test.openNext(&dir, O_RDONLY))
|
||||||
|
{
|
||||||
|
// If error there is no next file to open.
|
||||||
|
if(file_test.getError() > 0) {
|
||||||
|
file_test.close();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
file_test.getName(name, MAX_MAC_PATH + 1);
|
||||||
|
|
||||||
|
if(name[0] == '.')
|
||||||
|
continue;
|
||||||
|
if (count == index)
|
||||||
|
{
|
||||||
|
dir.close();
|
||||||
|
return file_test;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
file_test.close();
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
file_test.close();
|
||||||
|
dir.close();
|
||||||
|
return file_test;
|
||||||
|
}
|
||||||
|
|
||||||
|
File file; // global so we can keep it open while transferring.
|
||||||
|
byte onGetFile(SCSI_DEVICE *dev, const byte *cdb) {
|
||||||
|
uint8_t index = cdb[1];
|
||||||
|
uint32_t offset = ((uint32_t)cdb[2] << 24) | ((uint32_t)cdb[3] << 16) | ((uint32_t)cdb[4] << 8) | cdb[5];
|
||||||
|
if (offset == 0) // first time, open the file.
|
||||||
|
{
|
||||||
|
file = get_file_from_index(index);
|
||||||
|
if(!file.isDirectory() && !file.isReadable())
|
||||||
|
{
|
||||||
|
dev->m_senseKey = SCSI_SENSE_ILLEGAL_REQUEST;
|
||||||
|
dev->m_additional_sense_code = SCSI_ASC_INVALID_FIELD_IN_CDB;
|
||||||
|
return SCSI_STATUS_CHECK_CONDITION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t file_total = file.size();
|
||||||
|
memset(m_buf, 0, MAC_BLK_SIZE);
|
||||||
|
file.seekSet(offset * MAC_BLK_SIZE);
|
||||||
|
int read_bytes = file.read(m_buf, MAC_BLK_SIZE);
|
||||||
|
writeDataPhase(read_bytes, m_buf);
|
||||||
|
if(offset * MAC_BLK_SIZE >= file_total) // transfer done, close.
|
||||||
|
{
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
return SCSI_STATUS_GOOD;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Prepares a file for receiving. The file name is null terminated in the scsi data.
|
||||||
|
*/
|
||||||
|
File receveFile;
|
||||||
|
byte onSendFilePrep(SCSI_DEVICE *dev, const byte *cdb)
|
||||||
|
{
|
||||||
|
char file_name[MAX_MAC_PATH+1];
|
||||||
|
|
||||||
|
memset(file_name, '\0', MAX_MAC_PATH+1);
|
||||||
|
readDataPhase(MAX_MAC_PATH+1, m_buf);
|
||||||
|
strcpy(file_name, (char *)m_buf);
|
||||||
|
|
||||||
|
SD.chdir("/shared");
|
||||||
|
receveFile.open(file_name, FILE_WRITE);
|
||||||
|
SD.chdir("/");
|
||||||
|
if(receveFile.isOpen() && receveFile.isWritable()) {
|
||||||
|
receveFile.rewind();
|
||||||
|
receveFile.sync();
|
||||||
|
return SCSI_STATUS_GOOD;
|
||||||
|
} else {
|
||||||
|
receveFile.close();
|
||||||
|
dev->m_senseKey = SCSI_SENSE_ILLEGAL_REQUEST;
|
||||||
|
dev->m_additional_sense_code = SCSI_ASC_INVALID_FIELD_IN_CDB;
|
||||||
|
return SCSI_STATUS_CHECK_CONDITION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
byte onSendFileEnd(SCSI_DEVICE *dev, const byte *cdb)
|
||||||
|
{
|
||||||
|
receveFile.sync();
|
||||||
|
receveFile.close();
|
||||||
|
return SCSI_STATUS_GOOD;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte onSendFile10(SCSI_DEVICE *dev, const byte *cdb)
|
||||||
|
{
|
||||||
|
if(!receveFile.isOpen() || !receveFile.isWritable()) {
|
||||||
|
dev->m_senseKey = SCSI_SENSE_ILLEGAL_REQUEST;
|
||||||
|
dev->m_additional_sense_code = SCSI_ASC_INVALID_FIELD_IN_CDB;
|
||||||
|
return SCSI_STATUS_CHECK_CONDITION;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Number of bytes sent this request, 1..512.
|
||||||
|
uint16_t bytes_sent = ((uint16_t)cdb[1] << 8) | cdb[2];
|
||||||
|
// 512 byte offset of where to put these bytes.
|
||||||
|
uint32_t offset = ((uint32_t)cdb[3] << 16) | ((uint32_t)cdb[4] << 8) | cdb[5];
|
||||||
|
uint16_t buf_size = SCSI_BUF_SIZE;
|
||||||
|
// Check if last block of file, and not the only block in file.
|
||||||
|
if(bytes_sent < buf_size)
|
||||||
|
{
|
||||||
|
buf_size = bytes_sent;
|
||||||
|
}
|
||||||
|
readDataPhase(buf_size, m_buf);
|
||||||
|
receveFile.seekCur(offset * SCSI_BUF_SIZE);
|
||||||
|
receveFile.write(m_buf, buf_size);
|
||||||
|
if(receveFile.getWriteError())
|
||||||
|
{
|
||||||
|
receveFile.clearWriteError();
|
||||||
|
receveFile.close();
|
||||||
|
dev->m_senseKey = SCSI_SENSE_ILLEGAL_REQUEST;
|
||||||
|
dev->m_additional_sense_code = SCSI_ASC_INVALID_FIELD_IN_CDB;
|
||||||
|
return SCSI_STATUS_CHECK_CONDITION;
|
||||||
|
}
|
||||||
|
return SCSI_STATUS_GOOD;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read Defect Data
|
||||||
|
*/
|
||||||
|
byte onReadDefectData(SCSI_DEVICE *dev, const byte *cdb)
|
||||||
|
{
|
||||||
|
byte response[4] = {
|
||||||
|
0x0, // Reserved
|
||||||
|
cdb[2], // echo back Reserved, Plist, Glist, Defect list format
|
||||||
|
cdb[7], cdb[8] // echo back defect list length
|
||||||
|
};
|
||||||
|
writeDataPhase(4, response);
|
||||||
|
return SCSI_STATUS_GOOD;
|
||||||
|
}
|
||||||
|
|
||||||
void setBlockLength(SCSI_DEVICE *dev, uint32_t length)
|
void setBlockLength(SCSI_DEVICE *dev, uint32_t length)
|
||||||
{
|
{
|
||||||
dev->m_blocksize = dev->m_rawblocksize = length;
|
dev->m_blocksize = dev->m_rawblocksize = length;
|
||||||
@@ -1879,7 +2135,7 @@ byte onModeSelect(SCSI_DEVICE *dev, const byte *cdb)
|
|||||||
*/
|
*/
|
||||||
byte onReZeroUnit(SCSI_DEVICE *dev, const byte *cdb) {
|
byte onReZeroUnit(SCSI_DEVICE *dev, const byte *cdb) {
|
||||||
LOGN("-ReZeroUnit");
|
LOGN("-ReZeroUnit");
|
||||||
// Make sure we have an image with atleast a first byte.
|
// Make sure we have an image with at least a first byte.
|
||||||
// Actually seeking to the position wont do anything, so dont.
|
// Actually seeking to the position wont do anything, so dont.
|
||||||
return checkBlockCommand(dev, 0, 0);
|
return checkBlockCommand(dev, 0, 0);
|
||||||
}
|
}
|
||||||
@@ -1936,6 +2192,9 @@ byte onReadBuffer(SCSI_DEVICE *dev, const byte *cdb)
|
|||||||
{
|
{
|
||||||
byte mode = cdb[1] & 7;
|
byte mode = cdb[1] & 7;
|
||||||
unsigned m_scsi_buf_size = 0;
|
unsigned m_scsi_buf_size = 0;
|
||||||
|
#if DEBUG > 0
|
||||||
|
uint32_t allocLength = ((uint32_t)cdb[6] << 16) | ((uint32_t)cdb[7] << 8) | cdb[8];
|
||||||
|
#endif
|
||||||
|
|
||||||
LOGN("-ReadBuffer");
|
LOGN("-ReadBuffer");
|
||||||
LOGHEXN(mode);
|
LOGHEXN(mode);
|
||||||
@@ -1955,7 +2214,6 @@ 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(" ");
|
||||||
}
|
}
|
||||||
@@ -2004,20 +2262,6 @@ byte onSendDiagnostic(SCSI_DEVICE *dev, const byte *cdb)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Read Defect Data
|
|
||||||
*/
|
|
||||||
byte onReadDefectData(SCSI_DEVICE *dev, const byte *cdb)
|
|
||||||
{
|
|
||||||
byte response[4] = {
|
|
||||||
0x0, // Reserved
|
|
||||||
cdb[2], // echo back Reserved, Plist, Glist, Defect list format
|
|
||||||
cdb[7], cdb[8] // echo back defect list length
|
|
||||||
};
|
|
||||||
writeDataPhase(4, response);
|
|
||||||
return SCSI_STATUS_GOOD;
|
|
||||||
}
|
|
||||||
|
|
||||||
static byte onReadTOC(SCSI_DEVICE *dev, const byte *cdb)
|
static byte onReadTOC(SCSI_DEVICE *dev, const byte *cdb)
|
||||||
{
|
{
|
||||||
uint8_t msf = cdb[1] & 0x02;
|
uint8_t msf = cdb[1] & 0x02;
|
||||||
|
@@ -99,8 +99,6 @@ enum SCSI_DEVICE_TYPE
|
|||||||
#define IO PB7 // SCSI:I/O
|
#define IO PB7 // SCSI:I/O
|
||||||
|
|
||||||
#define SD_CS PA4 // SDCARD:CS
|
#define SD_CS PA4 // SDCARD:CS
|
||||||
#define LED PC13 // LED
|
|
||||||
#define LED2 PA0 // External LED
|
|
||||||
|
|
||||||
// Image Set Selector
|
// Image Set Selector
|
||||||
#ifdef XCVR
|
#ifdef XCVR
|
||||||
@@ -116,17 +114,29 @@ enum SCSI_DEVICE_TYPE
|
|||||||
#define PBREG GPIOB->regs
|
#define PBREG GPIOB->regs
|
||||||
#define PCREG GPIOC->regs
|
#define PCREG GPIOC->regs
|
||||||
|
|
||||||
// LED control
|
|
||||||
#define LED_ON() PCREG->BSRR = 0b00100000000000000000000000000000; PAREG->BSRR = 0b00000000000000000000000000000001;
|
|
||||||
#define LED_OFF() PCREG->BSRR = 0b00000000000000000010000000000000; PAREG->BSRR = 0b00000000000000010000000000000000;
|
|
||||||
|
|
||||||
// Virtual pin (Arduio compatibility is slow, so make it MCU-dependent)
|
// Virtual pin (Arduio compatibility is slow, so make it MCU-dependent)
|
||||||
#define PA(BIT) (BIT)
|
#define PA(BIT) (BIT)
|
||||||
#define PB(BIT) (BIT+16)
|
#define PB(BIT) (BIT+16)
|
||||||
|
#define PC(BIT) (BIT+32)
|
||||||
|
|
||||||
// Virtual pin decoding
|
// Virtual pin decoding
|
||||||
#define GPIOREG(VPIN) ((VPIN)>=16?PBREG:PAREG)
|
#define GPIOREG(VPIN) ((VPIN)>=16?((VPIN)>=32?PCREG:PBREG):PAREG)
|
||||||
#define BITMASK(VPIN) (1<<((VPIN)&15))
|
#define BITMASK(VPIN) (1<<((VPIN)&15))
|
||||||
|
|
||||||
|
// Built-in LED
|
||||||
|
#define LED PC13
|
||||||
|
#define vLED PC(13)
|
||||||
|
#define LED_MODE GPIO_OUTPUT_OD
|
||||||
|
|
||||||
|
// External LED
|
||||||
|
#define LED2 PA0
|
||||||
|
#define vLED2 PA(0)
|
||||||
|
#define LED2_MODE GPIO_OUTPUT_PP
|
||||||
|
|
||||||
|
// LED control
|
||||||
|
#define LED_ON() GPIOREG(vLED)->BSRR = BITMASK(vLED) << (LED_MODE == GPIO_OUTPUT_PP ? 0 : 16); GPIOREG(vLED2)->BSRR = BITMASK(vLED2) << (LED2_MODE == GPIO_OUTPUT_PP ? 0 : 16);
|
||||||
|
#define LED_OFF() GPIOREG(vLED)->BSRR = BITMASK(vLED) << (LED_MODE == GPIO_OUTPUT_PP ? 16 : 0); GPIOREG(vLED2)->BSRR = BITMASK(vLED2) << (LED2_MODE == GPIO_OUTPUT_PP ? 16 : 0);
|
||||||
|
|
||||||
#define vATN PA(8) // SCSI:ATN
|
#define vATN PA(8) // SCSI:ATN
|
||||||
#define vBSY PA(9) // SCSI:BSY
|
#define vBSY PA(9) // SCSI:BSY
|
||||||
#define vACK PA(10) // SCSI:ACK
|
#define vACK PA(10) // SCSI:ACK
|
||||||
@@ -235,14 +245,15 @@ enum SCSI_DEVICE_TYPE
|
|||||||
// Put DB and DP in output mode
|
// Put DB and DP in output mode
|
||||||
#define SCSI_DB_OUTPUT() { PBREG->CRL=(PBREG->CRL &0xfffffff0)|DB_MODE_OUT; PBREG->CRH = 0x11111111*DB_MODE_OUT; }
|
#define SCSI_DB_OUTPUT() { PBREG->CRL=(PBREG->CRL &0xfffffff0)|DB_MODE_OUT; PBREG->CRH = 0x11111111*DB_MODE_OUT; }
|
||||||
// Put DB and DP in input mode
|
// Put DB and DP in input mode
|
||||||
#define SCSI_DB_INPUT() { PBREG->CRL=(PBREG->CRL &0xfffffff0)|DB_MODE_IN ; PBREG->CRH = (uint32_t)(0x11111111*DB_MODE_IN); }
|
#define SCSI_DB_INPUT() { PBREG->CRL=(PBREG->CRL &0xfffffff0)|DB_MODE_IN ; PBREG->CRH = (uint32_t)0x11111111*DB_MODE_IN; }
|
||||||
|
|
||||||
// HDDiamge file
|
// HDDiamge file
|
||||||
#define HDIMG_ID_POS 2 // Position to embed ID number
|
#define HDIMG_ID_POS 2 // Position to embed ID number
|
||||||
#define HDIMG_LUN_POS 3 // Position to embed LUN numbers
|
#define HDIMG_LUN_POS 3 // Position to embed LUN numbers
|
||||||
#define HDIMG_BLK_POS 5 // Position to embed block size numbers
|
#define HDIMG_BLK_POS 5 // Position to embed block size numbers
|
||||||
#define MAX_FILE_PATH 64 // Maximum file name length
|
#define MAX_FILE_PATH 64 // Maximum file name length
|
||||||
|
#define MAX_MAC_PATH 32 // Maximum file name length on vintage macs
|
||||||
|
#define MAC_BLK_SIZE 4096
|
||||||
/*
|
/*
|
||||||
* Data byte to BSRR register setting value and parity table
|
* Data byte to BSRR register setting value and parity table
|
||||||
*/
|
*/
|
||||||
|
@@ -51,6 +51,14 @@
|
|||||||
#define SCSI_READ12 0xA8
|
#define SCSI_READ12 0xA8
|
||||||
#define SCSI_VERIFY12 0xAF
|
#define SCSI_VERIFY12 0xAF
|
||||||
|
|
||||||
|
#define BLUESCSI_LIST_FILES 0xD0
|
||||||
|
#define BLUESCSI_GET_FILE 0xD1
|
||||||
|
#define BLUESCSI_COUNT_FILES 0xD2
|
||||||
|
#define BLUESCSI_SEND_PREP 0xD3
|
||||||
|
#define BLUESCSI_SEND 0xD4
|
||||||
|
#define BLUESCSI_SEND_END 0xD5
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define SCSI_TOC_LENGTH 20 // length for default CDROM TOC
|
#define SCSI_TOC_LENGTH 20 // length for default CDROM TOC
|
||||||
|
|
||||||
|
@@ -31,6 +31,9 @@
|
|||||||
#define SCSI_ASC_MEDIUM_NOT_PRESENT 0x3A00
|
#define SCSI_ASC_MEDIUM_NOT_PRESENT 0x3A00
|
||||||
#define SCSI_ASC_LUN_NOT_READY_MANUAL_INTERVENTION_REQUIRED 0x0403
|
#define SCSI_ASC_LUN_NOT_READY_MANUAL_INTERVENTION_REQUIRED 0x0403
|
||||||
|
|
||||||
|
// OpenRetroSCSI Vendor Sense
|
||||||
|
#define OPEN_RETRO_SCSI_TOO_MANY_FILES 0x0001
|
||||||
|
|
||||||
|
|
||||||
// SCSI mode page codes
|
// SCSI mode page codes
|
||||||
#define SCSI_SENSE_MODE_VENDOR 0x00
|
#define SCSI_SENSE_MODE_VENDOR 0x00
|
||||||
@@ -44,6 +47,8 @@
|
|||||||
#define SCSI_SENSE_MODE_CDROM_AUDIO_CONTROL 0x0E
|
#define SCSI_SENSE_MODE_CDROM_AUDIO_CONTROL 0x0E
|
||||||
#define SCSI_SENSE_MODE_VENDOR_APPLE 0x30
|
#define SCSI_SENSE_MODE_VENDOR_APPLE 0x30
|
||||||
|
|
||||||
|
#define SCSI_SENSE_MODE_VENDOR_BLUESCSI 0x31 // Lookup range for vndr
|
||||||
|
|
||||||
#define SCSI_SENSE_MODE_ALL 0x3F
|
#define SCSI_SENSE_MODE_ALL 0x3F
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user