利用HD/IDE layer的ioctl函数接口获取HD/IDE的磁盘容量。HDIO_DRIVE_TASK
能发出訪问LBA地址的命令。但不能读写数据。
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <linux/hdreg.h>
#include <linux/types.h>
#include <sys/stat.h>
#include <scsi/sg.h>
#include <scsi/scsi.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/time.h>
#define ATA_DRQ (1 << 3) /* data request i/o */
#define ATA_ERR (1 << 0) /* have an error */
#define DRIVER_SENSE 0x08
#define CONDITION_GOOD 0x02
#define ATA_PASS_THRU_12 12
#define ATA_12 0xa1
#define ATA_PASS_THRU_16 16
#define ATA_16 0x85
#define u64 unsigned long long
#define u32 unsigned int
#define u8 unsigned char
#define u16 unsigned short
//ATA commands
enum {
ATA_OP_DSM = 0x06, // Data Set Management (TRIM)
ATA_OP_READ_PIO = 0x20,
ATA_OP_READ_PIO_ONCE =0x21,
ATA_OP_READ_LONG =0x22,
ATA_OP_READ_LONG_ONCE =0x23,
ATA_OP_READ_PIO_EXT =0x24,
ATA_OP_READ_DMA_EXT =0x25,
ATA_OP_READ_FPDMA =0x60, // NCQ
ATA_OP_WRITE_PIO =0x30,
ATA_OP_WRITE_LONG =0x32,
ATA_OP_WRITE_LONG_ONCE =0x33,
ATA_OP_WRITE_PIO_EXT =0x34,
ATA_OP_WRITE_DMA_EXT =0x35,
ATA_OP_WRITE_FPDMA =0x61, // NCQ
ATA_OP_READ_VERIFY =0x40,
ATA_OP_READ_VERIFY_ONCE =0x41,
ATA_OP_READ_VERIFY_EXT =0x42,
ATA_OP_WRITE_UNC_EXT =0x45, // lba48, no data, uses feat reg
ATA_OP_FORMAT_TRACK =0x50,
ATA_OP_DOWNLOAD_MICROCODE = 0x92,
ATA_OP_STANDBYNOW2 =0x94,
ATA_OP_CHECKPOWERMODE2 =0x98,
ATA_OP_SLEEPNOW2 =0x99,
ATA_OP_PIDENTIFY =0xa1,
ATA_OP_READ_NATIVE_MAX =0xf8,
ATA_OP_READ_NATIVE_MAX_EXT = 0x27,
ATA_OP_SMART = 0xb0,
ATA_OP_DCO = 0xb1,
ATA_OP_ERASE_SECTORS =0xc0,
ATA_OP_READ_DMA = 0xc8,
ATA_OP_WRITE_DMA =0xca,
ATA_OP_DOORLOCK = 0xde,
ATA_OP_DOORUNLOCK =0xdf,
ATA_OP_STANDBYNOW1 =0xe0,
ATA_OP_IDLEIMMEDIATE =0xe1,
ATA_OP_SETIDLE = 0xe3,
ATA_OP_SET_MAX = 0xf9,
ATA_OP_SET_MAX_EXT =0x37,
ATA_OP_SET_MULTIPLE =0xc6,
ATA_OP_CHECKPOWERMODE1 =0xe5,
ATA_OP_SLEEPNOW1 =0xe6,
ATA_OP_FLUSHCACHE =0xe7,
ATA_OP_FLUSHCACHE_EXT =0xea,
ATA_OP_IDENTIFY = 0xec,
ATA_OP_SETFEATURES =0xef,
ATA_OP_SECURITY_SET_PASS = 0xf1,
ATA_OP_SECURITY_UNLOCK =0xf2,
ATA_OP_SECURITY_ERASE_PREPARE = 0xf3,
ATA_OP_SECURITY_ERASE_UNIT = 0xf4,
ATA_OP_SECURITY_FREEZE_LOCK = 0xf5,
ATA_OP_SECURITY_DISABLE =0xf6,
ATA_OP_VENDOR_SPECIFIC_0x80 = 0x80,
/* added by openvox */
ATA_OP_SET_MAX_SET_PASSWORD = 0xf9,
};
int verbose = 1;
u8 last_identify_op = 0;
u16 *id;
static u64 get_disk_size(const char*name)
{
const char *ptr = name + strlen(name) - 3;
u64 size;
char buff[128];
FILE *fp;
sprintf(buff,"/sys/block/%s/size",ptr);
if(NULL == (fp = fopen(buff,"r"))){
perror("fopen");
return 0;
}
fscanf(fp,"%lld",&size);
fclose(fp);
return size;
}
/*!
IssuingATA commands
*/
int ata_ioctl(int fd)
{
unsigned char cdb[7];
int err = 0;
cdb[0] = ATA_OP_READ_NATIVE_MAX ; //command id ATA_OP_READ_NATIVE_MAX_ADDRESS 0xf8
cdb[1] = 0x00; //feature id
cdb[2] = 0x00; //number of sectors
cdb[3]= 0x00; //LBAlow
cdb[4] = 0x00; //LBA mid
cdb[5] = 0x00; //LBA high
cdb[6] = 0x40; // device select
if (-1 == (err = ioctl(fd, HDIO_DRIVE_TASK, (void *)cdb))) {
perror("HDIO_DRIVE_TASK erro in ata_ioctl!\n");
return -1;
}
printf ("status %02x\n", cdb[0]);
printf("error %02x\n", cdb[1]);
printf("n sect %02x\n", cdb[2]);
printf("LBA L %02x\n", cdb[3]);
printf("LBA M %02x\n", cdb[4]);
printf("LBA H %02x\n", cdb[5]);
printf("select %02x\n", cdb[6]);
return 0;
}
static void get_identify_data (int fd)
{
staticu8 args[4+512];
inti = 0;
memset(args,0, sizeof(args));
last_identify_op= ATA_OP_IDENTIFY;
args[0]= last_identify_op;
args[3]= 1; /* sector count */
if(do_drive_cmd(fd, args, 0)) {
perror(" HDIO_DRIVE_CMD(identify)failed");
return;
}
printf("incomingdata : \n");
for(; i < 512; i++)
{ if(i == 0)
printf("\n0 :");
printf("%02x ",args[i+4]);
if ((i+1) % 20 == 0)
printf("\n%d:",i+1);
}
printf("\n");
}
int main(int argc, char *argv[])
{
u64 offset = 0;
int fd;
u64 capacity;
int size;
if (argc != 2) {
printf("Usage: %s devname\n",argv[0]);
printf("\n");
return 0;
}
capacity = get_disk_size(argv[1]);
printf("HDD capacity = %lld\n",capacity);
if(-1 == (fd = open(argv[1],O_RDWR))){
perror("open");
return fd;
}
get_identify_data(fd);
if(ata_ioctl(fd) != 0)
{
printf("ata_ioctl error !\n");
exit(-1);
}
close(fd);
return 0;
}
博约分享代码:http://blog.csdn.net/yuesichiu/article/details/40535501