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;
}