NTSTATUS StartPolling(PDEVICE_EXTENSION pdx) { PIO_STACK_LOCATION stack; KIRQL OldIrql; NTSTATUS status; ASSERT(pdx->PollingIrp); KeAcquireSpinLock(&pdx->PollLock, &OldIrql); if(pdx->PollPending) { KeReleaseSpinLock(&pdx->PollLock, OldIrql); return STATUS_SUCCESS; } KeReleaseSpinLock(&pdx->PollLock, OldIrql); status = IoAcquireRemoveLock(&pdx->RemoveLock, pdx->PollingIrp); if(!NT_SUCCESS(status)) { KeAcquireSpinLock(&pdx->PollLock, &OldIrql); pdx->PollPending = FALSE; KeReleaseSpinLock(&pdx->PollLock, OldIrql); return status; } // safe to do since we passed in FALSE for the second parameter // of IoAllocateIrp IoInitializeIrp(pdx->PollingIrp, sizeof(IRP), pdx->LowerDeviceObject->StackSize); IoSetCompletionRoutine( pdx->PollingIrp, (PIO_COMPLETION_ROUTINE) OnPollComplete, pdx, TRUE, TRUE, TRUE ); stack = IoGetNextIrpStackLocation(pdx->PollingIrp); memset(&pdx->PollingUrb, 0, sizeof(URB)); UsbBuildInterruptOrBulkTransferRequest( &pdx->PollingUrb, sizeof(_URB_BULK_OR_INTERRUPT_TRANSFER), pdx->hinpipe, &pdx->PollingBuffer[0], NULL, POLLING_BUFFER_SIZE, (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK), NULL ); stack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; stack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB; stack->Parameters.Others.Argument1 = &pdx->PollingUrb; pdx->PollPending = TRUE; return IoCallDriver(pdx->LowerDeviceObject, pdx->PollingIrp); }
NTSTATUS SerialWrite( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: This is the dispatch routine for write. It validates the parameters for the write request and if all is ok and there are no outstanding write requests, it then checks to see if there is enough room for the data in the controllers Tx buffer. It places the request on the work queue if it can't place all the data in the controllers buffer, or there is an outstanding write request. Arguments: DeviceObject - Pointer to the device object for this device Irp - Pointer to the IRP for the current request Return Value: If the io is zero length then it will return STATUS_SUCCESS, otherwise this routine will return STATUS_PENDING, or the result of trying to write the data to the waiting controller. --*/ { PDIGI_DEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension; PDIGI_CONTROLLER_EXTENSION ControllerExt = DeviceExt->ParentControllerExt; NTSTATUS Status; #if DBG LARGE_INTEGER CurrentSystemTime; #endif ASSERT( IoGetCurrentIrpStackLocation(Irp)->MajorFunction == IRP_MJ_WRITE ); if (DeviceObject==ControllerExt->ControllerDeviceObject) { /* ** No writes allowed to controller. */ Irp->IoStatus.Status = STATUS_ACCESS_VIOLATION; Irp->IoStatus.Information = 0; DigiIoCompleteRequest( Irp, IO_NO_INCREMENT ); return STATUS_ACCESS_VIOLATION; } if( DeviceExt->DeviceState != DIGI_DEVICE_STATE_OPEN ) { Irp->IoStatus.Status = STATUS_CANCELLED; Irp->IoStatus.Information = 0; DigiIoCompleteRequest( Irp, IO_NO_INCREMENT ); return STATUS_CANCELLED; } InterlockedIncrement(&ControllerExt->PerfData.WriteRequests); InterlockedIncrement(&DeviceExt->PerfData.WriteRequests); #if DBG KeQuerySystemTime( &CurrentSystemTime ); #endif DigiDump( (DIGIIRP|DIGIFLOW|DIGIWRITE), ("Entering SerialWrite: port = %s\tIRP = 0x%x\t%u:%u\n", DeviceExt->DeviceDbgString, Irp, CurrentSystemTime.HighPart, CurrentSystemTime.LowPart) ); // // Check first for a write length of 0, then for a NULL buffer! // if( IoGetCurrentIrpStackLocation( Irp )->Parameters.Write.Length == 0 ) { // // We assume a write of 0 length is valid. Just complete the request // and return. // Irp->IoStatus.Information = 0L; Irp->IoStatus.Status = STATUS_SUCCESS; DigiIoCompleteRequest( Irp, IO_NO_INCREMENT ); DigiDump( DIGITXTRACE, ("port %s requested a zero length write\n", DeviceExt->DeviceDbgString) ); #if DBG KeQuerySystemTime( &CurrentSystemTime ); #endif DigiDump( (DIGIFLOW|DIGIWRITE), ("Exiting SerialWrite: port = %s\t%u:%u\n", DeviceExt->DeviceDbgString, CurrentSystemTime.HighPart, CurrentSystemTime.LowPart) ); return( STATUS_SUCCESS ); } if( Irp->AssociatedIrp.SystemBuffer == NULL ) { // // This is most definitely a No No! // DigiDump( DIGIERRORS, ("SerialWrite - Invalid Irp->AssociatedIrp.SystemBuffer!\n") ); Irp->IoStatus.Information = 0L; Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; DigiIoCompleteRequest( Irp, IO_NO_INCREMENT ); #if DBG KeQuerySystemTime( &CurrentSystemTime ); #endif DigiDump( DIGIFLOW, ("Exiting SerialWrite: port = %s ret = %d\t%u:%u\n", DeviceExt->DeviceDbgString, STATUS_INVALID_PARAMETER, CurrentSystemTime.HighPart, CurrentSystemTime.LowPart) ); return( STATUS_INVALID_PARAMETER ); } // // Mark the IRP as being "not started." // StartWriteRequest will set this field to zero. // WriteTxBuffer updates the field to the number of bytes written. // Irp->IoStatus.Information = MAXULONG; DigiDump( DIGIWRITE, (" #bytes to write: %d\n", IoGetCurrentIrpStackLocation(Irp)->Parameters.Write.Length) ); #if DBG if( DigiDebugLevel & DIGITXTRACE ) { PUCHAR Temp = Irp->AssociatedIrp.SystemBuffer; ULONG i; DigiDump( DIGITXTRACE, ("TXTRACE: %s: TxLength = %d (0x%x)", DeviceExt->DeviceDbgString, IoGetCurrentIrpStackLocation( Irp )->Parameters.Write.Length, IoGetCurrentIrpStackLocation( Irp )->Parameters.Write.Length) ); for( i = 0; i < IoGetCurrentIrpStackLocation( Irp )->Parameters.Write.Length; i++ ) { if( (i & 15) == 0 ) DigiDump( DIGITXTRACE, ( "\n\t") ); DigiDump( DIGITXTRACE, ( "-%02x", Temp[i]) ); } DigiDump( DIGITXTRACE, ("\n") ); } #endif // // If we are doing RAS, then we wait for any data in // the transmit queue to be put on the wire. // if( DeviceExt->SpecialFlags & DIGI_SPECIAL_FLAG_FAST_RAS ) { PIRP NewIrp; //#undef IO_ALLOC_IRP_WORKS, at least under 3.5 (807) checked build (IoFreeIrp reports corrupted memory) #ifdef IO_ALLOC_IRP_WORKS NewIrp = IoAllocateIrp( 2, FALSE ); #else NewIrp = DigiAllocMem( NonPagedPool, IoSizeOfIrp( 2 ) ); #endif if( NewIrp ) { PIO_STACK_LOCATION NewIrpSp; IoInitializeIrp( NewIrp, IoSizeOfIrp( 2 ), 2 ); IoSetCompletionRoutine( NewIrp, FreeDigiIrp, NULL, TRUE, TRUE, TRUE ); IoSetNextIrpStackLocation( NewIrp ); NewIrpSp = IoGetCurrentIrpStackLocation( NewIrp ); NewIrpSp->MajorFunction = IRP_MJ_FLUSH_BUFFERS; NewIrpSp->DeviceObject = DeviceObject; DigiDump( 0, ("Inserting flush irp 0x%x on %s\n", NewIrp, DeviceExt->DeviceDbgString) ); (VOID) DigiStartIrpRequest( ControllerExt, DeviceExt, &DeviceExt->WriteQueue, NewIrp, StartWriteRequest ); } } Status = DigiStartIrpRequest( ControllerExt, DeviceExt, &DeviceExt->WriteQueue, Irp, StartWriteRequest ); #if DBG KeQuerySystemTime( &CurrentSystemTime ); #endif DigiDump( (DIGIFLOW|DIGIWRITE), ("Exiting SerialWrite: port = %s\t%u:%u\n", DeviceExt->DeviceDbgString, CurrentSystemTime.HighPart, CurrentSystemTime.LowPart) ); return( Status ); } // end SerialWrite
/* * @implemented */ VOID IssueUniqueIdChangeNotifyWorker(IN PUNIQUE_ID_WORK_ITEM WorkItem, IN PMOUNTDEV_UNIQUE_ID UniqueId) { PIRP Irp; NTSTATUS Status; PFILE_OBJECT FileObject; PIO_STACK_LOCATION Stack; PDEVICE_OBJECT DeviceObject; /* Get the device object */ Status = IoGetDeviceObjectPointer(&(WorkItem->DeviceName), FILE_READ_ATTRIBUTES, &FileObject, &DeviceObject); if (!NT_SUCCESS(Status)) { RemoveWorkItem(WorkItem); return; } /* And then, the attached device */ DeviceObject = IoGetAttachedDeviceReference(FileObject->DeviceObject); /* Initialize the IRP */ Irp = WorkItem->Irp; IoInitializeIrp(Irp, IoSizeOfIrp(WorkItem->StackSize), (CCHAR)WorkItem->StackSize); if (InterlockedExchange((PLONG)&(WorkItem->Event), 0) != 0) { ObDereferenceObject(FileObject); ObDereferenceObject(DeviceObject); RemoveWorkItem(WorkItem); return; } Irp->AssociatedIrp.SystemBuffer = WorkItem->IrpBuffer; Irp->Tail.Overlay.Thread = PsGetCurrentThread(); RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, UniqueId, UniqueId->UniqueIdLength + sizeof(USHORT)); Stack = IoGetNextIrpStackLocation(Irp); Stack->Parameters.DeviceIoControl.InputBufferLength = UniqueId->UniqueIdLength + sizeof(USHORT); Stack->Parameters.DeviceIoControl.OutputBufferLength = WorkItem->IrpBufferLength; Stack->Parameters.DeviceIoControl.Type3InputBuffer = 0; Stack->Parameters.DeviceIoControl.IoControlCode = IOCTL_MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY; Stack->MajorFunction = IRP_MJ_DEVICE_CONTROL; Status = IoSetCompletionRoutineEx(WorkItem->DeviceExtension->DeviceObject, Irp, UniqueIdChangeNotifyCompletion, WorkItem, TRUE, TRUE, TRUE); if (!NT_SUCCESS(Status)) { ObDereferenceObject(FileObject); ObDereferenceObject(DeviceObject); RemoveWorkItem(WorkItem); return; } /* Call the driver */ IoCallDriver(DeviceObject, Irp); ObDereferenceObject(FileObject); ObDereferenceObject(DeviceObject); }