www.pudn.com > pdiusbd12 source.rar > Ocrw.c


/*++ 
 
Copyright (c) 1995  Microsoft Corporation 
 
Module Name: 
 
   ocrw.c 
 
Abstract: 
 
   read/write io test code 
 
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) 1996 Microsoft Corporation.  All Rights Reserved. 
 
 
Revision History: 
 
    5-4-96 : created 
 
--*/ 
 
#define DRIVER 
 
#include "wdm.h" 
#include "stdarg.h" 
#include "stdio.h" 
 
#include "usbdi.h" 
#include "usbdlib.h" 
#include "D12.h" 
#include "d12irp.h" 
 
 
//****************************************************************************** 
// 
// D12_CompletionStop() 
// 
// IO Completion Routine which just stops further completion of the Irp 
// 
//****************************************************************************** 
 
NTSTATUS 
D12_CompletionStop ( 
    IN PDEVICE_OBJECT   DeviceObject, 
    IN PIRP             Irp, 
    IN PVOID            Context 
    ) 
{ 
    return STATUS_MORE_PROCESSING_REQUIRED; 
} 
 
//****************************************************************************** 
// 
// D12_GetCurrentFrame() 
// 
//****************************************************************************** 
 
ULONG 
D12_GetCurrentFrame ( 
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP           Irp 
    ) 
{ 
    PDEVICE_EXTENSION           deviceExtension; 
    PIO_STACK_LOCATION          nextStack; 
    NTSTATUS                    ntStatus; 
    struct _URB_GET_CURRENT_FRAME_NUMBER urb; 
 
    deviceExtension   = DeviceObject->DeviceExtension; 
 
    // Initialize the URB 
    // 
    urb.Hdr.Function = URB_FUNCTION_GET_CURRENT_FRAME_NUMBER; 
    urb.Hdr.Length   = sizeof(urb); 
    urb.FrameNumber = (ULONG)-1; 
 
    // Set the IRP parameters to pass the URB down the stack 
    // 
    nextStack = IoGetNextIrpStackLocation(Irp); 
 
    nextStack->Parameters.Others.Argument1 = &urb; 
 
    nextStack->Parameters.DeviceIoControl.IoControlCode =  
        IOCTL_INTERNAL_USB_SUBMIT_URB;                     
 
    nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; 
 
    // Since this Irp is borrowed for URB_FUNCTION_GET_CURRENT_FRAME_NUMBER 
    // before it is passed down later for the real URB request after this 
    // routine returns, set a completion routine which stop further completion 
    // of the Irp. 
    // 
    IoSetCompletionRoutine( 
        Irp, 
        D12_CompletionStop, 
        NULL,   // Context 
        TRUE,   // InvokeOnSuccess 
        TRUE,   // InvokeOnError 
        TRUE    // InvokeOnCancel 
        ); 
 
    // Now pass the Irp down the stack 
    // 
    ntStatus = IoCallDriver( 
                   deviceExtension->TopOfStackDeviceObject,  
                   Irp 
                   ); 
 
    // Don't need to wait for completion because JD guarantees that 
    // URB_FUNCTION_GET_CURRENT_FRAME_NUMBER will never return STATUS_PENDING 
 
    return urb.FrameNumber; 
} 
 
 
//****************************************************************************** 
// 
// D12_BuildIsoRequest() 
// 
//****************************************************************************** 
 
PURB 
D12_BuildIsoRequest( 
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP Irp, 
    IN PD12_PIPE PipeHandle, 
    IN BOOLEAN Read 
    ) 
/*++ 
 
Routine Description: 
 
Arguments: 
 
    DeviceObject - pointer to the device extension for this instance of the 
                     82930 device. 
 
    Irp - 
 
    PipeHandle - 
 
Return Value: 
 
    initialized async urb. 
 
--*/ 
{ 
    ULONG siz; 
    ULONG length, packetSize, numPackets, i; 
    PURB urb = NULL; 
    PIO_STACK_LOCATION irpSp; 
    LARGE_INTEGER byteOffset; 
 
    irpSp = IoGetCurrentIrpStackLocation(Irp); 
 
    D12_KdPrint (("D12TEST.SYS: handle = 0x%x\n", PipeHandle)); 
 
    length = MmGetMdlByteCount(Irp->MdlAddress); 
 
    D12_KdPrint (("D12TEST.SYS: length = 0x%x\n", length)); 
 
    byteOffset = irpSp->Parameters.Read.ByteOffset; 
 
    D12_KdPrint (("D12TEST.SYS: offset = 0x%08X.%08X\n", 
                     byteOffset.HighPart, 
                     byteOffset.LowPart)); 
 
    packetSize = PipeHandle->PipeInfo->MaximumPacketSize; 
    numPackets = length/packetSize; 
    if (numPackets*packetSize < length) { 
        numPackets++; 
    } 
 
    siz = GET_ISO_URB_SIZE(numPackets); 
    urb = ExAllocatePool(NonPagedPool, siz); 
 
    D12_KdPrint (("D12TEST.SYS: siz = 0x%x urb 0x%x\n", siz, urb)); 
 
    if (urb) { 
        RtlZeroMemory(urb, siz); 
 
        urb->UrbIsochronousTransfer.Hdr.Length = (USHORT) siz; 
        urb->UrbIsochronousTransfer.Hdr.Function = 
                    URB_FUNCTION_ISOCH_TRANSFER; 
        urb->UrbIsochronousTransfer.PipeHandle = 
                   PipeHandle->PipeInfo->PipeHandle; 
        urb->UrbIsochronousTransfer.TransferFlags = 
            Read ? USBD_TRANSFER_DIRECTION_IN : 0; 
 
        urb->UrbIsochronousTransfer.TransferBufferMDL = 
            Irp->MdlAddress; 
        urb->UrbIsochronousTransfer.TransferBufferLength = 
            length; 
 
        if (byteOffset.HighPart) 
        { 
            urb->UrbIsochronousTransfer.StartFrame = 
                D12_GetCurrentFrame(DeviceObject, Irp) + 
                byteOffset.LowPart; 
        } 
        else 
        { 
            // start sending/receiving right away 
            urb->UrbIsochronousTransfer.TransferFlags |= 
                USBD_START_ISO_TRANSFER_ASAP; 
        } 
 
        urb->UrbIsochronousTransfer.NumberOfPackets = numPackets; 
        urb->UrbIsochronousTransfer.UrbLink = NULL; 
 
        for (i=0; i< urb->UrbIsochronousTransfer.NumberOfPackets; i++) { 
            urb->UrbIsochronousTransfer.IsoPacket[i].Offset 
                        = i * packetSize; 
        } 
 
        D12_KdPrint (("D12TEST.SYS: Init iso urb Length = 0x%x buf = 0x%x\n", 
            urb->UrbIsochronousTransfer.TransferBufferLength, 
            urb->UrbIsochronousTransfer.TransferBuffer)); 
    } 
 
    D12_KdPrint (("D12TEST.SYS: exit D12_BuildIsoRequest\n")); 
 
    return urb; 
} 
 
 
PURB 
D12_BuildAsyncRequest( 
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP Irp, 
    IN PD12_PIPE PipeHandle, 
    IN BOOLEAN Read 
    ) 
/*++ 
 
Routine Description: 
 
Arguments: 
 
    DeviceObject - pointer to the device extension for this instance of the 
                     82930 device. 
 
    Irp - 
 
    PipeHandle - 
 
Return Value: 
 
    initialized async urb. 
 
--*/ 
{ 
    ULONG siz; 
    ULONG length; 
    PURB urb = NULL; 
 
    D12_KdPrint (("D12TEST.SYS: handle = 0x%x\n", PipeHandle)); 
 
    length = MmGetMdlByteCount(Irp->MdlAddress); 
 
    D12_KdPrint (("D12TEST.SYS: length = 0x%x\n", length)); 
 
    siz = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER); 
    urb = ExAllocatePool(NonPagedPool, siz); 
 
    D12_KdPrint (("D12TEST.SYS: siz = 0x%x urb 0x%x\n", siz, urb)); 
 
    if (urb) { 
        RtlZeroMemory(urb, siz); 
 
        urb->UrbBulkOrInterruptTransfer.Hdr.Length = (USHORT) siz; 
        urb->UrbBulkOrInterruptTransfer.Hdr.Function = 
                    URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER; 
        urb->UrbBulkOrInterruptTransfer.PipeHandle = 
                   PipeHandle->PipeInfo->PipeHandle; 
        urb->UrbBulkOrInterruptTransfer.TransferFlags = 
            Read ? USBD_TRANSFER_DIRECTION_IN : 0; 
 
        // short packet is not treated as an error. 
        urb->UrbBulkOrInterruptTransfer.TransferFlags |=  
            USBD_SHORT_TRANSFER_OK;             
                 
        // 
        // no linkage for now 
        // 
 
        urb->UrbBulkOrInterruptTransfer.UrbLink = NULL; 
 
        urb->UrbBulkOrInterruptTransfer.TransferBufferMDL = 
            Irp->MdlAddress; 
        urb->UrbBulkOrInterruptTransfer.TransferBufferLength = 
            length; 
 
        D12_KdPrint (("D12TEST.SYS: Init async urb Length = 0x%x buf = 0x%x\n", 
            urb->UrbBulkOrInterruptTransfer.TransferBufferLength, 
            urb->UrbBulkOrInterruptTransfer.TransferBuffer)); 
    } 
 
    D12_KdPrint (("D12TEST.SYS: exit D12_BuildAsyncRequest\n")); 
 
    return urb; 
} 
 
 
NTSTATUS 
D12_AsyncReadWrite_Complete( 
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP Irp, 
    IN PVOID Context 
    ) 
/*++ 
 
Routine Description: 
 
 
Arguments: 
 
    DeviceObject - Pointer to the device object for the D12 device. 
 
    Irp - Irp completed. 
 
    Context - Driver defined context. 
 
Return Value: 
 
    The function value is the final status from the operation. 
 
--*/ 
{ 
    NTSTATUS			ntStatus = STATUS_SUCCESS; 
    PURB				urb; 
    PD12_RW_CONTEXT  context = Context; 
    PD12_PIPE		pipeHandle; 
    PFILE_OBJECT		fileObject; 
    PIO_STACK_LOCATION	irpStack; 
    PDEVICE_OBJECT      deviceObject; 
 
    if (Irp->PendingReturned) { 
        IoMarkIrpPending(Irp); 
    } 
 
    urb = context->Urb; 
    deviceObject = context->DeviceObject; 
 
	D12_RemovePendingIrp(deviceObject, Irp); 
 
    D12_KdPrint (("D12TEST.SYS: Async Completion: Length 0x%08X, Status 0x%08X\n", 
                     urb->UrbBulkOrInterruptTransfer.TransferBufferLength, 
                     urb->UrbHeader.Status)); 
 
    // 
    // set the length based on the TransferBufferLength 
    // value in the URB 
    // 
    Irp->IoStatus.Information = 
        urb->UrbBulkOrInterruptTransfer.TransferBufferLength; 
 
    irpStack = IoGetCurrentIrpStackLocation (Irp); 
    fileObject = irpStack->FileObject; 
 
	// get pipe handle 
	pipeHandle = fileObject->FsContext; 
 
 
    D12_DecrementIoCount(deviceObject);                        
 
    ExFreePool(context); 
    ExFreePool(urb); 
 
    return ntStatus; 
} 
 
 
NTSTATUS 
D12_IsoReadWrite_Complete( 
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP Irp, 
    IN PVOID Context 
    ) 
/*++ 
 
Routine Description: 
 
 
Arguments: 
 
    DeviceObject - Pointer to the device object for the D12 device. 
 
    Irp - Irp completed. 
 
    Context - Driver defined context. 
 
Return Value: 
 
    The function value is the final status from the operation. 
 
--*/ 
{ 
    NTSTATUS			ntStatus = STATUS_SUCCESS; 
    PURB				urb = Context; 
    PD12_PIPE		pipeHandle; 
    PFILE_OBJECT		fileObject; 
    PIO_STACK_LOCATION	irpStack; 
    ULONG               i; 
 
    if (Irp->PendingReturned) { 
        IoMarkIrpPending(Irp); 
    } 
 
    // 
    // BUGBUG check here for interesting iso error conditions 
    // 
    D12_KdPrint (("D12TEST.SYS: Iso Completion: StartFrame 0x%08X, Status 0x%08X\n", 
                     urb->UrbIsochronousTransfer.StartFrame, 
                     urb->UrbHeader.Status)); 
 
    for (i=0; i< urb->UrbIsochronousTransfer.NumberOfPackets; i++) 
    { 
        D12_KdPrint (("D12TEST.SYS: [%02d] Length 0x%08X, Status 0x%08X\n", 
                         i, 
                         urb->UrbIsochronousTransfer.IsoPacket[i].Length, 
                         urb->UrbIsochronousTransfer.IsoPacket[i].Status 
                        )); 
    } 
 
    // 
    // set the length based on the TransferBufferLength 
    // value in the URB 
    // 
    Irp->IoStatus.Information = 
        urb->UrbBulkOrInterruptTransfer.TransferBufferLength; 
 
    irpStack = IoGetCurrentIrpStackLocation (Irp); 
    fileObject = irpStack->FileObject; 
 
	// get pipe handle 
	pipeHandle = fileObject->FsContext; 
 
    D12_DecrementIoCount(DeviceObject);                        
 
    ExFreePool(urb); 
 
    return ntStatus; 
} 
 
 
NTSTATUS 
D12_Read( 
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP Irp 
    ) 
/*++ 
 
Routine Description: 
 
Arguments: 
 
    DeviceObject - pointer to the device object for this instance of the 82930 
                    devcice. 
 
 
Return Value: 
 
    NT status code 
 
--*/ 
{ 
    NTSTATUS ntStatus = STATUS_SUCCESS; 
    PD12_PIPE pipeHandle = NULL; 
    PFILE_OBJECT fileObject; 
    PIO_STACK_LOCATION irpStack, nextStack; 
    PDEVICE_EXTENSION deviceExtension; 
    PURB urb; 
    PD12_RW_CONTEXT context = NULL; 
 
    D12_KdPrint (("D12TEST.SYS: enter D12_Read\n")); 
 
    D12_IncrementIoCount(DeviceObject); 
 
    deviceExtension = DeviceObject->DeviceExtension; 
 
    if (deviceExtension->AcceptingRequests == FALSE) { 
        ntStatus = STATUS_DELETE_PENDING; 
        Irp->IoStatus.Status = ntStatus; 
        Irp->IoStatus.Information = 0; 
 
        IoCompleteRequest (Irp, 
                           IO_NO_INCREMENT 
                          ); 
 
        D12_DecrementIoCount(DeviceObject);                           
        return ntStatus; 
    } 
     
    irpStack = IoGetCurrentIrpStackLocation (Irp); 
    fileObject = irpStack->FileObject; 
 
    pipeHandle =  fileObject->FsContext; 
 
    if (!pipeHandle) { 
       ntStatus = STATUS_INVALID_HANDLE; 
       goto D12_Read_Reject; 
    } 
 
    // 
    // submit the write request to USB 
    // 
 
    switch (pipeHandle->PipeInfo->PipeType) { 
    case UsbdPipeTypeIsochronous: 
        D12_ResetPipe(DeviceObject, pipeHandle, FALSE); 
         
        urb = D12_BuildIsoRequest(DeviceObject, 
                                     Irp, 
                                     pipeHandle, 
                                     TRUE); 
        if (urb) { 
 
            nextStack = IoGetNextIrpStackLocation(Irp); 
            ASSERT(nextStack != NULL); 
            ASSERT(DeviceObject->StackSize>1); 
 
            nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; 
            nextStack->Parameters.Others.Argument1 = urb; 
            nextStack->Parameters.DeviceIoControl.IoControlCode = 
                IOCTL_INTERNAL_USB_SUBMIT_URB; 
 
            IoSetCompletionRoutine(Irp, 
                                   D12_IsoReadWrite_Complete, 
                                   urb, 
                                   TRUE, 
                                   TRUE, 
                                   TRUE); 
 
            D12_KdPrint (("D12TEST.SYS: IRP = 0x%x current = 0x%x next = 0x%x\n", 
                Irp, irpStack, nextStack)); 
 
            ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, 
                                    Irp); 
            goto D12_Read_Done; 
        } else { 
            ntStatus = STATUS_INSUFFICIENT_RESOURCES; 
        } 
        break; 
    case UsbdPipeTypeInterrupt: 
    case UsbdPipeTypeBulk: 
        urb = D12_BuildAsyncRequest(DeviceObject, 
                                       Irp, 
                                       pipeHandle, 
                                       TRUE); 
        if (urb) { 
            context = ExAllocatePool(NonPagedPool, sizeof(D12_RW_CONTEXT)); 
        } 
         
        if (urb && context) { 
            context->Urb = urb; 
            context->DeviceObject = DeviceObject; 
             
            nextStack = IoGetNextIrpStackLocation(Irp); 
            ASSERT(nextStack != NULL); 
            ASSERT(DeviceObject->StackSize>1); 
 
            nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; 
            nextStack->Parameters.Others.Argument1 = urb; 
            nextStack->Parameters.DeviceIoControl.IoControlCode = 
                IOCTL_INTERNAL_USB_SUBMIT_URB; 
 
            IoSetCompletionRoutine(Irp, 
                                   D12_AsyncReadWrite_Complete, 
                                   context, 
                                   TRUE, 
                                   TRUE, 
                                   TRUE); 
 
            D12_KdPrint (("D12TEST.SYS: IRP = 0x%x current = 0x%x next = 0x%x\n", 
                Irp, irpStack, nextStack)); 
 
			D12_AddPendingIrp(DeviceObject, Irp); 
            ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, 
                                    Irp); 
            goto D12_Read_Done; 
        } else { 
            ntStatus = STATUS_INSUFFICIENT_RESOURCES; 
        } 
 
        break; 
    default: 
        ntStatus = STATUS_INVALID_PARAMETER; 
        TRAP(); 
    } 
 
D12_Read_Reject: 
 
    Irp->IoStatus.Status = ntStatus; 
    Irp->IoStatus.Information = 0; 
 
    IoCompleteRequest (Irp, 
                       IO_NO_INCREMENT 
                       ); 
 
D12_Read_Done: 
 
    return ntStatus; 
} 
 
 
NTSTATUS 
D12_Write( 
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP Irp 
    ) 
/*++ 
 
Routine Description: 
 
Arguments: 
 
    DeviceObject - pointer to the device object for this instance of the 82930 
                    device. 
 
 
Return Value: 
 
    NT status code 
 
--*/ 
{ 
    NTSTATUS ntStatus = STATUS_SUCCESS; 
    PD12_PIPE pipeHandle = NULL; 
    PFILE_OBJECT fileObject; 
    PIO_STACK_LOCATION irpStack, nextStack; 
    PDEVICE_EXTENSION deviceExtension; 
    PURB urb; 
    PD12_RW_CONTEXT context = NULL; 
 
    D12_KdPrint (("D12TEST.SYS: enter D12_Write\n")); 
 
    D12_IncrementIoCount(DeviceObject); 
 
    deviceExtension = DeviceObject->DeviceExtension; 
 
    if (deviceExtension->AcceptingRequests == FALSE) { 
        ntStatus = STATUS_DELETE_PENDING; 
        Irp->IoStatus.Status = ntStatus; 
        Irp->IoStatus.Information = 0; 
 
        D12_DecrementIoCount(DeviceObject); 
 
        IoCompleteRequest (Irp, 
                           IO_NO_INCREMENT 
                          ); 
        return ntStatus; 
    } 
     
    irpStack = IoGetCurrentIrpStackLocation (Irp); 
    fileObject = irpStack->FileObject; 
 
//    MmProbeAndLockPages(Irp->MdlAddress, 
//                        KernelMode, 
//                        IoReadAccess); 
 
    pipeHandle =  fileObject->FsContext; 
    if (!pipeHandle) 
    { 
       ntStatus = STATUS_INVALID_HANDLE; 
       goto D12_Write_Reject; 
    } 
 
    // 
    // submit the write request to USB 
    // 
 
    switch (pipeHandle->PipeInfo->PipeType) { 
    case UsbdPipeTypeIsochronous: 
        D12_ResetPipe(DeviceObject, pipeHandle, FALSE); 
         
        urb = D12_BuildIsoRequest(DeviceObject, 
                                     Irp, 
                                     pipeHandle, 
                                     FALSE); 
        if (urb) { 
 
            nextStack = IoGetNextIrpStackLocation(Irp); 
            ASSERT(nextStack != NULL); 
            ASSERT(DeviceObject->StackSize>1); 
 
            nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; 
            nextStack->Parameters.Others.Argument1 = urb; 
            nextStack->Parameters.DeviceIoControl.IoControlCode = 
                IOCTL_INTERNAL_USB_SUBMIT_URB; 
 
            IoSetCompletionRoutine(Irp, 
                                   D12_IsoReadWrite_Complete, 
                                   urb, 
                                   TRUE, 
                                   TRUE, 
                                   TRUE); 
 
            D12_KdPrint (("D12TEST.SYS: IRP = 0x%x current = 0x%x next = 0x%x\n", 
                Irp, irpStack, nextStack)); 
 
            ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, 
                                    Irp); 
            goto D12_Write_Done; 
        } else { 
            ntStatus = STATUS_INSUFFICIENT_RESOURCES; 
        } 
        break; 
    case UsbdPipeTypeInterrupt: 
    case UsbdPipeTypeBulk: 
        urb = D12_BuildAsyncRequest(DeviceObject, 
                                       Irp, 
                                       pipeHandle, 
                                       FALSE); 
 
        if (urb) { 
            context = ExAllocatePool(NonPagedPool, sizeof(D12_RW_CONTEXT)); 
        } 
         
        if (urb && context) { 
            context->Urb = urb; 
            context->DeviceObject = DeviceObject;                                        
             
            nextStack = IoGetNextIrpStackLocation(Irp); 
            ASSERT(nextStack != NULL); 
            ASSERT(DeviceObject->StackSize>1); 
 
            nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; 
            nextStack->Parameters.Others.Argument1 = urb; 
            nextStack->Parameters.DeviceIoControl.IoControlCode = 
                IOCTL_INTERNAL_USB_SUBMIT_URB; 
 
            IoSetCompletionRoutine(Irp, 
                                   D12_AsyncReadWrite_Complete, 
                                   context, 
                                   TRUE, 
                                   TRUE, 
                                   TRUE); 
 
            D12_KdPrint (("D12TEST.SYS: IRP = 0x%x current = 0x%x next = 0x%x\n", 
                Irp, irpStack, nextStack)); 
 
			D12_AddPendingIrp(DeviceObject, Irp); 
            ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, 
                                    Irp); 
            goto D12_Write_Done; 
        } else { 
            ntStatus = STATUS_INSUFFICIENT_RESOURCES; 
        } 
 
        break; 
    default: 
        ntStatus = STATUS_INVALID_PARAMETER; 
        TRAP(); 
    } 
 
D12_Write_Reject: 
 
    Irp->IoStatus.Status = ntStatus; 
    Irp->IoStatus.Information = 0; 
 
    IoCompleteRequest (Irp, 
                       IO_NO_INCREMENT 
                       ); 
 
D12_Write_Done: 
 
    return ntStatus; 
} 
 
 
NTSTATUS 
D12_Close( 
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP Irp 
    ) 
/*++ 
 
Routine Description: 
 
Arguments: 
 
    DeviceObject - pointer to the device object for this instance of the 82930 
                    devcice. 
 
 
Return Value: 
 
    NT status code 
 
--*/ 
{ 
    NTSTATUS ntStatus; 
    PFILE_OBJECT fileObject; 
    PIO_STACK_LOCATION irpStack; 
    PDEVICE_EXTENSION deviceExtension; 
    PD12_PIPE pipeHandle = NULL; 
 
    D12_KdPrint (("D12TEST.SYS: entering D12_Close\n")); 
 
    D12_IncrementIoCount(DeviceObject); 
 
    deviceExtension = DeviceObject->DeviceExtension; 
    irpStack = IoGetCurrentIrpStackLocation (Irp); 
    fileObject = irpStack->FileObject; 
 
    if (fileObject->FsContext) { 
        // closing pipe handle 
        pipeHandle =  fileObject->FsContext; 
        D12_KdPrint (("D12TEST.SYS: closing pipe %x\n", pipeHandle)); 
 
        pipeHandle->Opened = FALSE; 
    } 
 
    Irp->IoStatus.Status = STATUS_SUCCESS; 
    Irp->IoStatus.Information = 0; 
 
 
    ntStatus = Irp->IoStatus.Status; 
 
    IoCompleteRequest (Irp, 
                       IO_NO_INCREMENT 
                       ); 
                        
    D12_DecrementIoCount(DeviceObject); 
 
    D12_KdPrint (("D12TEST.SYS: exit D12_Close\n")); 
    return ntStatus; 
} 
 
 
NTSTATUS 
D12_Create( 
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP Irp 
    ) 
/*++ 
 
Routine Description: 
 
    // 
    // Entry point for CreateFile calls 
    // user mode apps may open "\\.\D12-x\yy" 
    // where yy is the internal pipe id 
    // 
 
Arguments: 
 
    DeviceObject - pointer to the device object for this instance of the 82930 
                    devcice. 
 
 
Return Value: 
 
    NT status code 
 
--*/ 
{ 
    NTSTATUS ntStatus = STATUS_SUCCESS; 
    PD12_PIPE pipeHandle = NULL; 
    PFILE_OBJECT fileObject; 
    PIO_STACK_LOCATION irpStack; 
    PDEVICE_EXTENSION deviceExtension; 
    ULONG i; 
 
    D12_KdPrint (("D12TEST.SYS: entering D12_Create\n")); 
 
    D12_IncrementIoCount(DeviceObject); 
 
    deviceExtension = DeviceObject->DeviceExtension; 
 
    if (deviceExtension->AcceptingRequests == FALSE) { 
        ntStatus = STATUS_DELETE_PENDING; 
        Irp->IoStatus.Status = ntStatus; 
        Irp->IoStatus.Information = 0; 
 
        IoCompleteRequest (Irp, 
                           IO_NO_INCREMENT 
                          ); 
 
        D12_DecrementIoCount(DeviceObject);                           
         
        return ntStatus; 
    } 
     
    irpStack = IoGetCurrentIrpStackLocation (Irp); 
    fileObject = irpStack->FileObject; 
 
    // fscontext is null for device 
    fileObject->FsContext = NULL; 
 
    if (fileObject->FileName.Length != 0) { 
 
        ntStatus = STATUS_INSUFFICIENT_RESOURCES; 
 
        // 
        // a name was specified, convert it to a pipe id 
        // 
 
        for (i=0; iFileName.Buffer, 
                                  deviceExtension->PipeList[i].Name, 
                                  fileObject->FileName.Length) 
                    == fileObject->FileName.Length && 
                !deviceExtension->PipeList[i].Opened) { 
                // 
                // found a match 
                // 
                pipeHandle = &deviceExtension->PipeList[i]; 
                //D12_ResetPipe(DeviceObject, pipeHandle); 
                break; 
            } 
        } 
    } 
 
	// if we are opening a pipe set stuff up and set FsContext 
    if (pipeHandle) { 
        D12_KdPrint (("D12TEST.SYS: open pipe %x\n", pipeHandle)); 
        fileObject->FsContext = pipeHandle; 
        pipeHandle->Opened = TRUE; 
		pipeHandle->bPerfTimerEnabled = FALSE; 
        ntStatus = STATUS_SUCCESS; 
    } 
 
    Irp->IoStatus.Status = ntStatus; 
    Irp->IoStatus.Information = 0; 
 
    IoCompleteRequest (Irp, 
                       IO_NO_INCREMENT 
                       ); 
 
    D12_DecrementIoCount(DeviceObject);                                
 
    D12_KdPrint (("D12TEST.SYS: exit D12_Create %x\n", ntStatus)); 
 
    return ntStatus; 
}