?? main.c
字號:
/*++
Copyright (c) 1997-1998 Microsoft Corporation
Module Name:
main.c
Abstract:
This file contains a driver skeleton that demonstrates how to locate
and set up a PCI device.
Note that this driver assumes that only a single I/O will be completed
per interrupt. If the hardware will support overlapped, concurrent I/O
operations, the driver will have to be redesigned.
Author:
Steve Dziok (SteveDz)
Environment:
Kernel mode
Revision History:
--*/
#include "pcidma.h"
#ifdef DBG
#define DEBUG_BUFFER_SIZE 512
ULONG DebugPrintLevel = 0;
UCHAR DebugBuffer[DEBUG_BUFFER_SIZE];
#endif
//
// Make sure the initialization code is removed from memory after use.
//
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#endif
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
Determine if a PCI device exists, setup relevant structures,
claim resources, connect interrupts, and report status back to
the system. Most of the work done is in routines called by
DriverEntry.
Arguments:
DriverObject - Pointer to the driver object created by the I/O manager.
RegistryPath - Pointer to the driver specific key
\Registry
\Machine
\System
\CurrentControlSet
\Services
\<DriverName>
Return Value:
NTSTATUS
--*/
{
PPCI_DEVICE_LOCATION pciDeviceInfo;
PPCI_DEVICE_LIST pciDeviceList;
NTSTATUS status = STATUS_SUCCESS;
USHORT deviceNumber;
BOOLEAN foundOne = FALSE;
DebugPrint((0, "DriverEntry routine\n"));
DebugPrint((3, "DriverObject 0x%x \n", DriverObject));
//
// Set up the device driver entry points.
//
DriverObject->MajorFunction[IRP_MJ_READ] = PciDmaReadWrite;
DriverObject->MajorFunction[IRP_MJ_WRITE] = PciDmaReadWrite;
DriverObject->DriverStartIo = PciDmaStartIo;
DriverObject->DriverUnload = PciDmaUnload;
DriverObject->MajorFunction[IRP_MJ_CREATE] = PciDmaCreateClose;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = PciDmaCreateClose;
//
// Allocate storage for the list of PCI devices.
//
pciDeviceList = (PPCI_DEVICE_LIST)
ExAllocatePoolWithTag(NonPagedPool,
MAX_PCIDEVICELIST_ENTRIES * sizeof(PCI_DEVICE_LIST),
EX_POOL_TAG_VALUE
);
if (!pciDeviceList) {
DebugPrint((1, "Unable to allocate storage for pciDeviceList \n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Find all the specified PCI devices.
//
status = FindPciDevice(PCI_VENDOR_ID,
PCI_DEVICE_ID,
pciDeviceList
);
if (!NT_SUCCESS(status)) {
DebugPrint((2, "Error locating PCI device. Status = %x \n",
status
));
ExFreePool(pciDeviceList);
return status;
}
//
// Set up each of the located PCI devices.
//
for ( deviceNumber = 0;
deviceNumber < pciDeviceList->Count && deviceNumber < MAXIMUM_DEVICES_SUPPORTED;
deviceNumber++ ) {
//
// Get current PCI device location.
//
pciDeviceInfo = &pciDeviceList->List[deviceNumber];
status = SetupPciDevice(DriverObject,
RegistryPath,
pciDeviceInfo->BusNumber,
pciDeviceInfo->SlotNumber.u.AsULONG,
deviceNumber
);
//
// Save the fact that one or more devices were found and configured.
//
if (NT_SUCCESS(status)) {
foundOne = TRUE;
}
}
//
// Free the temporary storage.
//
if (pciDeviceList) {
ExFreePool(pciDeviceList);
}
//
// If at least one device found, indicate this fact. If no devices
// found, return this fact and the system will unload this driver.
//
if (foundOne) {
return STATUS_SUCCESS;
} else {
return STATUS_NO_SUCH_DEVICE;
}
} // DriverEntry
NTSTATUS
PciDmaCreateClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Create (open) or Close the device. This routine doesn't do
anything except complete the IRP.
Arguments:
DeviceObject - Object representing a particular adapter.
Irp - IRP_MJ_CREATE or IRP_MJ_CLOSE I/O request.
Return Value:
NTSTATUS
--*/
{
DebugPrint((3, "PciDmaCreateClose \n"));
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
} // PciDmaCreateClose
VOID
PciDmaUnload(
IN PDRIVER_OBJECT DriverObject
)
/*++
Routine Description:
Prepare the driver for unload. For all the device objects created
for this driver, loop through each one, disconnect interrupts, unmap
memory and I/O spaces, free memory, etc.
Arguments:
DriverObject - Pointer to the driver object created by the I/O manager.
Return Value:
None
--*/
{
PDEVICE_OBJECT deviceObject = DriverObject->DeviceObject;
PDEVICE_OBJECT nextDevice;
DebugPrint((3, "PciDmaUnload \n"));
//
// For each device object, clean up the device interaction with
// the system.
//
while (deviceObject) {
DebugPrint((2, "Removing DeviceObject at %x \n",
deviceObject
));
//
// Save a pointer to the next device, if any.
//
nextDevice = deviceObject->NextDevice;
//
// Free device resources and delete the device.
//
FreeDeviceResources(DriverObject,
deviceObject
);
//
// Continue with the next device object.
//
deviceObject = nextDevice;
}
} // PciDmaUnload
NTSTATUS
PciDmaReadWrite(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Handle the Read or Write request. This driver was designed to
process more than one IRP into the driver, but only one IRP is active
on the adapter at any one time. In other words, several I/Os will be
queued at the top level, but only one I/O will ever be processed on the
adapter at any instant in time. The driver will have to be modified if
the adapter can handle more than one active IRP.
Arguments:
DeviceObject - Object representing a particular adapter.
Irp - IRP_MJ_READ or IRP_MJ_WRITE I/O request.
Return Value:
NTSTATUS
--*/
{
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
ULONG transferPages;
ULONG transferByteCount = irpStack->Parameters.Read.Length;
//
// Insure that the IRP information is correct. If it is not,
// complete the IRP with the proper error status.
//
if (0 == transferByteCount) {
DebugPrint((2, "Zero transfer length input to read/write \n"));
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INVALID_PARAMETER;
}
//
// Calculate number of pages in this transfer.
//
transferPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(Irp->MdlAddress),
irpStack->Parameters.Read.Length
);
//
// Check if request length is greater than the maximum number of
// bytes that the hardware can transfer. Either split the request
// into multiple requests or fail the original request. This driver
// will fail requests if it is too large.
//
if (transferByteCount > deviceExtension->MaximumTransferLength ||
transferPages > deviceExtension->MaximumPhysicalPages) {
DebugPrint((2, "Requested transfer larger than device capabilities \n"));
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INVALID_PARAMETER;
}
//
// Add a check for data alignment if this is a device restriction.
//
//
// Mark IRP as pending.
//
IoMarkIrpPending(Irp);
//
// Start the I/O request.
//
IoStartPacket(DeviceObject,
Irp,
NULL,
NULL
);
return STATUS_PENDING;
} // PciDmaReadWrite
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -