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

📄 usbios.c

📁 usb相关的
💻 C
📖 第 1 页 / 共 2 页
字号:
/*++

Copyright (c) 1999 Microsoft Corporation

Module Name:

    Usbios.c 

Abstract:

    USB device driver for USB LS-120 drive
    Interface for IOS I/O requests

Environment:

    kernel mode only

Notes:

  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  PURPOSE.

  Copyright (c) 1999 Microsoft Corporation.  All Rights Reserved.


Revision History:

    01/13/99: MRB  Adapted from BULKUSB DDK sample.

--*/
#define GLOBAL_VARS

#include "wdm.h"
#include "stdarg.h"
#include "stdio.h"
#include "usbdi.h"
#include "usbdlib.h"
#include "usbls120.h"
#include "USBLS120.h"




PDEVICE_OBJECT _stdcall
USBLS120_GetNextPDO(
    IN PDEVICE_OBJECT *Fdo
    )
/*++
Routine Description:

    Called by the IOS port driver. Walks list of FDOs 
    associated with this driver, returning the PDO the FDO
    is attached to.  Allows IOS port driver to distinguish
    between multiple instances of the USB LS-120 drive.

 Arguments:

    DeviceObject -- ptr to previous FDO, or NULL if returning 1st PDO

Return Value:

    Next PDO, or
    NULL if no more FDOs associated with this driver.
--*/
{
    PDEVICE_EXTENSION DeviceExtension;

    // First Fdo?
    if (NULL == *Fdo) {

        // Get first Device Object associated with this driver
        *Fdo = USBLS120DriverObject->DeviceObject;

    } else {

        // Get next device object for this driver
        *Fdo = (*Fdo)->NextDevice;
    }

    // No more device obects?
    if (NULL == *Fdo)
        return NULL;

    //Filter out our own child PDOs
    DeviceExtension = (*Fdo)->DeviceExtension;

    while (DO_FDO != DeviceExtension->DeviceObjectType) {
        *Fdo = (*Fdo)->NextDevice;
        if (NULL == *Fdo)
            return NULL;
        DeviceExtension = (*Fdo)->DeviceExtension;
    }

    return DeviceExtension->PhysicalDeviceObject;
}
	


VOID _stdcall
USBLS120_RegisterCompletionHandler(
    PDEVICE_OBJECT DeviceObject,
    COMPLETION_HANDLER CompletionHandler
    )
/*++
Routine Description:

    Called by the IOS port driver. Registers a completion
    handler in the port driver that is called whenever
    we complete an I/O request.

 Arguments:

    DeviceObject -- FDO we are registering the completion handler for.
    CompletionHandler - Address of completion handler.

Return Value:

    None.        
--*/
{
    PDEVICE_EXTENSION DeviceExtension;

    USBLS120_KdPrint( DBGLVL_HIGH,("enter USBLS120_RegisterCompletionHandler\n"));

    DeviceExtension = DeviceObject->DeviceExtension;
	
    DeviceExtension->CompleteRequest = CompletionHandler;
}


VOID _stdcall
USBLS120_StartRequest(
    IN PIOPACKET IoPacket
    )
/*++
Routine Description:

    Called by the IOS port driver to start an I/O request

    Please Note!! - All USB transfers that occur in response
    to this request must be done asynchronously.  IOS/IFSMGR
    implements their own thread blocking mechanism, and it
    is possible to create a race condition if we also block
    waiting for a USB transfer to complete.

 Arguments:

    IoPacket -- Structure containing pertient information about the
                I/O request.

Return Value:

    None.
--*/
{
    PURB Urb;
    PIRP Irp;
    CHAR StackSize;
    PDEVICE_EXTENSION DeviceExtension;
    PIO_STACK_LOCATION NextStack;
    ULONG UrbSize;
    ULONG i;
    PDEVICE_OBJECT DeviceObject;

    USBLS120_KdPrint( DBGLVL_HIGH,("enter USBLS120_TransferCommand\n"));

    USBLS120_KdPrint( DBGLVL_HIGH,("DataBuffer=%x, DataLength=%x, Flags=%x, Iop=%x\n",
                     IoPacket->DataBuffer,
                     IoPacket->DataLength,
                     IoPacket->Flags,
                     IoPacket->Iop));

#ifdef DBG
    // Dump CDB contents
    for (i=0; i<IoPacket->CdbLength; i++)
                USBLS120_KdPrint( DBGLVL_HIGH,("  CDB[%x]=%x\n", i,((char*)(IoPacket->Cdb))[i]));
#endif

    DeviceObject = (PDEVICE_OBJECT)(IoPacket->Fdo);

    DeviceExtension = DeviceObject->DeviceExtension;

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

    if (!Irp) {
        USBLS120_KdPrint( DBGLVL_MINIMUM,("Failure due to memory error\n"));

        // Can't allocate IRP - complete request with error and return
        IoPacket->Status = IO_STATUS_OUT_OF_MEMORY;
        DeviceExtension->CompleteRequest(IoPacket);
        return;
    }
	
    // Allocate URB.  It will be reused for the data transfer, so insure
    // it is large enough for both control and bulk transfers
    UrbSize = max(sizeof (struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
                  sizeof (struct _URB_BULK_OR_INTERRUPT_TRANSFER) );

    Urb = ExAllocatePool(NonPagedPool, UrbSize);

    if (!Urb) {
        USBLS120_KdPrint( DBGLVL_MINIMUM,("Failure due to memory error\n"));

        IoFreeIrp(Irp);

        IoPacket->Status = IO_STATUS_OUT_OF_MEMORY;
        DeviceExtension->CompleteRequest(IoPacket);
        return;
    }
	
    // Store all the transfer request info in our device extension
    DeviceExtension->Urb = Urb;
    DeviceExtension->Irp = Irp;
    DeviceExtension->CurrentSGD = 0;
    DeviceExtension->IoPacket = IoPacket;

    if (IoPacket->Flags & (IO_FLAGS_DATA_IN | IO_FLAGS_DATA_OUT))
        DeviceExtension->DataLeft = IoPacket->DataLength;
    else
        DeviceExtension->DataLeft = 0;


    // Build URB for the ADSC command used to send the CDB to our USB drive
    UsbBuildVendorRequest(
        Urb,
        URB_FUNCTION_CLASS_INTERFACE,
        (USHORT) sizeof (struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
        0,
        0,
        ADSC,
        0,
        0,
        IoPacket->Cdb,
        NULL,
        IoPacket->CdbLength,
        NULL
        );

    NextStack = IoGetNextIrpStackLocation(Irp);
    

    USBLS120_ASSERT(NextStack != NULL);
    USBLS120_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,
        USBLS120_TransferCommandComplete,
        DeviceObject, 
        TRUE,    // invoke on success
        TRUE,    // invoke on error
        TRUE     // invoke on cancellation of the Irp
        );

    USBLS120_IncrementIoCount(DeviceObject);


    // Pass Irp to the USB driver stack
    // We don't look at the return status, since we will 
    // always complete the request IOS request in the 
    // completion handler, regardless of success or error.
    IoCallDriver(DeviceExtension->TopOfStackDeviceObject, Irp);
}


NTSTATUS
USBLS120_TransferCommandComplete(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp,
    IN PVOID Reference
    )
/*++
Routine Description:

    Completion handler for command phase of I/O request.

 Arguments:

    DeviceObject - Previous device object.
    Irp - Irp used for sending command.
    Reference - Our FDO.

Return Value:

    STATUS_SUCCESS if successful.
--*/

{
    NTSTATUS NtStatus;
    PURB Urb;
    PIO_STACK_LOCATION irpStack;
    PDEVICE_EXTENSION DeviceExtension;
    PIOPACKET IoPacket;

    USBLS120_KdPrint( DBGLVL_HIGH,("enter USBLS120_TransferCommandComplete\n"));


    USBLS120_DecrementIoCount((PDEVICE_OBJECT)Reference);

    DeviceExtension = ((PDEVICE_OBJECT)(Reference))->DeviceExtension;
    IoPacket = DeviceExtension->IoPacket;

    Urb = DeviceExtension->Urb;
	    
    USBLS120_KdPrint(
        DBGLVL_HIGH,
        ("Urb Status=%x, Irp Status=%x\n",
        Urb->UrbHeader.Status,
        Irp->IoStatus.Status)
        );

    NtStatus = Irp->IoStatus.Status;
	
    if (!NT_SUCCESS(NtStatus)) {
        USBLS120_KdPrint( DBGLVL_MINIMUM,("Command Block Failure!!!\n"));

        IoFreeIrp(Irp);
        ExFreePool(Urb);

        // Device failed Command Block, complete with error
        IoPacket->Status = IO_STATUS_DEVICE_ERROR;
        DeviceExtension->CompleteRequest(IoPacket);

    } else if (0 != DeviceExtension->DataLeft) {
        // Normally we would simply start transferring the bulk data right now.
        // However, this function is called in the context of the completion
        // handler for the command transfer.  There is a bug in the Windows 
        // 98 golden version of UHCD.SYS that disables bandwidth reclamation 
        // during IRP completion.  This means that any bulk transfers scheduled 
        // at this time would only transfer at 1 packet per frame, approximately 

⌨️ 快捷键说明

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