http://anadoxin.org/blog

Sending ATA commands on Linux

Fri, 12 September 2014 :: #cpp :: #hardware :: #linux

It appears that any user can send an ATA message on Linux. The function that allows this is called ioctl, by using message identifier 0x31F (HDIO_DRIVE_CMD).

It is possible to send, i.e. ATA IDENTIFY message by using 0xEC message. This command should return a device identification information. Other status indication message is implemented by the 0xA1 message, but the device needs to properly implement PACKET extensions, so it needs to be an ATAPI device.

#include <iostream>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <sys/ioctl.h>

using namespace std;

int main(void) {
	int fd = ::open("/dev/sda", O_RDONLY | O_DIRECT);
	if(fd != -1) {
		uint8_t buf[512] = { 0xEC, 0, 0, 1, 0 };
		int ret = ::ioctl(fd, 0x31F, buf);

		for(int i = 0; i < 512; ++i) {
			::putchar(buf[i]);
		}
	} else {
		::perror("open");
	}

	::close(fd);
	return 0;
}

The data you'll get will be encoded in big endian notation, so you need to fix this by using necessary shifts and bswaps.

ATA Identify example