00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00023 #include <wdm.h>
00024 #include "cbm_driver.h"
00025 #include "i_iec.h"
00026
00027 #ifdef USE_DPC
00028
00043 static VOID
00044 WaitCancelRoutine(IN PDEVICE_OBJECT Fdo, IN PIRP Irp)
00045 {
00046 PDEVICE_EXTENSION pdx;
00047
00048 FUNC_ENTER();
00049
00050 pdx = Fdo->DeviceExtension;
00051
00052
00053
00054 DBG_DPC((DBG_PREFIX "Cancelling IRP 0x%p", Irp));
00055 DBG_IRQL( == DISPATCH_LEVEL);
00056 IoReleaseCancelSpinLock(Irp->CancelIrql);
00057
00058
00059
00060
00061 DBG_IRQL( <= DISPATCH_LEVEL);
00062 KeSetEvent(&pdx->EventWaitForListener, IO_NO_INCREMENT, FALSE);
00063
00064 FUNC_LEAVE();
00065 }
00066
00067 #endif // #ifdef USE_DPC
00068
00080 VOID
00081 cbmiec_wait_for_listener(IN PDEVICE_EXTENSION Pdx, IN BOOLEAN SendEoi)
00082 {
00083 ULONG NumberOfAcks = SendEoi ? 2 : 1;
00084
00085 FUNC_ENTER();
00086
00087 PERF_EVENT_VERBOSE(0x1100, NumberOfAcks);
00088
00089
00090
00091
00092
00093
00094
00095
00096 DBG_ASSERT(CBMIEC_GET(PP_DATA_IN));
00097
00098 if (Pdx->ParallelPortAllocatedInterrupt)
00099 {
00100 LONG ret;
00101
00102
00103
00104
00105
00106
00107 PERF_EVENT_VERBOSE(0x1101, NumberOfAcks);
00108 ret = InterlockedExchange(&Pdx->IrqCount, NumberOfAcks);
00109 DBG_ASSERT(ret==0);
00110 PERF_EVENT_VERBOSE(0x1102, ret);
00111
00112
00113
00114 DBG_IRQ(("Allow Interrupts"));
00115 CBMIEC_SET(PP_LP_IRQ);
00116
00121
00122
00123 DBG_IRQ(("Release CLK_OUT"));
00124 CBMIEC_RELEASE(PP_CLK_OUT);
00125
00126 #ifdef USE_DPC
00127
00128
00129
00130
00131 PERF_EVENT_VERBOSE(0x1103, 0);
00132 DBG_VERIFY(IoSetCancelRoutine(Pdx->IrpQueue.CurrentIrp, WaitCancelRoutine) DBGDO(== NULL));
00133
00134
00135
00136 PERF_EVENT_VERBOSE(0x1104, 0);
00137 DBG_DPC((DBG_PREFIX "CALL KeWaitForSingleObject()"));
00138 KeWaitForSingleObject(&Pdx->EventWaitForListener, Executive, KernelMode, FALSE, NULL);
00139 DBG_DPC((DBG_PREFIX "RETURN from KeWaitForSingleObject()"));
00140
00141 PERF_EVENT_VERBOSE(0x1105, 0);
00142
00143
00144
00145 if (IoSetCancelRoutine(Pdx->IrpQueue.CurrentIrp, NULL) == NULL)
00146 {
00147 PERF_EVENT_VERBOSE(0x1106, -1);
00148
00149
00150
00151
00152 InterlockedExchange(&Pdx->IrqCount, 0);
00153 }
00154
00155 #else
00156
00157
00158
00159 while (!QueueShouldCancelCurrentIrp(&Pdx->IrpQueue) && Pdx->IrqCount)
00160 {
00161 cbmiec_schedule_timeout(libiec_global_timeouts.T_WaitForListener_Granu_T_H);
00162 }
00163 #endif
00164
00165 DBG_IRQ(("IrqCount = 0"));
00166
00167
00168
00169 CBMIEC_RELEASE(PP_LP_IRQ);
00170 DBG_IRQ(("No more Interrupts"));
00171 }
00172 else
00173 {
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00188 cbmiec_block_irq(Pdx);
00189
00190
00191
00192 CBMIEC_RELEASE(PP_CLK_OUT);
00193
00194
00195
00196 while (!QueueShouldCancelCurrentIrp(&Pdx->IrpQueue) && NumberOfAcks)
00197 {
00198 while (!QueueShouldCancelCurrentIrp(&Pdx->IrpQueue) && CBMIEC_GET(PP_DATA_IN))
00199 {
00200
00201 KeStallExecutionProcessor(1);
00202 }
00203
00204 if (!CBMIEC_GET(PP_DATA_IN))
00205 {
00206 if (--NumberOfAcks == 0)
00207 {
00208 CBMIEC_SET(PP_CLK_OUT);
00209 DBG_SUCCESS((DBG_PREFIX "continue to send%s EOI", SendEoi ? "" : " no"));
00210 }
00211 else
00212 {
00213 while (!QueueShouldCancelCurrentIrp(&Pdx->IrpQueue) && !CBMIEC_GET(PP_DATA_IN))
00214 {
00215
00216 KeStallExecutionProcessor(1);
00217 }
00218 }
00219 }
00220 }
00221
00222
00223
00224 cbmiec_release_irq(Pdx);
00225 }
00226
00227 PERF_EVENT_VERBOSE(0x1107, 0);
00228 FUNC_LEAVE();
00229 }