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);
}
Beispiel #2
0
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
Beispiel #3
0
/*
 * @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);
}