Exemple #1
0
/*! \brief Write some bytes to the IEC bus

 \param Pdx
   Pointer to the device extension.

 \param Buffer
   Pointer to a buffer where the read bytes are written to.

 \param Size
   Maximum number of characters to read from the bus.

 \param Written
   Pointer to the variable which will hold the number of written bytes.

 \return 
   If the routine succeeds, it returns STATUS_SUCCESS. Otherwise, it
   returns one of the error status values.

 ATN is released on return of this routine
*/
NTSTATUS
cbmiec_raw_write(IN PDEVICE_EXTENSION Pdx, 
                 IN const PUCHAR Buffer, IN ULONG Size, 
                 OUT ULONG *Written)
{
    NTSTATUS ntStatus;

#if DBG
    unsigned i;
#endif

    FUNC_ENTER();

    PERF_EVENT_VERBOSE(0x1000, 0);

    FUNC_PARAM((DBG_PREFIX "Buffer = 0x%p, Size = 0x%04x", Buffer, Size));

#if DBG
    for (i=0;i<Size;i++)
    {
        FUNC_PARAM((DBG_PREFIX "   output %2u: 0x%02x '%c'", i, (unsigned int) Buffer[i], (UCHAR) Buffer[i]));
    }
#endif

    PERF_EVENT_VERBOSE(0x1001, 0);

    ntStatus = cbmiec_i_raw_write(Pdx, Buffer, Size, Written, 0, 0);

    PERF_EVENT_VERBOSE(0x1002, 0);

    FUNC_LEAVE_NTSTATUS(ntStatus);
}
Exemple #2
0
/*! \brief Wait until listener is ready to receive

 This function waits until a listener is ready.

 \param Pdx
   Pointer to the device extension.

 \param SendEoi
   TRUE if we want to signal an EOI.
   FALSE otherwise.
*/
VOID
cbmiec_wait_for_listener(IN PDEVICE_EXTENSION Pdx, IN BOOLEAN SendEoi)
{
    ULONG NumberOfAcks = SendEoi ? 2 : 1;

    FUNC_ENTER();

    PERF_EVENT_VERBOSE(0x1100, NumberOfAcks);

    // This function has two incarnations. The first one
    // is used if we have successfully allocated the interrupt.
    // In this case, we just wait until the ISR has done the
    // essential work

    // When entering this function, DATA_IN should not be active

    DBG_ASSERT(CBMIEC_GET(PP_DATA_IN));

    if (Pdx->ParallelPortAllocatedInterrupt)
    {
        LONG ret;

        // This is implementation 1. It needs a working
        // ISR. The main work is done there

        // Tell the ISR how many interrupts to wait for

        PERF_EVENT_VERBOSE(0x1101, NumberOfAcks);
        ret = InterlockedExchange(&Pdx->IrqCount, NumberOfAcks);
        DBG_ASSERT(ret==0);
        PERF_EVENT_VERBOSE(0x1102, ret);

        // in the sequel, allow interrupts to occur

        DBG_IRQ(("Allow Interrupts"));
        CBMIEC_SET(PP_LP_IRQ);

        /*! \todo Shouldn't we make sure that there
         * is no spurious interrupt until now?
         */

        // Give the LISTENer the sign: We want to send something

        DBG_IRQ(("Release CLK_OUT"));
        CBMIEC_RELEASE(PP_CLK_OUT);

#ifdef USE_DPC

        // set the cancel routine which will wake us up if we do not get
        // an IRQ, and a cancellation is requested

        PERF_EVENT_VERBOSE(0x1103, 0);
        DBG_VERIFY(IoSetCancelRoutine(Pdx->IrpQueue.CurrentIrp, WaitCancelRoutine) DBGDO(== NULL));

        // Now, wait until we have been signalled

        PERF_EVENT_VERBOSE(0x1104, 0);
        DBG_DPC((DBG_PREFIX "CALL KeWaitForSingleObject()"));
        KeWaitForSingleObject(&Pdx->EventWaitForListener, Executive, KernelMode, FALSE, NULL);
        DBG_DPC((DBG_PREFIX "RETURN from KeWaitForSingleObject()"));

        PERF_EVENT_VERBOSE(0x1105, 0);

        // we do not need the cancel routine anymore:

        if (IoSetCancelRoutine(Pdx->IrpQueue.CurrentIrp, NULL) == NULL)
        {
            PERF_EVENT_VERBOSE(0x1106, -1);
            // the cancel routine was called!

            // Make sure the IrqCount is resetted to zero.

            InterlockedExchange(&Pdx->IrqCount, 0);
        }

#else

        // Wait until the listener has told us that it is able to listen

        while (!QueueShouldCancelCurrentIrp(&Pdx->IrpQueue) && Pdx->IrqCount)
        {
            cbmiec_schedule_timeout(libiec_global_timeouts.T_WaitForListener_Granu_T_H);
        }
#endif

        DBG_IRQ(("IrqCount = 0"));

        // from here on, no interrupts will be generated anymore

        CBMIEC_RELEASE(PP_LP_IRQ);
        DBG_IRQ(("No more Interrupts"));
    }