\r
#include "device.h"\r
#include "scsi.h"\r
+#include "scsiPhy.h"\r
#include "config.h"\r
#include "disk.h"\r
#include "sd.h"\r
return result;\r
}\r
\r
+// Callback once all data has been read in the data out phase.\r
+static void doFormatUnitComplete(void)\r
+{\r
+ // TODO start writing the initialisation pattern to the SD\r
+ // card\r
+ scsiDev.phase = STATUS;\r
+}\r
+\r
+static void doFormatUnitSkipData(int bytes)\r
+{\r
+ // We may not have enough memory to store the initialisation pattern and\r
+ // defect list data. Since we're not making use of it yet anyway, just\r
+ // discard the bytes.\r
+ scsiEnterPhase(DATA_OUT);\r
+ int i;\r
+ for (i = 0; i < bytes; ++i)\r
+ {\r
+ scsiReadByte(); \r
+ }\r
+}\r
\r
-static void doFormatUnit()\r
+// Callback from the data out phase.\r
+static void doFormatUnitPatternHeader(void)\r
{\r
- // Low-level formatting is not required.\r
- // Nothing left to do.\r
+ int defectLength =\r
+ ((((uint16_t)scsiDev.data[2])) << 8) +\r
+ scsiDev.data[3];\r
+ \r
+ int patternLength =\r
+ ((((uint16_t)scsiDev.data[4 + 2])) << 8) +\r
+ scsiDev.data[4 + 3];\r
+\r
+ doFormatUnitSkipData(defectLength + patternLength);\r
+ doFormatUnitComplete();\r
+}\r
+\r
+// Callback from the data out phase.\r
+static void doFormatUnitHeader(void)\r
+{\r
+ int IP = (scsiDev.data[1] & 0x08) ? 1 : 0;\r
+ int DSP = (scsiDev.data[1] & 0x04) ? 1 : 0;\r
+ \r
+ if (! DSP) // disable save parameters\r
+ {\r
+ configSave(); // Save the "MODE SELECT savable parameters"\r
+ }\r
+ \r
+ if (IP)\r
+ {\r
+ // We need to read the initialisation pattern header first.\r
+ scsiDev.dataLen += 4;\r
+ scsiDev.phase = DATA_OUT;\r
+ scsiDev.postDataOutHook = doFormatUnitPatternHeader;\r
+ }\r
+ else\r
+ {\r
+ // Read the defect list data\r
+ int defectLength =\r
+ ((((uint16_t)scsiDev.data[2])) << 8) +\r
+ scsiDev.data[3];\r
+ doFormatUnitSkipData(defectLength);\r
+ doFormatUnitComplete();\r
+ }\r
}\r
\r
static void doReadCapacity()\r
else if (command == 0x04)\r
{\r
// FORMAT UNIT\r
- doFormatUnit();\r
+ // We don't really do any formatting, but we need to read the correct\r
+ // number of bytes in the DATA_OUT phase to make the SCSI host happy.\r
+ \r
+ int fmtData = (scsiDev.cdb[1] & 0x10) ? 1 : 0;\r
+ if (fmtData)\r
+ {\r
+ // We need to read the parameter list, but we don't know how\r
+ // big it is yet. Start with the header.\r
+ scsiDev.dataLen = 4;\r
+ scsiDev.phase = DATA_OUT;\r
+ scsiDev.postDataOutHook = doFormatUnitHeader;\r
+ }\r
+ else\r
+ {\r
+ // No data to read, we're already finished!\r
+ }\r
}\r
else if (command == 0x08)\r
{\r
{\r
// REQUEST SENSE\r
uint32 allocLength = scsiDev.cdb[4];\r
- if (allocLength == 0) allocLength = 256;\r
- memset(scsiDev.data, 0, 18);\r
+\r
+ // As specified by the SASI and SCSI1 standard.\r
+ // Newer initiators won't be specifying 0 anyway.\r
+ if (allocLength == 0) allocLength = 4;\r
+\r
+ memset(scsiDev.data, 0, 256); // Max possible alloc length\r
scsiDev.data[0] = 0xF0;\r
scsiDev.data[2] = scsiDev.sense.code & 0x0F;\r
\r
scsiDev.data[6] = transfer.lba;\r
\r
// Additional bytes if there are errors to report\r
- int responseLength;\r
- if (scsiDev.sense.code == NO_SENSE)\r
- {\r
- responseLength = 8;\r
- }\r
- else\r
- {\r
- responseLength = 18;\r
- scsiDev.data[7] = 10; // additional length\r
- scsiDev.data[12] = scsiDev.sense.asc >> 8;\r
- scsiDev.data[13] = scsiDev.sense.asc;\r
- }\r
+ scsiDev.data[7] = 10; // additional length\r
+ scsiDev.data[12] = scsiDev.sense.asc >> 8;\r
+ scsiDev.data[13] = scsiDev.sense.asc;\r
\r
// Silently truncate results. SCSI-2 spec 8.2.14.\r
- enter_DataIn(\r
- (allocLength < responseLength) ? allocLength : responseLength\r
- );\r
+ enter_DataIn(allocLength);\r
\r
// This is a good time to clear out old sense information.\r
scsiDev.sense.code = NO_SENSE;\r