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

📄 isapnp.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 3 页
字号:
    } else {
		  switch (type) {
		  case ISAPNP_LRIN_ID_STRING_ANSI:
  			ParseAnsiName(&Card->Name, &size);
			  break;

      default:
  			DPRINT("Ignoring large tag Type 0x%X for Card %d\n",
          type, Card->CardId);
		  }
    }
skip:
  if (size > 0)
    Skip(size);
  }

  return TRUE;
}


/*
 * Compute ISA PnP checksum for first eight bytes
 */
static UCHAR Checksum(PUCHAR data)
{
	ULONG i, j;
	UCHAR checksum = 0x6a, bit, b;

	for (i = 0; i < 8; i++) {
		b = data[i];
		for (j = 0; j < 8; j++) {
			bit = 0;
			if (b & (1 << j))
				bit = 1;
			checksum = ((((checksum ^ (checksum >> 1)) &
        0x01) ^ bit) << 7) | (checksum >> 1);
		}
	}
	return checksum;
}


/*
 * Build a resource list for a logical ISA PnP device
 */
static NTSTATUS BuildResourceList(PISAPNP_LOGICAL_DEVICE LogicalDevice,
  PIO_RESOURCE_LIST DestinationList,
  ULONG Priority)
{
  PLIST_ENTRY CurrentEntry, Entry;
  PISAPNP_CONFIGURATION_LIST List;
  PISAPNP_DESCRIPTOR Descriptor;
  ULONG i;

  if (IsListEmpty(&LogicalDevice->Configuration))
    return STATUS_NOT_FOUND;

  CurrentEntry = LogicalDevice->Configuration.Flink;
  while (CurrentEntry != &LogicalDevice->Configuration) {
    List = CONTAINING_RECORD(
      CurrentEntry, ISAPNP_CONFIGURATION_LIST, ListEntry);

    if (List->Priority == Priority) {

      DPRINT("Logical device %d  DestinationList 0x%X\n",
        LogicalDevice->Number,
        DestinationList);

      DestinationList->Version = 1;
      DestinationList->Revision = 1;
      DestinationList->Count = LogicalDevice->DescriptorCount;

      i = 0;
      Entry = List->ListHead.Flink;
      while (Entry != &List->ListHead) {
        Descriptor = CONTAINING_RECORD(
          Entry, ISAPNP_DESCRIPTOR, ListEntry);

        DPRINT("Logical device %d  Destination 0x%X(%d)\n",
          LogicalDevice->Number,
          &DestinationList->Descriptors[i],
          i);

        RtlCopyMemory(&DestinationList->Descriptors[i],
          &Descriptor->Descriptor,
          sizeof(IO_RESOURCE_DESCRIPTOR));

        i++;

        Entry = Entry->Flink;
      }

      RemoveEntryList(&List->ListEntry);

      ExFreePool(List);

      return STATUS_SUCCESS;
    }

    CurrentEntry = CurrentEntry->Flink;
  }

  return STATUS_UNSUCCESSFUL;
}


/*
 * Build resource lists for a logical ISA PnP device
 */
static NTSTATUS BuildResourceLists(PISAPNP_LOGICAL_DEVICE LogicalDevice)
{
  ULONG ListSize;
  ULONG Priority;
  ULONG SingleListSize;
  PIO_RESOURCE_LIST p;
  NTSTATUS Status;

  ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST)
    - sizeof(IO_RESOURCE_LIST)
    + LogicalDevice->ConfigurationSize;

  DPRINT("Logical device %d  ListSize 0x%X  ConfigurationSize 0x%X  DescriptorCount %d\n",
    LogicalDevice->Number, ListSize,
    LogicalDevice->ConfigurationSize,
    LogicalDevice->DescriptorCount);

  LogicalDevice->ResourceLists =
    (PIO_RESOURCE_REQUIREMENTS_LIST)ExAllocatePoolWithTag(
      PagedPool, ListSize, TAG_ISAPNP);
	if (!LogicalDevice->ResourceLists)
		return STATUS_INSUFFICIENT_RESOURCES;

  RtlZeroMemory(LogicalDevice->ResourceLists, ListSize);

  SingleListSize = sizeof(IO_RESOURCE_LIST) +
    (LogicalDevice->DescriptorCount - 1) *
    sizeof(IO_RESOURCE_DESCRIPTOR);

  DPRINT("SingleListSize %d\n", SingleListSize);

  Priority = 0;
  p = &LogicalDevice->ResourceLists->List[0];
  do {
    Status = BuildResourceList(LogicalDevice, p, Priority);
    if (NT_SUCCESS(Status)) {
      p = (PIO_RESOURCE_LIST)((ULONG)p + SingleListSize);
      Priority++;
    }
  } while (Status != STATUS_NOT_FOUND);

  LogicalDevice->ResourceLists->ListSize = ListSize;
  LogicalDevice->ResourceLists->AlternativeLists = Priority + 1;

  return STATUS_SUCCESS;
}


/*
 * Build resource lists for a ISA PnP card
 */
static NTSTATUS BuildResourceListsForCard(PISAPNP_CARD Card)
{
  PISAPNP_LOGICAL_DEVICE LogicalDevice;
  PLIST_ENTRY CurrentEntry;
  NTSTATUS Status;

  CurrentEntry = Card->LogicalDevices.Flink;
  while (CurrentEntry != &Card->LogicalDevices) {
    LogicalDevice = CONTAINING_RECORD(
      CurrentEntry, ISAPNP_LOGICAL_DEVICE, CardListEntry);
    Status = BuildResourceLists(LogicalDevice);
    if (!NT_SUCCESS(Status))
      return Status;
    CurrentEntry = CurrentEntry->Flink;
  }

  return STATUS_SUCCESS;
}


/*
 * Build resource lists for all present ISA PnP cards
 */
static NTSTATUS BuildResourceListsForAll(
  PISAPNP_DEVICE_EXTENSION DeviceExtension)
{
  PLIST_ENTRY CurrentEntry;
  PISAPNP_CARD Card;
  NTSTATUS Status;

  CurrentEntry = DeviceExtension->CardListHead.Flink;
  while (CurrentEntry != &DeviceExtension->CardListHead) {
    Card = CONTAINING_RECORD(
      CurrentEntry, ISAPNP_CARD, ListEntry);
    Status = BuildResourceListsForCard(Card);
    if (!NT_SUCCESS(Status))
      return Status;
    CurrentEntry = CurrentEntry->Flink;
  }

  return STATUS_SUCCESS;
}


/*
 * Build device list for all present ISA PnP cards
 */
static NTSTATUS BuildDeviceList(PISAPNP_DEVICE_EXTENSION DeviceExtension)
{
	ULONG csn;
	UCHAR header[9], checksum;
  PISAPNP_CARD Card;

  DPRINT("Called\n");

	SendWait();
	SendKey();
	for (csn = 1; csn <= 10; csn++) {
		SendWake((UCHAR)csn);
		Peek(header, 9);
		checksum = Checksum(header);

    if (checksum == 0x00 || checksum != header[8])  /* Invalid CSN */
			continue;

		DPRINT("VENDOR: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
			header[0], header[1], header[2], header[3],
			header[4], header[5], header[6], header[7], header[8]);

    Card = (PISAPNP_CARD)ExAllocatePoolWithTag(
      PagedPool, sizeof(ISAPNP_CARD), TAG_ISAPNP);
    if (!Card)
      return STATUS_INSUFFICIENT_RESOURCES;

    RtlZeroMemory(Card, sizeof(ISAPNP_CARD));

		Card->CardId = (USHORT) csn;
		Card->VendorId = (header[1] << 8) | header[0];
		Card->DeviceId = (header[3] << 8) | header[2];
		Card->Serial = (header[7] << 24) | (header[6] << 16) | (header[5] << 8) | header[4];

    InitializeListHead(&Card->LogicalDevices);
    KeInitializeSpinLock(&Card->LogicalDevicesLock);

    ParseResourceMap(DeviceExtension, Card);

    ExInterlockedInsertTailList(&DeviceExtension->CardListHead,
      &Card->ListEntry,
      &DeviceExtension->GlobalListLock);
	}

  return STATUS_SUCCESS;
}


static NTSTATUS
ISAPNPQueryBusRelations(
  IN PDEVICE_OBJECT DeviceObject,
  IN PIRP Irp,
  PIO_STACK_LOCATION IrpSp)
{
  PISAPNP_DEVICE_EXTENSION DeviceExtension;
  PISAPNP_LOGICAL_DEVICE LogicalDevice;
  PDEVICE_RELATIONS Relations;
  PLIST_ENTRY CurrentEntry;
  NTSTATUS Status = STATUS_SUCCESS;
  ULONG Size;
  ULONG i;

  DPRINT("Called\n");

  DeviceExtension = (PISAPNP_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

  if (Irp->IoStatus.Information) {
    /* FIXME: Another bus driver has already created a DEVICE_RELATIONS
              structure so we must merge this structure with our own */
  }

  Size = sizeof(DEVICE_RELATIONS) + sizeof(Relations->Objects) *
    (DeviceExtension->DeviceListCount - 1);
  Relations = (PDEVICE_RELATIONS)ExAllocatePoolWithTag(PagedPool, Size, TAG_ISAPNP);
  if (!Relations)
    return STATUS_INSUFFICIENT_RESOURCES;

  Relations->Count = DeviceExtension->DeviceListCount;

  i = 0;
  CurrentEntry = DeviceExtension->DeviceListHead.Flink;
  while (CurrentEntry != &DeviceExtension->DeviceListHead) {
    LogicalDevice = CONTAINING_RECORD(
      CurrentEntry, ISAPNP_LOGICAL_DEVICE, DeviceListEntry);

    if (!LogicalDevice->Pdo) {
      /* Create a physical device object for the
         device as it does not already have one */
      Status = IoCreateDevice(DeviceObject->DriverObject, 0,
        NULL, FILE_DEVICE_CONTROLLER, 0, FALSE, &LogicalDevice->Pdo);
      if (!NT_SUCCESS(Status)) {
        DPRINT("IoCreateDevice() failed with status 0x%X\n", Status);
        ExFreePool(Relations);
        return Status;
      }

      LogicalDevice->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
    }

    /* Reference the physical device object. The PnP manager
       will dereference it again when it is no longer needed */
    ObReferenceObject(LogicalDevice->Pdo);

    Relations->Objects[i] = LogicalDevice->Pdo;

    i++;

    CurrentEntry = CurrentEntry->Flink;
  }

  Irp->IoStatus.Information = (ULONG)Relations;

  return Status;
}


static NTSTATUS
ISAPNPQueryDeviceRelations(
  IN PDEVICE_OBJECT DeviceObject,
  IN PIRP Irp,
  PIO_STACK_LOCATION IrpSp)
{
  PISAPNP_DEVICE_EXTENSION DeviceExtension;
  NTSTATUS Status;

  DPRINT("Called\n");

  DeviceExtension = (PISAPNP_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

  if (DeviceExtension->State == dsStopped)
    return STATUS_UNSUCCESSFUL;

  switch (IrpSp->Parameters.QueryDeviceRelations.Type) {
    case BusRelations:
      Status = ISAPNPQueryBusRelations(DeviceObject, Irp, IrpSp);
      break;

    default:
      Status = STATUS_NOT_IMPLEMENTED;
  }

  return Status;
}


static NTSTATUS
ISAPNPStartDevice(
  IN PDEVICE_OBJECT DeviceObject,
  IN PIRP Irp,
  PIO_STACK_LOCATION IrpSp)
{
  PISAPNP_DEVICE_EXTENSION DeviceExtension;
  NTSTATUS Status;
  ULONG NumCards;

  DPRINT("Called\n");

  DeviceExtension = (PISAPNP_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

  if (DeviceExtension->State == dsStarted)
    return STATUS_SUCCESS;

  NumCards = IsolatePnPCards();

  DPRINT("Number of ISA PnP cards found: %d\n", NumCards);

  Status = BuildDeviceList(DeviceExtension);
  if (!NT_SUCCESS(Status)) {
    DPRINT("BuildDeviceList() failed with status 0x%X\n", Status);
    return Status;
  }

  Status = BuildResourceListsForAll(DeviceExtension);
  if (!NT_SUCCESS(Status)) {
    DPRINT("BuildResourceListsForAll() failed with status 0x%X\n", Status);
    return Status;
  }

  DeviceExtension->State = dsStarted;

  return STATUS_SUCCESS;
}


static NTSTATUS
ISAPNPStopDevice(
  IN PDEVICE_OBJECT DeviceObject,
  IN PIRP Irp,
  PIO_STACK_LOCATION IrpSp)
{
  PISAPNP_DEVICE_EXTENSION DeviceExtension;

  DPRINT("Called\n");

  DeviceExtension = (PISAPNP_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

  if (DeviceExtension->State != dsStopped) {
    /* FIXME: Stop device */
    DeviceExtension->State = dsStopped;
  }

  return STATUS_SUCCESS;
}


static NTSTATUS
STDCALL
ISAPNPDispatchOpenClose(
  IN PDEVICE_OBJECT DeviceObject,
  IN PIRP Irp)
{
  DPRINT("Called\n");

  Irp->IoStatus.Status = STATUS_SUCCESS;
  Irp->IoStatus.Information = FILE_OPENED;
  IoCompleteRequest(Irp, IO_NO_INCREMENT);

  return STATUS_SUCCESS;
}


static NTSTATUS
STDCALL
ISAPNPDispatchReadWrite(
  IN PDEVICE_OBJECT PhysicalDeviceObject,
  IN PIRP Irp)
{
  DPRINT("Called\n");

  Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
  Irp->IoStatus.Information = 0;
  IoCompleteRequest(Irp, IO_NO_INCREMENT);

  return STATUS_UNSUCCESSFUL;
}


static NTSTATUS
STDCALL
ISAPNPDispatchDeviceControl(
  IN PDEVICE_OBJECT DeviceObject,
  IN PIRP Irp)
{
  PIO_STACK_LOCATION IrpSp;
  NTSTATUS Status;

  DPRINT("Called\n");

  Irp->IoStatus.Information = 0;

  IrpSp = IoGetCurrentIrpStackLocation(Irp);
  switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
  default:
    DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
    Status = STATUS_NOT_IMPLEMENTED;
    break;
  }

  if (Status != STATUS_PENDING) {
    Irp->IoStatus.Status = Status;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
  }

  DPRINT("Leaving. Status 0x%X\n", Status);

  return Status;
}


static NTSTATUS
STDCALL
ISAPNPControl(
  IN PDEVICE_OBJECT DeviceObject,
  IN PIRP Irp)
{
  PIO_STACK_LOCATION IrpSp;
  NTSTATUS Status;

  DPRINT("Called\n");

  IrpSp = IoGetCurrentIrpStackLocation(Irp);
  switch (IrpSp->MinorFunction) {
  case IRP_MN_QUERY_DEVICE_RELATIONS:
    Status = ISAPNPQueryDeviceRelations(DeviceObject, Irp, IrpSp);
    break;

  case IRP_MN_START_DEVICE:
    Status = ISAPNPStartDevice(DeviceObject, Irp, IrpSp);
    break;

  case IRP_MN_STOP_DEVICE:
    Status = ISAPNPStopDevice(DeviceObject, Irp, IrpSp);
    break;

  default:
    DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
    Status = STATUS_NOT_IMPLEMENTED;
    break;
  }

  if (Status != STATUS_PENDING) {
    Irp->IoStatus.Status = Status;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
  }

  DPRINT("Leaving. Status 0x%X\n", Status);

  return Status;
}


static NTSTATUS
STDCALL
ISAPNPAddDevice(
  IN PDRIVER_OBJECT DriverObject,
  IN PDEVICE_OBJECT PhysicalDeviceObject)
{
  PISAPNP_DEVICE_EXTENSION DeviceExtension;
  PDEVICE_OBJECT Fdo;
  NTSTATUS Status;

  DPRINT("Called\n");

  Status = IoCreateDevice(DriverObject, sizeof(ISAPNP_DEVICE_EXTENSION),
    NULL, FILE_DEVICE_BUS_EXTENDER, FILE_DEVICE_SECURE_OPEN, TRUE, &Fdo);
  if (!NT_SUCCESS(Status)) {
    DPRINT("IoCreateDevice() failed with status 0x%X\n", Status);
    return Status;
  }

  DeviceExtension = (PISAPNP_DEVICE_EXTENSION)Fdo->DeviceExtension;

  DeviceExtension->Pdo = PhysicalDeviceObject;

  DeviceExtension->Ldo =
    IoAttachDeviceToDeviceStack(Fdo, PhysicalDeviceObject);

  InitializeListHead(&DeviceExtension->CardListHead);
  InitializeListHead(&DeviceExtension->DeviceListHead);
  DeviceExtension->DeviceListCount = 0;
  KeInitializeSpinLock(&DeviceExtension->GlobalListLock);

  DeviceExtension->State = dsStopped;

  Fdo->Flags &= ~DO_DEVICE_INITIALIZING;

  DPRINT("Done AddDevice\n");

  return STATUS_SUCCESS;
}


NTSTATUS
STDCALL
DriverEntry(
  IN PDRIVER_OBJECT DriverObject,
  IN PUNICODE_STRING RegistryPath)
{
  DbgPrint("ISA Plug and Play Bus Driver\n");

  DriverObject->MajorFunction[IRP_MJ_CREATE] = ISAPNPDispatchOpenClose;
  DriverObject->MajorFunction[IRP_MJ_CLOSE] = ISAPNPDispatchOpenClose;
  DriverObject->MajorFunction[IRP_MJ_READ] = ISAPNPDispatchReadWrite;
  DriverObject->MajorFunction[IRP_MJ_WRITE] = ISAPNPDispatchReadWrite;
  DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ISAPNPDispatchDeviceControl;
  DriverObject->MajorFunction[IRP_MJ_PNP] = ISAPNPControl;
  DriverObject->DriverExtension->AddDevice = ISAPNPAddDevice;

  return STATUS_SUCCESS;
}

/* EOF */

⌨️ 快捷键说明

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