1

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)

Siong Thye Goh
  • 3,518
  • 10
  • 23
  • 31
Easyhyum
  • 307
  • 1
  • 3
  • 5

1 Answers1

0

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.

Mike Andrews
  • 3,045
  • 18
  • 28
  • Thank you but when i try which you comment it doesn't work... i don't know why command sometimes get in the device and sometimes can't... – Easyhyum Jun 13 '19 at 00:25