⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 io.c

📁 这个是一个开源项目, 有能力的人可以一起来写
💻 C
📖 第 1 页 / 共 3 页
字号:
  if (pIoPortWrite->sendBreak) {
    /* get BREAK char */

    dataChar.data.chr.type = RW_DATA_TYPE_CHR_BREAK;
    dataChar.data.chr.chr = 0;
    dataChar.data.chr.isChr = TRUE;
  } else {
    /* get XON or XOFF char */

    switch (pIoPortWrite->sendXonXoff) {
    case C0C_XCHAR_ON:
      dataChar.data.chr.type = RW_DATA_TYPE_CHR_XCHR;
      dataChar.data.chr.chr = pIoPortWrite->specialChars.XonChar;
      dataChar.data.chr.isChr = TRUE;
      break;
    case C0C_XCHAR_OFF:
      dataChar.data.chr.type = RW_DATA_TYPE_CHR_XCHR;
      dataChar.data.chr.chr = pIoPortWrite->specialChars.XoffChar;
      dataChar.data.chr.isChr = TRUE;
      break;
    default:
      dataChar.data.chr.type = RW_DATA_TYPE_CHR_NONE;
      dataChar.data.chr.isChr = FALSE;
    }
  }

  /* get first pIrpWrite */

  wasWrite = FALSE;
  doneWrite = 0;
  firstWrite = TRUE;

  if(startWrite) {
    dataIrpWrite.data.irp.pIrp = pQueueWrite->pCurrent;
    pCancelRoutineWrite = NULL;
  } else {
    dataIrpWrite.data.irp.pIrp =
        StartCurrentIrp(pQueueWrite, &pCancelRoutineWrite, &firstWrite);
  }

  /* read/write direct */

  while (dataIrpRead.data.irp.pIrp) {
    if (dataChar.data.chr.isChr) {
      if (!pWriteLimit || *pWriteLimit) {
        if (CAN_WRITE_RW_DATA_CHR(pIoPortWrite, dataChar)) {
          if (dataIrpRead.data.irp.status == STATUS_PENDING) {
            SIZE_T done = 0;

            ReadWriteDirect(dataIrpRead.data.irp.pIrp,
                            &dataChar,
                            &dataIrpRead.data.irp.status,
                            pIoPortRead,
                            pQueueToComplete,
                            pWriteLimit,
                            &doneRead, &done);

            if (done) {
              if (pWriteDelay)
                pWriteDelay->sentFrames += done;
            }
          }
        }
        else
        if (pWriteDelay) {
          pWriteDelay->sentFrames += *pWriteLimit;
          *pWriteLimit = 0;
        }
      }
    }

    while (dataIrpWrite.data.irp.pIrp) {
      if (IoGetCurrentIrpStackLocation(dataIrpWrite.data.irp.pIrp)->MajorFunction ==
                                                                IRP_MJ_FLUSH_BUFFERS)
      {
        dataIrpWrite.data.irp.status = STATUS_SUCCESS;
      } else {
        dataIrpWrite.data.irp.status = STATUS_PENDING;

        if (!pWriteLimit || *pWriteLimit) {
          if (!pIoPortWrite->writeHolding) {
            if (dataIrpRead.data.irp.status == STATUS_PENDING) {
              SIZE_T done = 0;

              ReadWriteDirect(dataIrpRead.data.irp.pIrp,
                              &dataIrpWrite,
                              &dataIrpRead.data.irp.status,
                              pIoPortRead,
                              pQueueToComplete,
                              pWriteLimit,
                              &doneRead, &done);

              if (done) {
                doneWrite += done;
                wasWrite = TRUE;

                if (pWriteDelay)
                  pWriteDelay->sentFrames += done;
              }
            }
          }
          else
          if (pWriteDelay) {
            pWriteDelay->sentFrames += *pWriteLimit;
            *pWriteLimit = 0;
          }
        }
      }

      if (dataIrpWrite.data.irp.status == STATUS_PENDING)
        break;

      if(startWrite && firstWrite) {
        status = dataIrpWrite.data.irp.status;
        ShiftQueue(pQueueWrite);
      } else {
        StopCurrentIrp(dataIrpWrite.data.irp.status, pCancelRoutineWrite, firstWrite,
                       doneWrite, pIoPortWrite, pQueueWrite, pQueueToComplete);
      }

      /* get next pIrpWrite */

      doneWrite = 0;
      firstWrite = FALSE;

      dataIrpWrite.data.irp.pIrp =
          StartCurrentIrp(pQueueWrite, &pCancelRoutineWrite, &firstWrite);
    }

    if (startRead && firstRead) {
      if (dataIrpRead.data.irp.status == STATUS_PENDING)
        dataIrpRead.data.irp.status =
            SetIrpTimeout(pIoPortRead, dataIrpRead.data.irp.pIrp);

      status = dataIrpRead.data.irp.status;

      if (dataIrpRead.data.irp.status != STATUS_PENDING)
        ShiftQueue(pQueueRead);
    } else {
      dataIrpRead.data.irp.status = StopCurrentIrp(
          dataIrpRead.data.irp.status, pCancelRoutineRead, firstRead,
          doneRead, pIoPortRead, pQueueRead, pQueueToComplete);
    }

    /* get next pIrpRead */

    if (dataIrpRead.data.irp.status != STATUS_PENDING) {
      dataIrpRead.data.irp.status = STATUS_PENDING;
      doneRead = 0;
      firstRead = FALSE;
      dataIrpRead.data.irp.pIrp =
          StartCurrentIrp(pQueueRead, &pCancelRoutineRead, &firstRead);
    } else {
      dataIrpRead.data.irp.pIrp = NULL;
    }
  }

  /* write to buffer */

  if (dataChar.data.chr.isChr) {
    if (!pWriteLimit || *pWriteLimit) {
      if (CAN_WRITE_RW_DATA_CHR(pIoPortWrite, dataChar)) {
        SIZE_T done = 0;

        WriteBuffer(&dataChar, pIoPortRead,
                    pQueueToComplete, pWriteLimit, &done);

        readBufBusyEnd = C0C_BUFFER_BUSY(&pIoPortRead->readBuf);

        if (readBufBusyBeg < readBufBusyEnd) {
          if ((pIoPortRead->waitMask & SERIAL_EV_RX80FULL) &&
              readBufBusyEnd > pIoPortRead->readBuf.size80 &&
              readBufBusyBeg <= pIoPortRead->readBuf.size80)
          {
            pIoPortRead->eventMask |= SERIAL_EV_RX80FULL;
            WaitComplete(pIoPortRead, pQueueToComplete);
          }

          UpdateHandFlow(pIoPortRead, FALSE, pQueueToComplete);
          readBufBusyBeg = readBufBusyEnd;
        }

        if (pIoPortRead->emuOverrun &&
            dataChar.data.chr.isChr &&
            CAN_WRITE_RW_DATA_CHR(pIoPortWrite, dataChar) &&
            C0C_BUFFER_BUSY(&pIoPortRead->readBuf) >= C0C_BUFFER_SIZE(&pIoPortRead->readBuf))
        {
          WriteOverrun(&dataChar, pIoPortRead,
                       pQueueToComplete, pWriteLimit, &done);
        }

        if (done) {
          if (pWriteDelay)
            pWriteDelay->sentFrames += done;
        }
      }
      else
      if (pWriteDelay) {
        pWriteDelay->sentFrames += *pWriteLimit;
        *pWriteLimit = 0;
      }
    }
  }

  if (!dataChar.data.chr.isChr) {
    switch (dataChar.data.chr.type) {
    case RW_DATA_TYPE_CHR_XCHR:
      pIoPortWrite->sendXonXoff = 0;
      break;
    case RW_DATA_TYPE_CHR_BREAK:
      if (pIoPortWrite->sendBreak) {
        pIoPortWrite->sendBreak = FALSE;
        if (pIoPortRead->escapeChar) {
          UCHAR lsr = 0x10;  /* break interrupt indicator */

          if (!pIoPortRead->amountInWriteQueue || pIoPortRead->writeHolding)
            lsr |= 0x60;  /* transmit holding register empty and transmitter empty indicators */

          InsertLsrMst(pIoPortRead, FALSE,  lsr, pQueueToComplete);
        }
        if (pIoPortRead->handFlow.FlowReplace & SERIAL_BREAK_CHAR)
          InsertChar(pIoPortRead, pIoPortRead->specialChars.BreakChar, pQueueToComplete);
      }
      break;
    }
  }

  while (dataIrpWrite.data.irp.pIrp) {
    if (IoGetCurrentIrpStackLocation(dataIrpWrite.data.irp.pIrp)->MajorFunction ==
                                                              IRP_MJ_FLUSH_BUFFERS)
    {
      dataIrpWrite.data.irp.status = STATUS_SUCCESS;
    } else {
      dataIrpWrite.data.irp.status = STATUS_PENDING;

      if (!pWriteLimit || *pWriteLimit) {
        if (!pIoPortWrite->writeHolding) {
          SIZE_T done = 0;

          WriteBuffer(&dataIrpWrite, pIoPortRead,
                      pQueueToComplete, pWriteLimit, &done);

          readBufBusyEnd = C0C_BUFFER_BUSY(&pIoPortRead->readBuf);

          if (readBufBusyBeg < readBufBusyEnd) {
            if ((pIoPortRead->waitMask & SERIAL_EV_RX80FULL) &&
                readBufBusyEnd > pIoPortRead->readBuf.size80 &&
                readBufBusyBeg <= pIoPortRead->readBuf.size80)
            {
              pIoPortRead->eventMask |= SERIAL_EV_RX80FULL;
              WaitComplete(pIoPortRead, pQueueToComplete);
            }

            UpdateHandFlow(pIoPortRead, FALSE, pQueueToComplete);
            readBufBusyBeg = readBufBusyEnd;
          }

          if (pIoPortRead->emuOverrun &&
              dataIrpWrite.data.irp.status == STATUS_PENDING &&
              !pIoPortWrite->writeHolding &&
              C0C_BUFFER_BUSY(&pIoPortRead->readBuf) >= C0C_BUFFER_SIZE(&pIoPortRead->readBuf))
          {
            WriteOverrun(&dataIrpWrite, pIoPortRead,
                         pQueueToComplete, pWriteLimit, &done);
          }

          if (done) {
            doneWrite += done;
            wasWrite = TRUE;

            if (pWriteDelay)
              pWriteDelay->sentFrames += done;
          }
        }
        else
        if (pWriteDelay) {
          pWriteDelay->sentFrames += *pWriteLimit;
          *pWriteLimit = 0;
        }
      }
    }

    if(startWrite && firstWrite) {
      if (dataIrpWrite.data.irp.status == STATUS_PENDING)
        dataIrpWrite.data.irp.status =
            SetIrpTimeout(pIoPortWrite, dataIrpWrite.data.irp.pIrp);

      status = dataIrpWrite.data.irp.status;

      if (dataIrpWrite.data.irp.status != STATUS_PENDING)
        ShiftQueue(pQueueWrite);
    } else {
      dataIrpWrite.data.irp.status =
          StopCurrentIrp(dataIrpWrite.data.irp.status, pCancelRoutineWrite, firstWrite,
                         doneWrite, pIoPortWrite, pQueueWrite, pQueueToComplete);
    }

    /* get next pIrpWrite */

    if (dataIrpWrite.data.irp.status != STATUS_PENDING) {
      doneWrite = 0;
      firstWrite = FALSE;
      dataIrpWrite.data.irp.pIrp = StartCurrentIrp(pQueueWrite, &pCancelRoutineWrite, &firstWrite);
    } else {
      dataIrpWrite.data.irp.pIrp = NULL;
    }
  }

  if (wasWrite && !pQueueWrite->pCurrent &&
      pIoPortWrite->waitMask & SERIAL_EV_TXEMPTY)
  {
    pIoPortWrite->eventMask |= SERIAL_EV_TXEMPTY;
    WaitComplete(pIoPortWrite, pQueueToComplete);
  }

  UpdateTransmitToggle(pIoPortWrite, pQueueToComplete);

  return status;
}

NTSTATUS ReadWrite(
    PC0C_IO_PORT pIoPortRead,
    BOOLEAN startRead,
    PC0C_IO_PORT pIoPortWrite,
    BOOLEAN startWrite,
    PLIST_ENTRY pQueueToComplete)
{
  NTSTATUS status;

  status = TryReadWrite(
      pIoPortRead, startRead,
      pIoPortWrite, startWrite,
      pQueueToComplete);

  pIoPortWrite->tryWrite = FALSE;

  while (pIoPortRead->tryWrite) {
    PC0C_IO_PORT pIoPortTmp;

    pIoPortTmp = pIoPortRead;
    pIoPortRead = pIoPortWrite;
    pIoPortWrite = pIoPortTmp;

    TryReadWrite(
        pIoPortRead, FALSE,
        pIoPortWrite, FALSE,
        pQueueToComplete);

    pIoPortWrite->tryWrite = FALSE;

    if (status == STATUS_PENDING && (startRead || startWrite))
      break;
  }

  return status;
}

VOID SetModemStatus(
    IN PC0C_IO_PORT pIoPort,
    IN ULONG bits,
    IN ULONG mask,
    PLIST_ENTRY pQueueToComplete)
{
  ULONG modemStatusOld;
  ULONG modemStatusChanged;

  modemStatusOld = pIoPort->modemStatus;

  pIoPort->modemStatus |= bits & mask;
  pIoPort->modemStatus &= ~(~bits & mask);

  /* DCD = DSR */
  if (pIoPort->modemStatus & C0C_MSB_DSR)
    pIoPort->modemStatus |= C0C_MSB_RLSD;
  else
    pIoPort->modemStatus &= ~C0C_MSB_RLSD;

  modemStatusChanged = modemStatusOld ^ pIoPort->modemStatus;

  if (modemStatusChanged) {
    TraceModemStatus(pIoPort);

    SetModemStatusHolding(pIoPort);

    if (pIoPort->escapeChar)
      InsertLsrMst(pIoPort, TRUE,
          (UCHAR)(pIoPort->modemStatus | (modemStatusChanged >> 4)), pQueueToComplete);

    if (modemStatusChanged & C0C_MSB_CTS)
      pIoPort->eventMask |= pIoPort->waitMask & SERIAL_EV_CTS;

    if (modemStatusChanged & C0C_MSB_DSR)
      pIoPort->eventMask |= pIoPort->waitMask & SERIAL_EV_DSR;

    if (modemStatusChanged & C0C_MSB_RING)
      pIoPort->eventMask |= pIoPort->waitMask & SERIAL_EV_RING;

    if (modemStatusChanged & C0C_MSB_RLSD)
      pIoPort->eventMask |= pIoPort->waitMask & SERIAL_EV_RLSD;

    WaitComplete(pIoPort, pQueueToComplete);
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -