ATA_PASS_THROUGH_DIRECT有时会返回998(0x3E6)错误。 [英] ATA_PASS_THROUGH_DIRECT sometimes returned 998 (0x3E6) error.
问题描述
您好先生
我正在使用ATA_PASS_THROUGH_DIRECT将具有特定数据的供应商命令传输到我们的产品。
我做了缓冲区对齐。
如果缓冲区大小超过4KB,DeviceIoControl有时会返回错误代码998(0x3E6)。
但它偶尔会起作用。这对我来说真的很困扰。
附上代码供你参考。
#define ALIGNED_ADDR(base,AlignUnit) (PVOID)(((int)的(碱)+(AlignUnit))及 - ((AlignUnit) - 1))的#define
&ALIGN_UNIT NBSP;     0x10的
的SendData(HANDLE手柄,INT驱动,BYTE *数据,整数数据尺寸,IDE_REGS REGS,BYTE LBA_Mode)
{
    int size;
DWORD bytrv = 0;
IDE_REGS * pCurrentTask;
BYTE * DataBuffer;
ATA_PASS_THROUGH_DIRECT PassThroughDirect;
memset(& PassThroughDirect,0,sizeof(ATA_PASS_THROUGH_DIRECT));
//使数据缓冲区与CACHE对齐,遵循MSDN要求
DataBuffer =(BYTE *)malloc(DataSize + ALIGN_UNIT);
memset(DataBuffer,0,DataSize);
PassThroughDirect.DataBuffer = ALIGNED_ADDR(DataBuffer,ALIGN_UNIT);
memcpy(PassThroughDirect.DataBuffer,data,DataSize);
PassThroughDirect.ReservedAsUchar = 0;
PassThroughDirect.ReservedAsUlong = 0;
PassThroughDirect.AtaFlags =(USHORT)(ATA_FLAGS_DATA_OUT | ATA_FLAGS_USE_DMA | ATA_FLAGS_DRDY_REQUIRED);
    PassThroughDirect.TimeOutValue = 10;
PassThroughDirect.Length = sizeof(PassThroughDirect);
PassThroughDirect.DataTransferLength = DataSize;
size =(int)PassThroughDirect.Length +(int)PassThroughDirect.DataTransferLength;
pCurrentTask =(IDE_REGS *)& PassThroughDirect.CurrentTaskFile [0];
pCurrentTask-> bfeaturesreg = Regs.bfeaturesreg;
pCurrentTask-> bsectornumberreg = Regs.bsectornumberreg;
pCurrentTask-> bsectorcountreg =(BYTE)((数据尺寸+ SECTOR_SIZE - 1)/ SECTOR_SIZE);
&NBSP;&NBSP;&NBSP; pCurrentTask-> bdriveheadreg =(BYTE)(0XA0 |((驱动器&安培; 1) - ;< 4)|(LBA_Mode<&10 6));
&NBSP;&NBSP;&NBSP; pCurrentTask-> bcylhighreg = Regs.bcylhighreg;
pCurrentTask-> bcyllowreg = Regs.bcyllowreg;
pCurrentTask-> bcommandreg = Regs.bcommandreg;
如果(0 = DeviceIoControl的(手柄,IOCTL_ATA_PASS_THROUGH_DIRECT,
&NBSP;!&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&安培; PassThroughDirect,大小,
&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP ; & PassThroughDirect,尺寸和& bytrv,0)) {
&NBSP;&NBSP;&NBSP; //等待数据传输完成
&NBSP;&NBSP;&NBSP; //甚至我们使用非重叠功能
&NBSP;&NBSP;&NBSP; //如果我们发布资源并返回,有时仍会失败
&NBSP;&NBSP;&NBSP; //在DeviceIoControl返回后立即发送 &NBSP;&NBSP;&NBSP;睡眠(1000);
&NBSP;&NBSP;&NBSP;免费(DataBuffer);
&NBSP;&NBSP;&NBSP; if(pCurrentTask-> bcommandreg == 0x00)
&NBSP;&NBSP;&NBSP; &NBSP;&NBSP;&NBSP;返回FALSE;
&NBSP;&NBSP;&NBSP; if(pCurrentTask-> bcommandreg& 0x01)
&NBSP;&NBSP;&NBSP; &NBSP;&NBSP;&NBSP;返回FALSE;
返回TRUE;
}
免费(DataBuffer);
返回FALSE;
问候,
吉姆
Hi sir
I am using ATA_PASS_THROUGH_DIRECT to transfer a vendor command with specific data to our product.
I had done buffer alignment.
DeviceIoControl sometimes returns Error code 998 (0x3E6) if the buffer size is more than 4KB.
But it does work good occasionally. This really bothered me for a long while.
Append the code for your reference.
#define ALIGNED_ADDR(base, AlignUnit) (PVOID)(((int)(base) + (AlignUnit)) & ~((AlignUnit) - 1))
#define ALIGN_UNIT 0x10
SendData(HANDLE handle, int drive, BYTE * data, int DataSize, IDE_REGS Regs, BYTE LBA_Mode)
{
int size;
DWORD bytrv = 0;
IDE_REGS * pCurrentTask ;
BYTE * DataBuffer ;
ATA_PASS_THROUGH_DIRECT PassThroughDirect ;
memset(&PassThroughDirect, 0, sizeof(ATA_PASS_THROUGH_DIRECT)) ;
// Make data buffer to be CACHE-aligned, follow MSDN requirement
DataBuffer = (BYTE *)malloc(DataSize + ALIGN_UNIT) ;
memset(DataBuffer, 0, DataSize) ;
PassThroughDirect.DataBuffer = ALIGNED_ADDR(DataBuffer, ALIGN_UNIT) ;
memcpy(PassThroughDirect.DataBuffer, data, DataSize) ;
PassThroughDirect.ReservedAsUchar = 0;
PassThroughDirect.ReservedAsUlong = 0;
PassThroughDirect.AtaFlags = (USHORT)(ATA_FLAGS_DATA_OUT | ATA_FLAGS_USE_DMA | ATA_FLAGS_DRDY_REQUIRED);
PassThroughDirect.TimeOutValue = 10;
PassThroughDirect.Length = sizeof(PassThroughDirect);
PassThroughDirect.DataTransferLength = DataSize;
size = (int)PassThroughDirect.Length + (int)PassThroughDirect.DataTransferLength;
pCurrentTask = (IDE_REGS *)&PassThroughDirect.CurrentTaskFile[0] ;
pCurrentTask->bfeaturesreg = Regs.bfeaturesreg;
pCurrentTask->bsectornumberreg = Regs.bsectornumberreg;
pCurrentTask->bsectorcountreg = (BYTE)((DataSize + SECTOR_SIZE - 1)/ SECTOR_SIZE);
pCurrentTask->bdriveheadreg = (BYTE)(0xA0 | ((drive & 1) << 4) | (LBA_Mode << 6));
pCurrentTask->bcylhighreg = Regs.bcylhighreg;
pCurrentTask->bcyllowreg = Regs.bcyllowreg;
pCurrentTask->bcommandreg = Regs.bcommandreg;
if (0 != DeviceIoControl(handle, IOCTL_ATA_PASS_THROUGH_DIRECT,
&PassThroughDirect, size,
&PassThroughDirect, size, &bytrv, 0))
{
// wait for data transfer complete
// even we are using non-overlapped function
// it sometimes still be failed if we release resource and return
// immediately after DeviceIoControl returned
Sleep(1000) ;
free(DataBuffer) ;
if (pCurrentTask->bcommandreg == 0x00)
return FALSE ;
if (pCurrentTask->bcommandreg & 0x01)
return FALSE ;
return TRUE;
}
free(DataBuffer) ;
return FALSE ;
}
Regards,
Jim
推荐答案
平台是Vista
这篇关于ATA_PASS_THROUGH_DIRECT有时会返回998(0x3E6)错误。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!