ATA download microcode DMA

I don’t know if this is the right place to post this but.

I am trying to do a microcode download dma (0x93) to a drive and deviceiocontrol seems to be returning at once. I have got microcode download (0x92) working. Can someone take a look at the code and see if there are any obvious errors please.

#define SF_SATA_ONE_SECTOR_BUFFER_SIZE 512
#define SF_DOWNLOAD_MC_MAX_SECTOR_SIZE 64

#define ATA_CMD_DOWNLOAD_MC 0x92
#define ATA_CMD_DOWNLOAD_MC_DMA 0x93

#define UINT8 unsigned char
#define UINT16 unsigned short
#define UINT32 unsigned int
#define INT8 char
#define INT16 short
#define INT32 int

typedef char CHAR;

DWORD DownloadMicroCodeFromBufferDMA(UINT8 *Buffer, UINT32 BufferLength, CHAR *_Label)
{
INT32 ReturnValue = 0;
DWORD err = 0;

HANDLE DeviceHandle = CreateFileA(_Label,GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL);
if (DeviceHandle == INVALID_HANDLE_VALUE) {
err = GetLastError();
return err;
}

INT32 SizeofDataBuffer = BufferLength + sizeof(ATA_PASS_THROUGH_EX);
UINT32 NumSectorsToCopy = (BufferLength + (SF_SATA_ONE_SECTOR_BUFFER_SIZE - 1)) / SF_SATA_ONE_SECTOR_BUFFER_SIZE;

ATA_PASS_THROUGH_EX *WIN_ATA = (ATA_PASS_THROUGH_EX *) _aligned_malloc(SizeofDataBuffer, 512);
memset(WIN_ATA, 0, SizeofDataBuffer);

WIN_ATA->Length = sizeof(ATA_PASS_THROUGH_EX);
WIN_ATA->TimeOutValue = 9;
WIN_ATA->DataBufferOffset = (ULONG_PTR) sizeof(ATA_PASS_THROUGH_EX);
WIN_ATA->DataTransferLength = BufferLength;

DWORD InBufferSize = sizeof(ATA_PASS_THROUGH_EX) + BufferLength;
DWORD OutBufferSize = sizeof(ATA_PASS_THROUGH_EX);
WIN_ATA->AtaFlags = ATA_FLAGS_DATA_OUT | ATA_FLAGS_USE_DMA;

UINT8 *pDest = (UINT8 *) (((ULONG_PTR) WIN_ATA) + sizeof(ATA_PASS_THROUGH_EX));
memcpy(pDest, Buffer, BufferLength);

WIN_ATA->CurrentTaskFile[0] = 0x07;
WIN_ATA->CurrentTaskFile[1] = (UINT8)(NumSectorsToCopy & 0xFF);
WIN_ATA->CurrentTaskFile[2] = (UINT8)(NumSectorsToCopy >> 8);
WIN_ATA->CurrentTaskFile[3] = 0;
WIN_ATA->CurrentTaskFile[4] = 0;
WIN_ATA->CurrentTaskFile[6] = ATA_CMD_DOWNLOAD_MC_DMA;

INT32 BytesRead = 0;
ReturnValue = DeviceIoControl(DeviceHandle, IOCTL_ATA_PASS_THROUGH, WIN_ATA, InBufferSize, WIN_ATA, OutBufferSize, (LPDWORD) &BytesRead, NULL);
if (ReturnValue != 0) {
err = GetLastError();
}

printf(“DeviceIoControl: ReturnValue:0x%02X, ErrorRegister:0x%02X, StatusRegister:0x%02X\n”, ReturnValue, WIN_ATA->CurrentTaskFile[0], WIN_ATA->CurrentTaskFile[6]);

_aligned_free(WIN_ATA);

CloseHandle(DeviceHandle);

return err;
}

Is DeviceIoControl returning 0 or 1? If 1, what does GetLastError() return? If 0, is the new firmware version reflected in drive information?

Gary Little
H (952) 223-1349
C (952) 454-4629
xxxxx@comcast.net

On Aug 17, 2011, at 5:03 PM, xxxxx@gmail.com wrote:

I don’t know if this is the right place to post this but.

I am trying to do a microcode download dma (0x93) to a drive and deviceiocontrol seems to be returning at once. I have got microcode download (0x92) working. Can someone take a look at the code and see if there are any obvious errors please.

#define SF_SATA_ONE_SECTOR_BUFFER_SIZE 512
#define SF_DOWNLOAD_MC_MAX_SECTOR_SIZE 64

#define ATA_CMD_DOWNLOAD_MC 0x92
#define ATA_CMD_DOWNLOAD_MC_DMA 0x93

#define UINT8 unsigned char
#define UINT16 unsigned short
#define UINT32 unsigned int
#define INT8 char
#define INT16 short
#define INT32 int

typedef char CHAR;

DWORD DownloadMicroCodeFromBufferDMA(UINT8 *Buffer, UINT32 BufferLength, CHAR *_Label)
{
INT32 ReturnValue = 0;
DWORD err = 0;

HANDLE DeviceHandle = CreateFileA(_Label,GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL);
if (DeviceHandle == INVALID_HANDLE_VALUE) {
err = GetLastError();
return err;
}

INT32 SizeofDataBuffer = BufferLength + sizeof(ATA_PASS_THROUGH_EX);
UINT32 NumSectorsToCopy = (BufferLength + (SF_SATA_ONE_SECTOR_BUFFER_SIZE - 1)) / SF_SATA_ONE_SECTOR_BUFFER_SIZE;

ATA_PASS_THROUGH_EX *WIN_ATA = (ATA_PASS_THROUGH_EX *) _aligned_malloc(SizeofDataBuffer, 512);
memset(WIN_ATA, 0, SizeofDataBuffer);

WIN_ATA->Length = sizeof(ATA_PASS_THROUGH_EX);
WIN_ATA->TimeOutValue = 9;
WIN_ATA->DataBufferOffset = (ULONG_PTR) sizeof(ATA_PASS_THROUGH_EX);
WIN_ATA->DataTransferLength = BufferLength;

DWORD InBufferSize = sizeof(ATA_PASS_THROUGH_EX) + BufferLength;
DWORD OutBufferSize = sizeof(ATA_PASS_THROUGH_EX);
WIN_ATA->AtaFlags = ATA_FLAGS_DATA_OUT | ATA_FLAGS_USE_DMA;

UINT8 *pDest = (UINT8 *) (((ULONG_PTR) WIN_ATA) + sizeof(ATA_PASS_THROUGH_EX));
memcpy(pDest, Buffer, BufferLength);

WIN_ATA->CurrentTaskFile[0] = 0x07;
WIN_ATA->CurrentTaskFile[1] = (UINT8)(NumSectorsToCopy & 0xFF);
WIN_ATA->CurrentTaskFile[2] = (UINT8)(NumSectorsToCopy >> 8);
WIN_ATA->CurrentTaskFile[3] = 0;
WIN_ATA->CurrentTaskFile[4] = 0;
WIN_ATA->CurrentTaskFile[6] = ATA_CMD_DOWNLOAD_MC_DMA;

INT32 BytesRead = 0;
ReturnValue = DeviceIoControl(DeviceHandle, IOCTL_ATA_PASS_THROUGH, WIN_ATA, InBufferSize, WIN_ATA, OutBufferSize, (LPDWORD) &BytesRead, NULL);
if (ReturnValue != 0) {
err = GetLastError();
}

printf(“DeviceIoControl: ReturnValue:0x%02X, ErrorRegister:0x%02X, StatusRegister:0x%02X\n”, ReturnValue, WIN_ATA->CurrentTaskFile[0], WIN_ATA->CurrentTaskFile[6]);

_aligned_free(WIN_ATA);

CloseHandle(DeviceHandle);

return err;
}


NTFSD is sponsored by OSR

For our schedule of debugging and file system seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

> -----Original Message-----

From: xxxxx@lists.osr.com [mailto:bounce-470827-
xxxxx@lists.osr.com] On Behalf Of xxxxx@gmail.com
Sent: Wednesday, August 17, 2011 4:03 PM
To: Windows File Systems Devs Interest List
Subject: [ntfsd] ATA download microcode DMA

I don’t know if this is the right place to post this but.

I am trying to do a microcode download dma (0x93) to a drive and
deviceiocontrol seems to be returning at once. I have got microcode
download
(0x92) working. Can someone take a look at the code and see if there are
any
obvious errors please.

Since you are asking for DMA, you might need to use the
IOCTL_ATA_PASSTHROUGH_DIRECT and the associated struct. Totally not sure of
that, though.

#define SF_SATA_ONE_SECTOR_BUFFER_SIZE 512
#define SF_DOWNLOAD_MC_MAX_SECTOR_SIZE 64

#define ATA_CMD_DOWNLOAD_MC 0x92
#define ATA_CMD_DOWNLOAD_MC_DMA 0x93

#define UINT8 unsigned char
#define UINT16 unsigned short
#define UINT32 unsigned int
#define INT8 char
#define INT16 short
#define INT32 int

typedef char CHAR;

DWORD DownloadMicroCodeFromBufferDMA(UINT8 *Buffer, UINT32 BufferLength,
CHAR
*_Label)
{
INT32 ReturnValue = 0;
DWORD err = 0;

HANDLE DeviceHandle = CreateFileA(_Label,GENERIC_READ |
GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
FILE_FLAG_NO_BUFFERING, NULL);
if (DeviceHandle == INVALID_HANDLE_VALUE) {
err = GetLastError();
return err;
}

INT32 SizeofDataBuffer = BufferLength + sizeof(ATA_PASS_THROUGH_EX);
UINT32 NumSectorsToCopy = (BufferLength +
(SF_SATA_ONE_SECTOR_BUFFER_SIZE - 1)) / SF_SATA_ONE_SECTOR_BUFFER_SIZE;

ATA_PASS_THROUGH_EX *WIN_ATA = (ATA_PASS_THROUGH_EX *)
_aligned_malloc(SizeofDataBuffer, 512);
memset(WIN_ATA, 0, SizeofDataBuffer);

WIN_ATA->Length = sizeof(ATA_PASS_THROUGH_EX);
WIN_ATA->TimeOutValue = 9;
WIN_ATA->DataBufferOffset = (ULONG_PTR)
sizeof(ATA_PASS_THROUGH_EX);
WIN_ATA->DataTransferLength = BufferLength;

DWORD InBufferSize = sizeof(ATA_PASS_THROUGH_EX) + BufferLength;
DWORD OutBufferSize = sizeof(ATA_PASS_THROUGH_EX);
WIN_ATA->AtaFlags = ATA_FLAGS_DATA_OUT | ATA_FLAGS_USE_DMA;

UINT8 *pDest = (UINT8 *) (((ULONG_PTR) WIN_ATA) +
sizeof(ATA_PASS_THROUGH_EX));
memcpy(pDest, Buffer, BufferLength);

WIN_ATA->CurrentTaskFile[0] = 0x07;
WIN_ATA->CurrentTaskFile[1] = (UINT8)(NumSectorsToCopy & 0xFF);
WIN_ATA->CurrentTaskFile[2] = (UINT8)(NumSectorsToCopy >> 8);
WIN_ATA->CurrentTaskFile[3] = 0;
WIN_ATA->CurrentTaskFile[4] = 0;
WIN_ATA->CurrentTaskFile[6] = ATA_CMD_DOWNLOAD_MC_DMA;

INT32 BytesRead = 0;
ReturnValue = DeviceIoControl(DeviceHandle, IOCTL_ATA_PASS_THROUGH,
WIN_ATA, InBufferSize, WIN_ATA, OutBufferSize, (LPDWORD) &BytesRead,
NULL);

if (ReturnValue != 0) {
err = GetLastError();
}

printf(“DeviceIoControl: ReturnValue:0x%02X, ErrorRegister:0x%02X,
StatusRegister:0x%02X\n”, ReturnValue, WIN_ATA->CurrentTaskFile[0],
WIN_ATA-
>CurrentTaskFile[6]);

_aligned_free(WIN_ATA);

CloseHandle(DeviceHandle);

return err;
}

Hope that helps. Please post what you find.

Phil

Philip D. Barila

DeviceIoControl return 0. The error returned is 0x87, invalid parameter.

Tried direct, and get the same error (invalid parameter).

#define SF_SATA_ONE_SECTOR_BUFFER_SIZE 512
#define SF_DOWNLOAD_MC_MAX_SECTOR_SIZE 64

#define ATA_CMD_DOWNLOAD_MC 0x92
#define ATA_CMD_DOWNLOAD_MC_DMA 0x93

#define UINT8 unsigned char
#define UINT16 unsigned short
#define UINT32 unsigned int
#define INT8 char
#define INT16 short
#define INT32 int

typedef char CHAR;

void DownloadMicroCodeFromBufferDirect(UINT8 *Buffer, UINT32 BufferLength, CHAR *_Label)
{
INT32 ReturnValue = 0;
DWORD err;

HANDLE DeviceHandle = CreateFileA( _Label,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_NO_BUFFERING,
NULL);
if (DeviceHandle == INVALID_HANDLE_VALUE) {
err = GetLastError();
return;
}

INT32 SizeofDataBuffer = sizeof(ATA_PASS_THROUGH_DIRECT);
UINT32 NumSectorsToCopy = (BufferLength + (SF_SATA_ONE_SECTOR_BUFFER_SIZE - 1)) / SF_SATA_ONE_SECTOR_BUFFER_SIZE;

ATA_PASS_THROUGH_DIRECT *WIN_ATA = (ATA_PASS_THROUGH_DIRECT *) _aligned_malloc(SizeofDataBuffer, 512);
memset(WIN_ATA, 0, SizeofDataBuffer);

WIN_ATA->Length = sizeof(ATA_PASS_THROUGH_DIRECT);
WIN_ATA->TimeOutValue = 9;
WIN_ATA->DataBuffer = Buffer;
WIN_ATA->DataTransferLength = BufferLength;

DWORD InBufferSize = sizeof(ATA_PASS_THROUGH_DIRECT);
DWORD OutBufferSize = sizeof(ATA_PASS_THROUGH_DIRECT);
WIN_ATA->AtaFlags = ATA_FLAGS_DATA_OUT | ATA_FLAGS_USE_DMA;
//WIN_ATA->AtaFlags = ATA_FLAGS_DATA_OUT;

WIN_ATA->CurrentTaskFile[0] = 0x07;
WIN_ATA->CurrentTaskFile[1] = (UINT8)(NumSectorsToCopy & 0xFF);
WIN_ATA->CurrentTaskFile[2] = (UINT8)(NumSectorsToCopy >> 8);
WIN_ATA->CurrentTaskFile[3] = 0;
WIN_ATA->CurrentTaskFile[4] = 0;
WIN_ATA->CurrentTaskFile[6] = ATA_CMD_DOWNLOAD_MC_DMA;
//WIN_ATA->CurrentTaskFile[6] = ATA_CMD_DOWNLOAD_MC;

INT32 BytesRead = 0;
ReturnValue = DeviceIoControl( DeviceHandle,
IOCTL_ATA_PASS_THROUGH_DIRECT,
WIN_ATA,
InBufferSize,
WIN_ATA,
OutBufferSize,
(LPDWORD) &BytesRead,
NULL);

if (ReturnValue == 0) {
err = GetLastError();
printf(“DeviceIoControl: ReturnValue:0x%02X (0x%02X), ErrorRegister:0x%02X, StatusRegister:0x%02X\n”, ReturnValue, err, WIN_ATA->CurrentTaskFile[0], WIN_ATA->CurrentTaskFile[6]);
}

printf(“DeviceIoControl: ReturnValue:0x%02X, ErrorRegister:0x%02X, StatusRegister:0x%02X\n”, ReturnValue, WIN_ATA->CurrentTaskFile[0], WIN_ATA->CurrentTaskFile[6]);

_aligned_free(WIN_ATA);

CloseHandle(DeviceHandle);
}

Check your parameters. When using _DIRECT, your command buffer (InBuffer)
information is the pointer to the ATA struct and size. The Data buffer and
data buffer length is the OutBuffer and length. Direct is probably the best
for firmware download unless your firmware is relatively small.

Gary G. Little
H (952) 223-1349
C (952) 454-4629
xxxxx@comcast.net

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@gmail.com
Sent: Wednesday, August 17, 2011 5:40 PM
To: Windows File Systems Devs Interest List
Subject: RE:[ntfsd] ATA download microcode DMA

Tried direct, and get the same error (invalid parameter).

#define SF_SATA_ONE_SECTOR_BUFFER_SIZE 512 #define
SF_DOWNLOAD_MC_MAX_SECTOR_SIZE 64

#define ATA_CMD_DOWNLOAD_MC 0x92
#define ATA_CMD_DOWNLOAD_MC_DMA 0x93

#define UINT8 unsigned char
#define UINT16 unsigned short
#define UINT32 unsigned int
#define INT8 char
#define INT16 short
#define INT32 int

typedef char CHAR;

void DownloadMicroCodeFromBufferDirect(UINT8 *Buffer, UINT32 BufferLength,
CHAR *_Label) {
INT32 ReturnValue = 0;
DWORD err;

HANDLE DeviceHandle = CreateFileA( _Label,

GENERIC_READ | GENERIC_WRITE,

FILE_SHARE_READ | FILE_SHARE_WRITE,

NULL,

OPEN_EXISTING,

FILE_FLAG_NO_BUFFERING,

NULL);
if (DeviceHandle == INVALID_HANDLE_VALUE) {
err = GetLastError();
return;
}

INT32 SizeofDataBuffer = sizeof(ATA_PASS_THROUGH_DIRECT);
UINT32 NumSectorsToCopy = (BufferLength +
(SF_SATA_ONE_SECTOR_BUFFER_SIZE - 1)) / SF_SATA_ONE_SECTOR_BUFFER_SIZE;

ATA_PASS_THROUGH_DIRECT *WIN_ATA = (ATA_PASS_THROUGH_DIRECT *)
_aligned_malloc(SizeofDataBuffer, 512);
memset(WIN_ATA, 0, SizeofDataBuffer);

WIN_ATA->Length = sizeof(ATA_PASS_THROUGH_DIRECT);
WIN_ATA->TimeOutValue = 9;
WIN_ATA->DataBuffer = Buffer;
WIN_ATA->DataTransferLength = BufferLength;

DWORD InBufferSize = sizeof(ATA_PASS_THROUGH_DIRECT);
DWORD OutBufferSize = sizeof(ATA_PASS_THROUGH_DIRECT);
WIN_ATA->AtaFlags = ATA_FLAGS_DATA_OUT | ATA_FLAGS_USE_DMA;
//WIN_ATA->AtaFlags = ATA_FLAGS_DATA_OUT;

WIN_ATA->CurrentTaskFile[0] = 0x07;
WIN_ATA->CurrentTaskFile[1] = (UINT8)(NumSectorsToCopy & 0xFF);
WIN_ATA->CurrentTaskFile[2] = (UINT8)(NumSectorsToCopy >> 8);
WIN_ATA->CurrentTaskFile[3] = 0;
WIN_ATA->CurrentTaskFile[4] = 0;
WIN_ATA->CurrentTaskFile[6] = ATA_CMD_DOWNLOAD_MC_DMA;
//WIN_ATA->CurrentTaskFile[6] = ATA_CMD_DOWNLOAD_MC;

INT32 BytesRead = 0;
ReturnValue = DeviceIoControl( DeviceHandle,

IOCTL_ATA_PASS_THROUGH_DIRECT,

WIN_ATA,

InBufferSize,

WIN_ATA,

OutBufferSize,

(LPDWORD) &BytesRead,

NULL);

if (ReturnValue == 0) {
err = GetLastError();
printf(“DeviceIoControl: ReturnValue:0x%02X (0x%02X),
ErrorRegister:0x%02X, StatusRegister:0x%02X\n”, ReturnValue, err,
WIN_ATA->CurrentTaskFile[0], WIN_ATA->CurrentTaskFile[6]);
}

printf(“DeviceIoControl: ReturnValue:0x%02X, ErrorRegister:0x%02X,
StatusRegister:0x%02X\n”, ReturnValue, WIN_ATA->CurrentTaskFile[0],
WIN_ATA->CurrentTaskFile[6]);

_aligned_free(WIN_ATA);

CloseHandle(DeviceHandle);
}


NTFSD is sponsored by OSR

For our schedule of debugging and file system seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

__________ Information from ESET Smart Security, version of virus signature
database 6386 (20110817) __________

The message was checked by ESET Smart Security.

http://www.eset.com

What is the difference between this code (0x93) and the download
microcode code that works, the ATA_FLAGS_USE_DMA flag?

Regards,