Reputation: 359
My code is as follows:
unsigned char cmd[16];
cmd[0] = WRITE_16;
//lba is start address
cmd[2] = (lba >> 54) & 0xFF;
cmd[3] = (lba >> 48) & 0xFF;
cmd[4] = (lba >> 40) & 0xFF;
cmd[5] = (lba >> 32) & 0xFF;
cmd[6] = (lba >> 24) & 0xFF;
cmd[7] = (lba >> 16) & 0xFF;
cmd[8] = (lba >> 8) & 0xFF;
cmd[9] = lba & 0xFF;
//len is transfer length
cmd[10] = (len >> 24) & 0xFF;
cmd[11] = (len >> 16) & 0xFF;
cmd[12] = (len >> 8) & 0xFF;
cmd[13] = len & 0xFF;
void* buffer;
buffer = malloc(len*512);
__u64 buffer_len = 512*len;
io_hdr.interface_id = 'S';
io_hdr.cmd_len = sizeof(cmd);
io_hdr.mx.sb_len = sizeof(sense);
io_hdr.dxfer_direction = SG_DXFER_TO_FROM_DEV;
io_hdr.dxfer_len = buffer_len;
io_hdr.dxferp = buffer;
io_hdr.cmdp = cmd;
io_hdr.sbp = sense;
io_hdr.timeout = 30000;
ioctl(fd, SG_IO, &io_hdr);
If I send cmd transfer length over 1345, it sometimes work and sometimes it doesn't work. If thetransfer length grows up, the portion that doesn't work goes up too. There's no uart log or kernel log when cmd doesn't work.
ps. If cmd doesn't work, errno says 22(invalid argument)
Upvotes: 1
Views: 184
Reputation: 3205
You're not initializing the bytes in the SCSI CDB to zero, so sometimes there's trash in cmd[1]
, cmd[14]
, and cmd[15]
. Add a call to memset
up at the top, or initialize the array with = { };
.
Also, I know a bunch of examples use this technique for initializing the command structure, but man, it's really going to drive you nuts. I recommend defining an __attribute__ ((packed))
structure for the CDB that uses bitfields.
Lastly, the line cmd[2] = (lba >> 54) & 0xFF;
should shift lba
by 56 bits, not 54 bits.
Upvotes: 0