📄 usbios.c
字号:
/*++
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 + -