📄 isapnp.c
字号:
} 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 + -