我正在尝试将ATA命令发送到Windows中的物理磁盘,并从设备获取响应.
注意:在这种情况下,我想发送
IDENTIFY DEVICE
(0xEC)命令.设备将响应512字节的数据块.(特别是我对第119行的第0位感兴趣 - 设备对TRIM
命令的支持).
我知道我需要CreateFile
用来打开设备:
handle = CreateFile(
"\\.\PhysicalDrive0", GENERIC_READ, FILE_SHARE_READ,
nil, // no security attributes
OPEN_EXISTING,
0, // flags and attributes
nil // no template file
);
Run Code Online (Sandbox Code Playgroud)
但在此之后,我陷入困境,无法做什么.
我想过发送0xEC
使用[DeviceIoControl][4]
:
// const ATACommand_IdentifyDevice = 0xEC;
uint bytesReturned = 0;
DeviceIoControl(handle,
0xEC, // IO Control Code
nil, // input buffer not needed
0, // input buffer is zero bytes
@buffer, // output buffer to store …
Run Code Online (Sandbox Code Playgroud) 我目前正在开发一个业余爱好操作系统,特别是ATA驱动程序.我在使用带有中断的PIO数据输入命令时遇到了一些问题.我正在尝试执行READ MULTIPLE命令,逐块地从驱动器读取多个扇区,每个块都有一个中断触发.
如果我请求读取4个块(每个块1个扇区).我希望得到4个中断,每个数据块一个.收到第4个中断后,我可以识别出我已经传输了所有数据并相应地更新了我的请求结构.但是,在VirtualBox中,我发现在传输完最后一个数据块后,我收到了另一个中断(STATUS = 0x50,READY,OVERLAPPED MODE SERVER REQ).我可以简单地读取STATUS寄存器然后清除它,但我不认为我应该根据规格接收第5个中断.
那么确认ATA设备发出的中断的正确方法是什么?
在这个例子中,我发出了一个READ MULTIPLE命令,然后我的ISR执行以下操作:
PIO数据输入命令协议的ATA规范并不表示您需要读取状态寄存器.由此我假设当我收到中断时,我所要做的就是遵循协议并通过将EOI发送到PIC完成.至于nIEN的设置/清除,在处理VirtualBox时我发现如果我不这样做,我就不会收到任何超过第一个的中断.所以我在进入ISR时设置了nIEN,然后在我离开之前将其清除.我认为这不会产生任何影响,但它必须与读/写特定寄存器有关.
我想将可信发送/可信接收发送到我的硬盘。我找到了这个页面: ATA Trusted Commands in Linux。(谢谢 ehemient 和德米特里·奥布霍夫)。
现在,我的麻烦是如何设置 libata allowed_tpm = 1。我使用的是 Ubuntu 13.10。我的代码与 Dmitry Obukhov 相同(它非常适合识别和所有其他命令,但不适用于受信任的命令。)
从另一个角度看之后,我做了这些:
- In BIOS, set AHCI mode.
Run Code Online (Sandbox Code Playgroud)
在终端中:
- sudo dmesg -c:
[ 0.157207] SCSI subsystem initialized.
[ 0.157209] ACPI: bus type ATA registered.
[ 0.157236] libata version 3.00 loaded.
[ 0.878999] ahci 0000:00:1f.2: AHCI 0001.0300 32 slots 6 ports 6
Gbps 0x3 impl SATA mode.
[ 0.887125] ata1: SATA max UDMA/133 abar m2048@0xf7c16000 port
0xf7c16100 irq 41.
[ 0.887127] ata2: …
Run Code Online (Sandbox Code Playgroud) 这是调用 insl 的函数。
void ide_read_buffer(unsigned char channel, unsigned char reg, unsigned int buffer,
unsigned int quads) {
/* WARNING: This code contains a serious bug. The inline assembly trashes ES and
* ESP for all of the code the compiler generates between the inline
* assembly blocks.
*/
if (reg > 0x07 && reg < 0x0C)
ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
asm("pushw %es; movw %ds, %ax; movw %ax, %es");
if (reg < 0x08)
insl(channels[channel].base + reg - 0x00, buffer, quads); …
Run Code Online (Sandbox Code Playgroud) 同事,
我正在实现对 ATA 可信命令的支持
0x5C, TRUSTED RECEIVE,
0x5D, TRUSTED RECEIVE DMA,
0x5E, TRUSTED SEND
0x5F, TRUSTED SEND DMA,
Run Code Online (Sandbox Code Playgroud)
用于 Linux(两台主机,Fedora 12 和 14)以支持自加密驱动器。我从这个页面http://www.jukie.net/bart/blog/ata-via-scsi中获取了一个代码作为基本代码。对于可信接收(在这一层,它与 IDENTIFY, 0xEC 相同):
sg_io.interface_id = 'S';
sg_io.cmdp = cdb;
sg_io.cmd_len = sizeof(cdb);
sg_io.dxferp = data_in_buffer;
sg_io.dxfer_len = data_in_length; // multiple of 512
sg_io.dxfer_direction = SG_DXFER_FROM_DEV;
sg_io.sbp = sense;
sg_io.mx_sb_len = sizeof(sense);
sg_io.timeout = 5000; // 5 seconds
cdb[0] = 0x85; // pass-through ATA16 command (no translation)
cdb[1] = (4 << 1); // data-in
cdb[2] = …
Run Code Online (Sandbox Code Playgroud)