⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aoe.c

📁 WinAoE is an open source GPLv3 driver for using AoE (ATA over Ethernet) on Microsoft Windows
💻 C
📖 第 1 页 / 共 2 页
字号:
        KeQuerySystemTime(&MaxSectorsPerPacketSendTime);
        DeviceExtension->Disk.SearchState = GettingMaxSectorsPerPacket;
        DeviceExtension->Disk.Timeout = 200000;
        break;
      default:
        DbgPrint("AoESearchBootDrive Undefined SearchState!\n");
        ExFreePool(Tag->PacketData);
        ExFreePool(Tag);
        KeReleaseSpinLock(&DeviceExtension->Disk.SpinLock, Irql);
        continue;
        break;
    }

    Tag->Next = NULL;
    KeAcquireSpinLock(&SpinLock, &InnerIrql);
    if (TagList == NULL) {
      TagList = Tag;
      Tag->Previous = NULL;
    } else {
      TagListLast->Next = Tag;
      Tag->Previous = TagListLast;
    }
    TagListLast = Tag;
    KeReleaseSpinLock(&SpinLock, InnerIrql);
    KeReleaseSpinLock(&DeviceExtension->Disk.SpinLock, Irql);
  }
}

NTSTATUS STDCALL AoERequest(IN PDEVICEEXTENSION DeviceExtension, IN REQUESTMODE Mode, IN LONGLONG StartSector, IN ULONG SectorCount, IN PUCHAR Buffer, IN PIRP Irp) {
  PREQUEST Request;
  PTAG Tag, NewTagList = NULL, PreviousTag = NULL;
  KIRQL Irql;
  ULONG i;

  if (Stop) {
    Irp->IoStatus.Information = 0;
    Irp->IoStatus.Status = STATUS_CANCELLED;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return STATUS_CANCELLED;
  }

  if (SectorCount < 1) {
    DbgPrint("AoERequest SectorCount < 1!!\n");
    Irp->IoStatus.Information = 0;
    Irp->IoStatus.Status = STATUS_CANCELLED;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return STATUS_CANCELLED;
  }

  if ((Request = (PREQUEST)ExAllocatePool(NonPagedPool, sizeof(REQUEST))) == NULL) {
    DbgPrint("AoERequest ExAllocatePool Request\n");
    Irp->IoStatus.Information = 0;
    Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return STATUS_INSUFFICIENT_RESOURCES;
  }
  RtlZeroMemory(Request, sizeof(REQUEST));
  Request->Mode = Mode;
  Request->SectorCount = SectorCount;
  Request->Buffer = Buffer;
  Request->Irp = Irp;
  Request->TagCount = 0;

  for (i = 0; i < SectorCount; i += DeviceExtension->Disk.MaxSectorsPerPacket) {
    if ((Tag = (PTAG)ExAllocatePool(NonPagedPool, sizeof(TAG))) == NULL) {
      DbgPrint("AoERequest ExAllocatePool Tag\n");
      Tag = NewTagList;
      while (Tag != NULL) {
        PreviousTag = Tag;
        Tag = Tag->Next;
        ExFreePool(PreviousTag->PacketData);
        ExFreePool(PreviousTag);
      }
      ExFreePool(Request);
      Irp->IoStatus.Information = 0;
      Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
      IoCompleteRequest(Irp, IO_NO_INCREMENT);
      return STATUS_INSUFFICIENT_RESOURCES;
    }
    RtlZeroMemory(Tag, sizeof(TAG));
    Tag->Type = RequestType;
    Tag->Request = Request;
    Tag->DeviceExtension = DeviceExtension;
    Request->TagCount++;
    Tag->Id = 0;
    Tag->BufferOffset = i * SECTORSIZE;
    Tag->SectorCount = ((SectorCount - i) < DeviceExtension->Disk.MaxSectorsPerPacket?SectorCount - i:DeviceExtension->Disk.MaxSectorsPerPacket);
    Tag->PacketSize = sizeof(AOE);
    if (Mode == Write) Tag->PacketSize += Tag->SectorCount * SECTORSIZE;
    if ((Tag->PacketData = (PAOE)ExAllocatePool(NonPagedPool, Tag->PacketSize)) == NULL) {
      DbgPrint("AoERequest ExAllocatePool Tag->PacketData\n");
      ExFreePool(Tag);
      Tag = NewTagList;
      while (Tag != NULL) {
        PreviousTag = Tag;
        Tag = Tag->Next;
        ExFreePool(PreviousTag->PacketData);
        ExFreePool(PreviousTag);
      }
      ExFreePool(Request);
      Irp->IoStatus.Information = 0;
      Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
      IoCompleteRequest(Irp, IO_NO_INCREMENT);
      return STATUS_INSUFFICIENT_RESOURCES;
    }
    RtlZeroMemory(Tag->PacketData, Tag->PacketSize);
    Tag->PacketData->Ver = AOEPROTOCOLVER;
    Tag->PacketData->Major = htons((USHORT)DeviceExtension->Disk.Major);
    Tag->PacketData->Minor = (UCHAR)DeviceExtension->Disk.Minor;
    Tag->PacketData->Tag = 0;
    Tag->PacketData->Command = 0;
    Tag->PacketData->ExtendedAFlag = TRUE;
    if (Mode == Read) {
      Tag->PacketData->Cmd = 0x24;                 // READ SECTOR
    } else {
      Tag->PacketData->Cmd = 0x34;                 // WRITE SECTOR
      Tag->PacketData->WriteAFlag = 1;
    }
    Tag->PacketData->Count = (UCHAR)Tag->SectorCount;
    Tag->PacketData->Lba0 = (UCHAR)(((StartSector + i) >> 0) & 255);
    Tag->PacketData->Lba1 = (UCHAR)(((StartSector + i) >> 8) & 255);
    Tag->PacketData->Lba2 = (UCHAR)(((StartSector + i) >> 16) & 255);
    Tag->PacketData->Lba3 = (UCHAR)(((StartSector + i) >> 24) & 255);
    Tag->PacketData->Lba4 = (UCHAR)(((StartSector + i) >> 32) & 255);
    Tag->PacketData->Lba5 = (UCHAR)(((StartSector + i) >> 40) & 255);

    if (Mode == Write) RtlCopyMemory(Tag->PacketData->Data, &Buffer[Tag->BufferOffset], Tag->SectorCount * SECTORSIZE);
    Tag->Previous = PreviousTag;
    Tag->Next = NULL;
    if (NewTagList == NULL) {
      NewTagList = Tag;
    } else {
      PreviousTag->Next = Tag;
    }
    PreviousTag = Tag;
  }
  Request->TotalTags = Request->TagCount;

  KeAcquireSpinLock(&SpinLock, &Irql);
  if (TagListLast == NULL) {
    TagList = NewTagList;
  } else {
    TagListLast->Next = NewTagList;
    NewTagList->Previous = TagListLast;
  }
  TagListLast = Tag;
  KeReleaseSpinLock(&SpinLock, Irql);
  KeSetEvent(&ThreadSignalEvent, 0, FALSE);

  Irp->IoStatus.Information = 0;
  Irp->IoStatus.Status = STATUS_PENDING;
  IoMarkIrpPending(Irp);
  return STATUS_PENDING;
}

NTSTATUS STDCALL AoEReply(IN PUCHAR SourceMac, IN PUCHAR DestinationMac, IN PUCHAR Data, IN UINT DataSize) {
  PAOE Reply = (PAOE)Data;
  LONGLONG LBASize;
  PTAG Tag;
  KIRQL Irql;
  BOOLEAN Found = FALSE;
  LARGE_INTEGER CurrentTime;

  if (!Reply->ResponseFlag) return STATUS_SUCCESS;

  if (ProbeTag->Id == Reply->Tag) {
    RtlCopyMemory(&LBASize, &Reply->Data[200], sizeof(LONGLONG));
    BusAddTarget(DestinationMac, SourceMac, ntohs(Reply->Major), Reply->Minor, LBASize);
    return STATUS_SUCCESS;
  }

  KeAcquireSpinLock(&SpinLock, &Irql);
  if (TagList == NULL) {
    KeReleaseSpinLock(&SpinLock, Irql);
    return STATUS_SUCCESS;
  }
  Tag = TagList;
  while (Tag != NULL) {
    if ((Tag->Id == Reply->Tag) && (Tag->PacketData->Major == Reply->Major) && (Tag->PacketData->Minor == Reply->Minor)) {
      Found = TRUE;
      break;
    }
    Tag = Tag->Next;
  }
  if (!Found) {
    KeReleaseSpinLock(&SpinLock, Irql);
    return STATUS_SUCCESS;
  } else {
    if (Tag->Previous == NULL) TagList = Tag->Next;
    else Tag->Previous->Next = Tag->Next;
    if (Tag->Next == NULL) TagListLast = Tag->Previous;
    else Tag->Next->Previous = Tag->Previous;
    OutstandingTags--;
    if (OutstandingTags < 0) DbgPrint("!!OutstandingTags < 0 (AoEReply)!!\n");
    KeSetEvent(&ThreadSignalEvent, 0, FALSE);
  }
  KeReleaseSpinLock(&SpinLock, Irql);

  if (RtlCompareMemory(Tag->DeviceExtension->Disk.ServerMac, "\xff\xff\xff\xff\xff\xff", 6) == 6) {
    RtlCopyMemory(Tag->DeviceExtension->Disk.ServerMac, SourceMac, 6);
    DbgPrint("Major: %d minor: %d found on server %02x:%02x:%02x:%02x:%02x:%02x\n", Tag->DeviceExtension->Disk.Major, Tag->DeviceExtension->Disk.Minor, SourceMac[0], SourceMac[1], SourceMac[2], SourceMac[3], SourceMac[4], SourceMac[5]);
  }

  KeQuerySystemTime(&CurrentTime);
  Tag->DeviceExtension->Disk.Timeout -= (ULONG)((Tag->DeviceExtension->Disk.Timeout - (CurrentTime.QuadPart - Tag->FirstSendTime.QuadPart)) / 1024);
  if (Tag->DeviceExtension->Disk.Timeout > 100000000) Tag->DeviceExtension->Disk.Timeout = 100000000;

  switch (Tag->Type) {
    case SearchDriveType:
      KeAcquireSpinLock(&Tag->DeviceExtension->Disk.SpinLock, &Irql);
      switch (Tag->DeviceExtension->Disk.SearchState) {
        case GettingSize:
          RtlCopyMemory(&Tag->DeviceExtension->Disk.LBADiskSize, &Reply->Data[200], sizeof(LONGLONG));
          Tag->DeviceExtension->Disk.SearchState = GetGeometry;
          break;
        case GettingGeometry:
          Tag->DeviceExtension->Disk.Heads = 255;       // FIXME use real values from partition table
          Tag->DeviceExtension->Disk.Sectors = 63;
          Tag->DeviceExtension->Disk.Cylinders = Tag->DeviceExtension->Disk.LBADiskSize / (Tag->DeviceExtension->Disk.Heads * Tag->DeviceExtension->Disk.Sectors);
          Tag->DeviceExtension->Disk.LBADiskSize = Tag->DeviceExtension->Disk.Cylinders * Tag->DeviceExtension->Disk.Heads * Tag->DeviceExtension->Disk.Sectors;
          Tag->DeviceExtension->Disk.SearchState = GetMaxSectorsPerPacket;
          break;
        case GettingMaxSectorsPerPacket:
          DataSize -= sizeof(AOE);
          if (DataSize < (Tag->DeviceExtension->Disk.MaxSectorsPerPacket * SECTORSIZE)) {
            DbgPrint("AoEReply Packet size too low while getting MaxSectorsPerPacket (tried %d, got size of %d)\n", Tag->DeviceExtension->Disk.MaxSectorsPerPacket, DataSize);
            Tag->DeviceExtension->Disk.MaxSectorsPerPacket--;
            Tag->DeviceExtension->Disk.SearchState = Done;
          } else if (Tag->DeviceExtension->Disk.MTU < (sizeof(AOE) + ((Tag->DeviceExtension->Disk.MaxSectorsPerPacket + 1) * SECTORSIZE))) {
            DbgPrint("AoEReply Got MaxSectorsPerPacket %d at size of %d. MTU of %d reached\n", Tag->DeviceExtension->Disk.MaxSectorsPerPacket, DataSize, Tag->DeviceExtension->Disk.MTU);
            Tag->DeviceExtension->Disk.SearchState = Done;
          } else {
            DbgPrint("AoEReply Got MaxSectorsPerPacket %d at size of %d, trying next...\n", Tag->DeviceExtension->Disk.MaxSectorsPerPacket, DataSize);
            Tag->DeviceExtension->Disk.SearchState = GetMaxSectorsPerPacket;
          }
          break;
        default:
          DbgPrint("AoEReply Undefined SearchState!\n");
          break;
      }
      KeReleaseSpinLock(&Tag->DeviceExtension->Disk.SpinLock, Irql);
      KeSetEvent(&Tag->DeviceExtension->Disk.SearchEvent, 0, FALSE);
      break;
    case RequestType:
      if (Tag->Request->Mode == Read) RtlCopyMemory(&Tag->Request->Buffer[Tag->BufferOffset], Reply->Data, Tag->SectorCount * SECTORSIZE);
      if (InterlockedDecrement(&Tag->Request->TagCount) == 0) {
        Tag->Request->Irp->IoStatus.Information = Tag->Request->SectorCount * SECTORSIZE;
        Tag->Request->Irp->IoStatus.Status = STATUS_SUCCESS;
        CompletePendingIrp(Tag->Request->Irp);
        ExFreePool(Tag->Request);
      }
      break;
    default:
      DbgPrint("Unknown tag type??\n");
      break;
  }

  KeSetEvent(&ThreadSignalEvent, 0, FALSE);
  ExFreePool(Tag->PacketData);
  ExFreePool(Tag);
  return STATUS_SUCCESS;
}

VOID STDCALL AoEResetProbe() {
  ProbeTag->SendTime.QuadPart = 0LL;
}

VOID STDCALL Thread(IN PVOID StartContext) {
  LARGE_INTEGER Timeout, CurrentTime, ProbeTime, ReportTime;
  ULONG NextTagId = 1;
  PTAG Tag;
  KIRQL Irql;
  ULONG Sends = 0;
  ULONG Resends = 0;
  ULONG ResendFails = 0;
  ULONG Fails = 0;
  ULONG RequestTimeout = 0;

  DbgPrint("Thread\n");
  ReportTime.QuadPart = 0LL;
  ProbeTime.QuadPart = 0LL;

  while (TRUE) {
    Timeout.QuadPart = -100000LL;               // 100.000 * 100ns = 10.000.000 ns = 10ms
    KeWaitForSingleObject(&ThreadSignalEvent, Executive, KernelMode, FALSE, &Timeout);
    KeResetEvent(&ThreadSignalEvent);
    if (Stop) {
      DbgPrint("Stopping thread...\n");
      PsTerminateSystemThread(STATUS_SUCCESS);
    }
    BusCleanupTargetList();

    KeQuerySystemTime(&CurrentTime);
    if (CurrentTime.QuadPart > (ReportTime.QuadPart + 10000000LL)) {
//      DbgPrint("Sends: %d  Resends: %d  ResendFails: %d  Fails: %d  OutstandingTags: %d  RequestTimeout: %d\n", Sends, Resends, ResendFails, Fails, OutstandingTags, RequestTimeout);
      Sends = 0;
      Resends = 0;
      ResendFails = 0;
      Fails = 0;
      KeQuerySystemTime(&ReportTime);
    }

    if (CurrentTime.QuadPart > (ProbeTag->SendTime.QuadPart + 100000000LL)) {
      ProbeTag->Id = NextTagId++;
      if (NextTagId == 0) NextTagId++;
      ProbeTag->PacketData->Tag = ProbeTag->Id;
      ProtocolSend("\xff\xff\xff\xff\xff\xff", "\xff\xff\xff\xff\xff\xff", (PUCHAR)ProbeTag->PacketData, ProbeTag->PacketSize, NULL);
      KeQuerySystemTime(&ProbeTag->SendTime);
    }

    KeAcquireSpinLock(&SpinLock, &Irql);
    if (TagList == NULL) {
      KeReleaseSpinLock(&SpinLock, Irql);
      continue;
    }
    Tag = TagList;
    while (Tag != NULL) {
      RequestTimeout = Tag->DeviceExtension->Disk.Timeout;
      if (Tag->Id == 0) {
        if (OutstandingTags <= 64) {
        //if (OutstandingTags <= 102400) {
          if (OutstandingTags < 0) DbgPrint("!!OutstandingTags < 0 (Thread)!!\n");
          Tag->Id = NextTagId++;
          if (NextTagId == 0) NextTagId++;
          Tag->PacketData->Tag = Tag->Id;
          if (ProtocolSend(Tag->DeviceExtension->Disk.ClientMac, Tag->DeviceExtension->Disk.ServerMac, (PUCHAR)Tag->PacketData, Tag->PacketSize, Tag)) {
            KeQuerySystemTime(&Tag->FirstSendTime);
            KeQuerySystemTime(&Tag->SendTime);
            OutstandingTags++;
	    Sends++;
          } else {
            Fails++;
            Tag->Id = 0;
            break;
          }
        }
      } else {
        KeQuerySystemTime(&CurrentTime);
        if (CurrentTime.QuadPart > (Tag->SendTime.QuadPart + (LONGLONG)(Tag->DeviceExtension->Disk.Timeout * 2))) {
          if (ProtocolSend(Tag->DeviceExtension->Disk.ClientMac, Tag->DeviceExtension->Disk.ServerMac, (PUCHAR)Tag->PacketData, Tag->PacketSize, Tag)) {
            KeQuerySystemTime(&Tag->SendTime);
            Tag->DeviceExtension->Disk.Timeout += Tag->DeviceExtension->Disk.Timeout / 1000;
            if (Tag->DeviceExtension->Disk.Timeout > 100000000) Tag->DeviceExtension->Disk.Timeout = 100000000;
            Resends++;
          } else {
            ResendFails++;
            break;
          }
        }
      }
      Tag = Tag->Next;
      if (Tag == TagList) {
        DbgPrint("!!Taglist Cyclic!!\n");
        break;
      }
    }
    KeReleaseSpinLock(&SpinLock, Irql);
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -