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

📄 pnp.c

📁 如题:POLAR LPC23XX-EK_DEMO software_Keil
💻 C
📖 第 1 页 / 共 4 页
字号:
/*++


Module Name:

    Pnp.c

Abstract:

    Plug and Play module

Environment:

    kernel mode only

Notes:

  Copyright (c) 1997-2000 Maverick Corporation.  All Rights Reserved.


Revision History:

    04/26/00: created

--*/


#include "wdm.h"
#include "stdarg.h"
#include "stdio.h"

#include "usbdi.h"
#include "usbdlib.h"
#include "usbcom.h"

ULONG GlobalPdaCount = 0;

VOID 
ASICInitRoutine(
     IN  PDEVICE_OBJECT DeviceObject
    )    
{
    PURB Urb;
    PIRP Irp;
    CHAR StackSize;
    PDEVICE_OBJECT stackDeviceObject;
    PDEVICE_EXTENSION DeviceExtension;
    PIO_STACK_LOCATION NextStack;
    ULONG UrbSize;
    ULONG i;
    NTSTATUS ntStatus = STATUS_SUCCESS;
    NTSTATUS waitStatus;

    #define INIT_ARRAY_SIZE 3

    USHORT  AsicInitData[INIT_ARRAY_SIZE][3] = 
    { {0xF4,0x0000,0x0000 },
      {0xFA,0x0011,0x0060 },
      {0xFA,0x0008,0x0081 }
    };


    DeviceExtension = DeviceObject->DeviceExtension;
    stackDeviceObject = DeviceExtension->TopOfStackDeviceObject;

    // Allocate IRP for our I/O request
    StackSize = (CCHAR)(DeviceExtension->TopOfStackDeviceObject->StackSize + 1);
    Irp = IoAllocateIrp(StackSize, FALSE);

    if (!Irp) {
        DbgPrint("Failure due to memory error\n");
        // Can't init ASIC
        return;
    }
	
    // Allocate URB.  It will be reused for the data transfer, so insure
    // it is large enough for both control and bulk transfers
    UrbSize = sizeof (struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);


    Urb = ExAllocatePool(NonPagedPool, UrbSize);

    if (!Urb)
    {
      DbgPrint ("Failure due to memory error\n");
      IoFreeIrp(Irp);
      return;
    }

    for(i= 0; i < INIT_ARRAY_SIZE; i++)
	  {
	    KEVENT initASICEvent;

            KeInitializeEvent(&initASICEvent, NotificationEvent, FALSE);

	    // Build URB for the ADSC command used to send the CDB to our USB drive
	    UsbBuildVendorRequest(
				  Urb,
				  URB_FUNCTION_VENDOR_DEVICE,
				  (USHORT) sizeof (struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
				  0,
				  0,
				  (UCHAR) AsicInitData[i][0],        //ADSC,
				  AsicInitData[i][1],        //ADSC,
				  AsicInitData[i][2],        //ADSC,
				  NULL,
				  NULL,
				  0,
				  NULL
				  );

	    NextStack = IoGetNextIrpStackLocation(Irp);
    
	    ASSERT(NextStack != NULL);
	    ASSERT(DeviceObject->StackSize>1);

    // Initialize our Irp
	    NextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
	    NextStack->Parameters.Others.Argument1 = Urb;
	    NextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;

	    // Register our Irp completion handler
	    IoSetCompletionRoutine (
				   Irp,
				   UsbCom_IrpCompletionRoutine,
				   &initASICEvent, 
				   TRUE,    // invoke on success
				   TRUE,    // invoke on error
				   TRUE     // invoke on cancellation of the Irp
				   );

	    UsbCom_IncrementIoCount(DeviceObject);

	    // Pass Irp to the USB driver stack
	    ntStatus = IoCallDriver(stackDeviceObject, Irp);
	    
            if (ntStatus == STATUS_PENDING) {

	      // wait for irp to complete
	      waitStatus = KeWaitForSingleObject(
						 &initASICEvent,
						 Suspended,
						 KernelMode,
						 FALSE,
						 NULL
						 );
	      
            }

	    UsbCom_DecrementIoCount(DeviceObject);
	    
	  }
    
    IoFreeIrp(Irp);
    ExFreePool(Urb);



}


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

Routine Description:

    Dispatch table routine for IRP_MJ_PNP.
    Process the Plug and Play IRPs sent to this device.

Arguments:

    DeviceObject - pointer to our FDO (Functional Device Object)

    Irp          - pointer to an I/O Request Packet

Return Value:

    NT status code

--*/
{

    PIO_STACK_LOCATION irpStack;
    PDEVICE_EXTENSION deviceExtension;
    NTSTATUS ntStatus = STATUS_SUCCESS;
    NTSTATUS waitStatus;
    PDEVICE_OBJECT stackDeviceObject;
    KEVENT startDeviceEvent;


    //
    // Get a pointer to the current location in the Irp. This is where
    //     the function codes and parameters are located.
    //
    irpStack = IoGetCurrentIrpStackLocation (Irp);

    //
    // Get a pointer to the device extension
    //

    deviceExtension = DeviceObject->DeviceExtension;
    stackDeviceObject = deviceExtension->TopOfStackDeviceObject;

    DbgPrint("enter UsbCom_ProcessPnPIrp() IRP_MJ_PNP, minor %s, -- %x\n",
        UsbCom_StringForPnpMnFunc( irpStack->MinorFunction ), irpStack->MinorFunction );

	// inc the FDO device extension's pending IO count for this Irp
    UsbCom_IncrementIoCount(DeviceObject);

    ASSERT( IRP_MJ_PNP == irpStack->MajorFunction );

    switch (irpStack->MinorFunction) {
    case IRP_MN_START_DEVICE:

        // The PnP Manager sends this IRP after it has assigned resources,
        // if any, to the device. The device may have been recently enumerated
        // and is being started for the first time, or the device may be
        // restarting after being stopped for resource reconfiguration.

        // Initialize an event we can wait on for the PDO to be done with this irp
        KeInitializeEvent(&startDeviceEvent, NotificationEvent, FALSE);
        IoCopyCurrentIrpStackLocationToNext(Irp);

        // Set a completion routine so it can signal our event when
        //  the PDO is done with the Irp
        IoSetCompletionRoutine(Irp,
                               UsbCom_IrpCompletionRoutine,
                               &startDeviceEvent,  // pass the event to the completion routine as the Context
                               TRUE,    // invoke on success
                               TRUE,    // invoke on error
                               TRUE);   // invoke on cancellation


        // let the PDO process the IRP
        ntStatus = IoCallDriver(stackDeviceObject,
                                Irp);

        // if PDO is not done yet, wait for the event to be set in our completion routine
        if (ntStatus == STATUS_PENDING) {
             // wait for irp to complete

            waitStatus = KeWaitForSingleObject(
                &startDeviceEvent,
                Suspended,
                KernelMode,
                FALSE,
                NULL);

            ntStatus = Irp->IoStatus.Status;
        }

        if (NT_SUCCESS(ntStatus)) {

            // Now we're ready to do our own startup processing.
            // USB client drivers such as us set up URBs (USB Request Packets) to send requests
            // to the host controller driver (HCD). The URB structure defines a format for all
            // possible commands that can be sent to a USB device.
            // Here, we request the device descriptor and store it,
            // and configure the device.
            ntStatus = UsbCom_StartDevice(DeviceObject);
            Irp->IoStatus.Status = ntStatus;
        }

        IoCompleteRequest (Irp,
                           IO_NO_INCREMENT
                           );
#ifdef  USE_SMARTNIC
	    // Initialize
	    ASICInitRoutine(DeviceObject);
	    // Give the device another  second to settle.
	    KeStallExecutionProcessor(1000);
#endif		

        UsbCom_DecrementIoCount(DeviceObject);
        return ntStatus;  // end, case IRP_MN_START_DEVICE
   

    case IRP_MN_QUERY_STOP_DEVICE:

        // The IRP_MN_QUERY_STOP_DEVICE/IRP_MN_STOP_DEVICE sequence only occurs
        // during "polite" shutdowns, such as the user explicitily requesting the
        // service be stopped in, or requesting unplug from the Pnp tray icon.
        // This sequence is NOT received during "impolite" shutdowns,
        // such as someone suddenly yanking the USB cord or otherwise
        // unexpectedly disabling/resetting the device.

        // If a driver sets STATUS_SUCCESS for this IRP,
        // the driver must not start any operations on the device that
        // would prevent that driver from successfully completing an IRP_MN_STOP_DEVICE
        // for the device.
        // For mass storage devices such as disk drives, while the device is in the
        // stop-pending state,the driver holds IRPs that require access to the device,
        // but for most USB devices, there is no 'persistent storage', so we will just
        // refuse any more IO until restarted or the stop is cancelled

        // If a driver in the device stack determines that the device cannot be
        // stopped for resource reconfiguration, the driver is not required to pass
        // the IRP down the device stack. If a query-stop IRP fails,
        // the PnP Manager sends an IRP_MN_CANCEL_STOP_DEVICE to the device stack,
        // notifying the drivers for the device that the query has been cancelled
        // and that the device will not be stopped.


        // It is possible to receive this irp when the device has not been started
        //  ( as on a boot device )
        if (!deviceExtension->DeviceStarted) { // if get when never started, just pass on
            DbgPrint("UsbCom_ProcessPnPIrp() IRP_MN_QUERY_STOP_DEVICE when device not started\n");
            IoSkipCurrentIrpStackLocation (Irp);
            ntStatus = IoCallDriver (deviceExtension->TopOfStackDeviceObject, Irp);
            UsbCom_DecrementIoCount(DeviceObject);

            return ntStatus;
        }

        // Cancel any pending io requests; we may not have gotten a query first!
//        UsbCom_CancelPendingIo( DeviceObject );

        // If any pipes are still open, call USBD with URB_FUNCTION_ABORT_PIPE
        // This call will also close the pipes; if any user close calls get through,
        // they will be noops
        UsbCom_AbortPipes( DeviceObject );

        deviceExtension->StopDeviceRequested = TRUE;

        // Wait for any io request pending in our driver to
        // complete before returning success.
                // This  event is set when deviceExtension->PendingIoCount goes to 1
        waitStatus = KeWaitForSingleObject(
                    &deviceExtension->NoPendingIoEvent,
                    Suspended,
                    KernelMode,
                    FALSE,
                    NULL);

        Irp->IoStatus.Status = STATUS_SUCCESS;
        

        break; // end, case IRP_MN_QUERY_STOP_DEVICE

    case IRP_MN_CANCEL_STOP_DEVICE:

                // The PnP Manager uses this IRP to inform the drivers for a device
                // that the device will not be stopped for resource reconfiguration.
                // This should only be received after a successful IRP_MN_QUERY_STOP_DEVICE.


        // It is possible to receive this irp when the device has not been started
        if (!deviceExtension->DeviceStarted) { // if get when never started, just pass on
            DbgPrint("UsbCom_ProcessPnPIrp() IRP_MN_CANCEL_STOP_DEVICE when device not started\n");
            IoSkipCurrentIrpStackLocation (Irp);
            ntStatus = IoCallDriver (deviceExtension->TopOfStackDeviceObject, Irp);
            UsbCom_DecrementIoCount(DeviceObject);
            return ntStatus;
        }

⌨️ 快捷键说明

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