HalBuildScatterGatherListV2

NTSTATUS __stdcall HalBuildScatterGatherListV2(
        PADAPTER_OBJECT AdapterObject,
        INT64 a2,
        UINT64 a3,
        INT64 a4,
        INT64 a5,
        INT64 arg28,
        INT64 a7,
        CHAR a8,
        PVOID P,
        INT64 a10){
  int v14; 
  NTSTATUS result; 
  PVOID v16; 
  char *PoolWithTag; 
  char *v18; 
  __int64 v19; 
  unsigned int v20; 
  unsigned int ByteOffset; 
  char *v22; 
  unsigned int ByteCount; 
  _MDL *v24; 
  _MDL *v25; 
  _MDL *Next; 
  unsigned int v27; 
  unsigned int v28; 
  unsigned int v29; 
  bool v30; 
  unsigned int v31; 
  __int64 v32; 
  CHAR v33; 
  unsigned int v34; 
  char *v35; 
  _QWORD *v36; 
  int AdapterChannel; 
  VOID **v38; 
  INT64 DeferFlushing; 
  INT64 a6; 
  unsigned int v41; 
  PDRIVER_CONTROL ExecutionRoutine; 
  UINT64 NumberOfBytes; 
  INT64 v45; 

  v45 = a4;
  LODWORD(ExecutionRoutine) = 0;
  v41 = 0;
  LODWORD(NumberOfBytes) = 0;
  if( !a3 )
    return -1073741811;
  v14 = a5;
  result = HalpCalculateScatterGatherListSize(
             AdapterObject,
             (_MDL *)a3,
             (VOID *)a4,
             (unsigned int)a5,
             &NumberOfBytes,
             (UINT64 *)&ExecutionRoutine,
             (UINT64 *)&v41);
  if( result >= 0 )
  {
    if( AdapterObject->NeedsMapRegisters )
    {
      v34 = v41;
      v33 = a8;
    }
    else if( AdapterObject->CacheCoherent || (v33 = a8) != 0 || (v34 = v41) == 0 )
    {
      v16 = P;
      if( P )
      {
        if( (unsigned int)a10 >= (unsigned int)NumberOfBytes )
        {
          PoolWithTag = (char *)P;
LABEL_8:
          v18 = PoolWithTag + 16;
          v19 = *(_QWORD *)(a3 + 32) + *(unsigned int *)(a3 + 44);
          v20 = a5;
          *((_QWORD *)PoolWithTag + 1) = 0i64;
          ByteOffset = a4 & 0xFFF;
          v22 = PoolWithTag + 16;
          ByteCount = v19 + *(_DWORD *)(a3 + 40) - a4;
          v24 = (_MDL *)(a3 + 8 * (((a4 - (v19 & 0xFFFFFFFFFFFFF000ui64)) >> 12) + 6));
          if( v20 )
          {
            v25 = (_MDL *)a3;
            do
            {
              Next = v25->Next;
              v27 = v20;
              v28 = v20;
              if( ByteCount <= v20 )
                v27 = ByteCount;
              if( Next )
                v28 = v27;
              v29 = v20 - v27;
              v20 = 0;
              if( Next )
                v20 = v29;
              v30 = AdapterObject->CacheCoherent == 0;
              LODWORD(a5) = v20;
              if( v30 )
              {
                if( v25 == (_MDL *)a3 )
                  v35 = (char *)v45;
                else
                  v35 = (char *)v25->StartVa + ByteOffset;
                LOBYTE(a6) = 0;
                LOBYTE(DeferFlushing) = a8;
                HalpDmaFlushBuffer((_DOUBLE)Next, v25, v35, v28, DeferFlushing, a6);
                v20 = a5;
                v18 = PoolWithTag + 16;
              }
              if( v28 )
              {
                do
                {
                  v31 = 4096 - ByteOffset;
                  v32 = ByteOffset + ((__int64)v24->Next << 12);
                  *((_DWORD *)v22 + 2) = 4096 - ByteOffset;
                  *(_QWORD *)v22 = v32;
                  if( 4096 - ByteOffset > v28 )
                  {
                    *((_DWORD *)v22 + 2) = v28;
                    v31 = v28;
                  }
                  v28 -= v31;
                  if( v22 != v18 )
                  {
                    if( v32 == *((_QWORD *)v22 - 3) + *((unsigned int *)v22 - 4)
                      && (((__int64)v24->Next ^ ((__int64)&v24->Next[-1].ByteOffset + 3)) & 0xFFFFFFFFFFF00000ui64) == 0 )
                    {
                      *((_DWORD *)v22 - 4) += v31;
                      v22 -= 24;
                    }
                    v18 = PoolWithTag + 16;
                  }
                  ByteOffset = 0;
                  v22 += 24;
                  v24 = (_MDL *)((char *)v24 + 8);
                }
                while( v28 );
                v20 = a5;
              }
              v25 = v25->Next;
              if( !v25 )
                break;
              ByteOffset = v25->ByteOffset;
              v24 = v25 + 1;
              ByteCount = v25->ByteCount;
            }
            while( v20 );
            v16 = P;
          }
          *(_DWORD *)PoolWithTag = (v22 - PoolWithTag - 16) / 24;
          if( v16 )
            *((_QWORD *)PoolWithTag + 1) = 1i64;
          ((void(__fastcall *)(INT64, _QWORD, char *, INT64))arg28)(a2, *(_QWORD *)(a2 + 32), PoolWithTag, a7);
          return 0;
        }
        return -1073741789;
      }
      PoolWithTag = (char *)ExAllocatePoolWithTag(0x200ui64, (unsigned int)NumberOfBytes, 543973704i64);
      if( PoolWithTag )
        goto LABEL_8;
      return -1073741670;
    }
    v36 = P;
    if( P )
    {
      if( (unsigned int)a10 < (unsigned int)NumberOfBytes )
        return -1073741789;
      *(_DWORD *)P |= 1u;
    }
    else
    {
      v38 = ExAllocatePoolWithTag(0x200ui64, (unsigned int)NumberOfBytes, 543973704i64);
      v36 = v38;
      if( !v38 )
        return -1073741670;
      *(_DWORD *)v38 = 0;
    }
    v36[4] = v45;
    v36[15] = arg28;
    v36[16] = a7;
    v36[1] = a3;
    v36[2] = 0i64;
    *((_DWORD *)v36 + 10) = v14;
    v36[18] = AdapterObject;
    *((_BYTE *)v36 + 152) = v33;
    v30 = AdapterObject->NeedsMapRegisters == 0;
    v36[10] = v36;
    if( !v30 )
      v34 = (unsigned int)ExecutionRoutine;
    *((_DWORD *)v36 + 11) = v34;
    v36[12] = a2;
    v36[13] = *(_QWORD *)(a2 + 32);
    AdapterChannel = HalAllocateAdapterChannel(
                       (INT64)AdapterObject,
                       (INT64)(v36 + 6),
                       v34,
                       (INT64)HalpAllocateAdapterCallbackV2);
    if( AdapterChannel < 0 )
      ExFreePoolWithTag(v36, 0);
    return AdapterChannel;
  }
  return result;
}

Referenced by:

HalGetScatterGatherList