|
|
/*++
Module Name:
isr.c
Environment:
Kernel mode
Revision History :
--*/
#include "precomp.h"
BOOLEAN MoxaISR( IN PKINTERRUPT InterruptObject, IN PVOID Context ) {
PMOXA_GLOBAL_DATA globalData; PMOXA_DEVICE_EXTENSION extension; USHORT boardNo, port, portNo, temp; PUSHORT ip; PIO_STACK_LOCATION irpSp; UCHAR ack; BOOLEAN servicedAnInterrupt = FALSE; BOOLEAN thisPassServiced; PLIST_ENTRY firstInterruptEntry = Context; PLIST_ENTRY interruptEntry; PMOXA_MULTIPORT_DISPATCH dispatch;
MoxaIRQok = TRUE; if (!firstInterruptEntry) return (servicedAnInterrupt);
MoxaKdPrint(MX_DBG_TRACE_ISR,("Enter ISR(first=%x)\n",firstInterruptEntry)); if (IsListEmpty(firstInterruptEntry)) return (servicedAnInterrupt);
do { thisPassServiced = FALSE; interruptEntry = firstInterruptEntry->Flink;
do {
PMOXA_CISR_SW cisrsw = CONTAINING_RECORD( interruptEntry, MOXA_CISR_SW, SharerList ); MoxaKdPrint(MX_DBG_TRACE_ISR,("CISRSW=%x\n",cisrsw));
if (!cisrsw) return (servicedAnInterrupt); dispatch = &cisrsw->Dispatch; globalData = dispatch->GlobalData; boardNo = (USHORT)dispatch->BoardNo; if (!globalData || boardNo < 0) return (servicedAnInterrupt); MoxaKdPrint(MX_DBG_TRACE_ISR,("Board=%d,Pending=%x,IntIndx=%x,BoardReady=%d\n", boardNo, *globalData->IntPend[boardNo], *globalData->IntNdx[boardNo], globalData->BoardReady[boardNo] )); if (globalData->PciIntAckBase[boardNo]) { ack = READ_PORT_UCHAR(globalData->PciIntAckBase[boardNo]); MoxaKdPrint(MX_DBG_TRACE_ISR,("Ack Interrupt%d/%x/%x\n",boardNo,globalData->PciIntAckBase[boardNo],ack)); ack |= 4; WRITE_PORT_UCHAR(globalData->PciIntAckBase[boardNo],ack);
}
if ((globalData->BoardReady[boardNo] == TRUE) &&(*globalData->IntPend[boardNo] == 0xff) &&((*globalData->IntNdx[boardNo] == 0)||( *globalData->IntNdx[boardNo]==0x80)) ) {
servicedAnInterrupt = TRUE; thisPassServiced = TRUE;
ip = (PUSHORT)(globalData->IntTable[boardNo] + *globalData->IntNdx[boardNo]);
for (port=0; port<globalData->NumPorts[boardNo]; port++) {
portNo = boardNo * MAXPORT_PER_CARD + port; if (!(extension = globalData->Extension[portNo])) continue;
if ((temp = ip[extension->PortIndex]) != 0) {
ip[extension->PortIndex] = 0; if ((!extension->DeviceIsOpened) || (extension->PowerState != PowerDeviceD0)) continue;
if (temp & (IntrTx | IntrTxTrigger)) { if (extension->WriteLength) {
if (!extension->IsrOutFlag) { extension->IsrOutFlag = 1; MoxaInsertQueueDpc( &extension->IsrOutDpc, NULL, NULL, extension );
} } else if (*(PSHORT)(extension->PortOfs + HostStat) & (WakeupTx|WakeupTxTrigger)) {
*(PSHORT)(extension->PortOfs + HostStat) &= ~(WakeupTx|WakeupTxTrigger);
irpSp = IoGetCurrentIrpStackLocation( extension->CurrentWriteIrp); extension->CurrentWriteIrp->IoStatus.Information = irpSp->Parameters.Write.Length; MoxaInsertQueueDpc( &extension->CompleteWriteDpc, NULL, NULL, extension );
} }
if (temp & IntrRxTrigger) { if (extension->ReadLength) {
if (!extension->IsrInFlag) { extension->IsrInFlag = 1; MoxaInsertQueueDpc( &extension->IsrInDpc, NULL, NULL, extension );
} } }
if (temp & IntrRx) {
if (extension->IsrWaitMask & SERIAL_EV_RXCHAR) extension->HistoryMask |= SERIAL_EV_RXCHAR; }
if (temp & IntrEvent) { if (extension->IsrWaitMask & SERIAL_EV_RXFLAG) extension->HistoryMask |= SERIAL_EV_RXFLAG; }
if (temp & IntrRx80Full) {
if (extension->IsrWaitMask & SERIAL_EV_RX80FULL) extension->HistoryMask |= SERIAL_EV_RX80FULL; }
if (temp & IntrBreak) { extension->ErrorWord |= SERIAL_ERROR_BREAK; if (extension->IsrWaitMask & SERIAL_EV_BREAK) extension->HistoryMask |= SERIAL_EV_BREAK; if (extension->HandFlow.ControlHandShake & SERIAL_ERROR_ABORT) { MoxaInsertQueueDpc( &extension->CommErrorDpc, NULL, NULL, extension );
} }
if (temp & IntrLine) {
//
// 9-24-01 by William
//
#if 0
MoxaInsertQueueDpc( &extension->IntrLineDpc, NULL, NULL, extension ); #endif
USHORT modemStatus;
MoxaFuncGetLineStatus( extension->PortOfs, &modemStatus ); if (extension->IsrWaitMask & (SERIAL_EV_CTS | SERIAL_EV_DSR | SERIAL_EV_RLSD)) { USHORT change;
change = modemStatus ^ extension->ModemStatus; if ((change & LSTATUS_CTS) && (extension->IsrWaitMask & SERIAL_EV_CTS)) extension->HistoryMask |= SERIAL_EV_CTS; if ((change & LSTATUS_DSR) && (extension->IsrWaitMask & SERIAL_EV_DSR)) extension->HistoryMask |= SERIAL_EV_DSR; if ((change & LSTATUS_DCD) && (extension->IsrWaitMask & SERIAL_EV_RLSD)) extension->HistoryMask |= SERIAL_EV_RLSD; }
extension->ModemStatus = modemStatus;
// end
}
if (temp & IntrError) { //
// 9-24-01 by William
//
#if 0
MoxaInsertQueueDpc( &extension->IntrErrorDpc, NULL, NULL, extension ); #endif
USHORT dataError;
MoxaFuncGetDataError( extension->PortOfs, &dataError );
if ( dataError & SERIAL_ERROR_QUEUEOVERRUN ) { extension->PerfStats.BufferOverrunErrorCount++; } if (dataError & SERIAL_ERROR_OVERRUN) { extension->PerfStats.SerialOverrunErrorCount++; } if (dataError & SERIAL_ERROR_PARITY) { extension->PerfStats.ParityErrorCount++; } if (dataError & SERIAL_ERROR_FRAMING) { extension->PerfStats.FrameErrorCount++; } extension->ErrorWord |= (dataError & (SERIAL_ERROR_OVERRUN | SERIAL_ERROR_PARITY | SERIAL_ERROR_FRAMING | SERIAL_ERROR_QUEUEOVERRUN));
if (extension->IsrWaitMask & SERIAL_EV_ERR) {
if (dataError & (SERIAL_ERROR_OVERRUN | SERIAL_ERROR_PARITY | SERIAL_ERROR_FRAMING)) extension->HistoryMask |= SERIAL_EV_ERR; } if (extension->HandFlow.ControlHandShake & SERIAL_ERROR_ABORT) { MoxaInsertQueueDpc( &extension->CommErrorDpc, NULL, NULL, extension );
} // end
} if (extension->IrpMaskLocation && extension->HistoryMask) { *extension->IrpMaskLocation = extension->HistoryMask; extension->IrpMaskLocation = NULL; extension->HistoryMask = 0; extension->CurrentWaitIrp->IoStatus.Information = sizeof(ULONG); MoxaInsertQueueDpc( &extension->CommWaitDpc, NULL, NULL, extension );
} }
}
*globalData->IntPend[boardNo] = 0;
} interruptEntry = interruptEntry->Flink; servicedAnInterrupt |= thisPassServiced;
} while (interruptEntry != firstInterruptEntry); } while (thisPassServiced == TRUE);
MoxaKdPrint(MX_DBG_TRACE_ISR,("Exit ISR\n")); return (servicedAnInterrupt);
}
VOID MoxaIsrIn( IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemContext1, IN PVOID SystemContext2 ) {
PMOXA_DEVICE_EXTENSION extension = DeferredContext; KIRQL oldIrql;
IoAcquireCancelSpinLock(&oldIrql);
KeSynchronizeExecution( extension->Interrupt, MoxaIsrGetData, extension );
IoReleaseCancelSpinLock(oldIrql); MoxaDpcEpilogue(extension, Dpc); }
BOOLEAN MoxaIsrGetData( IN PVOID Context ) { PMOXA_DEVICE_EXTENSION extension = Context; PIO_STACK_LOCATION irpSp; USHORT max;
if (extension->ReadLength) {
extension->NumberNeededForRead = extension->ReadLength;
MoxaGetData(extension);
extension->ReadLength = extension->NumberNeededForRead;
if (!extension->ReadLength) { *(PSHORT)(extension->PortOfs + HostStat) &= ~WakeupRxTrigger;
irpSp = IoGetCurrentIrpStackLocation( extension->CurrentReadIrp); extension->CurrentReadIrp->IoStatus.Information = irpSp->Parameters.Read.Length;
extension->CountOnLastRead = MOXA_COMPLETE_READ_COMPLETE;
MoxaInsertQueueDpc( &extension->CompleteReadDpc, NULL, NULL, extension ); } else { /* 8-14-01 by William
max = *(PUSHORT)(extension->PortOfs + RX_mask) - 128; */ max = *(PUSHORT)(extension->PortOfs + RX_mask) - RX_offset;
if (extension->NumberNeededForRead > max)
*(PUSHORT)(extension->PortOfs + Rx_trigger) = max;
else *(PUSHORT)(extension->PortOfs + Rx_trigger) = (USHORT)extension->NumberNeededForRead; *(PSHORT)(extension->PortOfs + HostStat) |= WakeupRxTrigger;
} }
extension->IsrInFlag = 0;
return FALSE; }
VOID MoxaIsrOut( IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemContext1, IN PVOID SystemContext2 ) {
PMOXA_DEVICE_EXTENSION extension = DeferredContext; KIRQL oldIrql;
IoAcquireCancelSpinLock(&oldIrql);
KeSynchronizeExecution( extension->Interrupt, MoxaIsrPutData, extension );
IoReleaseCancelSpinLock(oldIrql); MoxaDpcEpilogue(extension, Dpc); }
BOOLEAN MoxaIsrPutData( IN PVOID Context ) { PMOXA_DEVICE_EXTENSION extension = Context;
if (extension->WriteLength)
MoxaPutData(extension);
extension->IsrOutFlag = 0;
return FALSE; }
VOID MoxaIntrLine( IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemContext1, IN PVOID SystemContext2 ) {
PMOXA_DEVICE_EXTENSION extension = DeferredContext; KIRQL oldIrql; PUCHAR ofs = extension->PortOfs; USHORT modemStatus;
MoxaFuncGetLineStatus( ofs, &modemStatus ); if (extension->IsrWaitMask & (SERIAL_EV_CTS | SERIAL_EV_DSR | SERIAL_EV_RLSD)) { USHORT change;
change = modemStatus ^ extension->ModemStatus; if ((change & LSTATUS_CTS) && (extension->IsrWaitMask & SERIAL_EV_CTS)) extension->HistoryMask |= SERIAL_EV_CTS; if ((change & LSTATUS_DSR) && (extension->IsrWaitMask & SERIAL_EV_DSR)) extension->HistoryMask |= SERIAL_EV_DSR; if ((change & LSTATUS_DCD) && (extension->IsrWaitMask & SERIAL_EV_RLSD)) extension->HistoryMask |= SERIAL_EV_RLSD; }
extension->ModemStatus = modemStatus;
IoAcquireCancelSpinLock(&oldIrql);
if (extension->IrpMaskLocation && extension->HistoryMask) {
*extension->IrpMaskLocation = extension->HistoryMask; extension->IrpMaskLocation = NULL; extension->HistoryMask = 0; extension->CurrentWaitIrp->IoStatus.Information = sizeof(ULONG); MoxaInsertQueueDpc( &extension->CommWaitDpc, NULL, NULL, extension );
}
IoReleaseCancelSpinLock(oldIrql); MoxaDpcEpilogue(extension, Dpc); }
VOID MoxaIntrError( IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemContext1, IN PVOID SystemContext2 ) {
PMOXA_DEVICE_EXTENSION extension = DeferredContext; KIRQL oldIrql; PUCHAR ofs = extension->PortOfs; USHORT dataError;
KeAcquireSpinLock( &extension->ControlLock, &oldIrql );
MoxaFuncGetDataError( ofs, &dataError );
KeReleaseSpinLock( &extension->ControlLock, oldIrql );
if ( dataError & SERIAL_ERROR_QUEUEOVERRUN ) { extension->PerfStats.BufferOverrunErrorCount++; } if (dataError & SERIAL_ERROR_OVERRUN) { extension->PerfStats.SerialOverrunErrorCount++; } if (dataError & SERIAL_ERROR_PARITY) { extension->PerfStats.ParityErrorCount++; } if (dataError & SERIAL_ERROR_FRAMING) { extension->PerfStats.FrameErrorCount++; } extension->ErrorWord |= (dataError & (SERIAL_ERROR_OVERRUN | SERIAL_ERROR_PARITY | SERIAL_ERROR_FRAMING | SERIAL_ERROR_QUEUEOVERRUN));
if (extension->IsrWaitMask & SERIAL_EV_ERR) {
if (dataError & (SERIAL_ERROR_OVERRUN | SERIAL_ERROR_PARITY | SERIAL_ERROR_FRAMING)) extension->HistoryMask |= SERIAL_EV_ERR; }
if (extension->HandFlow.ControlHandShake & SERIAL_ERROR_ABORT) { MoxaInsertQueueDpc( &extension->CommErrorDpc, NULL, NULL, extension );
}
IoAcquireCancelSpinLock(&oldIrql);
if (extension->IrpMaskLocation && extension->HistoryMask) {
*extension->IrpMaskLocation = extension->HistoryMask; extension->IrpMaskLocation = NULL; extension->HistoryMask = 0; extension->CurrentWaitIrp->IoStatus.Information = sizeof(ULONG); MoxaInsertQueueDpc( &extension->CommWaitDpc, NULL, NULL, extension );
} IoReleaseCancelSpinLock(oldIrql); MoxaDpcEpilogue(extension, Dpc); }
|