More cleanup of the SMART ATA passthrough commands
[JMraidcon.git] / src / JMraidcon.c
index e51918d..dd7bc68 100644 (file)
 #include <string.h>
 #include "jm_crc.h"
 #include "sata_xor.h"
-#include <arpa/inet.h>
+#include <asm/byteorder.h> // For __le32_to_cpu etc
 
 #define SECTORSIZE (512)
 #define READ_CMD (0x28)
 #define WRITE_CMD (0x2a)
 #define RW_CMD_LEN (10)
 
-const uint8_t probe1[] =    { 0x25, 0x03, 0x7b, 0x19,  0x0b, 0xa8, 0x75, 0x3c,  0,0,0,0,0,0,0,0 };
-const uint8_t probe1end[] = { 0xdb, 0xa1, 0xec, 0x10,  0xd9, 0x10, 0x6d, 0x70 };
-
-const uint8_t probe2[] =    { 0x25, 0x03, 0x7b, 0x19,  0x37, 0xe3, 0x88, 0x03,  0,0,0,0,0,0,0,0 };
-const uint8_t probe2end[] = { 0xdb, 0xa1, 0xec, 0x10,  0x1e, 0x51, 0x58, 0x69 };
-
-const uint8_t probe3[] =    { 0x25, 0x03, 0x7b, 0x19,  0xf3, 0x05, 0x97, 0x68,  0,0,0,0,0,0,0,0 };
-const uint8_t probe3end[] = { 0xdb, 0xa1, 0xec, 0x10,  0x07, 0x4b, 0x23, 0xfe };
-
-const uint8_t probe4[] =    { 0x25, 0x03, 0x7b, 0x19,  0x3a, 0x52, 0x0c, 0xe0,  0,0,0,0,0,0,0,0 };
-const uint8_t probe4end[] = { 0xdb, 0xa1, 0xec, 0x10,  0xdb, 0x7a, 0xe5, 0x5b };
+#define JM_RAID_WAKEUP_CMD    ( 0x197b0325 )
+#define JM_RAID_SCRAMBLED_CMD ( 0x197b0322 )
 
 // First 4 bytes are always the same for all the scrambled commands, next 4 bytes forms an incrementing command id
-const uint8_t probe6[]={ 0x22, 0x03, 0x7b, 0x19, 0x06,0x00,0x00,0x00, 0x00, 0x01, 0x02, 0xff, 0x01 }; // This returns very little info (at the end)?
-const uint8_t probe7[]={ 0x22, 0x03, 0x7b, 0x19, 0x0b,0x00,0x00,0x00, 0x00, 0x01, 0x01, 0xff }; // This cmd returns the "RAID Manager" name
-const uint8_t probe8[]={ 0x22, 0x03, 0x7b, 0x19, 0x0c,0x00,0x00,0x00, 0x00, 0x01, 0x02, 0xff, 0x0a };
-const uint8_t probe9[]={ 0x22, 0x03, 0x7b, 0x19, 0x0e,0x00,0x00,0x00, 0x00, 0x02, 0x01, 0xff }; // This returns the names of disks attached (or in a specific RAID volume?)
-const uint8_t probe11[]={ 0x22, 0x03, 0x7b, 0x19, 0x10,0x00,0x00,0x00, 0x00, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 }; // Identify disk0?
-const uint8_t probe12[]={ 0x22, 0x03, 0x7b, 0x19, 0x11,0x00,0x00,0x00, 0x00, 0x02, 0x02, 0xff, 0x01, 0x00, 0x00, 0x00, 0x01 }; // Identify disk1?
-const uint8_t probe13[]={ 0x22, 0x03, 0x7b, 0x19, 0x12,0x00,0x00,0x00, 0x00, 0x02, 0x02, 0xff, 0x02, 0x00, 0x00, 0x00, 0x02 }; // Identify disk2?
-const uint8_t probe14[]={ 0x22, 0x03, 0x7b, 0x19, 0x13,0x00,0x00,0x00, 0x00, 0x02, 0x02, 0xff, 0x03, 0x00, 0x00, 0x00, 0x03 }; // Identify disk3?
-const uint8_t probe15[]={ 0x22, 0x03, 0x7b, 0x19, 0x14,0x00,0x00,0x00, 0x00, 0x02, 0x02, 0xff, 0x04, 0x00, 0x00, 0x00, 0x04 }; // Identify disk4?
-const uint8_t probe16[]={ 0x22, 0x03, 0x7b, 0x19, 0x15,0x00,0x00,0x00, 0x00, 0x03, 0x02, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 }; // AWARD I5, wtf??
-const uint8_t probe17[]={ 0x22, 0x03, 0x7b, 0x19, 0x16,0x00,0x00,0x00, 0x00, 0x03, 0x02, 0xff, 0x01, 0x00, 0x00, 0x00, 0x01 }; // ??
-const uint8_t probe18[]={ 0x22, 0x03, 0x7b, 0x19, 0x17,0x00,0x00,0x00, 0x00, 0x03, 0x02, 0xff, 0x02, 0x00, 0x00, 0x00, 0x02 }; // ??
-const uint8_t probe19[]={ 0x22, 0x03, 0x7b, 0x19, 0x18,0x00,0x00,0x00, 0x00, 0x03, 0x02, 0xff, 0x03, 0x00, 0x00, 0x00, 0x03 }; // ??
-const uint8_t probe20[]={ 0x22, 0x03, 0x7b, 0x19, 0x19,0x00,0x00,0x00, 0x00, 0x03, 0x02, 0xff, 0x04, 0x00, 0x00, 0x00, 0x04 }; // ??
-const uint8_t probe21[]={ 0x22, 0x03, 0x7b, 0x19, 0x1a,0x00,0x00,0x00, 0x00, 0x01, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; // Returns nothing?
-const uint8_t probe23[]={ 0x22, 0x03, 0x7b, 0x19, 0x1c,0x00,0x00,0x00, 0x00, 0x02, 0x03, 0xff, 0x00, 0x02, 0x00, 0xe0, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x00, 0xc2, 0x00, 0xa0, 0x00, 0xb0 }; // SMART data disk0?
-const uint8_t probe24[]={ 0x22, 0x03, 0x7b, 0x19, 0x1d,0x00,0x00,0x00, 0x00, 0x02, 0x03, 0xff, 0x00, 0x02, 0x00, 0xe0, 0x00, 0x00, 0xd1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x00, 0xc2, 0x00, 0xa0, 0x00, 0xb0 }; // SMART data disk0 part2?
-const uint8_t probe25[]={ 0x22, 0x03, 0x7b, 0x19, 0x1e,0x00,0x00,0x00, 0x00, 0x02, 0x03, 0xff, 0x01, 0x02, 0x00, 0xe0, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x00, 0xc2, 0x00, 0xa0, 0x00, 0xb0 }; // SMART data disk1?
-const uint8_t probe26[]={ 0x22, 0x03, 0x7b, 0x19, 0x1f,0x00,0x00,0x00, 0x00, 0x02, 0x03, 0xff, 0x01, 0x02, 0x00, 0xe0, 0x00, 0x00, 0xd1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x00, 0xc2, 0x00, 0xa0, 0x00, 0xb0 }; // SMART data disk1 part2?
-const uint8_t probe27[]={ 0x22, 0x03, 0x7b, 0x19, 0x20,0x00,0x00,0x00, 0x00, 0x02, 0x03, 0xff, 0x02, 0x02, 0x00, 0xe0, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x00, 0xc2, 0x00, 0xa0, 0x00, 0xb0 }; // SMART data disk2?
-const uint8_t probe28[]={ 0x22, 0x03, 0x7b, 0x19, 0x21,0x00,0x00,0x00, 0x00, 0x02, 0x03, 0xff, 0x02, 0x02, 0x00, 0xe0, 0x00, 0x00, 0xd1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x00, 0xc2, 0x00, 0xa0, 0x00, 0xb0 }; // SMART data disk2 part2?
+// (and these 8 bytes are now automatically prepended and no longer listed here)
+const uint8_t probe6[]={ 0x00, 0x01, 0x02, 0xff, 0x01 }; // This returns very little info (at the end)?
+const uint8_t probe7[]={ 0x00, 0x01, 0x01, 0xff }; // This cmd returns the "RAID Manager" name
+const uint8_t probe8[]={ 0x00, 0x01, 0x02, 0xff, 0x0a };
+const uint8_t probe9[]={ 0x00, 0x02, 0x01, 0xff }; // This returns the names of disks attached (or in a specific RAID volume?)
+
+// The Identify disk commands does not return the data in the same format as the normal IDENTIFY DEVICE!??
+const uint8_t probe11[]={ 0x00, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 }; // Identify disk0
+const uint8_t probe12[]={ 0x00, 0x02, 0x02, 0xff, 0x01, 0x00, 0x00, 0x00, 0x01 }; // Identify disk1
+const uint8_t probe13[]={ 0x00, 0x02, 0x02, 0xff, 0x02, 0x00, 0x00, 0x00, 0x02 }; // Identify disk2
+const uint8_t probe14[]={ 0x00, 0x02, 0x02, 0xff, 0x03, 0x00, 0x00, 0x00, 0x03 }; // Identify disk3
+const uint8_t probe15[]={ 0x00, 0x02, 0x02, 0xff, 0x04, 0x00, 0x00, 0x00, 0x04 }; // Identify disk4
+const uint8_t probe16[]={ 0x00, 0x03, 0x02, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 }; // AWARD I5, wtf??
+const uint8_t probe17[]={ 0x00, 0x03, 0x02, 0xff, 0x01, 0x00, 0x00, 0x00, 0x01 }; // ??
+const uint8_t probe18[]={ 0x00, 0x03, 0x02, 0xff, 0x02, 0x00, 0x00, 0x00, 0x02 }; // ??
+const uint8_t probe19[]={ 0x00, 0x03, 0x02, 0xff, 0x03, 0x00, 0x00, 0x00, 0x03 }; // ??
+const uint8_t probe20[]={ 0x00, 0x03, 0x02, 0xff, 0x04, 0x00, 0x00, 0x00, 0x04 }; // ??
+const uint8_t probe21[]={ 0x00, 0x01, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; // Returns nothing?
+const uint8_t probe23[]={ 0x00, 0x02, 0x03, 0xff, 0x00, 0x02, 0x00, 0xe0, 0x00, 0x00,         // disk0 ata passthrough
+        0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x00, 0xc2, 0x00, 0xa0, 0x00, 0xb0, 0x00 }; // SMART READ ATTRIBUTE VALUE ata cmd
+
+const uint8_t probe24[]={ 0x00, 0x02, 0x03, 0xff, 0x00, 0x02, 0x00, 0xe0, 0x00, 0x00,         // disk0 ata passthrough, again
+        0xd1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x00, 0xc2, 0x00, 0xa0, 0x00, 0xb0, 0x00 }; // SMART READ ATTRIBUTE THRESHOLDS ata cmd
+
+const uint8_t probe25[]={ 0x00, 0x02, 0x03, 0xff, 0x01, 0x02, 0x00, 0xe0, 0x00, 0x00,         // disk1 ata passthrough
+        0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x00, 0xc2, 0x00, 0xa0, 0x00, 0xb0, 0x00 }; // SMART READ ATTRIBUTE VALUE ata cmd
+
+const uint8_t probe26[]={ 0x00, 0x02, 0x03, 0xff, 0x01, 0x02, 0x00, 0xe0, 0x00, 0x00,         // disk1 ata passthrough, again
+        0xd1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x00, 0xc2, 0x00, 0xa0, 0x00, 0xb0, 0x00 }; // SMART READ ATTRIBUTE THRESHOLDS ata cmd
+
+const uint8_t probe27[]={ 0x00, 0x02, 0x03, 0xff, 0x02, 0x02, 0x00, 0xe0, 0x00, 0x00,         // disk2 ata passthrough
+        0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x00, 0xc2, 0x00, 0xa0, 0x00, 0xb0, 0x00 }; // SMART READ ATTRIBUTE VALUE ata cmd
+
+const uint8_t probe28[]={ 0x00, 0x02, 0x03, 0xff, 0x02, 0x02, 0x00, 0xe0, 0x00, 0x00,         // disk2 ata passthrough, again
+        0xd1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x00, 0xc2, 0x00, 0xa0, 0x00, 0xb0, 0x00 }; // SMART READ ATTRIBUTE THRESHOLDS ata cmd
 
     sg_io_hdr_t io_hdr;
 #warning FIXME: Should not use a hard-coded sector number (0x21), even though it is backed up and restored afterwards
@@ -80,8 +85,7 @@ uint32_t Do_JM_Cmd( int theFD, uint32_t* theCmd, uint32_t* theResp ) {
     uint32_t myCRC = JM_CRC( theCmd, 0x7f );
 
     // Stash the CRC at the end
-#warning FIXME: CRC in request must be little-endian, no matter what the host arch is
-    theCmd[0x7f] = myCRC;
+    theCmd[0x7f] = __cpu_to_le32( myCRC );
 //    printf("Command CRC: 0x%08x\n", myCRC);
 
     // Make the data look really 31337 (or not)
@@ -101,9 +105,8 @@ uint32_t Do_JM_Cmd( int theFD, uint32_t* theCmd, uint32_t* theResp ) {
     SATA_XOR( theResp );
 
     myCRC = JM_CRC( theResp, 0x7f);
-#warning FIXME: CRC in response is little-endian, no matter what the host arch is
-    if( myCRC != theResp[0x7f] ) {
-        printf( "Warning: Response CRC 0x%08x does not match the calculated 0x%08x!!\n", theResp[0x7f], myCRC );
+    if( myCRC != __le32_to_cpu( theResp[0x7f] ) ) {
+        printf( "Warning: Response CRC 0x%08x does not match the calculated 0x%08x!!\n", __le32_to_cpu( theResp[0x7f] ), myCRC );
         retval=1;
     }
     return retval;
@@ -115,7 +118,7 @@ static void hexdump(uint8_t* thePtr, uint32_t theLen) {
         printf("0x%02x, ", thePtr[looper]);
         if((looper&0x0f)==0x0f) {
             int asc;
-            for(asc=looper-0x0f; asc<looper; asc++) {
+            for(asc=looper-0x0f; asc<=looper; asc++) {
                 uint8_t theOut=thePtr[asc];
                 if(theOut<0x20 || theOut>0x7f) theOut='.';
                 printf("%c",theOut);
@@ -128,11 +131,17 @@ static void hexdump(uint8_t* thePtr, uint32_t theLen) {
 
 static void TestCmd( int theFD, uint8_t* theCmd, uint32_t theLen) {
     uint8_t tempBuf1[SECTORSIZE];
+    uint32_t* tempBuf1_32 = (uint32_t*)tempBuf1;
     uint8_t tempBuf2[SECTORSIZE];
+    static uint32_t cmdNum = 1;
 
     // Entire sector is always sent, so zero fill cmd
     memset( tempBuf1, 0, SECTORSIZE );
-    memcpy( tempBuf1, theCmd, theLen );
+    memcpy( tempBuf1+0x08, theCmd, theLen );
+
+    tempBuf1_32[0] = __cpu_to_le32( JM_RAID_SCRAMBLED_CMD );
+    tempBuf1_32[1] = __cpu_to_le32( cmdNum++ );
+    theLen+=0x08; // Adding the SCRAMBLED_CMD and command number
 
     printf( "Sending command:\n");
     hexdump( tempBuf1, (theLen+0x0f)&0x1f0 );
@@ -189,8 +198,16 @@ int main(int argc, char * argv[])
     }
 
     // Generate and send the initial "wakeup" data
-    // I haven't gotten the CRC figured out on these ones yet
+    // No idea what the second dword represents at this point
     // Note that these (and all other writes) should be directed to an unused sector!!
+    memset( probeBuf, 0, SECTORSIZE );
+
+    // For wide access
+    uint32_t* probeBuf32 = (uint32_t*)probeBuf;
+
+    // Populate with the static data
+    probeBuf32[0 >> 2] = __cpu_to_le32( JM_RAID_WAKEUP_CMD );
+    probeBuf32[0x1f8 >> 2] = __cpu_to_le32( 0x10eca1db );
     for( uint32_t i=0x10; i<0x1f8; i++ ) {
         probeBuf[i] = i&0xff;
     }
@@ -199,17 +216,25 @@ int main(int argc, char * argv[])
     rwCmdBlk[0] = WRITE_CMD;
     io_hdr.dxferp = probeBuf;
 
-    memcpy(probeBuf, probe1, 0x10);
-    memcpy(probeBuf+0x1f8, probe1end, 0x08);
+    // The only value (except the CRC at the end) that changes between the 4 wakeup sectors
+    probeBuf32[4 >> 2] = __cpu_to_le32( 0x3c75a80b );
+    uint32_t myCRC = JM_CRC( probeBuf32, 0x1fc >> 2 );
+    probeBuf32[0x1fc >> 2] = __cpu_to_le32( myCRC );
     ioctl(sg_fd, SG_IO, &io_hdr);
-    memcpy(probeBuf, probe2, 0x10);
-    memcpy(probeBuf+0x1f8, probe2end, 0x08);
+
+    probeBuf32[4 >> 2] = __cpu_to_le32( 0x0388e337 );
+    myCRC = JM_CRC( probeBuf32, 0x1fc >> 2 );
+    probeBuf32[0x1fc >> 2] = __cpu_to_le32( myCRC );
     ioctl(sg_fd, SG_IO, &io_hdr);
-    memcpy(probeBuf, probe3, 0x10);
-    memcpy(probeBuf+0x1f8, probe3end, 0x08);
+
+    probeBuf32[4 >> 2] = __cpu_to_le32( 0x689705f3 );
+    myCRC = JM_CRC( probeBuf32, 0x1fc >> 2 );
+    probeBuf32[0x1fc >> 2] = __cpu_to_le32( myCRC );
     ioctl(sg_fd, SG_IO, &io_hdr);
-    memcpy(probeBuf, probe4, 0x10);
-    memcpy(probeBuf+0x1f8, probe4end, 0x08);
+
+    probeBuf32[4 >> 2] = __cpu_to_le32( 0xe00c523a );
+    myCRC = JM_CRC( probeBuf32, 0x1fc >> 2 );
+    probeBuf32[0x1fc >> 2] = __cpu_to_le32( myCRC );
     ioctl(sg_fd, SG_IO, &io_hdr);
 
     // Initial probe complete, now send scrambled commands to the same sector