Hi,
I'm trying to read/write to specific sectors (512 bytes) in a SATA storage media(/dev/sda) using ioctl and some simple SCSI read/write commands. I'm having some problems with consistency and just getting it to work. Here's what I've tried:
Using read(10)/read(12), when I send the ioctl over to the device, instead of getting the 1st 512 bytes, I get some identification info instead. For example if the drive is a Toshiba drive I'd see the TOSHIBA and the model number, which is actually the ata ident information.
When I use read(6) and send the ioctl, this seems to work for my HDD despite read(6)'s transfer length field being only 8 bytes. I guess the ioctl's transfer length overrides the SCSI CDB's transfer length? I don't know. Despite this, on some HDDs the io_hdr.info and io_hdr.masked_status is non-zero, which indicates a possible error?
However, when I use read(6) to test on a USB memory stick, it gives me the ident information again instead of the 512byte sector.
As for writes, I've only tried write(6) so far, but whenever I send the ioctl out, it would just hang there forever until I close the shell. I'm wondering what I'm doing wrong?
My function (in this case reading a 512byte sector from LBA 0) is as follows:
The write_sector() code is similar except for appropriate changes in io_hdr and wrCmdBlk[].Code:int read_sector(const char *device_name, unsigned char *data) int fd, res; const int t_length = 512; // 512 bytes transferred unsigned char rdCmdBlk6[SCSI_CDB6_LEN] = { SCSI_READ6, // Command 0, 0, 0, 0, 0 }; unsigned char sense_b[SENSE_BUFF_LEN]; sg_io_hdr_t io_hdr; // Open device fd = open(device_name, O_RDONLY); // Prepare SCSI READ (6) command rdCmdBlk6[1] = 0x00; // LBA rdCmdBlk6[2] = 0x00; // LBA rdCmdBlk6[3] = 0x00; // LBA rdCmdBlk6[4] = t_length; // transfer length // 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 = t_length; // Data transfer length(512) io_hdr.dxferp = data; // 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) { close(fd); return -1; } // 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 { close(fd); return -1; } else { close(fd); return 0; } }
Anyone knows what's going on?
Thanks!



LinkBack URL
About LinkBacks


