mirror of
https://github.com/dkgrizzly/GreenSCSI.git
synced 2024-12-26 16:29:45 +00:00
Command shell updates and quirks modes
This commit is contained in:
parent
178cffa658
commit
0c04852ad8
751
src/cmd.ino
751
src/cmd.ino
File diff suppressed because it is too large
Load Diff
@ -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 */
|
||||
|
134
src/defaults.ino
134
src/defaults.ino
@ -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
|
||||
}
|
||||
|
||||
};
|
||||
|
17
src/disk.ino
17
src/disk.ino
@ -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
403
src/dump.ino
Executable 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
464
src/eggs.ino
Executable 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);
|
||||
}
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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];
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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];
|
||||
|
Loading…
Reference in New Issue
Block a user