Thursday, November 19, 2015

Issue SATA commands directly through IOCTL

Directly write to SATA interface to perform simple read and write operation on a storage device.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include <scsi/sg.h>
#include <scsi/scsi.h>
main()
{
 int fd;
 unsigned char buffer[512];

 fd=open("/dev/sda", O_RDWR );

 ReadSector(fd, 0, 1, buffer);
 WriteSector(fd, 0, 1, buffer);
}


// return 0 on fail
// return 1 on success
int ReadSector(int fd, int sector, int nsec, unsigned char *pbuffer)
{
 int res;
 int t_length;
 sg_io_hdr_t io_hdr;
 unsigned char sense_b[SG_MAX_SENSE];
 unsigned char rdCmdBlk6[6];

 t_length = 512;              // 512 bytes transferred per sec

// Prepare SCSI READ (6) command
 rdCmdBlk6[0]  = READ_6;           // COMMAND
 rdCmdBlk6[1]  = (sector & 0xFF0000 ) >> 16;           // LBA
 rdCmdBlk6[2]  = (sector & 0xff00) >> 8;         // LBA
 rdCmdBlk6[3]  = sector & 0xff;  // LBA
 rdCmdBlk6[4]  = nsec;
 rdCmdBlk6[5]  = 0x00;

// Prepare the sg_io_hdr_t structure
 memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
 io_hdr.interface_id = 'S';                  // Always set to 'S' for sg driver
 io_hdr.cmd_len = sizeof(rdCmdBlk6);         // Size of SCSI command
 io_hdr.mx_sb_len  = sizeof(sense_b);        // Max sense buffer size(for error)
 io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; // Data transfer direction(no data)
 io_hdr.dxfer_len = nsec*t_length;                // Data transfer length(512)
 io_hdr.dxferp = pbuffer;                       // Data transfer buffer(none)
 io_hdr.cmdp = rdCmdBlk6;                    // SCSI command buffer
 io_hdr.sbp = sense_b;                       // Sense buffer
 io_hdr.timeout = 5000;                      // Timeout(5s)

// Sends the command to device
 if ((res = ioctl(fd, SG_IO, &io_hdr)) < 0) {
   return 0;
 }

// Error processing
 if ( ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK) || // check info
      (io_hdr.masked_status != 0x00) ||                  // check status(0 if ioctl success)
      (io_hdr.msg_status != 0x00) ||                     // check message status
      (io_hdr.host_status != 0x00) ||                    // check host status
      (io_hdr.driver_status != 0x00) )                   // check driver status
 {
   return 0;
 } else {
   return 1;
 }
}

int WriteSector(int fd, int sector, int nsec, unsigned char *pbuffer)
{
 int res;
 int t_length;
 sg_io_hdr_t io_hdr;
 unsigned char sense_b[SG_MAX_SENSE];
 unsigned char rdCmdBlk6[6] ;
 t_length = 512;              // 512 bytes transferred per sec

// Prepare SCSI WRITE (6) command
 rdCmdBlk6[0]  = WRITE_6;           // COMMAND
 rdCmdBlk6[1]  = (sector & 0xFF0000 ) >> 16;           // LBA
 rdCmdBlk6[2]  = (sector & 0xff00) >> 8;         // LBA
 rdCmdBlk6[3]  = sector & 0xff;  // LBA
 rdCmdBlk6[4]  = nsec;
 rdCmdBlk6[5]  = 0x00;

// Prepare the sg_io_hdr_t structure
 memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
 io_hdr.interface_id = 'S';                  // Always set to 'S' for sg driver
 io_hdr.cmd_len = sizeof(rdCmdBlk6);         // Size of SCSI command
 io_hdr.mx_sb_len  = sizeof(sense_b);        // Max sense buffer size(for error)
 io_hdr.dxfer_direction = SG_DXFER_TO_DEV; // Data transfer direction(no data)
 io_hdr.dxfer_len = nsec*t_length;                // Data transfer length(512)
 io_hdr.dxferp = pbuffer;                       // Data transfer buffer(none)
 io_hdr.cmdp = rdCmdBlk6;                    // SCSI command buffer
 io_hdr.sbp = sense_b;                       // Sense buffer
 io_hdr.timeout = 5000;                      // Timeout(5s)

// Sends the command to device
 if ((res = ioctl(fd, SG_IO, &io_hdr)) < 0) {
   return 0;
 }

// Error processing
 if ( ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK) || // check info
      (io_hdr.masked_status != 0x00) ||                  // check status(0 if ioctl success)
      (io_hdr.msg_status != 0x00) ||                     // check message status
      (io_hdr.host_status != 0x00) ||                    // check host status
      (io_hdr.driver_status != 0x00) )                   // check driver status
 {
   return 0;
 } else {
   return 1;
 }
}

No comments:

Post a Comment