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

📄 genport.c

📁 win2000下ISA接口的串口板卡的驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
/*++

Copyright (c) 1990-2000 Microsoft Corporation, All Rights Reserved
 
Module Name:

    genport.c

Abstract:  Generic Port I/O driver for Windows 2000


Author:    Author:    Robert R. Howell  January 8, 1993


Environment:

    Kernel mode

Revision History:

 Robert B. Nelson (Microsoft)     January 12, 1993
      Cleaned up comments
      Enabled and tested resource reporting
      Added code to retrieve I/O address and port count from the Registry.

 Robert B. Nelson (Microsoft)     March 1, 1993
      Added support for byte, word, and long I/O.
      Added support for MIPS.
      Fixed resource reporting.

 Robert B. Nelson (Microsoft)     May 1, 1993
      Fixed port number validation.

 Robert B. Nelson (Microsoft)     Oct 25, 1993
      Fixed MIPS support.
      
 Eliyas Yakub 
    Fixed AddressSpace Bug          Nov 30, 1997

 Eliyas Yakub
    Converted to Windows 2000       Dec 29, 1998
    Fixed bugs						Feb 17, 2000

--*/
#include "precomp.h"
#ifdef ALLOC_PRAGMA
#pragma alloc_text (INIT, DriverEntry)
#pragma alloc_text (PAGE, GpdAddDevice)
#pragma alloc_text (PAGE, GpdDispatchPnp)
#pragma alloc_text (PAGE, GpdDispatchSystemControl)
#pragma alloc_text (PAGE, GpdUnload)
#pragma alloc_text (PAGE, GpdDispatch)
#pragma alloc_text (PAGE, GpdInterruptService)
#pragma alloc_text (PAGE, DpcForIsr)
#pragma alloc_text (PAGE, DpcForRec)
#pragma alloc_text (PAGE, SerialRead)
#pragma alloc_text (PAGE, SerialWrite)
#pragma alloc_text (PAGE, SerialSetBaud)
#pragma alloc_text (PAGE, SerialReadData)
#pragma alloc_text (PAGE, SerialWriteData)
#pragma alloc_text (PAGE, SerialReadPort)
#pragma alloc_text (PAGE, SerialWritePort)
#pragma alloc_text (PAGE, SerialIsSendEmtpy)
#pragma alloc_text (PAGE, GpdIoctlReadPort)
#pragma alloc_text (PAGE, GpdIoctlWritePort)
#pragma alloc_text (PAGE, GpdStartDevice)
#endif


NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT  DriverObject,
    IN PUNICODE_STRING RegistryPath
    )
/*++

Routine Description:

    Installable driver initialization entry point.
    This entry point is called directly by the I/O system.

Arguments:

    DriverObject - pointer to the driver object

    RegistryPath - pointer to a unicode string representing the path,
                   to driver-specific key in the registry.

Return Value:

    STATUS_SUCCESS

--*/
{

    UNREFERENCED_PARAMETER (RegistryPath);

    DebugPrint (("Entered Driver Entry\n"));
    DebugPrint (("RegistryPath.Buffer = %s\n",RegistryPath->Buffer));
    //
    // Create dispatch points for the IRPs.
    //
    
    DriverObject->MajorFunction[IRP_MJ_CREATE]          = GpdDispatch;
    DriverObject->MajorFunction[IRP_MJ_CLOSE]           = GpdDispatch;
    DriverObject->MajorFunction[IRP_MJ_READ]            = SerialRead;
    DriverObject->MajorFunction[IRP_MJ_WRITE]           = SerialWrite;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]  = GpdDispatch;
    DriverObject->DriverUnload                          = GpdUnload;
    DriverObject->MajorFunction[IRP_MJ_PNP]            = GpdDispatchPnp;
    DriverObject->MajorFunction[IRP_MJ_POWER]          = GpdDispatchPower;
    DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = GpdDispatchSystemControl;
    DriverObject->DriverExtension->AddDevice           = GpdAddDevice;

    return STATUS_SUCCESS;
}


NTSTATUS
GpdAddDevice(
    IN PDRIVER_OBJECT DriverObject,
    IN PDEVICE_OBJECT PhysicalDeviceObject
    )
/*++

Routine Description:

    The Plug & Play subsystem is handing us a brand new PDO, for which we
    (by means of INF registration) have been asked to provide a driver.

    We need to determine if we need to be in the driver stack for the device.
    Create a functional device object to attach to the stack
    Initialize that device object
    Return status success.

    Remember: we can NOT actually send ANY non pnp IRPS to the given driver
    stack, UNTIL we have received an IRP_MN_START_DEVICE.

Arguments:

    DeviceObject - pointer to a device object.

    PhysicalDeviceObject -  pointer to a device object created by the
                            underlying bus driver.

Return Value:

    NT status code.

--*/
{
    NTSTATUS                status = STATUS_SUCCESS;
    PDEVICE_OBJECT          deviceObject = NULL;
    PLOCAL_DEVICE_INFO      deviceInfo; 
    UNICODE_STRING          ntDeviceName;
    UNICODE_STRING          win32DeviceName;
    DebugPrint (("-- Entered GpdAddDevice\n"));

    PAGED_CODE();

    RtlInitUnicodeString(&ntDeviceName, GPD_DEVICE_NAME);       //GPD_DEVICE_NAME 就是宏定义 L"\\Device\\Gpd0"
	DebugPrint((">>> ntDeviceName.len=%d Buffer=%s\n"
		,ntDeviceName.Length
		,ntDeviceName.Buffer));
    //
    // Create a device object.
    //

    status = IoCreateDevice (DriverObject,
                             sizeof (LOCAL_DEVICE_INFO),
                             &ntDeviceName,
                             GPD_TYPE,
                             0,
                             FALSE,
                             &deviceObject);//分配内存并初始化一个设备deviceObject

    
    if (!NT_SUCCESS (status)) {
        //
        // Either not enough memory to create a deviceobject or another
        // deviceobject with the same name exits. This could happen
        // if you install another instance of this device.
        //
        return status;
    }

    RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME);//#define DOS_DEVICE_NAME L"\\DosDevices\\GpdDev"
	DebugPrint((">>> win32DeviceName.Buffer=%s \n",win32DeviceName.Buffer));

    status = IoCreateSymbolicLink( &win32DeviceName, &ntDeviceName );//在设备和用户可见设备名之间建立连接

    if (!NT_SUCCESS(status))    // If we we couldn't create the link then
    {                           //  abort installation.
        IoDeleteDevice(deviceObject);
        return status;
    }

    deviceInfo = (PLOCAL_DEVICE_INFO) deviceObject->DeviceExtension;//提取设备信息(包括地址:地址范围等)
	DebugPrint((">>> PortAddr=%X PortCount=%d\n",
		(unsigned int)deviceInfo->PortBase ,
		deviceInfo->PortCount ));
	DebugPrint((">>> PortMemyType=%d \n",
		(unsigned int)deviceInfo->PortMemoryType   ));
    deviceInfo->NextLowerDriver = IoAttachDeviceToDeviceStack (//把deviceObject 附属到 物理设备PhysicalDeviceObject上
                                       deviceObject,
                                       PhysicalDeviceObject);//PhysicalDeviceObject是入口参数
    if(NULL == deviceInfo->NextLowerDriver) {
        IoDeleteSymbolicLink(&win32DeviceName);
        IoDeleteDevice(deviceObject);
        return STATUS_NO_SUCH_DEVICE;
    }

    IoInitializeRemoveLock (&deviceInfo->RemoveLock , 
                            PORTIO_TAG,
                            1, // MaxLockedMinutes 
                            5); // HighWatermark, this parameter is 
                                // used only on checked build.
    //
    // Set the flag if the device is not holding a pagefile
    // crashdump file or hibernate file. 
    // 
    
    deviceObject->Flags |=  DO_POWER_PAGABLE;

    deviceInfo->DeviceObject = deviceObject;//deviceInfo就是我们自己定义的设备参数(地址,地址空间等)
    deviceInfo->Removed = FALSE;
    deviceInfo->Started = FALSE;
    deviceInfo->FoundInterrupt = FALSE;
	deviceInfo->Com_Have_IRQ = -1;
    deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

    //
    // This values is based on the hardware design.
    // Let us assume the address is in I/O space. 
    //
    deviceInfo->PortMemoryType = 1; 
	IoInitializeDpcRequest(deviceObject,DpcForIsr);


    DebugPrint(("AddDevice: %p to %p->%p \n", deviceObject, 
                       deviceInfo->NextLowerDriver,
                       PhysicalDeviceObject));


    return STATUS_SUCCESS;

}

NTSTATUS 
GpdCompletionRoutine(
    IN PDEVICE_OBJECT   DeviceObject,
    IN PIRP             Irp,
    IN PVOID            Context
    )
/*++

Routine Description:

    The completion routine for plug & play irps that needs to be
    processed first by the lower drivers. 

Arguments:

   DeviceObject - pointer to a device object.   

   Irp - pointer to an I/O Request Packet.

   Context - pointer to an event object.

Return Value:

      NT status code

--*/
{
    PKEVENT             event;

    event = (PKEVENT) Context;

    UNREFERENCED_PARAMETER(DeviceObject);

    if (Irp->PendingReturned) {
        IoMarkIrpPending(Irp);
    }

    //
    // We could switch on the major and minor functions of the IRP to perform
    // different functions, but we know that Context is an event that needs
    // to be set.
    //
    KeSetEvent(event, 0, FALSE);

    //
    // Allows the caller to reuse the IRP
    //
    return STATUS_MORE_PROCESSING_REQUIRED;
}


NTSTATUS
GpdDispatchPnp (
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
/*++

Routine Description:

    The plug and play dispatch routines.

    Most of these the driver will completely ignore.
    In all cases it must pass the IRP to the next lower driver.

Arguments:

   DeviceObject - pointer to a device object.

   Irp - pointer to an I/O Request Packet.

Return Value:

      NT status code

--*/
{
    PIO_STACK_LOCATION          irpStack;
    NTSTATUS                    status = STATUS_SUCCESS;
    KEVENT                      event;        
    UNICODE_STRING              win32DeviceName;
    PLOCAL_DEVICE_INFO          deviceInfo,df;
	int i,j;
    PAGED_CODE();

    deviceInfo = (PLOCAL_DEVICE_INFO) DeviceObject->DeviceExtension;
    irpStack = IoGetCurrentIrpStackLocation(Irp);

    status = IoAcquireRemoveLock (&deviceInfo->RemoveLock, Irp);
    if (!NT_SUCCESS (status)) {
        Irp->IoStatus.Status = status;
        IoCompleteRequest (Irp, IO_NO_INCREMENT);
        return status;
    }

    DebugPrint(("%s\n",PnPMinorFunctionString(irpStack->MinorFunction)));

    switch (irpStack->MinorFunction) {
    case IRP_MN_START_DEVICE:

        //
        // The device is starting.
        //
        // We cannot touch the device (send it any non pnp irps) until a
        // start device has been passed down to the lower drivers.
        //
        IoCopyCurrentIrpStackLocationToNext(Irp);
        KeInitializeEvent(&event,
                          NotificationEvent,
                          FALSE
                          );

        IoSetCompletionRoutine(Irp,
                               (PIO_COMPLETION_ROUTINE) GpdCompletionRoutine, 
                               &event,
                               TRUE,
                               TRUE,
                               TRUE);
                               
        status = IoCallDriver(deviceInfo->NextLowerDriver, Irp);

        if (STATUS_PENDING == status) {
            KeWaitForSingleObject(
               &event,
               Executive, // Waiting for reason of a driver
               KernelMode, // Must be kernelmode if event memory is in stack
               FALSE, // No allert
               NULL); // No timeout
        }

        if (NT_SUCCESS(status) && NT_SUCCESS(Irp->IoStatus.Status)) {

            status = GpdStartDevice(DeviceObject, Irp);
            if(NT_SUCCESS(status))
            {
                //
                // As we are successfully now back from our start device
                // we can do work.
                //
				//我增加的代码
				//IoConnectInterrupt(,,,);
				if(deviceInfo->FoundInterrupt )
				{
					status = IoConnectInterrupt(&deviceInfo->InterruptObject,
												GpdInterruptService,

⌨️ 快捷键说明

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