ATA_PASS_THROUGH_DIRECT有时会返回998(0x3E6)错误。 [英] ATA_PASS_THROUGH_DIRECT sometimes returned 998 (0x3E6) error.

查看:124
本文介绍了ATA_PASS_THROUGH_DIRECT有时会返回998(0x3E6)错误。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好先生

我正在使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆