📄 io.c
字号:
PNTSTATUS pStatusRead,
PC0C_IO_PORT pReadIoPort,
PLIST_ENTRY pQueueToComplete,
PSIZE_T pWriteLimit,
PSIZE_T pReadDone,
PSIZE_T pWriteDone)
{
SIZE_T readDone, writeDone;
SIZE_T writeLength, readLength;
C0C_FLOW_FILTER flowFilter;
PVOID pWriteBuf, pReadBuf;
BOOLEAN isBreak;
isBreak = FALSE;
pReadBuf = GET_REST_BUFFER(pIrpRead, pIrpRead->IoStatus.Information);
readLength = IoGetCurrentIrpStackLocation(pIrpRead)->Parameters.Read.Length
- pIrpRead->IoStatus.Information;
if (pDataWrite->type == RW_DATA_TYPE_IRP) {
PIRP pIrpWrite = pDataWrite->data.irp.pIrp;
pWriteBuf = GET_REST_BUFFER(pIrpWrite, pIrpWrite->IoStatus.Information);
writeLength = GetWriteLength(pIrpWrite) - pIrpWrite->IoStatus.Information;
} else {
HALT_UNLESS1(pDataWrite->type == RW_DATA_TYPE_CHR, pDataWrite->type);
pWriteBuf = &pDataWrite->data.chr.chr;
writeLength = pDataWrite->data.chr.isChr ? 1 : 0;
if (pDataWrite->data.chr.type == RW_DATA_TYPE_CHR_BREAK)
isBreak = TRUE;
}
FlowFilterInit(pReadIoPort, &flowFilter);
CopyCharsWithEscape(
&pReadIoPort->readBuf, &flowFilter,
pReadBuf, readLength,
pWriteBuf, (pWriteLimit && writeLength > *pWriteLimit) ? *pWriteLimit : writeLength,
&readDone, &writeDone);
if (pWriteLimit)
*pWriteLimit -= writeDone;
pIrpRead->IoStatus.Information += readDone;
if (pDataWrite->type == RW_DATA_TYPE_IRP) {
pDataWrite->data.irp.pIrp->IoStatus.Information += writeDone;
pReadIoPort->pIoPortRemote->amountInWriteQueue -= (ULONG)writeDone;
}
if (readDone == readLength)
*pStatusRead = STATUS_SUCCESS;
if (writeDone == writeLength) {
if (pDataWrite->type == RW_DATA_TYPE_IRP) {
pDataWrite->data.irp.status = STATUS_SUCCESS;
} else {
HALT_UNLESS1(pDataWrite->type == RW_DATA_TYPE_CHR, pDataWrite->type);
pDataWrite->data.chr.isChr = FALSE;
}
}
if (writeDone) {
OnRxChars(pReadIoPort, writeDone, &flowFilter, pQueueToComplete);
if (isBreak)
OnRxBreak(pReadIoPort, pQueueToComplete);
else
pReadIoPort->pIoPortRemote->perfStats.TransmittedCount += (ULONG)writeDone;
}
*pReadDone += readDone;
*pWriteDone += writeDone;
}
VOID InsertDirect(
PC0C_RAW_DATA pRawData,
PIRP pIrpRead,
PNTSTATUS pStatusWrite,
PNTSTATUS pStatusRead,
PSIZE_T pReadDone)
{
SIZE_T readDone;
SIZE_T readLength;
PVOID pReadBuf;
pReadBuf = GET_REST_BUFFER(pIrpRead, pIrpRead->IoStatus.Information);
readLength = IoGetCurrentIrpStackLocation(pIrpRead)->Parameters.Read.Length
- pIrpRead->IoStatus.Information;
readDone = WriteRawData(pRawData, pStatusWrite, pReadBuf, readLength);
pIrpRead->IoStatus.Information += readDone;
if (readDone == readLength)
*pStatusRead = STATUS_SUCCESS;
*pReadDone += readDone;
}
PIRP StartCurrentIrp(PC0C_IRP_QUEUE pQueue, PDRIVER_CANCEL *ppCancelRoutine, PBOOLEAN pFirst)
{
while (pQueue->pCurrent) {
PIRP pIrp;
pIrp = pQueue->pCurrent;
#pragma warning(push, 3)
*ppCancelRoutine = IoSetCancelRoutine(pIrp, NULL);
#pragma warning(pop)
if (*ppCancelRoutine) {
#if DBG
HALT_UNLESS(!pQueue->started);
pQueue->started = TRUE;
#endif /* DBG */
return pIrp;
}
ShiftQueue(pQueue);
*pFirst = FALSE;
}
return NULL;
}
NTSTATUS StopCurrentIrp(
NTSTATUS status,
PDRIVER_CANCEL pCancelRoutine,
BOOLEAN first,
SIZE_T done,
PC0C_IO_PORT pIoPort,
PC0C_IRP_QUEUE pQueue,
PLIST_ENTRY pQueueToComplete)
{
PIRP pIrp;
#if DBG
HALT_UNLESS(pQueue->started);
pQueue->started = FALSE;
#endif /* DBG */
pIrp = pQueue->pCurrent;
if (status == STATUS_PENDING && done) {
PC0C_IRP_STATE pState;
pState = GetIrpState(pIrp);
HALT_UNLESS(pState);
if ((pState->flags & C0C_IRP_FLAG_WAIT_ONE) != 0) {
status = STATUS_SUCCESS;
}
else
if (first && (pState->flags & C0C_IRP_FLAG_INTERVAL_TIMEOUT) != 0) {
SetIntervalTimeout(pIoPort);
}
}
if (!first && status == STATUS_PENDING)
status = SetIrpTimeout(pIoPort, pIrp);
HALT_UNLESS(pCancelRoutine);
if (status == STATUS_PENDING) {
#pragma warning(push, 3)
IoSetCancelRoutine(pIrp, pCancelRoutine);
#pragma warning(pop)
if (pIrp->Cancel) {
#pragma warning(push, 3)
pCancelRoutine = IoSetCancelRoutine(pIrp, NULL);
#pragma warning(pop)
if (pCancelRoutine) {
ShiftQueue(pQueue);
pIrp->IoStatus.Status = STATUS_CANCELLED;
InsertTailList(pQueueToComplete, &pIrp->Tail.Overlay.ListEntry);
return STATUS_CANCELLED;
}
}
} else {
ShiftQueue(pQueue);
pIrp->IoStatus.Status = status;
InsertTailList(pQueueToComplete, &pIrp->Tail.Overlay.ListEntry);
}
return status;
}
NTSTATUS FdoPortIo(
short ioType,
PVOID pParam,
PC0C_IO_PORT pIoPort,
PC0C_IRP_QUEUE pQueue,
PLIST_ENTRY pQueueToComplete)
{
NTSTATUS status;
BOOLEAN first;
BOOLEAN firstCurrent;
PIRP pIrpCurrent;
PDRIVER_CANCEL pCancelRoutineCurrent;
SIZE_T done;
first = TRUE;
done = 0;
status = STATUS_PENDING;
for (firstCurrent = TRUE ; (pIrpCurrent = StartCurrentIrp(pQueue, &pCancelRoutineCurrent, &firstCurrent)) != NULL ; firstCurrent = FALSE) {
NTSTATUS statusCurrent;
SIZE_T doneCurrent;
statusCurrent = STATUS_PENDING;
doneCurrent = 0;
switch (ioType) {
case C0C_IO_TYPE_WAIT_COMPLETE:
HALT_UNLESS(pParam);
*((PULONG)pIrpCurrent->AssociatedIrp.SystemBuffer) = *((PULONG)pParam);
*((PULONG)pParam) = 0;
pIrpCurrent->IoStatus.Information = sizeof(ULONG);
statusCurrent = STATUS_SUCCESS;
break;
case C0C_IO_TYPE_INSERT:
HALT_UNLESS(pParam);
InsertDirect((PC0C_RAW_DATA)pParam, pIrpCurrent, &status, &statusCurrent, &doneCurrent);
break;
}
statusCurrent = StopCurrentIrp(statusCurrent,
pCancelRoutineCurrent,
firstCurrent,
doneCurrent,
pIoPort,
pQueue,
pQueueToComplete);
if (statusCurrent == STATUS_PENDING)
break;
}
if (status == STATUS_PENDING) {
switch (ioType) {
case C0C_IO_TYPE_INSERT:
HALT_UNLESS(pParam);
status = WriteRawDataToBuffer((PC0C_RAW_DATA)pParam, &pIoPort->readBuf);
if (status == STATUS_PENDING && !pIoPort->emuOverrun)
status = MoveRawData(&pIoPort->readBuf.insertData, (PC0C_RAW_DATA)pParam);
UpdateHandFlow(pIoPort, FALSE, pQueueToComplete);
break;
}
}
return status;
}
VOID InsertLsrMst(
PC0C_IO_PORT pIoPortRead,
BOOLEAN isMST,
UCHAR value,
PLIST_ENTRY pQueueToComplete)
{
C0C_RAW_DATA insertData;
insertData.size = 3;
insertData.data[0] = pIoPortRead->escapeChar;
insertData.data[1] = (UCHAR)(isMST ? SERIAL_LSRMST_MST : SERIAL_LSRMST_LSR_NODATA);
insertData.data[2] = value;
if (FdoPortIo(
C0C_IO_TYPE_INSERT,
&insertData,
pIoPortRead,
&pIoPortRead->irpQueues[C0C_QUEUE_READ],
pQueueToComplete) == STATUS_PENDING)
{
AlertOverrun(pIoPortRead, pQueueToComplete);
Trace00((PC0C_COMMON_EXTENSION)pIoPortRead->pDevExt,
L"WARNING: Lost SERIAL_LSRMST_", isMST ? L"MST" : L"LSR_NODATA");
}
}
VOID InsertChar(
PC0C_IO_PORT pIoPortRead,
UCHAR value,
PLIST_ENTRY pQueueToComplete)
{
C0C_RAW_DATA insertData;
insertData.size = 1;
insertData.data[0] = value;
if (FdoPortIo(
C0C_IO_TYPE_INSERT,
&insertData,
pIoPortRead,
&pIoPortRead->irpQueues[C0C_QUEUE_READ],
pQueueToComplete) == STATUS_PENDING)
{
AlertOverrun(pIoPortRead, pQueueToComplete);
Trace0((PC0C_COMMON_EXTENSION)pIoPortRead->pDevExt, L"WARNING: Lost char");
}
}
NTSTATUS TryReadWrite(
PC0C_IO_PORT pIoPortRead,
BOOLEAN startRead,
PC0C_IO_PORT pIoPortWrite,
BOOLEAN startWrite,
PLIST_ENTRY pQueueToComplete)
{
NTSTATUS status;
SIZE_T readBufBusyBeg, readBufBusyEnd;
RW_DATA dataIrpRead;
PC0C_IRP_QUEUE pQueueRead;
BOOLEAN firstRead;
PDRIVER_CANCEL pCancelRoutineRead;
SIZE_T doneRead;
RW_DATA dataChar;
RW_DATA dataIrpWrite;
PC0C_IRP_QUEUE pQueueWrite;
BOOLEAN firstWrite;
PDRIVER_CANCEL pCancelRoutineWrite;
SIZE_T doneWrite;
BOOLEAN wasWrite;
PC0C_ADAPTIVE_DELAY pWriteDelay;
SIZE_T writeLimit;
PSIZE_T pWriteLimit;
dataIrpRead.type = RW_DATA_TYPE_IRP;
dataChar.type = RW_DATA_TYPE_CHR;
dataIrpWrite.type = RW_DATA_TYPE_IRP;
pQueueRead = &pIoPortRead->irpQueues[C0C_QUEUE_READ];
pQueueWrite = &pIoPortWrite->irpQueues[C0C_QUEUE_WRITE];
pWriteDelay = pIoPortWrite->pWriteDelay;
if (pWriteDelay) {
if (pQueueWrite->pCurrent || pIoPortWrite->sendBreak || pIoPortWrite->sendXonXoff) {
StartWriteDelayTimer(pWriteDelay);
writeLimit = GetWriteLimit(pWriteDelay);
status = STATUS_PENDING;
} else {
writeLimit = 0;
status = STATUS_SUCCESS;
}
pWriteLimit = &writeLimit;
} else {
status = STATUS_SUCCESS;
pWriteLimit = NULL;
}
readBufBusyBeg = C0C_BUFFER_BUSY(&pIoPortRead->readBuf);
/* get first pIrpRead */
dataIrpRead.data.irp.status = STATUS_PENDING;
doneRead = 0;
firstRead = TRUE;
if (startRead) {
dataIrpRead.data.irp.pIrp = pQueueRead->pCurrent;
pCancelRoutineRead = NULL;
} else {
dataIrpRead.data.irp.pIrp = StartCurrentIrp(pQueueRead, &pCancelRoutineRead, &firstRead);
}
/* read from buffer */
while (dataIrpRead.data.irp.pIrp) {
dataIrpRead.data.irp.status = ReadBuffer(dataIrpRead.data.irp.pIrp, &pIoPortRead->readBuf, &doneRead);
if (dataIrpRead.data.irp.status == STATUS_PENDING)
break;
if (startRead && firstRead) {
status = dataIrpRead.data.irp.status;
ShiftQueue(pQueueRead);
} else {
StopCurrentIrp(dataIrpRead.data.irp.status, pCancelRoutineRead, firstRead,
doneRead, pIoPortRead, pQueueRead, pQueueToComplete);
}
/* get next pIrpRead */
doneRead = 0;
firstRead = FALSE;
dataIrpRead.data.irp.pIrp =
StartCurrentIrp(pQueueRead, &pCancelRoutineRead, &firstRead);
}
readBufBusyEnd = C0C_BUFFER_BUSY(&pIoPortRead->readBuf);
if (readBufBusyBeg > readBufBusyEnd) {
UpdateHandFlow(pIoPortRead, TRUE, pQueueToComplete);
readBufBusyBeg = readBufBusyEnd;
}
/* get char */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -