Отправка команды ATA "Чтение собственного максимального адреса (0x27, 0xF8), не отвечающего через контроллер SAS, с использованием SAT(перевод SCSI ATA)
Я хочу узнать родной максимальный адрес жесткого диска через интерфейс SAS. Я использую SAT (SCSI Ата перевод) с SCSI_PASS_THROUGH.
но невозможно найти какой-либо буфер или достоверную информацию о значении SCSI_PASS_THROUGH с IOCTL_SCSI_PASS_THROUGH с диска. значение cdb SCSI_PASS_THROUGH =
sptwb.Spt.CdbLength = 12;
sptwb.Spt.Cdb[0] = 0xA1;//ATA PASS THROUGH(12) OPERATION CODE(A1h)
sptwb.Spt.Cdb[1] = (4 << 1) | 0;
sptwb.Spt.Cdb[2] = (1 << 3) | (1 << 2) | 2;
sptwb.Spt.Cdb[3] = 0xe0;
sptwb.Spt.Cdb[4] = 0x00;
sptwb.Spt.Cdb[5] = 0x00;
sptwb.Spt.Cdb[6] = 0x00;
sptwb.Spt.Cdb[7] = 0x00;
sptwb.Spt.Cdb[8] = (UCHAR)0x40;//(UCHAR)head;
sptwb.Spt.Cdb[9] = 0x27;//COMMAND
Но не вернуть ни одного буфера. Пожалуйста, предоставьте точные параметры cdb для чтения собственного максимального адреса на машине SAS.
3 ответа
У меня нет всех соответствующих спецификаций SCSI передо мной. Поэтому я предполагаю, что вы правильно строите CDB SATL (Уровень трансляции SCSI ATA). Первое, что нужно проверить - завершен ли ioctl. То есть проверьте код возврата DeviceIoControl()
за True
или же False
а затем проверьте GetLastError()
определить, что пошло не так (если применимо). Если с ioctl все в порядке, проверьте член структуры SCSI_PASS_THROUGH_DIRECT .ScsiStatus
, Если это 0, то команда выполнена просто отлично. Если статус был 0, это может быть причиной отсутствия достоверной информации о смысле.
Я действительно исследовал эту самую команду, когда наткнулся на эту тему. Самые последние спецификации команд ATA, ACS-3 (от 28 октября 2013 г.), показывают, что команды Read Native Max Address и Read Native Max Address Ext устарели. Я нашел их определение в ACS-2. Самый последний черновик от 3 августа 2009 года показывает, что вывод этой команды не будет буфером. Скорее вывод будет в поле LBA возвращенной FIS Device-to-Host.
Приложение. Разговор оригинальной статьи заставляет меня поверить, что это было сделано в Windows. Я должен был включить, что процесс будет таким же для Linux, если вы используете его. Однако не используйте GetLastError()
чтобы определить, что пошло не так. В Linux код возврата от ioctl()
будет код, который вам нужен.
Если в Linux вы, скорее всего, используете драйвер sg и структуру sg_io_hdr_t. Эта структура также имеет .status
член, содержащий код состояния SCSI. В Linux или Windows вы всегда должны проверять этот код, потому что предполагать, что команда выполнена успешно, потому что ioctl сделал ошибку. В Linux доступны и другие драйверы сквозного доступа, например, интерфейс LSI MPT. Процесс все тот же, если вы используете это.
Я думаю, это то, что вы хотите:
это работает под cygwin или родным Linux с установленным «sg3_utils».
#!/bin/bash
dev=$1
sz=$(sg_raw 2>/dev/null -r 40 $dev 9e 10 00 00 00 00 00 00 00 00 00 00 00 0c 00 00 -b|xxd -p)
nb=$((0x${sz:0:16}+1))
bs=$((0x${sz:16:8}))
pbs=$((bs*2**0x${sz:24:4}))
echo Real number of blocks: $nb
echo Real HDD Size: $((nb*bs))
echo Logical Block Size: $bs
echo Physical Block Size: $pbs
p=$((0x$(sg_raw 2>/dev/null $dev -r 512 85 08 0e 00 00 00 01 00 00 00 00 00 00 00 ec 00 -o -|xxd -c 0 -ps|while read -N1 a;do read -N1 b;echo -n $b$a;done|cut -c 401-416|rev)))
echo User Addressable blocks: $p
echo User Addressable size: $(($p*bs))
./gethdsize.sh PD2 (device obtained with sg_scan)
выход:
Real number of blocks: 27344764928
Real HDD Size: 14000519643136
Logical Block Size: 512
Physical Block Size: 4096
User Addressable blocks: 27344750581
User Addressable size: 14000512297472
после сброса диска на max lba:
Real number of blocks: 27344764928
Real HDD Size: 14000519643136
Logical Block Size: 512
Physical Block Size: 4096
User Addressable blocks: 27344764928
User Addressable size: 14000519643136
Команда, которую вы пытаетесь реализовать, 0xF8 (Read Native Max Address) - это не команда SCSI, это команда ATA.
Код CDB 0xA1 действительно работает с API IOCTL_SCSI_PASS_THROUGH для получения команд SCSI/ATAPI на устройство. Но это не то, что вы хотите.
Попробуйте вместо этого IOCTL_ATA_PASSTHROUGH.
Пример и обсуждение здесь: Отправка команд ATA непосредственно на устройство в Windows?