Command shell updates and quirks modes

This commit is contained in:
David Kuder 2021-12-11 16:59:32 -05:00
parent 178cffa658
commit 0c04852ad8
13 changed files with 1804 additions and 182 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
#ifndef __CONFIG_H
#define __CONFIG_H
#define DEBUG 0 // 0:No debug information output (Faster by 2-3x+)
#define DEBUG 1 // 0:No debug information output (Faster by 2-3x+)
// 1: Debug information output to USB Serial
// 2: Debug information output to LOG.txt (slow)
@ -21,16 +21,19 @@
// HDD format
#define MAX_BLOCKSIZE (1 << 15) // Maximum BLOCK size (2048 to 8192 tested, 16384 had issues)
#define SCSI_INQUIRY_RESPONSE_SIZE 96
// Supported Device Types
#define SUPPORT_DISK true
#define SUPPORT_OPTICAL true
#define SUPPORT_TAPE false
#define SUPPORT_MO false
#define SUPPORT_INITIATOR true
// Compatibility Settings
#define SUPPORT_SASI false // Enable SASI compatiblity for Sharp X68000
#define SUPPORT_SASI_DEFAULT false // Turn it on by default
#define SUPPORT_APPLE true
#define SUPPORT_APPLE_DEFAULT false
#endif /* __CONFIG_H */

View File

@ -1,8 +1,26 @@
#include "config.h"
// SCSI Drive Vendor information
static uint8_t SCSI_INQUIRY_RESPONSE[][SCSI_INQUIRY_RESPONSE_SIZE] = {
#if SUPPORT_SASI
{
0x00, //Device type
0x00, //RMB = 0
0x01, //ISO,ECMA,ANSI version
0x01, //Response data format
35 - 4, //Additional data length
0, 0, //Reserve
0x00, //Support function
'N', 'E', 'C', 'I', 'T', 'S', 'U', ' ',
'A', 'r', 'd', 'S', 'C', 'S', 'i', 'n', 'o', ' ', ' ',' ', ' ', ' ', ' ', ' ',
'0', '0', '1', '0',
0
},
#endif /* SUPPORT_SASI */
#if SUPPORT_DISK
static uint8_t SCSI_DISK_INQUIRY_RESPONSE[96] = {
{
0x00, //device type
0x00, //RMB = 0
0x05, //ISO, ECMA, ANSI version
@ -18,27 +36,29 @@ static uint8_t SCSI_DISK_INQUIRY_RESPONSE[96] = {
// Revision Date (10 Bytes)
'2','0','2','1','/','1','1','/','2','2',
0
};
#endif /* SUPPORT_DISK */
},
#if SUPPORT_SASI
static uint8_t SCSI_NEC_INQUIRY_RESPONSE[96] = {
0x00, //Device type
{
0x00, //device type
0x00, //RMB = 0
0x01, //ISO,ECMA,ANSI version
0x01, //Response data format
0x05, //ISO, ECMA, ANSI version
0x02, //Response data format
35 - 4, //Additional data length
0, 0, //Reserve
0x00, //Support function
'N', 'E', 'C', 'I', 'T', 'S', 'U', ' ',
'A', 'r', 'd', 'S', 'C', 'S', 'i', 'n', 'o', ' ', ' ',' ', ' ', ' ', ' ', ' ',
'0', '0', '1', '0',
'S', 'E', 'A', 'G', 'A', 'T', 'E', ' ', // vendor 8
'S', 'T', '2', '2', '5', 'N', ' ', ' ', ' ', ' ', ' ',' ', ' ', ' ', ' ', ' ', // product 16
'1', '.', '0', ' ', // version 4
// Release Number (1 Byte)
0x20,
// Revision Date (10 Bytes)
'2','0','2','1','/','1','1','/','2','2',
0
};
#endif /* SUPPORT_SASI */
},
#endif /* SUPPORT_DISK */
#if SUPPORT_OPTICAL
static uint8_t SCSI_CDROM_INQUIRY_RESPONSE[96] = {
{
0x05, //device type
0x80, //RMB = 0
0x05, //ISO, ECMA, ANSI version
@ -54,11 +74,80 @@ static uint8_t SCSI_CDROM_INQUIRY_RESPONSE[96] = {
// Revision Date (10 Bytes)
'2','0','2','1','/','1','1','/','2','2',
0
};
},
{
0x05, //device type
0x80, //RMB = 0
0x05, //ISO, ECMA, ANSI version
0x02, //Response data format
46 - 4, //Additional data length
0, 0, //Reserve
0x00, //Support function
'S', 'O', 'N', 'Y', ' ', ' ', ' ', ' ', // vendor 8
'C', 'D', 'U', '-', '7', '6', 'S', ' ', ' ', ' ', ' ',' ', ' ', ' ', ' ', ' ', // product 16
'1', '.', '0', ' ', // version 4
// Release Number (1 Byte)
0x20,
// Revision Date (10 Bytes)
'2','0','2','1','/','1','1','/','2','2',
0
},
{
0x05, //device type
0x80, //RMB = 0
0x05, //ISO, ECMA, ANSI version
0x02, //Response data format
35 - 4, //Additional data length
0, 0, //Reserve
0x00, //Support function
'M', 'A', 'T', 'S', 'H', 'I', 'T', 'A', // vendor 8
'C', 'D', '-', 'R', 'O', 'M', ' ', 'C', 'R', '8', '0','0', '5', ' ', ' ', ' ', // product 16
'1', '.', '0', 'k', // version 4
0
},
{
0x05, //device type
0x80, //RMB = 0
0x05, //ISO, ECMA, ANSI version
0x02, //Response data format
35 - 4, //Additional data length
0, 0, //Reserve
0x00, //Support function
'D', 'E', 'C', ' ', ' ', ' ', ' ', ' ', // vendor 8
'R', 'R', 'D', '4', '5', ' ', ' ', ' ', '(', 'C', ')',' ', 'D', 'E', 'C', ' ', // product 16
'0', '4', '3', '6', // version 4
0
},
{
0x05, //device type
0x80, //RMB = 0
0x05, //ISO, ECMA, ANSI version
0x02, //Response data format
35 - 4, //Additional data length
0, 0, //Reserve
0x98, //Support function
'T', 'O', 'S', 'H', 'I', 'B', 'A', ' ', // vendor 8
'C', 'D', '-', 'R', 'O', 'M', ' ', 'X', 'M', '-', '3','3', '0', '1', 'T', 'A', // product 16
'0', '2', '7', '2', // version 4
0
},
{
0x05, //device type
0x80, //RMB = 0
0x05, //ISO, ECMA, ANSI version
0x02, //Response data format
35 - 4, //Additional data length
0, 0, //Reserve
0x98, //Support function
'T', 'O', 'S', 'H', 'I', 'B', 'A', ' ', // vendor 8
'C', 'D', '-', 'R', 'O', 'M', ' ', 'X', 'M', '-', '5','7', '0', '1', 'T', 'A', // product 16
'3', '1', '3', '6', // version 4
0
},
#endif /* SUPPORT_OPTICAL */
#if SUPPORT_TAPE
static uint8_t SCSI_TAPE_INQUIRY_RESPONSE[96] = {
{
0x01, //device type
0x80, //RMB = 0
0x03, //ISO, ECMA, ANSI version
@ -71,5 +160,16 @@ static uint8_t SCSI_TAPE_INQUIRY_RESPONSE[96] = {
'U', 'L', 'T', '3', '5', '8', '0', '-', 'T', 'D', '1',' ', ' ', ' ', ' ', ' ', // product 16
'M', 'B', 'N', '0', // version 4
0
};
},
#endif /* SUPPORT_TAPE */
// Invalid entry to mark end of data
{
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
' ', ' ', ' ', ' ',
0
}
};

View File

@ -115,16 +115,27 @@ void ConfigureDiskHandlers(VirtualDevice_t *vdev) {
vdev->m_handler[CMD_WRITE10] = &Write10CommandHandler;
vdev->m_handler[CMD_SEEK10] = &Seek10CommandHandler;
vdev->m_handler[CMD_MODE_SENSE10] = &ModeSenseCommandHandler;
vdev->m_handler[CMD_SEARCH_DATA_EQUAL] = &SearchDataEqualCommandHandler;
vdev->m_handler[CMD_READ_DEFECT_DATA] = &ReadDefectCommandHandler;
#if SUPPORT_SASI
if(m_sasi_mode)
if(vdev->m_quirks & QUIRKS_SASI)
vdev->m_handler[CMD_SET_DRIVE_PARAMETER] = &DTCsetDriveParameterCommandHandler;
#endif
#endif
#if SUPPORT_APPLE
if(vdev->m_quirks & QUIRKS_APPLE)
vdev->m_handler[CMD_MAC_UNKNOWN] = &AppleEECommandHandler;
#endif
}
// If config file exists, read the first three lines and copy the contents.
// File must be well formed or you will get junk in the SCSI Vendor fields.
void ConfigureDisk(VirtualDevice_t *vdev, const char *image_name) {
memcpy(vdev->m_inquiryresponse, SCSI_DISK_INQUIRY_RESPONSE, sizeof(SCSI_DISK_INQUIRY_RESPONSE));
for(int i = 0; SCSI_INQUIRY_RESPONSE[i][0] != 0xff; i++) {
if(SCSI_INQUIRY_RESPONSE[i][0] == DEV_DISK) {
memcpy(vdev->m_inquiryresponse, SCSI_INQUIRY_RESPONSE[i], SCSI_INQUIRY_RESPONSE_SIZE);
break;
}
}
if(image_name) {
char configname[MAX_FILE_PATH+1];

403
src/dump.ino Executable file
View File

@ -0,0 +1,403 @@
#if SUPPORT_INITIATOR
// Take control of the SCSI bus
void initiatorTakeBus() {
pinModeFastSlew(ATN, OUTPUT_OPENDRAIN);
pinModeFastSlew(ACK, OUTPUT_OPENDRAIN);
pinModeFastSlew(RST, OUTPUT_OPENDRAIN);
pinModeFastSlew(SEL, OUTPUT_OPENDRAIN);
pinMode(BSY, INPUT_PULLUP);
pinMode(MSG, INPUT_PULLUP);
pinMode(CD, INPUT_PULLUP);
pinMode(IO, INPUT_PULLUP);
pinMode(REQ, INPUT_PULLUP);
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);
SCSI_INITIATOR_INACTIVE();
}
// Return the bus to floating, allowing other hosts to take over
void initiatorReleaseBus() {
// 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();
}
// Issue a bus reset
void initiatorBusFree() {
SET_RST_ACTIVE();
delay(50);
SET_RST_INACTIVE();
delay(20);
}
// Selection phase, assert Host & Target ID bits and assert SEL, wait for BSY to be asserted by the target, or timeout.
int initiateSelection(uint8_t target_id, boolean withATN) {
int timeout = 10000;
GPIOB_PDDR = SCSI_DB_MASK;
SCSI_DB_OUTPUT((1 << target_id) | 0x80);
SET_SEL_ACTIVE();
while(timeout--) {
delay(20);
if(GET_BSY()) break;
}
if(withATN) SET_ATN_ACTIVE();
SET_SEL_INACTIVE();
SCSI_DB_INPUT();
return GET_BSY();
}
// Message Out phase, hold ATN asserted until the last message byte
int initiateMessageOut(const uint8_t *buf, uint8_t len) {
int timeout = 10000;
SET_ATN_ACTIVE();
while(timeout--) {
delay(20);
if(!GET_CD() && !GET_IO() && GET_MSG()) break;
}
if(timeout > 0) {
for(uint8_t x = 0; x < len; x++) {
timeout = 10000;
while(!GET_REQ() && (timeout--));
if(!timeout) break;
GPIOB_PDDR = SCSI_DB_MASK;
SCSI_DB_OUTPUT(buf[x]);
if((x + 1) == len)
SET_ATN_INACTIVE();
SET_ACK_ACTIVE();
timeout = 10000;
while(GET_REQ() && (timeout--));
SET_ACK_INACTIVE();
if(!timeout) break;
}
}
SET_ATN_INACTIVE();
SCSI_DB_INPUT();
return (timeout > 0);
}
// Message In phase, read a single byte from target once it's phase matches
int initiateMessageIn(uint8_t *buf) {
int timeout = 10000;
while(timeout--) {
delay(20);
if(!GET_CD() && GET_IO() && GET_MSG()) break;
}
if(timeout > 0) {
timeout = 10000;
while(!GET_REQ() && (timeout--));
if(!timeout) goto failed;
buf[0] = readIO();
SET_ACK_ACTIVE();
timeout = 10000;
while(GET_REQ() && (timeout--));
SET_ACK_INACTIVE();
}
failed:
return (timeout > 0);
}
// Command Out phase, tell the target what we want from it.
int initiateCommandOut(const uint8_t *buf, uint8_t len) {
int timeout = 10000;
while(timeout--) {
delay(20);
if(GET_CD() && !GET_IO() && !GET_MSG()) break;
}
if(timeout > 0) {
for(uint8_t x = 0; x < len; x++) {
timeout = 10000;
while(!GET_REQ() && (timeout--));
if(!timeout) break;
GPIOB_PDDR = SCSI_DB_MASK;
SCSI_DB_OUTPUT(buf[x]);
SET_ACK_ACTIVE();
timeout = 10000;
while(GET_REQ() && (timeout--));
SET_ACK_INACTIVE();
if(!timeout) break;
}
}
SCSI_DB_INPUT();
return (timeout > 0);
}
// Data Out phase, send data to target
int initiateDataOut(const uint8_t *buf, uint16_t len) {
int timeout = 10000;
while(timeout--) {
delay(20);
if(!GET_CD() && !GET_IO() && !GET_MSG()) break;
}
if(timeout > 0) {
for(uint16_t x = 0; x < len; x++) {
timeout = 10000;
while(!GET_REQ() && (timeout--));
if(!timeout) break;
GPIOB_PDDR = SCSI_DB_MASK;
SCSI_DB_OUTPUT(buf[x]);
SET_ACK_ACTIVE();
timeout = 10000;
while(GET_REQ() && (timeout--));
SET_ACK_INACTIVE();
if(!timeout) break;
}
}
SCSI_DB_INPUT();
return (timeout > 0);
}
// Data In phase, get data from target
int initiateDataIn(uint8_t *buf, uint16_t len) {
int timeout = 10000;
while(timeout--) {
delay(20);
if(!GET_CD() && GET_IO() && !GET_MSG()) break;
}
if(timeout > 0) {
for(uint16_t x = 0; x < len; x++) {
timeout = 10000;
while(!GET_REQ() && (timeout--));
if(!timeout) break;
buf[x] = readIO();
SET_ACK_ACTIVE();
timeout = 10000;
while(GET_REQ() && (timeout--));
SET_ACK_INACTIVE();
if(!timeout) break;
}
}
return (timeout > 0);
}
// Status In phase, read target's command status
int initiateStatusIn(uint8_t *buf) {
int timeout = 10000;
while(timeout--) {
delay(20);
if(GET_CD() && GET_IO() && !GET_MSG()) break;
}
if(timeout > 0) {
timeout = 10000;
while(!GET_REQ() && (timeout--));
if(!timeout) goto failed;
buf[0] = readIO();
SET_ACK_ACTIVE();
timeout = 10000;
while(GET_REQ() && (timeout--));
SET_ACK_INACTIVE();
}
failed:
return (timeout > 0);
}
int initiateReadCapacity(uint8_t target_id, uint32_t *blockSize, uint32_t *blockCount) {
initiatorTakeBus();
// Select Target
if(!initiateSelection(target_id, true)) goto failed;
// Select LUN 0
m_buf[0] = 0x80;
if(!initiateMessageOut(m_buf, 1)) goto failed;
// Execute Read Capacity
memset(m_cmd, 0x00, 10);
m_cmd[0] = CMD_READ_CAPACITY10;
if(!initiateCommandOut(m_cmd, 10)) goto failed;
// Get Data Back
if(!initiateDataIn(m_buf, 8)) goto failed;
*blockSize = (m_buf[0] << 24) | (m_buf[1] << 16) || (m_buf[2] << 8) | (m_buf[3] << 0);
*blockCount = (m_buf[4] << 24) | (m_buf[5] << 16) || (m_buf[6] << 8) | (m_buf[7] << 0);
// Get Status
if(!initiateStatusIn(m_buf)) goto failed;
// Get Messages
if(!initiateMessageIn(m_buf)) goto failed;
return 1;
failed:
initiatorBusFree();
initiatorReleaseBus();
return 0;
}
int initiateReadVolume(FsFile file, uint8_t target_id, uint32_t blockSize, uint32_t blockCount) {
uint32_t pos = 0;
initiatorTakeBus();
while(blockCount) {
uint32_t blocks = min(blockCount, (MAX_BLOCKSIZE / blockSize));
if(!initiateSelection(target_id, true)) goto failed;
// Select LUN 0
m_buf[0] = 0x80;
if(!initiateMessageOut(m_buf, 1)) goto failed;
// Execute Read
memset(m_cmd, 0x00, 10);
m_cmd[0] = CMD_READ10;
m_cmd[2] = (pos >> 24) & 0xff;
m_cmd[3] = (pos >> 16) & 0xff;
m_cmd[4] = (pos >> 8) & 0xff;
m_cmd[5] = (pos >> 0) & 0xff;
m_cmd[6] = (blocks >> 8) & 0xff;
m_cmd[7] = (blocks >> 0) & 0xff;
if(!initiateCommandOut(m_cmd, 10)) goto failed;
// Get Data Back
if(!initiateDataIn(m_buf, blockSize * blocks)) goto failed;
file.write(m_buf, blockSize * blocks);
// Get Status
if(!initiateStatusIn(m_buf)) goto failed;
// Get Messages
if(!initiateMessageIn(m_buf)) goto failed;
pos += blocks;
blockCount -= blocks;
}
return 1;
failed:
initiatorBusFree();
initiatorReleaseBus();
return 0;
}
void dumpcmd(int argc, char **argv) {
uint8_t target_id = 0xff;
uint32_t blockSize, blockCount;
char tmp_path[MAX_FILE_PATH+1];
FsFile file;
if(argc < 3) {
// Syntax error
return;
}
target_id = strtoul(argv[1], NULL, 0);
if(target_id > 7) {
Serial.print("ERROR");
if(scriptlevel >= 0) Serial.printf(" on line %d of '%s'", exec_line, exec_filename);
Serial.printf(": SCSI ID '%s' is not within range.\r\n", argv[1]);
return;
}
fixupPath(tmp_path, argv[2]);
if(strncmp(tmp_path, "/sd/", 4)) {
Serial.print("ERROR");
if(scriptlevel >= 0) Serial.printf(" on line %d of '%s'", exec_line, exec_filename);
Serial.printf(": Can only create images on the SD Card.\r\n");
return;
}
if(!file.open(tmp_path+3, O_WRONLY | O_CREAT | O_TRUNC)) {
Serial.print("ERROR");
if(scriptlevel >= 0) Serial.printf(" on line %d of '%s'", exec_line, exec_filename);
Serial.printf(": Unable to open '%s'.\r\n", tmp_path);
return;
}
detachInterrupt(RST);
detachInterrupt(SEL);
if(!initiateReadCapacity(target_id, &blockSize, &blockCount)) {
Serial.print("ERROR");
if(scriptlevel >= 0) Serial.printf(" on line %d of '%s'", exec_line, exec_filename);
Serial.printf(": Unable to read the capacity of SCSI target device.\r\n");
} else {
initiateReadVolume(file, target_id, blockSize, blockCount);
}
attachInterrupt(RST, onBusReset, FALLING);
attachInterrupt(SEL, SelectionPhaseISR, FALLING);
file.close();
}
#endif

464
src/eggs.ino Executable file
View File

@ -0,0 +1,464 @@
/*
* Don't put all your eggs in one basket,
*
* I suggest you not read this file if you don't want to spoil all the fun,
*
* because spoiled eggs smell bad.
*
*/
#include <unistd.h>
/*
* Based on SL version 5.02
* Copyright 1993,1998,2014 Toyoda Masashi (mtoyoda@acm.org)
* https://github.com/mtoyoda/sl
*
* Everyone is permitted to do anything on this program including copying,
* modifying, and improving, unless you try to pretend that you wrote it.
* i.e., the above copyright notice has to appear in all copies.
* THE AUTHOR DISCLAIMS ANY RESPONSIBILITY WITH REGARD TO THIS SOFTWARE.
*/
#define D51HEIGHT 10
#define D51FUNNEL 7
#define D51LENGTH 83
#define D51PATTERNS 6
#define D51STR1 " ==== ________ ___________ "
#define D51STR2 " _D _| |_______/ \\__I_I_____===__|_________| "
#define D51STR3 " |(_)--- | H\\________/ | | =|___ ___| "
#define D51STR4 " / | | H | | | | ||_| |_|| "
#define D51STR5 " | | | H |__--------------------| [___] | "
#define D51STR6 " | ________|___H__/__|_____/[][]~\\_______| | "
#define D51STR7 " |/ | |-----------I_____I [][] [] D |=======|__ "
#define D51WHL11 "__/ =| o |=-~~\\ /~~\\ /~~\\ /~~\\ ____Y___________|__ "
#define D51WHL12 " |/-=|___|= || || || |_____/~\\___/ "
#define D51WHL13 " \\_/ \\O=====O=====O=====O_/ \\_/ "
#define D51WHL21 "__/ =| o |=-~~\\ /~~\\ /~~\\ /~~\\ ____Y___________|__ "
#define D51WHL22 " |/-=|___|=O=====O=====O=====O |_____/~\\___/ "
#define D51WHL23 " \\_/ \\__/ \\__/ \\__/ \\__/ \\_/ "
#define D51WHL31 "__/ =| o |=-O=====O=====O=====O \\ ____Y___________|__ "
#define D51WHL32 " |/-=|___|= || || || |_____/~\\___/ "
#define D51WHL33 " \\_/ \\__/ \\__/ \\__/ \\__/ \\_/ "
#define D51WHL41 "__/ =| o |=-~O=====O=====O=====O\\ ____Y___________|__ "
#define D51WHL42 " |/-=|___|= || || || |_____/~\\___/ "
#define D51WHL43 " \\_/ \\__/ \\__/ \\__/ \\__/ \\_/ "
#define D51WHL51 "__/ =| o |=-~~\\ /~~\\ /~~\\ /~~\\ ____Y___________|__ "
#define D51WHL52 " |/-=|___|= O=====O=====O=====O|_____/~\\___/ "
#define D51WHL53 " \\_/ \\__/ \\__/ \\__/ \\__/ \\_/ "
#define D51WHL61 "__/ =| o |=-~~\\ /~~\\ /~~\\ /~~\\ ____Y___________|__ "
#define D51WHL62 " |/-=|___|= || || || |_____/~\\___/ "
#define D51WHL63 " \\_/ \\_O=====O=====O=====O/ \\_/ "
#define D51DEL " "
#define COAL01 " "
#define COAL02 " "
#define COAL03 " _________________ "
#define COAL04 " _| \\_____A "
#define COAL05 " =| | "
#define COAL06 " -| | "
#define COAL07 "__|________________________|_ "
#define COAL08 "|__________________________|_ "
#define COAL09 " |_D__D__D_| |_D__D__D_| "
#define COAL10 " \\_/ \\_/ \\_/ \\_/ "
#define COALDEL " "
#define LOGOHEIGHT 6
#define LOGOFUNNEL 4
#define LOGOLENGTH 84
#define LOGOPATTERNS 6
#define LOGO1 " ++ +------ "
#define LOGO2 " || |+-+ | "
#define LOGO3 " /---------|| | | "
#define LOGO4 " + ======== +-+ | "
#define LWHL11 " _|--O========O~\\-+ "
#define LWHL12 "//// \\_/ \\_/ "
#define LWHL21 " _|--/O========O\\-+ "
#define LWHL22 "//// \\_/ \\_/ "
#define LWHL31 " _|--/~O========O-+ "
#define LWHL32 "//// \\_/ \\_/ "
#define LWHL41 " _|--/~\\------/~\\-+ "
#define LWHL42 "//// \\_O========O "
#define LWHL51 " _|--/~\\------/~\\-+ "
#define LWHL52 "//// \\O========O/ "
#define LWHL61 " _|--/~\\------/~\\-+ "
#define LWHL62 "//// O========O_/ "
#define LCOAL1 "____ "
#define LCOAL2 "| \\@@@@@@@@@@@ "
#define LCOAL3 "| \\@@@@@@@@@@@@@_ "
#define LCOAL4 "| | "
#define LCOAL5 "|__________________| "
#define LCOAL6 " (O) (O) "
#define LCAR1 "____________________ "
#define LCAR2 "| ___ ___ ___ ___ | "
#define LCAR3 "| |_| |_| |_| |_| | "
#define LCAR4 "|__________________| "
#define LCAR5 "|__________________| "
#define LCAR6 " (O) (O) "
#define DELLN " "
#define C51HEIGHT 11
#define C51FUNNEL 7
#define C51LENGTH 87
#define C51PATTERNS 6
#define C51DEL " "
#define C51STR1 " ___ "
#define C51STR2 " _|_|_ _ __ __ ___________"
#define C51STR3 " D__/ \\_(_)___| |__H__| |_____I_Ii_()|_________|"
#define C51STR4 " | `---' |:: `--' H `--' | |___ ___| "
#define C51STR5 " +|~~~~~~~~++::~~~~~~~H~~+=====+~~~~~~|~~||_| |_|| "
#define C51STR6 " || | :: H +=====+ | |:: ...| "
#define C51STR7 "| | _______|_::-----------------[][]-----| | "
#define C51WH61 "| /~~ || |-----/~~~~\\ /[I_____I][][] --|||_______|__"
#define C51WH62 "------'|oOo|==[]=- || || | ||=======_|__"
#define C51WH63 "/~\\____|___|/~\\_| O=======O=======O |__|+-/~\\_| "
#define C51WH64 "\\_/ \\_/ \\____/ \\____/ \\____/ \\_/ "
#define C51WH51 "| /~~ || |-----/~~~~\\ /[I_____I][][] --|||_______|__"
#define C51WH52 "------'|oOo|===[]=- || || | ||=======_|__"
#define C51WH53 "/~\\____|___|/~\\_| O=======O=======O |__|+-/~\\_| "
#define C51WH54 "\\_/ \\_/ \\____/ \\____/ \\____/ \\_/ "
#define C51WH41 "| /~~ || |-----/~~~~\\ /[I_____I][][] --|||_______|__"
#define C51WH42 "------'|oOo|===[]=- O=======O=======O | ||=======_|__"
#define C51WH43 "/~\\____|___|/~\\_| || || |__|+-/~\\_| "
#define C51WH44 "\\_/ \\_/ \\____/ \\____/ \\____/ \\_/ "
#define C51WH31 "| /~~ || |-----/~~~~\\ /[I_____I][][] --|||_______|__"
#define C51WH32 "------'|oOo|==[]=- O=======O=======O | ||=======_|__"
#define C51WH33 "/~\\____|___|/~\\_| || || |__|+-/~\\_| "
#define C51WH34 "\\_/ \\_/ \\____/ \\____/ \\____/ \\_/ "
#define C51WH21 "| /~~ || |-----/~~~~\\ /[I_____I][][] --|||_______|__"
#define C51WH22 "------'|oOo|=[]=- O=======O=======O | ||=======_|__"
#define C51WH23 "/~\\____|___|/~\\_| || || |__|+-/~\\_| "
#define C51WH24 "\\_/ \\_/ \\____/ \\____/ \\____/ \\_/ "
#define C51WH11 "| /~~ || |-----/~~~~\\ /[I_____I][][] --|||_______|__"
#define C51WH12 "------'|oOo|=[]=- || || | ||=======_|__"
#define C51WH13 "/~\\____|___|/~\\_| O=======O=======O |__|+-/~\\_| "
#define C51WH14 "\\_/ \\_/ \\____/ \\____/ \\____/ \\_/ "
int ACCIDENT = 0;
int LOGO = 0;
int FLY = 0;
int C51 = 0;
#define COLS 80
#define LINES 24
#define ERR -1
#define OK 0
static char sB[LINES][COLS];
static char tL[COLS+1];
static void refresh()
{
int fX, oX, lC;
boolean pO;
for(int y = 0; y < LINES; y++) {
fX = 0; oX = 0; lC = 0; pO = false;
for(int x = 0; x < COLS; x++) {
if(!pO && (sB[y][x] != ' ')) { fX = x; pO = 1; }
if(pO && (sB[y][x] != ' ')) { lC = oX+1; }
if(pO) { tL[oX++] = sB[y][x]; }
}
tL[lC] = 0;
Serial.printf("\x1b[%d;%dH\x1b[1K%s\x1b[K", y+1, fX+1, tL);
}
}
int mvaddch(int y, int x, char c)
{
if((y < 0) || (y >= LINES) || (x < 0) || (x >= COLS)) return ERR;
if((c >= 0) && (c < ' ')) c = ' ';
sB[y][x] = c;
return OK;
}
int my_mvaddstr(int y, int x, const char *str)
{
for ( ; x < 0; ++x, ++str)
if (*str == '\0') return ERR;
for ( ; *str != '\0'; ++str, ++x)
if (mvaddch(y, x, *str) == ERR) return ERR;
return OK;
}
void option(char *str)
{
extern int ACCIDENT, LOGO, FLY, C51;
while (*str != '\0') {
switch (*str++) {
case 'a': ACCIDENT = 1; break;
case 'F': FLY = 1; break;
case 'l': LOGO = 1; break;
case 'c': C51 = 1; break;
default: break;
}
}
}
void slcmd(int argc, char *argv[])
{
int x, i;
ACCIDENT = 0;
LOGO = 0;
FLY = 0;
C51 = 0;
for (i = 1; i < argc; ++i) {
if (*argv[i] == '-') {
option(argv[i] + 1);
}
}
for(int y = 0; y < LINES; y++) {
for(int x = 0; x < COLS; x++) {
sB[y][x] = ' ';
}
}
Serial.print("\x1b[?25l\x1b[2J\x1b[H");
for (x = COLS - 1; ; --x) {
if (LOGO == 1) {
if (add_sl(x) == ERR) break;
}
else if (C51 == 1) {
if (add_C51(x) == ERR) break;
}
else {
if (add_D51(x) == ERR) break;
}
refresh();
delay(50);
}
delay(125);
Serial.print("\x1b[?25h\x1b[2J\x1b[H");
return;
}
int add_sl(int x)
{
static const char *sl[LOGOPATTERNS][LOGOHEIGHT + 1]
= {{LOGO1, LOGO2, LOGO3, LOGO4, LWHL11, LWHL12, DELLN},
{LOGO1, LOGO2, LOGO3, LOGO4, LWHL21, LWHL22, DELLN},
{LOGO1, LOGO2, LOGO3, LOGO4, LWHL31, LWHL32, DELLN},
{LOGO1, LOGO2, LOGO3, LOGO4, LWHL41, LWHL42, DELLN},
{LOGO1, LOGO2, LOGO3, LOGO4, LWHL51, LWHL52, DELLN},
{LOGO1, LOGO2, LOGO3, LOGO4, LWHL61, LWHL62, DELLN}};
static const char *coal[LOGOHEIGHT + 1]
= {LCOAL1, LCOAL2, LCOAL3, LCOAL4, LCOAL5, LCOAL6, DELLN};
static const char *car[LOGOHEIGHT + 1]
= {LCAR1, LCAR2, LCAR3, LCAR4, LCAR5, LCAR6, DELLN};
int i, y, py1 = 0, py2 = 0, py3 = 0;
if (x < - LOGOLENGTH) return ERR;
y = LINES / 2 - 3;
if (FLY == 1) {
y = (x / 6) + LINES - (COLS / 6) - LOGOHEIGHT;
py1 = 2; py2 = 4; py3 = 6;
}
for (i = 0; i <= LOGOHEIGHT; ++i) {
my_mvaddstr(y + i, x, sl[(LOGOLENGTH + x) / 3 % LOGOPATTERNS][i]);
my_mvaddstr(y + i + py1, x + 21, coal[i]);
my_mvaddstr(y + i + py2, x + 42, car[i]);
my_mvaddstr(y + i + py3, x + 63, car[i]);
}
if (ACCIDENT == 1) {
add_man(y + 1, x + 14);
add_man(y + 1 + py2, x + 45); add_man(y + 1 + py2, x + 53);
add_man(y + 1 + py3, x + 66); add_man(y + 1 + py3, x + 74);
}
add_smoke(y - 1, x + LOGOFUNNEL);
return OK;
}
int add_D51(int x)
{
static const char *d51[D51PATTERNS][D51HEIGHT + 1]
= {{D51STR1, D51STR2, D51STR3, D51STR4, D51STR5, D51STR6, D51STR7,
D51WHL11, D51WHL12, D51WHL13, D51DEL},
{D51STR1, D51STR2, D51STR3, D51STR4, D51STR5, D51STR6, D51STR7,
D51WHL21, D51WHL22, D51WHL23, D51DEL},
{D51STR1, D51STR2, D51STR3, D51STR4, D51STR5, D51STR6, D51STR7,
D51WHL31, D51WHL32, D51WHL33, D51DEL},
{D51STR1, D51STR2, D51STR3, D51STR4, D51STR5, D51STR6, D51STR7,
D51WHL41, D51WHL42, D51WHL43, D51DEL},
{D51STR1, D51STR2, D51STR3, D51STR4, D51STR5, D51STR6, D51STR7,
D51WHL51, D51WHL52, D51WHL53, D51DEL},
{D51STR1, D51STR2, D51STR3, D51STR4, D51STR5, D51STR6, D51STR7,
D51WHL61, D51WHL62, D51WHL63, D51DEL}};
static const char *coal[D51HEIGHT + 1]
= {COAL01, COAL02, COAL03, COAL04, COAL05,
COAL06, COAL07, COAL08, COAL09, COAL10, COALDEL};
int y, i, dy = 0;
if (x < - D51LENGTH) return ERR;
y = LINES / 2 - 5;
if (FLY == 1) {
y = (x / 7) + LINES - (COLS / 7) - D51HEIGHT;
dy = 1;
}
for (i = 0; i <= D51HEIGHT; ++i) {
my_mvaddstr(y + i, x, d51[(D51LENGTH + x) % D51PATTERNS][i]);
my_mvaddstr(y + i + dy, x + 53, coal[i]);
}
if (ACCIDENT == 1) {
add_man(y + 2, x + 43);
add_man(y + 2, x + 47);
}
add_smoke(y - 1, x + D51FUNNEL);
return OK;
}
int add_C51(int x)
{
static const char *c51[C51PATTERNS][C51HEIGHT + 1]
= {{C51STR1, C51STR2, C51STR3, C51STR4, C51STR5, C51STR6, C51STR7,
C51WH11, C51WH12, C51WH13, C51WH14, C51DEL},
{C51STR1, C51STR2, C51STR3, C51STR4, C51STR5, C51STR6, C51STR7,
C51WH21, C51WH22, C51WH23, C51WH24, C51DEL},
{C51STR1, C51STR2, C51STR3, C51STR4, C51STR5, C51STR6, C51STR7,
C51WH31, C51WH32, C51WH33, C51WH34, C51DEL},
{C51STR1, C51STR2, C51STR3, C51STR4, C51STR5, C51STR6, C51STR7,
C51WH41, C51WH42, C51WH43, C51WH44, C51DEL},
{C51STR1, C51STR2, C51STR3, C51STR4, C51STR5, C51STR6, C51STR7,
C51WH51, C51WH52, C51WH53, C51WH54, C51DEL},
{C51STR1, C51STR2, C51STR3, C51STR4, C51STR5, C51STR6, C51STR7,
C51WH61, C51WH62, C51WH63, C51WH64, C51DEL}};
static const char *coal[C51HEIGHT + 1]
= {COALDEL, COAL01, COAL02, COAL03, COAL04, COAL05,
COAL06, COAL07, COAL08, COAL09, COAL10, COALDEL};
int y, i, dy = 0;
if (x < - C51LENGTH) return ERR;
y = LINES / 2 - 5;
if (FLY == 1) {
y = (x / 7) + LINES - (COLS / 7) - C51HEIGHT;
dy = 1;
}
for (i = 0; i <= C51HEIGHT; ++i) {
my_mvaddstr(y + i, x, c51[(C51LENGTH + x) % C51PATTERNS][i]);
my_mvaddstr(y + i + dy, x + 55, coal[i]);
}
if (ACCIDENT == 1) {
add_man(y + 3, x + 45);
add_man(y + 3, x + 49);
}
add_smoke(y - 1, x + C51FUNNEL);
return OK;
}
void add_man(int y, int x)
{
static const char *man[2][2] = {{"", "(O)"}, {"Help!", "\\O/"}};
int i;
for (i = 0; i < 2; ++i) {
my_mvaddstr(y + i, x, man[(LOGOLENGTH + x) / 12 % 2][i]);
}
}
void add_smoke(int y, int x)
#define SMOKEPTNS 16
{
static struct smokes {
int y, x;
int ptrn, kind;
} S[1000];
static int sum = 0;
static const char *Smoke[2][SMOKEPTNS]
= {{"( )", "( )", "( )", "( )", "( )",
"( )" , "( )" , "( )" , "()" , "()" ,
"O" , "O" , "O" , "O" , "O" ,
" " },
{"(@@@)", "(@@@@)", "(@@@@)", "(@@@)", "(@@)",
"(@@)" , "(@)" , "(@)" , "@@" , "@@" ,
"@" , "@" , "@" , "@" , "@" ,
" " }};
static const char *Eraser[SMOKEPTNS]
= {" ", " ", " ", " ", " ",
" " , " " , " " , " " , " " ,
" " , " " , " " , " " , " " ,
" " };
static int dy[SMOKEPTNS] = { 2, 1, 1, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0 };
static int dx[SMOKEPTNS] = {-2, -1, 0, 1, 1, 1, 1, 1, 2, 2,
2, 2, 2, 3, 3, 3 };
int i;
if (x % 4 == 0) {
for (i = 0; i < sum; ++i) {
my_mvaddstr(S[i].y, S[i].x, Eraser[S[i].ptrn]);
S[i].y -= dy[S[i].ptrn];
S[i].x += dx[S[i].ptrn];
S[i].ptrn += (S[i].ptrn < SMOKEPTNS - 1) ? 1 : 0;
my_mvaddstr(S[i].y, S[i].x, Smoke[S[i].kind][S[i].ptrn]);
}
my_mvaddstr(y, x, Smoke[sum % 2][0]);
S[sum].y = y; S[sum].x = x;
S[sum].ptrn = 0; S[sum].kind = sum % 2;
sum ++;
}
}
void punishDirectory(int argc, char **argv) {
Serial.printf("You seem to have made a mistake, let me fix that for you...\r\n");
cmdDisplay();
Serial.printf("l");
delay(random(175,500));
Serial.printf("s");
delay(random(175,500));
for(int i = 1; i < argc; i++) {
Serial.printf(" ");
delay(random(175,500));
for(int x = 0; argv[i][x] != 0; x++) {
Serial.printf("%c", argv[i][x]);
delay(random(175,500));
}
}
Serial.printf("\r\n");
return showDirectory(argc, argv);
}

View File

@ -76,6 +76,13 @@ void ReassignBlocksCommandHandler() {
m_phase = PHASE_STATUSIN;
}
#if SUPPORT_APPLE
void AppleEECommandHandler() {
LOGN("[Apple:0xEE]");
m_phase = PHASE_STATUSIN;
}
#endif
/*
* MODE SENSE command processing.
*/
@ -110,7 +117,7 @@ void ModeSenseCommandHandler()
memset(m_responsebuffer, 0, sizeof(m_responsebuffer));
#if 0
if(m_sasi_mode) {
if(m_sel->m_quirks & QUIRKS_SASI) {
int pageCode = cmd2 & 0x3F;
// Assuming sector size 512, number of sectors 25, number of heads 8 as default settings
@ -298,7 +305,37 @@ void ModeSenseCommandHandler()
m_responsebuffer[len++] = 0x00; // Reserved
break;
#endif
case MODEPAGE_FORMAT_PARAMETERS:
#if SUPPORT_APPLE
case MODEPAGE_APPLE:
if( m_sel->m_quirks & QUIRKS_APPLE) {
m_responsebuffer[len++] = 0xb0;
m_responsebuffer[len++] = 0x16;
m_responsebuffer[len++] = 'A';
m_responsebuffer[len++] = 'P';
m_responsebuffer[len++] = 'P';
m_responsebuffer[len++] = 'L';
m_responsebuffer[len++] = 'E';
m_responsebuffer[len++] = ' ';
m_responsebuffer[len++] = 'C';
m_responsebuffer[len++] = 'O';
m_responsebuffer[len++] = 'M';
m_responsebuffer[len++] = 'P';
m_responsebuffer[len++] = 'U';
m_responsebuffer[len++] = 'T';
m_responsebuffer[len++] = 'E';
m_responsebuffer[len++] = 'R';
m_responsebuffer[len++] = ',';
m_responsebuffer[len++] = ' ';
m_responsebuffer[len++] = 'I';
m_responsebuffer[len++] = 'N';
m_responsebuffer[len++] = 'C';
m_responsebuffer[len++] = ' ';
m_responsebuffer[len++] = ' ';
m_responsebuffer[len++] = ' ';
}
break;
#endif
case MODEPAGE_FORMAT_PARAMETERS:
m_responsebuffer[len + 0] = MODEPAGE_FORMAT_PARAMETERS; //Page code
m_responsebuffer[len + 1] = 0x16; // Page length
m_responsebuffer[len + 11] = 0x3F;//Number of sectors / track
@ -385,6 +422,22 @@ void ModeSelect10CommandHandler() {
m_phase = PHASE_STATUSIN;
}
void SearchDataEqualCommandHandler() {
LOGN("[SearchDataEqual]");
m_phase = PHASE_STATUSIN;
}
void ReadDefectCommandHandler() {
LOGN("[ReadDefect]");
m_responsebuffer[0] = 0x00;
m_responsebuffer[1] = m_cmd[2];
m_responsebuffer[2] = 0x00; // List Length MSB
m_responsebuffer[3] = 0x00; // List Length LSB
writeDataPhase(4, m_responsebuffer);
m_phase = PHASE_STATUSIN;
}
void StartStopUnitCommandHandler() {
LOGN("[StartStopUnit]");
m_phase = PHASE_STATUSIN;

View File

@ -113,17 +113,17 @@ SdFs sd;
#define SET_REQ_ACTIVE() { GPIOA_PCOR = (1 << 13); }
#define SET_REQ_INACTIVE() { GPIOA_PSOR = (1 << 13); }
#define SET_MSG_ACTIVE() { GPIOD_PCOR = (1 << 2); }
#define SET_MSG_INACTIVE() { GPIOD_PSOR = (1 << 2); }
//#define SET_CD_ACTIVE() { GPIOD_PCOR = (1 << 7); }
//#define SET_CD_INACTIVE() { GPIOD_PSOR = (1 << 7); }
//#define SET_IO_ACTIVE() { GPIOA_PCOR = (1 << 12); }
//#define SET_IO_INACTIVE() { GPIOA_PSOR = (1 << 12); }
//#define SET_MSG_ACTIVE() { GPIOD_PCOR = (1 << 2); __asm__("nop""\n\t""nop""\n\t"); }
//#define SET_MSG_INACTIVE() { GPIOD_PSOR = (1 << 2); __asm__("nop""\n\t""nop""\n\t"); }
//#define SET_CD_ACTIVE() { GPIOD_PCOR = (1 << 7); __asm__("nop""\n\t""nop""\n\t"); }
//#define SET_CD_INACTIVE() { GPIOD_PSOR = (1 << 7); __asm__("nop""\n\t""nop""\n\t"); }
//#define SET_IO_ACTIVE() { GPIOA_PCOR = (1 << 12); __asm__("nop""\n\t""nop""\n\t"); }
//#define SET_IO_INACTIVE() { GPIOA_PSOR = (1 << 12); __asm__("nop""\n\t""nop""\n\t"); }
//#define SET_REQ_ACTIVE() { pinMode(REQ, OUTPUT_OPENDRAIN); digitalWrite(REQ, LOW); }
//#define SET_REQ_INACTIVE() { digitalWrite(REQ, HIGH); pinMode(REQ, INPUT); }
//#define SET_MSG_ACTIVE() { pinMode(MSG, OUTPUT_OPENDRAIN); digitalWrite(MSG, LOW); }
//#define SET_MSG_INACTIVE() { digitalWrite(MSG, HIGH); pinMode(MSG, INPUT); }
#define SET_MSG_ACTIVE() { pinMode(MSG, OUTPUT_OPENDRAIN); digitalWrite(MSG, LOW); }
#define SET_MSG_INACTIVE() { digitalWrite(MSG, HIGH); pinMode(MSG, INPUT); }
#define SET_CD_ACTIVE() { pinMode(CD, OUTPUT_OPENDRAIN); digitalWrite(CD, LOW); }
#define SET_CD_INACTIVE() { digitalWrite(CD, HIGH); pinMode(CD, INPUT); }
#define SET_IO_ACTIVE() { pinMode(IO, OUTPUT_OPENDRAIN); digitalWrite(IO, LOW); }
@ -131,7 +131,7 @@ SdFs sd;
//#define SET_BSY_ACTIVE() { pinMode(BSY, OUTPUT_OPENDRAIN); digitalWrite(BSY, LOW); }
//#define SET_BSY_INACTIVE() { digitalWrite(BSY, HIGH); pinMode(BSY, INPUT); }
#define SET_BSY_ACTIVE() { GPIOC_PCOR = (1 << 4); }
#define SET_BSY_ACTIVE() { GPIOC_PCOR = (1 << 4); __asm__("nop""\n\t"); }
#define SET_BSY_INACTIVE() { GPIOC_PSOR = (1 << 4); }
#define GET_ACK() (!(GPIOC_PDIR & (1 << 3)))
@ -140,12 +140,32 @@ SdFs sd;
#define GET_RST() (!(GPIOD_PDIR & (1 << 3)))
#define GET_SEL() (!(GPIOD_PDIR & (1 << 4)))
// Initiator Mode
#define SET_ACK_ACTIVE() { GPIOC_PCOR = (1 << 3); __asm__("nop""\n\t"); }
#define SET_ACK_INACTIVE() { GPIOC_PSOR = (1 << 3); }
#define SET_ATN_ACTIVE() { GPIOC_PCOR = (1 << 7); __asm__("nop""\n\t"); }
#define SET_ATN_INACTIVE() { GPIOC_PSOR = (1 << 7); }
#define SET_RST_ACTIVE() { GPIOD_PCOR = (1 << 3); __asm__("nop""\n\t"); }
#define SET_RST_INACTIVE() { GPIOD_PSOR = (1 << 3); }
#define SET_SEL_ACTIVE() { GPIOD_PCOR = (1 << 4); __asm__("nop""\n\t"); }
#define SET_SEL_INACTIVE() { GPIOD_PSOR = (1 << 4); }
#define GET_MSG() (!(GPIOD_PDIR & (1 << 2)))
#define GET_CD() (!(GPIOD_PDIR & (1 << 7)))
#define GET_IO() (!(GPIOA_PDIR & (1 << 12)))
#define GET_REQ() (!(GPIOA_PDIR & (1 << 13)))
// Turn on the output only for BSY
// BSY,REQ,MSG,CD,IO Turn on the output (no change required for OD)
#define SCSI_TARGET_ACTIVE() { }
// BSY,REQ,MSG,CD,IO Turn off output
#define SCSI_TARGET_INACTIVE() { SCSI_DB_INPUT(); SET_REQ_INACTIVE(); SET_MSG_INACTIVE(); SET_CD_INACTIVE(); SET_IO_INACTIVE(); SET_BSY_INACTIVE(); }
#define SCSI_INITIATOR_INACTIVE() { SCSI_DB_INPUT(); SET_SEL_INACTIVE(); SET_ACK_INACTIVE(); SET_ATN_INACTIVE(); SET_RST_INACTIVE(); }
#define SCSI_DB_MASK 0x00ff0800
// HDImage file
#define HDIMG_ID_POS 2 // Position to embed ID number
#define HDIMG_LUN_POS 3 // Position to embed LUN numbers
@ -175,9 +195,10 @@ typedef struct VirtualDevice_s
#if SUPPORT_TAPE
size_t m_filemarks; // Tape position counter (file marks since BOM)
#endif
uint8_t m_inquiryresponse[96];
uint8_t m_inquiryresponse[SCSI_INQUIRY_RESPONSE_SIZE];
CommandHandler_t m_handler[256];
msense_t m_sense;
uint16_t m_quirks;
} VirtualDevice_t;
VirtualDevice_t m_vdev[NUM_VDEV]; // Maximum number
@ -198,10 +219,7 @@ uint8_t m_msb[256]; // Command storage uint8_ts
uint8_t m_cmdlen;
uint8_t m_cmd[12];
uint8_t m_responsebuffer[256];
#if SUPPORT_SASI
boolean m_sasi_mode = SUPPORT_SASI_DEFAULT;
#endif
uint16_t default_quirks = (SUPPORT_SASI_DEFAULT ? QUIRKS_SASI : 0) | (SUPPORT_APPLE_DEFAULT ? QUIRKS_APPLE : 0);
uint16_t ledbits = 0;
uint8_t ledbit = 0;
@ -216,7 +234,7 @@ typedef enum {
phase_t m_phase = PHASE_BUSFREE;
// Log File
#define VERSION "1.2-20211126"
#define VERSION "1.2-20211204"
#if DEBUG == 2
#define LOG_FILENAME "LOG.txt"
FsFile LOG_FILE;
@ -377,9 +395,6 @@ void setup()
pinModeFastSlew(DB7, OUTPUT_OPENDRAIN);
pinModeFastSlew(DB8, OUTPUT_OPENDRAIN);
// DB and DP are input modes
SCSI_DB_INPUT();
// Turn off the output port
SCSI_TARGET_INACTIVE();
@ -404,8 +419,10 @@ void setup()
scsi_id_mask = 0x00;
// If greenscsi.cfg exists, run it
if(sd.exists("/greenscsi.cfg"))
execHandler((char*)"/sd/greenscsi.cfg");
if(sd.exists("/greenscsi.cfg")) {
execscript((char*)"/sd/greenscsi.cfg");
execLoop();
}
// Scan for images if we haven't defined any targets yet.
if(m_vdevcnt == 0) findImages();
@ -435,7 +452,7 @@ void findImages() {
#if SUPPORT_DISK or SUPPORT_OPTICAL
if((file_name.startsWith("hd") || file_name.startsWith("cd")) && (file_name.endsWith(".img") || file_name.endsWith(".hda"))) {
// Defaults for Hard Disks and CD-ROMs
int id = 1; // 0 and 3 are common in Macs for physical HD and CD, so avoid them.
int id = -1; // 0 and 3 are common in Macs for physical HD and CD, so avoid them.
int lun = 0;
int blk = 512;
@ -447,15 +464,16 @@ void findImages() {
if(tmp_id > -1 && tmp_id < NUM_SCSIID) {
id = tmp_id; // If valid id, set it, else use default
if(file_name_length > 3) { // HD0[N]
int tmp_lun = file_name[HDIMG_LUN_POS] - '0';
if(tmp_lun > -1 && tmp_lun < NUM_SCSILUN) {
lun = tmp_lun; // If valid id, set it, else use default
}
}
} else {
usedDefaultId++;
}
}
if(file_name_length > 3) { // HD0[N]
int tmp_lun = file_name[HDIMG_LUN_POS] - '0';
if(tmp_lun > -1 && tmp_lun < NUM_SCSILUN) {
lun = tmp_lun; // If valid id, set it, else use default
id = ++usedDefaultId;
lun = 0;
}
}

View File

@ -530,7 +530,7 @@ void ConfigureOpticalHandlers(VirtualDevice_t *vdev) {
vdev->m_handler[CMD_SEEK10] = &Seek10CommandHandler;
vdev->m_handler[CMD_READ_TOC] = &OpticalReadTOCCommandHandler;
vdev->m_handler[CMD_READ_HEADER] = &OpticalHeaderCommandHandler;
vdev->m_handler[CMD_GET_CONFIGURATION] = &OpticalGetConfigurationCommandHandler;
//vdev->m_handler[CMD_GET_CONFIGURATION] = &OpticalGetConfigurationCommandHandler;
vdev->m_handler[CMD_GET_EVENT_STATUS_NOTIFICATION] = &OpticalEventStatusCommandHandler;
vdev->m_handler[CMD_READ_DISC_INFORMATION] = &OpticalReadDiscInfoCommandHandler;
vdev->m_handler[CMD_MODE_SELECT10] = &ModeSelect10CommandHandler;
@ -540,7 +540,12 @@ void ConfigureOpticalHandlers(VirtualDevice_t *vdev) {
// If config file exists, read the first three lines and copy the contents.
// File must be well formed or you will get junk in the SCSI Vendor fields.
void ConfigureOptical(VirtualDevice_t *vdev, const char *image_name) {
memcpy(vdev->m_inquiryresponse, SCSI_CDROM_INQUIRY_RESPONSE, sizeof(SCSI_CDROM_INQUIRY_RESPONSE));
for(int i = 0; SCSI_INQUIRY_RESPONSE[i][0] != 0xff; i++) {
if(SCSI_INQUIRY_RESPONSE[i][0] == DEV_OPTICAL) {
memcpy(vdev->m_inquiryresponse, SCSI_INQUIRY_RESPONSE[i], SCSI_INQUIRY_RESPONSE_SIZE);
break;
}
}
if(image_name) {
char configname[MAX_FILE_PATH+1];

View File

@ -21,5 +21,42 @@ PartType_t PartType[] = {
{ 0xf9, "TinySCSI Optical LUN" },
{ 0xff, NULL }
};
#endif
/*
* Public domain MBR boot manager from https://github.com/egormkn/mbr-boot-manager
*/
uint8_t mbr_bin[512] = {
0xFA, 0xBC, 0x00, 0x7C, 0x31, 0xC0, 0x8E, 0xD0, 0x8E, 0xC0, 0x8E, 0xD8, 0x52, 0xBE, 0x00, 0x7C,
0xBF, 0x00, 0x06, 0xB9, 0x00, 0x02, 0xFC, 0xF3, 0xA4, 0xE9, 0x00, 0x8A, 0xFB, 0xB8, 0x03, 0x00,
0xCD, 0x10, 0xB8, 0x00, 0x06, 0xB7, 0x02, 0x31, 0xC9, 0xBA, 0x4F, 0x18, 0xCD, 0x10, 0xB8, 0x03,
0x01, 0xB9, 0x05, 0x01, 0xCD, 0x10, 0xB9, 0x04, 0x00, 0xBD, 0xEE, 0x07, 0x31, 0xDB, 0x55, 0x80,
0x7E, 0x00, 0x80, 0x75, 0x02, 0x88, 0xCB, 0xB4, 0x02, 0xBA, 0x22, 0x08, 0x00, 0xCE, 0xCD, 0x10,
0xBE, 0x8D, 0x07, 0xE8, 0x2B, 0x01, 0xB0, 0x30, 0x00, 0xC8, 0xB4, 0x0E, 0xCD, 0x10, 0x38, 0xCB,
0x75, 0x06, 0xBE, 0x98, 0x07, 0xE8, 0x19, 0x01, 0x5D, 0x83, 0xED, 0x10, 0xE2, 0xD0, 0x38, 0xFB,
0x75, 0x03, 0x43, 0xEB, 0x0A, 0xB4, 0x02, 0xCD, 0x16, 0x24, 0x03, 0x38, 0xF8, 0x74, 0x51, 0xB4,
0x02, 0xBA, 0x20, 0x08, 0x00, 0xDE, 0xCD, 0x10, 0x88, 0xFC, 0xCD, 0x16, 0x3D, 0x00, 0x48, 0x74,
0x11, 0x3D, 0x00, 0x50, 0x74, 0x14, 0x3D, 0x1B, 0x01, 0x74, 0x2D, 0x3D, 0x0D, 0x1C, 0x74, 0x30,
0xEB, 0xDD, 0x80, 0xFB, 0x01, 0x7E, 0x01, 0x4B, 0xEB, 0xD5, 0x80, 0xFB, 0x04, 0x73, 0x01, 0x43,
0xEB, 0xCD, 0xBE, 0x9D, 0x07, 0xE8, 0xC9, 0x00, 0xB8, 0x00, 0x86, 0xB9, 0x2D, 0x00, 0x31, 0xD2,
0xCD, 0x15, 0xEB, 0x04, 0xCD, 0x18, 0xCD, 0x19, 0xEA, 0x00, 0x00, 0xFF, 0xFF, 0xF4, 0xEB, 0xFD,
0x53, 0xB4, 0x02, 0xBA, 0x01, 0x01, 0xCD, 0x10, 0xB8, 0x00, 0x06, 0xB7, 0x02, 0x31, 0xC9, 0xBA,
0x4F, 0x18, 0xCD, 0x10, 0xBD, 0xAE, 0x07, 0x5B, 0xC1, 0xE3, 0x04, 0x01, 0xDD, 0x5A, 0x88, 0x56,
0x00, 0x55, 0xC6, 0x46, 0x11, 0x05, 0x88, 0x7E, 0x10, 0xB4, 0x41, 0xBB, 0xAA, 0x55, 0xCD, 0x13,
0x5D, 0x72, 0x0F, 0x81, 0xFB, 0x55, 0xAA, 0x75, 0x09, 0xF7, 0xC1, 0x01, 0x00, 0x74, 0x03, 0xFE,
0x46, 0x10, 0x66, 0x60, 0x80, 0x7E, 0x0A, 0x00, 0x74, 0x20, 0x66, 0x6A, 0x00, 0x66, 0xFF, 0x76,
0x08, 0x6A, 0x00, 0x68, 0x00, 0x7C, 0x6A, 0x01, 0x6A, 0x10, 0xB4, 0x42, 0x8A, 0x56, 0x00, 0x89,
0xE6, 0xCD, 0x13, 0x9F, 0x83, 0xC4, 0x10, 0x9E, 0xEB, 0x14, 0xB8, 0x01, 0x02, 0xBB, 0x00, 0x7C,
0x8A, 0x56, 0x00, 0x8A, 0x76, 0x01, 0x8A, 0x4E, 0x02, 0x8A, 0x6E, 0x03, 0xCD, 0x13, 0x66, 0x61,
0x73, 0x12, 0xFE, 0x4E, 0x11, 0x0F, 0x84, 0x59, 0xFF, 0x55, 0x30, 0xE4, 0x8A, 0x56, 0x00, 0xCD,
0x13, 0x5D, 0xEB, 0xAE, 0x81, 0x3E, 0xFE, 0x7D, 0x55, 0xAA, 0x0F, 0x85, 0x44, 0xFF, 0x83, 0x3E,
0x00, 0x7C, 0x00, 0x0F, 0x84, 0x3B, 0xFF, 0x8B, 0x56, 0x00, 0x30, 0xF6, 0xEA, 0x00, 0x7C, 0x00,
0x00, 0xB4, 0x0E, 0xAC, 0x3C, 0x00, 0x74, 0x04, 0xCD, 0x10, 0xEB, 0xF7, 0xC3, 0x50, 0x61, 0x72,
0x74, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x00, 0x20, 0x28, 0x41, 0x29, 0x00, 0x42, 0x6F, 0x6F,
0x74, 0x20, 0x73, 0x65, 0x63, 0x74, 0x6F, 0x72, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x0D, 0x0A,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA
};

View File

@ -42,6 +42,7 @@
#define CMD_READUPDATEDBLOCK10 0x2D
#define CMD_WRITEANDVERIFY10 0x2E /* Optional */
#define CMD_VERIFY10 0x2F
#define CMD_SEARCH_DATA_EQUAL 0x31 /* Optional */
#define CMD_PREFETCH_CACHE10 0x34 /* Optional */
#define CMD_READPOSITION10 0x34 /* Optional */
#define CMD_SYNCHRONIZE_CACHE10 0x35 /* Optional */
@ -165,4 +166,7 @@
extern const uint8_t db2scsiid[256];
#endif
#define QUIRKS_SASI 0b00000001
#define QUIRKS_APPLE 0b00000010
#endif

View File

@ -1,8 +1,6 @@
#include "config.h"
#include "scsi_defs.h"
#define SCSI_DB_MASK 0x00ff0800
/*
* Data uint8_t to GPIOB register setting value and parity table
*/
@ -68,7 +66,7 @@ void onBusReset(void)
#if SUPPORT_SASI
// SASI I / F for X1 turbo has RST pulse write cycle +2 clock ==
// I can't filter because it only activates about 1.25us
if(!m_sasi_mode) {
if(!(m_sel->m_quirks & QUIRKS_SASI)) {
#endif
if(digitalRead(RST)) return;
delayMicroseconds(20);
@ -101,11 +99,11 @@ inline void readHandshakeBlock(uint8_t *d, uint16_t len)
{
while(len) {
SET_REQ_ACTIVE();
while(!GET_ACK()) { if(m_isBusReset) { return 0; } }
while(!GET_ACK()) { if(m_isBusReset) { return; } }
*d++ = readIO();
len--;
SET_REQ_INACTIVE();
while(GET_ACK()) { if(m_isBusReset) { return 0; } }
while(GET_ACK()) { if(m_isBusReset) { return; } }
}
}
@ -118,10 +116,10 @@ inline void writeHandshake(uint8_t d)
SCSI_DB_OUTPUT(d);
SET_REQ_ACTIVE();
while(!GET_ACK()) { if(m_isBusReset) { return 0; } }
while(!GET_ACK()) { if(m_isBusReset) { return; } }
SET_REQ_INACTIVE();
SCSI_DB_INPUT();
while(GET_ACK()) { if(m_isBusReset) { return 0; } }
while(GET_ACK()) { if(m_isBusReset) { return; } }
}
inline void writeHandshakeBlock(const uint8_t *d, uint16_t len)
@ -130,10 +128,10 @@ inline void writeHandshakeBlock(const uint8_t *d, uint16_t len)
while(len) {
SCSI_DB_OUTPUT(*d++);
SET_REQ_ACTIVE();
while(!GET_ACK()) { if(m_isBusReset) { return 0; } }
while(!GET_ACK()) { if(m_isBusReset) { return; } }
len--;
SET_REQ_INACTIVE();
while(GET_ACK()) { if(m_isBusReset) { return 0; } }
while(GET_ACK()) { if(m_isBusReset) { return; } }
}
SCSI_DB_INPUT();
}

View File

@ -272,7 +272,12 @@ void ConfigureTapeHandlers(VirtualDevice_t *vdev) {
// If config file exists, read the first three lines and copy the contents.
// File must be well formed or you will get junk in the SCSI Vendor fields.
void ConfigureTape(VirtualDevice_t *vdev, const char *image_name) {
memcpy(vdev->m_inquiryresponse, SCSI_TAPE_INQUIRY_RESPONSE, sizeof(SCSI_CDROM_INQUIRY_RESPONSE));
for(int i = 0; SCSI_INQUIRY_RESPONSE[i][0] != 0xff; i++) {
if(SCSI_INQUIRY_RESPONSE[i][0] == DEV_TAPE) {
memcpy(vdev->m_inquiryresponse, SCSI_INQUIRY_RESPONSE[i], SCSI_INQUIRY_RESPONSE_SIZE);
break;
}
}
if(image_name) {
char configname[MAX_FILE_PATH+1];