Linux SCSI ATA CMD записи или чтения иногда работают, а иногда не работают, когда длина передачи превышает 1345 - PullRequest
1 голос
/ 12 июня 2019

Мой код выглядит следующим образом:

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);

Если я посылаю длину передачи cmd более 1345, это иногда работает, а иногда не работает.Если длина передачи увеличивается, то часть, которая не работает, тоже увеличивается.Там нет журнала uart или журнала ядра, когда cmd не работает.

пс.Если cmd не работает, errno говорит 22(invalid argument)

1 Ответ

0 голосов
/ 12 июня 2019

Вы не инициализируете байты в SCSI CDB нулем, поэтому иногда в cmd[1], cmd[14] и cmd[15] есть мусор.Добавьте вызов к memset вверху или инициализируйте массив с = { };.

Кроме того, я знаю множество примеров, использующих эту технику для инициализации структуры команд, но, черт возьми, это действительно сведет вас с ума.Я рекомендую определить структуру __attribute__ ((packed)) для CDB, которая использует битовые поля.

Наконец, строка cmd[2] = (lba >> 54) & 0xFF; должна сдвигать lba на 56 бит, а не на 54 бит.

...