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

📄 isr.c

📁 串口Windows驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
                                Extension->PerfStats.TransmittedCount++;
                                Extension->WmiPerfData.TransmittedCount++;
                                WRITE_TRANSMIT_HOLDING(
                                    Extension->Controller,
                                    Extension->ImmediateChar
                                    );

                                SerialInsertQueueDpc(
                                    &Extension->StartTimerLowerRTSDpc,
                                    NULL,
                                    NULL,
                                    Extension
                                    )?Extension->CountOfTryingToLowerRTS++:0;

                            } else {

                                Extension->PerfStats.TransmittedCount++;
                                Extension->WmiPerfData.TransmittedCount++;
                                WRITE_TRANSMIT_HOLDING(
                                    Extension->Controller,
                                    Extension->ImmediateChar
                                    );

                            }

                            Extension->HoldingEmpty = FALSE;

                            SerialInsertQueueDpc(
                                &Extension->CompleteImmediateDpc,
                                NULL,
                                NULL,
                                Extension
                                );

                        } else if (!Extension->TXHolding) {

                            ULONG amountToWrite;

                            if (Extension->FifoPresent) {

                                amountToWrite = (Extension->TxFifoAmount <
                                                 Extension->WriteLength)?
                                                Extension->TxFifoAmount:
                                                Extension->WriteLength;

                            } else {

                                amountToWrite = 1;

                            }
                            if ((Extension->HandFlow.FlowReplace &
                                 SERIAL_RTS_MASK) ==
                                 SERIAL_TRANSMIT_TOGGLE) {

                                //
                                // We have to raise if we're sending
                                // this character.
                                //

                                SerialSetRTS(Extension);

                                if (amountToWrite == 1) {

                                    Extension->PerfStats.TransmittedCount++;
                                    Extension->WmiPerfData.TransmittedCount++;
                                    WRITE_TRANSMIT_HOLDING(
                                        Extension->Controller,
                                        *(Extension->WriteCurrentChar)
                                        );

                                } else {

                                    Extension->PerfStats.TransmittedCount +=
                                        amountToWrite;
                                    Extension->WmiPerfData.TransmittedCount +=
                                       amountToWrite;
                                    WRITE_TRANSMIT_FIFO_HOLDING(
                                        Extension->Controller,
                                        Extension->WriteCurrentChar,
                                        amountToWrite
                                        );

                                }

                                SerialInsertQueueDpc(
                                    &Extension->StartTimerLowerRTSDpc,
                                    NULL,
                                    NULL,
                                    Extension
                                    )?Extension->CountOfTryingToLowerRTS++:0;

                            } else {

                                if (amountToWrite == 1) {

                                    Extension->PerfStats.TransmittedCount++;
                                    Extension->WmiPerfData.TransmittedCount++;
                                    WRITE_TRANSMIT_HOLDING(
                                        Extension->Controller,
                                        *(Extension->WriteCurrentChar)
                                        );

                                } else {

                                    Extension->PerfStats.TransmittedCount +=
                                        amountToWrite;
                                    Extension->WmiPerfData.TransmittedCount +=
                                        amountToWrite;
                                    WRITE_TRANSMIT_FIFO_HOLDING(
                                        Extension->Controller,
                                        Extension->WriteCurrentChar,
                                        amountToWrite
                                        );

                                }

                            }

                            Extension->HoldingEmpty = FALSE;
                            Extension->WriteCurrentChar += amountToWrite;
                            Extension->WriteLength -= amountToWrite;

                            if (!Extension->WriteLength) {

                                PIO_STACK_LOCATION IrpSp;
                                //
                                // No More characters left.  This
                                // write is complete.  Take care
                                // when updating the information field,
                                // we could have an xoff counter masquerading
                                // as a write irp.
                                //

                                IrpSp = IoGetCurrentIrpStackLocation(
                                            Extension->CurrentWriteIrp
                                            );

                                Extension->CurrentWriteIrp->
                                    IoStatus.Information =
                                    (IrpSp->MajorFunction == IRP_MJ_WRITE)?
                                        (IrpSp->Parameters.Write.Length):
                                        (1);

                                SerialInsertQueueDpc(
                                    &Extension->CompleteWriteDpc,
                                    NULL,
                                    NULL,
                                    Extension
                                    );

                            }

                        }

                    }

                    break;

                }

                case SERIAL_IIR_MS: {

                    SerialHandleModemUpdate(
                        Extension,
                        FALSE
                        );

                    break;

                }

            }

        } while (!((InterruptIdReg =
                    READ_INTERRUPT_ID_REG(Extension->Controller))
                    & SERIAL_IIR_NO_INTERRUPT_PENDING));

        //
        // Besides catching the WINBOND and SMC chip problems this
        // will also cause transmission to restart incase of an xon
        // char being received.  Don't remove.
        //

        if (SerialProcessLSR(Extension) & SERIAL_LSR_THRE) {

            if (!Extension->TXHolding &&
                (Extension->WriteLength ||
                 Extension->TransmitImmediate)) {

                goto doTrasmitStuff;

            }

        }

    }

    //
    // This will "unlock" the close and cause the event
    // to fire if we didn't queue any DPC's
    //

    {
       LONG pendingCnt;

       //
       // Increment once more.  This is just a quick test to see if we
       // have a chance of causing the event to fire... we don't want
       // to run a DPC on every ISR if we don't have to....
       //

retryDPCFiring:;

       InterlockedIncrement(&Extension->DpcCount);
       LOGENTRY(LOG_CNT, 'DpI4', 0, Extension->DpcCount, 0);

       //
       // Decrement and see if the lock above looks like the only one left.
       //

       pendingCnt = InterlockedDecrement(&Extension->DpcCount);
//       LOGENTRY(LOG_CNT, 'DpD5', 0, Extension->DpcCount, 0);

       if (pendingCnt == 1) {
          KeInsertQueueDpc(&Extension->IsrUnlockPagesDpc, NULL, NULL);
       } else {
          if (InterlockedDecrement(&Extension->DpcCount) == 0) {

//             LOGENTRY(LOG_CNT, 'DpD6', &Extension->IsrUnlockPagesDpc,
//                      Extension->DpcCount, 0);

             //
             // We missed it.  Retry...
             //

             InterlockedIncrement(&Extension->DpcCount);
             LOGENTRY(LOG_CNT, 'DpI5', &Extension->IsrUnlockPagesDpc,
                      Extension->DpcCount, 0);
             goto retryDPCFiring;
          }
       }
    }

    return ServicedAnInterrupt;

}

VOID
SerialPutChar(
    IN PSERIAL_DEVICE_EXTENSION Extension,
    IN UCHAR CharToPut
    )

/*++

Routine Description:

    This routine, which only runs at device level, takes care of
    placing a character into the typeahead (receive) buffer.

Arguments:

    Extension - The serial device extension.

Return Value:

    None.

--*/

{
   SERIAL_LOCKED_PAGED_CODE();

    //
    // If we have dsr sensitivity enabled then
    // we need to check the modem status register
    // to see if it has changed.
    //

    if (Extension->HandFlow.ControlHandShake &
        SERIAL_DSR_SENSITIVITY) {

        SerialHandleModemUpdate(
            Extension,
            FALSE
            );

        if (Extension->RXHolding & SERIAL_RX_DSR) {

            //
            // We simply act as if we haven't
            // seen the character if we have dsr
            // sensitivity and the dsr line is low.
            //

            return;

        }

    }

    //
    // If the xoff counter is non-zero then decrement it.
    // If the counter then goes to zero, complete that irp.
    //

    if (Extension->CountSinceXoff) {

        Extension->CountSinceXoff--;

        if (!Extension->CountSinceXoff) {

            Extension->CurrentXoffIrp->IoStatus.Status = STATUS_SUCCESS;
            Extension->CurrentXoffIrp->IoStatus.Information = 0;
            SerialInsertQueueDpc(
                &Extension->XoffCountCompleteDpc,
                NULL,
                NULL,
                Extension
                );

        }

    }

    //
    // Check to see if we are copying into the
    // users buffer or into the interrupt buffer.
    //
    // If we are copying into the user buffer
    // then we know there is always room for one more.
    // (We know this because if there wasn't room
    // then that read would have completed and we
    // would be using the interrupt buffer.)
    //
    // If we are copying into the interrupt buffer
    // then we will need to check if we have enough
    // room.
    //

    if (Extension->ReadBufferBase !=
        Extension->InterruptReadBuffer) {

        //
        // Increment the following value so
        // that the interval timer (if one exists
        // for this read) can know that a character
        // has been read.
        //

        Extension->ReadByIsr++;

        //
        // We are in the user buffer.  Place the
        // character into the buffer.  See if the
        // read is complete.
        //

        *Extension->CurrentCharSlot = CharToPut;

        if (Extension->CurrentCharSlot ==
            Extension->LastCharSlot) {

            //
            // We've filled up the users buffer.
            // Switch back to the interrupt buffer
            // and send off a DPC to Complete the read.
            //
            // It is inherent that when we were using
            // a user buffer that the interrupt buffer
            // was empty.
            //

            Extension->ReadBufferBase =
                Extension->InterruptReadBuffer;
            Extension->CurrentCharSlot =
                Extension->InterruptReadBuffer;
            Extension->FirstReadableChar =
                Extension->InterruptReadBuffer;
            Extension->LastCharSlot =
                Extension->InterruptReadBuffer +
                (Extension->BufferSize - 1);
            Extension->CharsInInterruptBuffer = 0;

            Extension->CurrentReadIrp->IoStatus.Information =
                IoGetCurrentIrpStackLocation(
                    Extension->CurrentReadIrp
                    )->Parameters.Read.Length;

            SerialInsertQueueDpc(
                &Extension->CompleteReadDpc,
                NULL,
                NULL,
                Extension
                );

        } else {

            //
            // Not done with the users read.
            //

            Extension->CurrentCharSlot++;

        }

    } else {

        //
        // We need to see if we reached our flow
        // control threshold.  If we have then
        // we turn on whatever flow control the
        // owner has specified.  If no flow
        // control was specified, well..., we keep
        // trying to receive characters and hope that
        // we have enough room.  Note that no matter
        // what flow control protocol we are using, it
        // will not prevent us from reading whatever
        // characters are available.
        //

        if ((Extension->HandFlow.ControlHandShake
             & SERIAL_DTR_MASK) ==
            SERIAL_DTR_HANDSHAKE) {

            //
            // If we are already doing a
            // dtr hold then we don't have
            // to do anything else.
            //

            if (!(Extension->RXHolding &
                  SERIAL_RX_DTR)) {

                if ((Extension->BufferSize -
                     Extension->HandFlow.XoffLimit)
                    <= (Extension->CharsInInterruptBuffer+1)) {

                    Extension->RXHolding |= SERIAL_RX_DTR;

                    SerialClrDTR(Extension);

                }

            }

        }

        if ((Extension->HandFlow.FlowReplace
             & SERIAL_RTS_MASK) ==
            SERIAL_RTS_HANDSHAKE) {

            //
            // If we are already doing a
            // rts hold then we don't have
            // to do anything else.
            //

            if (!(Extension->RXHolding &
                  SERIAL_RX_RTS)) {

                if ((Extension->BufferSize -
                     Extension->HandFlow.XoffLimit)
                    <= (Extension->CharsInInterruptBuffer+1)) {

                    Extension->RXHolding |= SERIAL_RX_RTS;

⌨️ 快捷键说明

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