Exemple #1
0
NTSTATUS StartIrp(
    PC0C_IO_PORT pIoPort,
    PIRP pIrp,
    PC0C_IRP_STATE pState,
    PC0C_IRP_QUEUE pQueue,
    PLIST_ENTRY pQueueToComplete,
    PC0C_FDOPORT_START_ROUTINE pStartRoutine)
{
  NTSTATUS status;

  pQueue->pCurrent = pIrp;
  pState->flags |= C0C_IRP_FLAG_IS_CURRENT;

  if (pState->iQueue == C0C_QUEUE_WRITE) {
    ULONG length = GetWriteLength(pIrp);

    if (length) {
      pIoPort->amountInWriteQueue += length;
      UpdateTransmitToggle(pIoPort, pQueueToComplete);
    }
  }

  status = pStartRoutine(pIoPort, pQueueToComplete);

  if (status == STATUS_PENDING) {
    pIrp->IoStatus.Status = STATUS_PENDING;
    IoMarkIrpPending(pIrp);
  } else {
    status = NoPending(pIrp, status);

    if (status != STATUS_PENDING) {
      PIO_STACK_LOCATION pIrpStack;

      if (pState->iQueue == C0C_QUEUE_WRITE) {
        pIoPort->amountInWriteQueue -=
            GetWriteLength(pIrp) - (ULONG)pIrp->IoStatus.Information;
      }

      pIrpStack = IoGetCurrentIrpStackLocation(pIrp);

      if (status == STATUS_CANCELLED ||
          (pIrpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL &&
              (pIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SERIAL_IMMEDIATE_CHAR ||
                  pIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SERIAL_XOFF_COUNTER)))
      {
        pIrp->IoStatus.Information = 0;
      }
    }

    if (pQueue->pCurrent == pIrp)
      ShiftQueue(pQueue);
  }

  return status;
}
Exemple #2
0
VOID FdoPortCompleteQueue(IN PLIST_ENTRY pQueueToComplete)
{
  while (!IsListEmpty(pQueueToComplete)) {
    PIRP pIrp;
    PC0C_IRP_STATE pState;
    PLIST_ENTRY pListEntry;
    PIO_STACK_LOCATION pIrpStack;

    pListEntry = RemoveHeadList(pQueueToComplete);
    pIrp = CONTAINING_RECORD(pListEntry, IRP, Tail.Overlay.ListEntry);
    pIrpStack = IoGetCurrentIrpStackLocation(pIrp);

    if (pIrp->IoStatus.Status == STATUS_TIMEOUT && pIrp->IoStatus.Information &&
        pIrpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL &&
            pIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SERIAL_XOFF_COUNTER)
    {
      pIrp->IoStatus.Status = STATUS_SERIAL_COUNTER_TIMEOUT;
    }

    TraceIrp("complete", pIrp, &pIrp->IoStatus.Status, TRACE_FLAG_RESULTS);

    pState = GetIrpState(pIrp);
    HALT_UNLESS(pState);

    if (pState->iQueue == C0C_QUEUE_WRITE) {
      KIRQL oldIrql;
      PC0C_IO_PORT pIoPort;

      pIoPort = FDO_PORT_TO_IO_PORT(IoGetCurrentIrpStackLocation(pIrp)->DeviceObject);

      KeAcquireSpinLock(pIoPort->pIoLock, &oldIrql);
      pIoPort->amountInWriteQueue -=
          GetWriteLength(pIrp) - (ULONG)pIrp->IoStatus.Information;
      KeReleaseSpinLock(pIoPort->pIoLock, oldIrql);
    }

    if (pIrp->IoStatus.Status == STATUS_CANCELLED ||
        (pIrpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL &&
            (pIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SERIAL_IMMEDIATE_CHAR ||
                pIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SERIAL_XOFF_COUNTER)))
    {
      pIrp->IoStatus.Information = 0;
    }

    IoCompleteRequest(pIrp, IO_SERIAL_INCREMENT);
  }
}
Exemple #3
0
NTSTATUS SetWriteTimeout(PC0C_IO_PORT pIoPort, PIRP pIrp)
{
  SERIAL_TIMEOUTS timeouts;
  BOOLEAN setTotal;
  ULONG multiplier;
  ULONG constant;

  KeCancelTimer(&pIoPort->timerWriteTotal);

  timeouts = pIoPort->timeouts;

  setTotal = FALSE;
  multiplier = 0;
  constant = 0;

  if (timeouts.WriteTotalTimeoutMultiplier || timeouts.WriteTotalTimeoutConstant) {
    setTotal = TRUE;
    multiplier = timeouts.WriteTotalTimeoutMultiplier;
    constant = timeouts.WriteTotalTimeoutConstant;
  }

  if (setTotal) {
    LARGE_INTEGER total;
    ULONG length;

    length = GetWriteLength(pIrp);

    total.QuadPart = ((LONGLONG)(UInt32x32To64(length, multiplier) + constant)) * -10000;

    KeSetTimer(
        &pIoPort->timerWriteTotal,
        total,
        &pIoPort->timerWriteTotalDpc);
  }

  return STATUS_PENDING;
}
Exemple #4
0
NTSTATUS FdoPortStartIrp(
    IN PC0C_IO_PORT pIoPort,
    IN PIRP pIrp,
    IN UCHAR iQueue,
    IN PC0C_FDOPORT_START_ROUTINE pStartRoutine)
{
  NTSTATUS status;
  LIST_ENTRY queueToComplete;
  KIRQL oldIrql;
  PC0C_IRP_QUEUE pQueue;
  PC0C_IRP_STATE pState;

  InitializeListHead(&queueToComplete);
  pState = GetIrpState(pIrp);

  HALT_UNLESS(pState);

  pState->flags = 0;
  pState->iQueue = iQueue;

  pQueue = &pIoPort->irpQueues[iQueue];

  KeAcquireSpinLock(pIoPort->pIoLock, &oldIrql);

  #pragma warning(push, 3)
  IoSetCancelRoutine(pIrp, CancelRoutine);
  #pragma warning(pop)

  if (pIrp->Cancel) {
    status = NoPending(pIrp, STATUS_CANCELLED);
  } else {
    if (!pQueue->pCurrent) {
      status = StartIrp(pIoPort, pIrp, pState, pQueue, &queueToComplete, pStartRoutine);
    } else {
      PIO_STACK_LOCATION pIrpStack;
      PIO_STACK_LOCATION pCurrentStack;

      pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
      pCurrentStack = IoGetCurrentIrpStackLocation(pQueue->pCurrent);

      if (pIrpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL &&
          pIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SERIAL_WAIT_ON_MASK)
      {
        status = NoPending(pIrp, STATUS_INVALID_PARAMETER);
      }
      else
      if (pIrpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL &&
          pIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SERIAL_IMMEDIATE_CHAR)
      {
        if (pCurrentStack->MajorFunction == IRP_MJ_DEVICE_CONTROL &&
            pCurrentStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SERIAL_IMMEDIATE_CHAR)
        {
          status = NoPending(pIrp, STATUS_INVALID_PARAMETER);
        } else {
          PC0C_IRP_STATE pCurrentState;

          pCurrentState = GetIrpState(pQueue->pCurrent);

          HALT_UNLESS(pCurrentState);

          pCurrentState->flags &= ~C0C_IRP_FLAG_IS_CURRENT;
          InsertHeadList(&pQueue->queue, &pQueue->pCurrent->Tail.Overlay.ListEntry);
          pCurrentState->flags |= C0C_IRP_FLAG_IN_QUEUE;

          status = StartIrp(pIoPort, pIrp, pState, pQueue, &queueToComplete, pStartRoutine);
        }
      }
      else {
        InsertTailList(&pQueue->queue, &pIrp->Tail.Overlay.ListEntry);
        pState->flags |= C0C_IRP_FLAG_IN_QUEUE;

        if (pState->iQueue == C0C_QUEUE_WRITE) {
          pIoPort->amountInWriteQueue += GetWriteLength(pIrp);
        }

        if (pCurrentStack->MajorFunction == IRP_MJ_DEVICE_CONTROL &&
            pCurrentStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SERIAL_XOFF_COUNTER &&
            pQueue->pCurrent->IoStatus.Information)
        {
          if (pIrpStack->MajorFunction == IRP_MJ_FLUSH_BUFFERS) {
            RemoveEntryList(&pIrp->Tail.Overlay.ListEntry);
            pState->flags &= ~C0C_IRP_FLAG_IN_QUEUE;
            status = NoPending(pIrp, STATUS_SUCCESS);
          } else {
            PIRP pIrpXoffCounter = pQueue->pCurrent;

            ShiftQueue(pQueue);
            CompleteIrp(pIrpXoffCounter, STATUS_SERIAL_MORE_WRITES, &queueToComplete);

            status = StartIrp(pIoPort, pIrp, pState, pQueue, &queueToComplete, pStartRoutine);
          }
        } else {
          pIrp->IoStatus.Status = STATUS_PENDING;
          IoMarkIrpPending(pIrp);
          status = STATUS_PENDING;
        }
      }
    }
  }

  KeReleaseSpinLock(pIoPort->pIoLock, oldIrql);

  FdoPortCompleteQueue(&queueToComplete);

  return status;
}