Merge branch 'master' of ssh://webhost.codesrc.com/home/michael/projects/SCSI2SD
[SCSI2SD.git] / software / SCSI2SD / src / scsi.c
index 15622d5..48b4c6d 100755 (executable)
@@ -53,7 +53,7 @@ static void enter_BusFree()
 {\r
        // This delay probably isn't needed for most SCSI hosts, but it won't\r
        // hurt either. It's possible some of the samplers needed this delay.\r
-       if (scsiDev.compatMode)\r
+       if (scsiDev.compatMode < COMPAT_SCSI2)\r
        {\r
                CyDelayUs(2);\r
        }\r
@@ -214,7 +214,7 @@ static void process_DataOut()
 \r
                if (scsiDev.parityError &&\r
                        (scsiDev.target->cfg->flags & CONFIG_ENABLE_PARITY) &&\r
-                       !scsiDev.compatMode)\r
+                       (scsiDev.compatMode >= COMPAT_SCSI2))\r
                {\r
                        scsiDev.target->sense.code = ABORTED_COMMAND;\r
                        scsiDev.target->sense.asc = SCSI_PARITY_ERROR;\r
@@ -264,6 +264,7 @@ static void process_Command()
        control = scsiDev.cdb[scsiDev.cdbLen - 1];\r
 \r
        scsiDev.cmdCount++;\r
+       TargetConfig* cfg = scsiDev.target->cfg;\r
 \r
        if (unlikely(scsiDev.resetFlag))\r
        {\r
@@ -273,8 +274,8 @@ static void process_Command()
                return;\r
        }\r
        else if (scsiDev.parityError &&\r
-               (scsiDev.target->cfg->flags & CONFIG_ENABLE_PARITY) &&\r
-               !scsiDev.compatMode)\r
+               (cfg->flags & CONFIG_ENABLE_PARITY) &&\r
+               (scsiDev.compatMode >= COMPAT_SCSI2))\r
        {\r
                scsiDev.target->sense.code = ABORTED_COMMAND;\r
                scsiDev.target->sense.asc = SCSI_PARITY_ERROR;\r
@@ -326,7 +327,7 @@ static void process_Command()
        // on receiving the unit attention response on boot, thus\r
        // triggering another unit attention condition.\r
        else if (scsiDev.target->unitAttention &&\r
-               (scsiDev.target->cfg->flags & CONFIG_ENABLE_UNIT_ATTENTION))\r
+               (cfg->flags & CONFIG_ENABLE_UNIT_ATTENTION))\r
        {\r
                scsiDev.target->sense.code = UNIT_ATTENTION;\r
                scsiDev.target->sense.asc = scsiDev.target->unitAttention;\r
@@ -352,6 +353,14 @@ static void process_Command()
        {\r
                enter_Status(CONFLICT);\r
        }\r
+       // Handle odd device types first that may override basic read and\r
+       // write commands. Will fall-through to generic disk handling.\r
+       else if (((cfg->deviceType == CONFIG_OPTICAL) && scsiCDRomCommand()) ||\r
+               ((cfg->deviceType == CONFIG_SEQUENTIAL) && scsiTapeCommand()) ||\r
+               ((cfg->deviceType == CONFIG_MO) && scsiMOCommand()))\r
+       {\r
+               // Already handled.\r
+       }\r
        else if (scsiDiskCommand())\r
        {\r
                // Already handled.\r
@@ -374,9 +383,7 @@ static void process_Command()
        {\r
                scsiReadBuffer();\r
        }\r
-       else if (\r
-               !scsiCDRomCommand() &&\r
-               !scsiModeCommand())\r
+       else if (!scsiModeCommand())\r
        {\r
                scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
                scsiDev.target->sense.asc = INVALID_COMMAND_OPERATION_CODE;\r
@@ -459,6 +466,7 @@ static void scsiReset()
        scsiDev.atnFlag = 0;\r
        scsiDev.resetFlag = 0;\r
        scsiDev.lun = -1;\r
+       scsiDev.compatMode = COMPAT_UNKNOWN;\r
 \r
        if (scsiDev.target)\r
        {\r
@@ -500,7 +508,6 @@ static void enter_SelectionPhase()
        scsiDev.phase = SELECTION;\r
        scsiDev.lun = -1;\r
        scsiDev.discPriv = 0;\r
-       scsiDev.compatMode = 0;\r
 \r
        scsiDev.initiatorId = -1;\r
        scsiDev.target = NULL;\r
@@ -513,6 +520,12 @@ static void enter_SelectionPhase()
 \r
 static void process_SelectionPhase()\r
 {\r
+       if (scsiDev.compatMode < COMPAT_SCSI2)\r
+       {\r
+               // Required for some older SCSI1 devices using a 5380 chip.\r
+               CyDelay(1);\r
+       }\r
+\r
        int sel = SCSI_ReadFilt(SCSI_Filt_SEL);\r
        int bsy = SCSI_ReadFilt(SCSI_Filt_BSY);\r
 \r
@@ -552,7 +565,15 @@ static void process_SelectionPhase()
                if (!scsiDev.atnFlag)\r
                {\r
                        target->unitAttention = 0;\r
-                       scsiDev.compatMode = 1;\r
+                       scsiDev.compatMode = COMPAT_SCSI1;\r
+               }\r
+               else if (!(target->cfg->flags & CONFIG_ENABLE_SCSI2))\r
+               {\r
+                       scsiDev.compatMode = COMPAT_SCSI1;\r
+               }\r
+               else if (scsiDev.compatMode == COMPAT_UNKNOWN)\r
+               {\r
+                       scsiDev.compatMode = COMPAT_SCSI2;\r
                }\r
 \r
                // We've been selected!\r
@@ -611,7 +632,7 @@ static void process_MessageOut()
 \r
        if (scsiDev.parityError &&\r
                (scsiDev.target->cfg->flags & CONFIG_ENABLE_PARITY) &&\r
-               !scsiDev.compatMode)\r
+               (scsiDev.compatMode >= COMPAT_SCSI2))\r
        {\r
                // Skip the remaining message bytes, and then start the MESSAGE_OUT\r
                // phase again from the start. The initiator will re-send the\r
@@ -713,7 +734,7 @@ static void process_MessageOut()
                        // Discard bytes.\r
                        extmsg[i] = scsiReadByte();\r
                }\r
-               \r
+\r
                if (extmsg[0] == 3 && msgLen == 2) // Wide Data Request\r
                {\r
                        // Negotiate down to 8bit\r
@@ -721,7 +742,7 @@ static void process_MessageOut()
                        static const uint8_t WDTR[] = {0x01, 0x02, 0x03, 0x00};\r
                        scsiWrite(WDTR, sizeof(WDTR));\r
                }\r
-               else if (extmsg[0] == 1 && msgLen == 5) // Synchronous data request\r
+               else if (extmsg[0] == 1 && msgLen == 3) // Synchronous data request\r
                {\r
                        // Negotiate back to async\r
                        scsiEnterPhase(MESSAGE_IN);\r
@@ -872,6 +893,7 @@ void scsiInit()
        scsiDev.resetFlag = 1;\r
        scsiDev.phase = BUS_FREE;\r
        scsiDev.target = NULL;\r
+       scsiDev.compatMode = COMPAT_UNKNOWN;\r
 \r
        int i;\r
        for (i = 0; i < MAX_SCSI_TARGETS; ++i)\r