|
@@ -124,7 +124,7 @@ inline byte readIO(void)
|
|
|
{
|
|
|
// Port input data register
|
|
|
uint32_t ret = GPIOD->regs->IDR;
|
|
|
- byte bret = (byte)~(((ret >> 8) & 0b11111111));
|
|
|
+ byte bret = (byte)~(((ret )));
|
|
|
#if READ_PARITY_CHECK
|
|
|
if((db_bsrr[bret]^ret)&1) // TODO fix parity calculation
|
|
|
m_sts |= 0x01; // parity error
|
|
@@ -283,6 +283,13 @@ void setup()
|
|
|
for (unsigned i = 0; i <= 255; i++) {
|
|
|
db_bsrr[i] = genBSRR(i);
|
|
|
}
|
|
|
+ // Serial initialization
|
|
|
+#if DEBUG == 1
|
|
|
+ serial.begin(115200);
|
|
|
+ serial.flush();
|
|
|
+ // If using a USB->TTL monitor instead of USB serial monitor - you can uncomment this.
|
|
|
+ //while (!Serial);
|
|
|
+#endif
|
|
|
gpioInit();
|
|
|
// Default all SCSI command handlers to onUnimplemented
|
|
|
for(unsigned i = 0; i < MAX_SCSI_COMMAND; i++)
|
|
@@ -348,12 +355,7 @@ void setup()
|
|
|
default_optical.release = 0x20;
|
|
|
memcpy(&default_optical.revision_date, "1995", 4);
|
|
|
|
|
|
- // Serial initialization
|
|
|
-#if DEBUG == 1
|
|
|
- serial.begin(115200);
|
|
|
- // If using a USB->TTL monitor instead of USB serial monitor - you can uncomment this.
|
|
|
- //while (!Serial);
|
|
|
-#endif
|
|
|
+
|
|
|
delay(3000);
|
|
|
|
|
|
|
|
@@ -364,13 +366,13 @@ void setup()
|
|
|
|
|
|
|
|
|
// Transceiver Pin Initialization
|
|
|
- pinMode(BOARD_SCSI_TAD, OUTPUT);
|
|
|
- pinMode(BOARD_SCSI_IND, OUTPUT);
|
|
|
- pinMode(BOARD_SCSI_DTD, OUTPUT);
|
|
|
+ pinMode(BOARD_SCSI_TAD, OUTPUT_OPEN_DRAIN);
|
|
|
+ pinMode(BOARD_SCSI_IND, OUTPUT_OPEN_DRAIN);
|
|
|
+ pinMode(BOARD_SCSI_DTD, OUTPUT_OPEN_DRAIN);
|
|
|
|
|
|
TRANSCEIVER_IO_SET(vIND,TR_INPUT);
|
|
|
TRANSCEIVER_IO_SET(vTAD,TR_INPUT);
|
|
|
-
|
|
|
+ TERMINATION_LOW();
|
|
|
|
|
|
|
|
|
|
|
@@ -385,6 +387,7 @@ void setup()
|
|
|
int mhz = 0;
|
|
|
// Try each speed bucket a few times, and go way down for very old SD cards
|
|
|
// Most will initialize immediately at the highest speed
|
|
|
+
|
|
|
int speedsToTry[] = {50, 49, 43, 42, 25, 24, 17, 16, 8, 7, 5, 4, 3, 1 };
|
|
|
for (int i = 0; i < sizeof(speedsToTry); i++) {
|
|
|
if(SD.begin(SdSpiConfig(SS, DEDICATED_SPI, SD_SCK_MHZ(speedsToTry[i])))) {
|
|
@@ -392,6 +395,7 @@ void setup()
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
LED1_OFF();
|
|
|
|
|
|
if(mhz == 0) {
|
|
@@ -401,9 +405,7 @@ void setup()
|
|
|
flashError(ERROR_NO_SDCARD);
|
|
|
}
|
|
|
initFileLog(mhz);
|
|
|
- serial.println("YYYYY");
|
|
|
readSDCardInfo();
|
|
|
- serial.println("XXXX");
|
|
|
|
|
|
//HD image file open
|
|
|
scsi_id_mask = 0x00;
|
|
@@ -667,8 +669,8 @@ void enableResetJmp(void) {
|
|
|
*/
|
|
|
inline byte readHandshake(void)
|
|
|
{
|
|
|
- SCSI_OUT(vREQ,active)
|
|
|
- //SCSI_DB_INPUT()
|
|
|
+
|
|
|
+ SCSI_OUT(vREQ,active);
|
|
|
while( ! SCSI_IN(vACK));
|
|
|
byte r = readIO();
|
|
|
SCSI_OUT(vREQ,inactive)
|
|
@@ -682,20 +684,23 @@ inline byte readHandshake(void)
|
|
|
inline void writeHandshake(byte d)
|
|
|
{
|
|
|
// This has a 400ns bus settle delay built in. Not optimal for multi-byte transfers.
|
|
|
- GPIOD->regs->BSRR = db_bsrr[d]; // setup DB,DBP (160ns) //PM2022 need to add parity from PE
|
|
|
+ serial.flush();
|
|
|
+
|
|
|
+ GPIOD->regs->BSRR = db_bsrr[d]; // setup DB,DBP (160ns)
|
|
|
TRANSCEIVER_IO_SET(vDTD,DB_OUTPUT)
|
|
|
- SCSI_DB_OUTPUT() // (180ns)
|
|
|
+ TRANSCEIVER_IO_SET(vIND,TR_OUTPUT)
|
|
|
+
|
|
|
// ACK.Fall to DB output delay 100ns(MAX) (DTC-510B)
|
|
|
- SCSI_OUT(vREQ,inactive) // setup wait (30ns)w
|
|
|
+ SCSI_OUT(vREQ,inactive) // setup wait (30ns)
|
|
|
SCSI_OUT(vREQ,inactive) // setup wait (30ns)
|
|
|
SCSI_OUT(vREQ,inactive) // setup wait (30ns)
|
|
|
SCSI_OUT(vREQ,active) // (30ns)
|
|
|
//while(!SCSI_IN(vACK)) { if(m_isBusReset){ SCSI_DB_INPUT() return; }}
|
|
|
while(!SCSI_IN(vACK));
|
|
|
// ACK.Fall to REQ.Raise delay 500ns(typ.) (DTC-510B)
|
|
|
- uint32_t bsrrCall = ((db_bsrr[0xff] & 0xFFDFFFFF) | 0x00000020);
|
|
|
+ uint32_t bsrrCall = (db_bsrr[0xff] );
|
|
|
GPIOE->regs->BSRR = bsrrCall; // DB=0xFF , SCSI_OUT(vREQ,inactive) //PM2022 should wirite data to bus
|
|
|
-
|
|
|
+ SCSI_OUT(vREQ,inactive)
|
|
|
// REQ.Raise to DB hold time 0ns
|
|
|
SCSI_DB_INPUT() // (150ns)
|
|
|
TRANSCEIVER_IO_SET(vDTD,DB_INPUT)
|
|
@@ -715,9 +720,9 @@ inline void writeHandshake(byte d)
|
|
|
*/
|
|
|
|
|
|
void writeDataLoop(uint32_t blocksize, const byte* srcptr) {
|
|
|
-#define REQ_ON() (PBREG->BSRR = req_rst_bit);
|
|
|
+#define REQ_ON() (PEREG->BSRR = req_rst_bit);
|
|
|
#define FETCH_BSRR_DB() (bsrr_val = bsrr_tbl[*srcptr++])
|
|
|
-#define REQ_OFF_DB_SET(BSRR_VAL) PBREG->BSRR = BSRR_VAL;
|
|
|
+#define REQ_OFF_DB_SET(BSRR_VAL) (PEREG->BSRR = req_bit);PDREG->BSRR = BSRR_VAL;
|
|
|
#define WAIT_ACK_ACTIVE() while((*port_b_idr>>(vACK&15)&1))
|
|
|
#define WAIT_ACK_INACTIVE() while(!(*port_b_idr>>(vACK&15)&1))
|
|
|
|
|
@@ -727,6 +732,7 @@ void writeDataLoop(uint32_t blocksize, const byte* srcptr) {
|
|
|
register uint32_t bsrr_val; // BSRR value to output (DB, DBP, REQ = ACTIVE)
|
|
|
|
|
|
register uint32_t req_bit = BITMASK(vREQ);
|
|
|
+
|
|
|
register uint32_t req_rst_bit = BITMASK(vREQ) << 16;
|
|
|
register volatile uint32 *port_b_idr = &(GPIOB->regs->IDR);
|
|
|
|
|
@@ -740,6 +746,7 @@ void writeDataLoop(uint32_t blocksize, const byte* srcptr) {
|
|
|
// Align the starts of the do/while and WAIT loops to an 8 byte prefetch.
|
|
|
|
|
|
do{
|
|
|
+
|
|
|
WAIT_ACK_INACTIVE();
|
|
|
REQ_ON();
|
|
|
// 4 cycles of work
|
|
@@ -779,14 +786,15 @@ void writeDataPhase(int len, const byte* p)
|
|
|
void writeDataPhaseSD(SCSI_DEVICE *dev, uint32_t adds, uint32_t len)
|
|
|
{
|
|
|
LOG (" DI(SD) ");
|
|
|
+
|
|
|
SCSI_PHASE_CHANGE(SCSI_PHASE_DATAIN);
|
|
|
//Bus settle delay 400ns, file.seek() measured at over 1000ns.
|
|
|
uint64_t pos = (uint64_t)adds * dev->m_rawblocksize;
|
|
|
- dev->m_file->seekSet(pos);
|
|
|
+ dev->m_file->seekSet(pos);
|
|
|
|
|
|
TRANSCEIVER_IO_SET(vDTD,DB_OUTPUT)
|
|
|
SCSI_DB_OUTPUT()
|
|
|
-
|
|
|
+
|
|
|
for(uint32_t i = 0; i < len; i++) {
|
|
|
// Asynchronous reads will make it faster ...
|
|
|
m_resetJmp = false;
|
|
@@ -912,28 +920,23 @@ void MsgIn2(int msg)
|
|
|
*/
|
|
|
void loop()
|
|
|
{
|
|
|
+
|
|
|
// Reset all DB and Target pins, switch transceivers to input
|
|
|
// Precaution against bugs or jumps which don't clean up properly
|
|
|
SCSI_DB_INPUT();
|
|
|
TRANSCEIVER_IO_SET(vDTD,DB_INPUT)
|
|
|
SCSI_TARGET_INACTIVE();
|
|
|
-
|
|
|
+ TRANSCEIVER_IO_SET(vIND,TR_INPUT)
|
|
|
// Reset target state bits (BSY, MSG, CD, REQ, IO)
|
|
|
|
|
|
- GPIOE->regs->BSRR = 0x00000074; // MSG, CD, REQ, IO
|
|
|
- GPIOB->regs->BSRR = 0x00000040; // BOARD_SCSI_BSY
|
|
|
- TRANSCEIVER_IO_SET(vTAD,TR_INPUT)
|
|
|
- TRANSCEIVER_IO_SET(vIND,TR_INPUT)
|
|
|
LED3_ON();
|
|
|
|
|
|
//int msg = 0;
|
|
|
m_msg = 0;
|
|
|
m_lun = 0xff;
|
|
|
SCSI_DEVICE *dev = (SCSI_DEVICE *)0; // HDD image for current SCSI-ID, LUN
|
|
|
+
|
|
|
do {
|
|
|
- serial.print(SCSI_IN(vBSY));
|
|
|
- serial.print(SCSI_IN(vSEL));
|
|
|
- serial.println(SCSI_IN(vRST));
|
|
|
} while( SCSI_IN(vBSY) || !SCSI_IN(vSEL) || SCSI_IN(vRST));
|
|
|
//do {} while( !SCSI_IN(vBSY) || SCSI_IN(vRST));
|
|
|
// We're in ARBITRATION
|
|
@@ -942,24 +945,25 @@ void loop()
|
|
|
//do {} while( SCSI_IN(vBSY) || !SCSI_IN(vSEL) || SCSI_IN(vRST));
|
|
|
//LOG(" S:"); LOGHEX(readIO()); LOG(" ");
|
|
|
// We're in SELECTION
|
|
|
-
|
|
|
+
|
|
|
byte scsiid = readIO() & scsi_id_mask;
|
|
|
+
|
|
|
if(SCSI_IN(vIO) || (scsiid) == 0) {
|
|
|
delayMicroseconds(1);
|
|
|
return;
|
|
|
}
|
|
|
// We've been selected
|
|
|
-
|
|
|
+ SCSI_OUT(vATN,inactive);
|
|
|
+ SCSI_OUT(vACK,inactive);
|
|
|
TRANSCEIVER_IO_SET(vTAD,TR_OUTPUT);
|
|
|
- TRANSCEIVER_IO_SET(vIND,TR_OUTPUT);
|
|
|
+ LOGN("SELECTED");
|
|
|
+
|
|
|
SCSI_TARGET_ACTIVE() // (BSY), REQ, MSG, CD, IO output turned on
|
|
|
|
|
|
// Set BSY to-when selected
|
|
|
SCSI_BSY_ACTIVE(); // Turn only BSY output ON, ACTIVE
|
|
|
-
|
|
|
// Wait until SEL becomes inactive
|
|
|
while(isHigh(digitalRead(BOARD_SCSI_SEL))) {}
|
|
|
-
|
|
|
// Ask for a TARGET-ID to respond
|
|
|
m_id = 31 - __builtin_clz(scsiid);
|
|
|
|
|
@@ -967,9 +971,9 @@ void loop()
|
|
|
if (setjmp(m_resetJmpBuf) == 1) {
|
|
|
LOGN("Reset, going to BusFree");
|
|
|
goto BusFree;
|
|
|
- }
|
|
|
- enableResetJmp();
|
|
|
+ }
|
|
|
|
|
|
+ enableResetJmp();
|
|
|
// In SCSI-2 this is mandatory, but in SCSI-1 it's optional
|
|
|
if(isHigh(digitalRead(BOARD_SCSI_ATN))) {
|
|
|
SCSI_PHASE_CHANGE(SCSI_PHASE_MESSAGEOUT);
|
|
@@ -1024,9 +1028,13 @@ void loop()
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
LOG("CMD:");
|
|
|
+
|
|
|
SCSI_PHASE_CHANGE(SCSI_PHASE_COMMAND);
|
|
|
+ SCSI_BSY_ACTIVE();
|
|
|
+ TRANSCEIVER_IO_SET(vTAD,TR_INPUT);
|
|
|
+ TRANSCEIVER_IO_SET(vIND,TR_OUTPUT);
|
|
|
+
|
|
|
// Bus settle delay 400ns. The following code was measured at 20ns before REQ asserted. Added another 380ns. STM32F103.
|
|
|
asm("nop;nop;nop;nop;nop;nop;nop;nop");// This asm causes some code reodering, which adds 270ns, plus 8 nop cycles for an additional 110ns. STM32F103
|
|
|
int len;
|
|
@@ -1055,6 +1063,7 @@ void loop()
|
|
|
LOG(":");
|
|
|
LOGHEX(cmd[i]);
|
|
|
}
|
|
|
+
|
|
|
// LUN confirmation
|
|
|
// if it wasn't set in the IDENTIFY then grab it from the CDB
|
|
|
if(m_lun > MAX_SCSILUN)
|
|
@@ -1069,7 +1078,7 @@ void loop()
|
|
|
LOG(" ");
|
|
|
|
|
|
// HDD Image selection
|
|
|
- if(m_lun >= NUM_SCSILUN)
|
|
|
+ if(m_lun >= NUM_SCSILUN && 1==0)
|
|
|
{
|
|
|
m_sts = SCSI_STATUS_GOOD;
|
|
|
|
|
@@ -1113,7 +1122,6 @@ void loop()
|
|
|
|
|
|
goto Status;
|
|
|
}
|
|
|
-
|
|
|
dev = &(scsi_device_list[m_id][m_lun]);
|
|
|
if(!dev->m_file)
|
|
|
{
|
|
@@ -1129,12 +1137,15 @@ void loop()
|
|
|
|
|
|
Status:
|
|
|
LOG(" STS:"); LOGHEX(m_sts);
|
|
|
- SCSI_PHASE_CHANGE(SCSI_PHASE_STATUS);
|
|
|
+
|
|
|
+ //SCSI_PHASE_CHANGE(SCSI_PHASE_STATUS);
|
|
|
+ SCSI_OUT(vCD,inactive);
|
|
|
// Bus settle delay 400ns built in to writeHandshake
|
|
|
writeHandshake(m_sts);
|
|
|
|
|
|
LOG(" MI:"); LOGHEX(m_msg);
|
|
|
- SCSI_PHASE_CHANGE(SCSI_PHASE_MESSAGEIN);
|
|
|
+ //SCSI_PHASE_CHANGE(SCSI_PHASE_MESSAGEIN);
|
|
|
+ SCSI_OUT(vMSG,active);
|
|
|
// Bus settle delay 400ns built in to writeHandshake
|
|
|
writeHandshake(m_msg);
|
|
|
|