Problem to read sector of hard disk via extended ATA commands

I am using extended ATA commands to read Disk drive(SSD or HDD both).
I have been read out many document based on ATA commands and finaly write a code to send extended commands to my disk.
I am using extended because i have to read out large disk like upto 4 TB using LBA addressing.

BOOL status = FALSE;
PATA_PASS_THROUGH_EX pATAData;
DWORD dataSize = sizeof(ATA_PASS_THROUGH_EX) + 512;
BYTE Buffer[sizeof(ATA_PASS_THROUGH_EX) + 512];
DWORD bytescopied = 0;

pATAData = (ATA_PASS_THROUGH_EX*)Buffer;

ZeroMemory(pATAData,dataSize); // clears the buffer

pATAData->Length = sizeof(ATA_PASS_THROUGH_EX);
pATAData->DataBufferOffset = sizeof(ATA_PASS_THROUGH_EX);
pATAData->DataTransferLength = 512;
pATAData->TimeOutValue = 2;

pATAData->CurrentTaskFile[0] = 0x00;
pATAData->CurrentTaskFile[1] = 0x01;         // want to read one sector only
pATAData->CurrentTaskFile[2] = 0x01;         // wnat to read 1st sector
pATAData->CurrentTaskFile[3] = 0x00;
pATAData->CurrentTaskFile[4] = 0x00;
pATAData->CurrentTaskFile[5] = 0x40;         // to support LBA addressing mode
pATAData->CurrentTaskFile[6] = 0x24; 
pATAData->CurrentTaskFile[7]=  0x00;
pATAData->AtaFlags =ATA_FLAGS_48BIT_COMMAND;  

pATAData->PreviousTaskFile[0] = 0x00;
pATAData->PreviousTaskFile[1] = 0x00;
pATAData->PreviousTaskFile[2] = 0x00;
pATAData->PreviousTaskFile[3] = 0x00;
pATAData->PreviousTaskFile[4] = 0x00;
pATAData->PreviousTaskFile[5] = 0x04;
pATAData->PreviousTaskFile[6] = 0x00;
pATAData->PreviousTaskFile[7]=  0x00;

 // command Read Sector(s) Ext(0x24)
/* sends the command to the device, **hDevice** is device handle*/
status = DeviceIoControl(hDevice, IOCTL_ATA_PASS_THROUGH, pATAData, dataSize,Buffer, dataSize, &bytescopied, NULL );

Open in new window


This is the code to read from disk, but it is not working. Function DeviceIoControl() return TRUE but it does not read any data from the disk, output buffer is empty.

The "Status" register (CurrentTaskFile[7] and "Error" register (CurrentTaskFile[0]) both are zero , no error returned.

Everything looks like ok but its not reading data from disk and i am unable to fine out what's wrong in this code.

Kindly provide a solution.

Thank You
SITPLAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

DavidPresidentCommented:
A few things to check
 - What is the block size of the HDD?  It could be 4K bytes, especially if it is a 4TB. As such, you'll need to adjust the sizes accordingly.    You can see what the size is by doing the EC identify ATA command, and then look at the resulting data structure.  (sorry, can't remember the offset of top of my head, but anybody who gets this far certainly shouldn't be a stranger to t13.org and the ATA spec manauls they have in order to look it up.

Also, you might want to make sure your code works, as is, with a small capacity HDD..   Maybe it is something non-obvious like your device driver / controller has crappy drivers and they won't let you do pass-through on a disk > FFFFFFFFh blocks. Or it may be emuating a SCSI target device.    So step back and look at the device manager and make sure it is presented as a native SATA device with the proper make/model of disk.  (One more thing, your driver may make this appear as a RAID disk , which is also doomed to fail)

Also set pATAData->PreviousTaskFile[6] = 0x24;  
Also you need ...
pATAData->ataFlags = ATA_FLAGS_48BIT_COMMAND | ATA_FLAGS_DRDY_REQUIRED | ATA_FLAGS_DATA_IN

Set a larger timeout value too, otherwise, real world code may fail if drive was asleep.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
SITPLAuthor Commented:
Thanks for your support.

Now my code is working but there is a small problem. I am unable to read or write more than 256 sectors in one call. Below 256 sector it works.

Kindly read the details:

When I am trying to pass an ATA command call for a data transfer of  > 256 sectors (512 Byte sectors), Through ATA_PASS_THORUGH_EXT struct, here i am sending the ATA 48 Bit(Extended) commands , in that it provides a 16 bit field (8 bit Current and 8 bit Previous reg) for Sector Count and ATA devices support sector counts for Read and Write "extended" (48 bit) commands up to 65536 sector.

Command that i am sending for transfer is WRITE MULTIPLE EXT(0x39),READ MULTIPLE EXT(0x29).

The DeviceIOControl function test program compiles fine, but it returns 0 when i want to transfer more than 256 sectors. If I set the data transfer length and Sector Count registers to 256 or less, it works.

Kindly help me.

Thanks
DavidPresidentCommented:
There is a max sector count that is controller/driver specific.  256 MAY be the limit for what you are using.   Other things, make sure the buffer you are using is aligned in memory. Windows has some form of an alloc command that lets you align in memory, sorry, can't remember what it is, but it is vital.

There is also a max limit on passthrough for the various forms of IOCTL for pass-through.   You'll have to see what the are.
But bottom line, 256 sectors MAY be the limit for your controller.  When I wrote ATA pass-through  years ago, i capped it at 256 because that was the limit that always worked no matter what hardware I used.
SITPLAuthor Commented:
Here I am confused. I just want to know the limit of controller where belongs.

Is it related to machine or Hard disk or Windows 7 OS or ATA command library?

Also Is there any way to increase this limit? like using latest ATA commands...


Thanks
DavidPresidentCommented:
The limit of # of blocks is a function of both the hardware controller and the device driver.  Whatever the limit is ... you're stuck with it.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Storage Hardware

From novice to tech pro — start learning today.