static uint8_t asyncTimings[][4] =\r
{\r
/* Speed, Assert, Deskew, Hold, Glitch */\r
-{/*1.5MB/s*/ 28, 18, 13, 13},\r
+{/*1.5MB/s*/ 28, 18, 13, 15},\r
{/*3.3MB/s*/ 13, 6, 6, 13},\r
{/*5MB/s*/ 9, 6, 6, 6}, // 80ns\r
{/*safe*/ 3, 6, 6, 6}, // Probably safe\r
\r
#define SCSI_FAST10_DESKEW 2 // 25ns\r
#define SCSI_FAST10_HOLD 3 // 33ns\r
-#define SCSI_FAST10_ASSERT 3 // 30ns\r
+#define SCSI_FAST10_WRITE_ASSERT 3 // 30ns. Overall clocks only works if fpga overhead is 3.\r
+\r
+// Slow down the cycle to be valid. 2x assert period is TOO FAST when\r
+// reading data. It's ok when writing due to the deskew.\r
+// 50ns. ie. 100ns / 2. Rounded down because there's likely a few extra cycles\r
+// here and there.\r
+#define SCSI_FAST10_READ_ASSERT 5\r
\r
// Fastest possible timing, probably not 20MB/s\r
#define SCSI_FAST20_DESKEW 1\r
: SCSI_FAST5_HOLD)\r
\r
\r
+// Number of overhead cycles per period.\r
+#define FPGA_OVERHEAD 2\r
+#define FPGA_CYCLES_PER_NS 9\r
+#define SCSI_PERIOD_CLKS(period) ((((int)period * 4) + (FPGA_CYCLES_PER_NS/2)) / FPGA_CYCLES_PER_NS)\r
+\r
// 3.125MB/s (80 period) to < 10MB/s sync\r
// Assumes a 108MHz fpga clock. (9 ns)\r
-// (((period * 4) / 2) * 0.8) / 9\r
-// Done using 3 fixed point math.\r
// 3:0 Assertion count, variable\r
-#define syncAssertion(period) ((((((int)period) * 177) + 750)/1000) & 0xF)\r
+#define syncAssertionWrite(period,deskew) ((SCSI_PERIOD_CLKS(period) - deskew - FPGA_OVERHEAD + 1) / 2)\r
+#define syncAssertionRead(period) syncAssertionWrite(period,0)\r
+\r
\r
// Time until we consider ourselves selected\r
// 400ns at 108MHz\r
asyncTiming[3]);\r
}\r
\r
-void scsiEnterPhase(int phase)\r
+void scsiEnterPhase(int newPhase)\r
{\r
// ANSI INCITS 362-2002 SPI-3 10.7.1:\r
// Phase changes are not allowed while REQ or ACK is asserted.\r
while (likely(!scsiDev.resetFlag) && scsiStatusACK()) {}\r
\r
- int newPhase = phase > 0 ? phase : 0;\r
int oldPhase = *SCSI_CTRL_PHASE;\r
\r
if (!scsiDev.resetFlag && (!scsiPhyFifoEmpty() || !scsiPhyFifoAltEmpty())) {\r
}\r
else if (scsiDev.target->syncPeriod <= 25)\r
{\r
- scsiSetTiming(SCSI_FAST10_ASSERT, SCSI_FAST10_DESKEW, SCSI_FAST10_HOLD, 1);\r
+ if (newPhase == DATA_IN)\r
+ {\r
+ scsiSetTiming(SCSI_FAST10_WRITE_ASSERT, SCSI_FAST10_DESKEW, SCSI_FAST10_HOLD, 1);\r
+ }\r
+ else\r
+ {\r
+ scsiSetTiming(SCSI_FAST10_READ_ASSERT, SCSI_FAST10_DESKEW, SCSI_FAST10_HOLD, 1);\r
+ }\r
}\r
else\r
{\r
int glitch =\r
scsiDev.target->syncPeriod < 35 ? 1 :\r
(scsiDev.target->syncPeriod < 45 ? 2 : 5);\r
+ int deskew = syncDeskew(scsiDev.target->syncPeriod);\r
+ int assertion;\r
+ if (newPhase == DATA_IN)\r
+ {\r
+ assertion = syncAssertionWrite(scsiDev.target->syncPeriod, deskew);\r
+ }\r
+ else\r
+ {\r
+ assertion = syncAssertionRead(scsiDev.target->syncPeriod);\r
+ }\r
scsiSetTiming(\r
- syncAssertion(scsiDev.target->syncPeriod),\r
- syncDeskew(scsiDev.target->syncPeriod),\r
+ assertion,\r
+ deskew,\r
syncHold(scsiDev.target->syncPeriod),\r
glitch);\r
}\r
\r
- // See note 26 in SCSI 2 standard: SCSI 1 implementations may assume\r
- // "leading edge of the first REQ pulse beyond the REQ/ACK offset\r
- // agreement would not occur until after the trailing edge of the\r
- // last ACK pulse within the agreement."\r
- // We simply subtract 1 from the offset to meet this requirement.\r
- if (scsiDev.target->syncOffset >= 2)\r
- {\r
- *SCSI_CTRL_SYNC_OFFSET = scsiDev.target->syncOffset - 1;\r
- } else {\r
- *SCSI_CTRL_SYNC_OFFSET = scsiDev.target->syncOffset;\r
- }\r
+ *SCSI_CTRL_SYNC_OFFSET = scsiDev.target->syncOffset;\r
}\r
- else\r
+ else if (newPhase >= 0)\r
{\r
\r
*SCSI_CTRL_SYNC_OFFSET = 0;\r
asyncTiming[3]);\r
}\r
\r
- *SCSI_CTRL_PHASE = newPhase;\r
- busSettleDelay();\r
+ if (newPhase >= 0)\r
+ {\r
+ *SCSI_CTRL_PHASE = newPhase;\r
+ busSettleDelay();\r
\r
- if (scsiDev.compatMode < COMPAT_SCSI2)\r
+ if (scsiDev.compatMode < COMPAT_SCSI2)\r
+ {\r
+ s2s_delay_us(100);\r
+ }\r
+ }\r
+ else\r
{\r
- s2s_delay_us(100);\r
+ *SCSI_CTRL_PHASE = 0;\r
}\r
-\r
}\r
}\r
\r
dmaInProgress = 0;\r
}\r
\r
- *SCSI_CTRL_PHASE = 0x00;\r
- *SCSI_CTRL_BSY = 0x00;\r
s2s_fpgaReset(); // Clears fifos etc.\r
\r
+ *SCSI_CTRL_PHASE = 0x00;\r
+ *SCSI_CTRL_BSY = 0x00;\r
scsiPhyFifoSel = 0;\r
*SCSI_FIFO_SEL = 0;\r
*SCSI_CTRL_DBX = 0;\r