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

📄 ieee1284.c

📁 鼠标Windows驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
/*++

Copyright (C) Microsoft Corporation, 1993 - 1999

Module Name:

    ieee1284.c

Abstract:

    This module contains the code to do ieee 1284 negotiation and termination.

Author:

    Timothy T. Wells (v-timtw)          13 Mar 97
    Robbie Harris (Hewlett-Packard)     21 May 98.  Added enough comments to the
                                                    Negotation proc to keep any developer happy.

Environment:

    Kernel mode

Revision History :

--*/

#include "pch.h"

VOID
IeeeTerminate1284Mode(
    IN  PPDO_EXTENSION   Pdx
    );

NTSTATUS
IeeeEnter1284Mode(
    IN  PPDO_EXTENSION   Pdx,
    IN  UCHAR               Extensibility
    );

//
// Definition of the Forward and Reverse Protocol Arrays
//
extern FORWARD_PTCL    afpForward[] = {

    //
    // Bounded ECP (Hardware)
    //
    PptIsBecpSupported,
    PptEnterBecpMode,
    PptTerminateBecpMode,
    ParEcpHwSetAddress,
    ParEcpEnterForwardPhase,           // Enter Forward
    ParEcpHwExitForwardPhase,           // Exit Forward
    ParEcpHwWrite,
    BOUNDED_ECP,
    FAMILY_BECP,             

    //
    // ECP Hardware
    //
    ParIsEcpHwSupported,        // This is resued for both read/write
    ParEnterEcpHwMode,
    ParTerminateHwEcpMode,
    ParEcpHwSetAddress,           
    ParEcpEnterForwardPhase,  // Enter Forward
    ParEcpHwExitForwardPhase,   // Exit Forward
    ParEcpHwWrite,
    ECP_HW_NOIRQ,
    FAMILY_ECP,

    //
    // Epp Hardware
    //
    ParIsEppHwSupported,
    ParEnterEppHwMode,
    ParTerminateEppHwMode,
    ParEppSetAddress,
    NULL,                               // Enter Forward
    NULL,                               // Exit Forward
    ParEppHwWrite,
    EPP_HW,
    FAMILY_EPP,

    //
    // Epp Software
    //
    ParIsEppSwWriteSupported,
    ParEnterEppSwMode,
    ParTerminateEppSwMode,
    ParEppSetAddress,
    NULL,                               // Enter Forward
    NULL,                               // Exit Forward
    ParEppSwWrite,
    EPP_SW,
    FAMILY_EPP,

    //
    // Ecp Software
    //
    ParIsEcpSwWriteSupported,
    ParEnterEcpSwMode,
    ParTerminateEcpMode,
    ParEcpSetAddress,
    NULL,                               // Enter Forward
    NULL,                               // Exit Forward
    ParEcpSwWrite,
    ECP_SW,
    FAMILY_ECP,

    //
    // IEEE Centronics
    //
    NULL,
    ParEnterSppMode,
    ParTerminateSppMode,
    NULL,
    NULL,           // Enter Forward
    NULL,           // Exit Forward
    SppIeeeWrite,
    IEEE_COMPATIBILITY,
    FAMILY_NONE,

    //
    // Centronics
    //
    NULL,
    ParEnterSppMode,
    ParTerminateSppMode,
    NULL,
    NULL,           // Enter Forward
    NULL,           // Exit Forward
    SppWrite,
    CENTRONICS,
    FAMILY_NONE,

    //
    // None...
    //
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,           // Enter Forward
    NULL,           // Exit Forward
    NULL,
    NONE,
    FAMILY_NONE
};

extern REVERSE_PTCL    arpReverse[] = {

    //
    // Bounded Ecp Mode
    //
    PptIsBecpSupported,
    PptEnterBecpMode,
    PptTerminateBecpMode,
    NULL,                       // Violates IEEE 1284.3 to set Reverse address for BECP
    PptEcpHwEnterReversePhase,   // Enter Reverse
    PptBecpExitReversePhase,     // Exit Reverse
    PptEcpHwDrainShadowBuffer,  // A read from Cached data
    PptEcpHwHaveReadData,         // Quick peek to see if Periph has reverse data without flipping the bus
                                // NOTE: This is crucial since it violates the 1284.3 BECP to flip
                                // blindly into reverse if the peripheral doesn't have data.
    PptBecpRead,
    BOUNDED_ECP,
    FAMILY_BECP,             

    //
    // Hardware Ecp Mode
    //
    ParIsEcpHwSupported,        // This is resued for both read/write
    ParEnterEcpHwMode,
    ParTerminateHwEcpMode,
    ParEcpHwSetAddress,           // Reuse the one in ecp.c
    PptEcpHwEnterReversePhase,  // Enter Reverse
    ParEcpHwExitReversePhase,   // Exit Reverse
    PptEcpHwDrainShadowBuffer,  // A read from Cached data
    PptEcpHwHaveReadData,       // Quick peek to see if Periph has reverse data without flipping the bus
    ParEcpHwRead,
    ECP_HW_NOIRQ,
    FAMILY_ECP,

    //
    // Epp Hardware
    //
    ParIsEppHwSupported,            // This is resued for both read/write
    ParEnterEppHwMode,
    ParTerminateEppHwMode,
    ParEppSetAddress,
    NULL,           // Enter Reverse
    NULL,           // Exit Reverse
    NULL,           // A read from Cached data
    NULL,           // Quick peek to see if Periph has reverse data without flipping the bus
    ParEppHwRead,
    EPP_HW,
    FAMILY_EPP,

    //
    // Epp Software Mode
    //
    ParIsEppSwReadSupported,
    ParEnterEppSwMode,
    ParTerminateEppSwMode,
    ParEppSetAddress,
    NULL,           // Enter Reverse
    NULL,           // Exit Reverse
    NULL,           // A read from Cached data
    NULL,           // Quick peek to see if Periph has reverse data without flipping the bus
    ParEppSwRead,
    EPP_SW,
    FAMILY_EPP,

    //
    // Ecp Software Mode
    //
    ParIsEcpSwReadSupported,
    ParEnterEcpSwMode,
    ParTerminateEcpMode,
    ParEcpSetAddress,
    ParEcpForwardToReverse,             // Enter Reverse
    ParEcpReverseToForward,             // Exit Reverse
    NULL,                               // A read from Cached data
    ParEcpHaveReadData,                 // Quick peek to see if Periph has reverse data without flipping the bus
    ParEcpSwRead,
    ECP_SW,
    FAMILY_ECP,

    //
    // Byte Mode
    //
    ParIsByteSupported,
    ParEnterByteMode,
    ParTerminateByteMode,
    NULL,
    NULL,           // Enter Reverse
    NULL,           // Exit Reverse
    NULL,           // A read from Cached data
    NULL,           // Quick peek to see if Periph has reverse data without flipping the bus
    ParByteModeRead,
    BYTE_BIDIR,
    FAMILY_REVERSE_BYTE,

    //
    // Nibble Mode
    //
    ParIsNibbleSupported,
    ParEnterNibbleMode,
    ParTerminateNibbleMode,
    NULL,
    NULL,           // Enter Reverse
    NULL,           // Exit Reverse
    NULL,           // A read from Cached data
    NULL,           // Quick peek to see if Periph has reverse data without flipping the bus
    ParNibbleModeRead,
    NIBBLE,
    FAMILY_REVERSE_NIBBLE,

    //
    // Channelized Nibble Mode
    //
    ParIsChannelizedNibbleSupported,
    ParEnterChannelizedNibbleMode,
    ParTerminateNibbleMode,
    NULL,
    NULL,           // Enter Reverse
    NULL,           // Exit Reverse
    NULL,           // A read from Cached data
    NULL,           // Quick peek to see if Periph has reverse data without flipping the bus
    ParNibbleModeRead,
    CHANNEL_NIBBLE,
    FAMILY_REVERSE_NIBBLE,
    
    //
    // None...
    //
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,           // Enter Reverse
    NULL,           // Exit Reverse
    NULL,           // A read from Cached data
    NULL,           // Quick peek to see if Periph has reverse data without flipping the bus
    NULL,
    NONE,
    FAMILY_NONE
};


VOID
IeeeTerminate1284Mode(
    IN  PPDO_EXTENSION   Pdx
    )

/*++

Routine Description:

    This routine terminates the interface back to compatibility mode.

Arguments:

    Controller  - Supplies the parallel port's controller address.

Return Value:

    None.

--*/

{
    PUCHAR Controller;
    PUCHAR wPortDCR;
    UCHAR  dcr, dsrMask, dsrValue;
    BOOLEAN bXFlag;
    BOOLEAN bUseXFlag = FALSE;

    Controller = Pdx->Controller;
    wPortDCR = Controller + OFFSET_DCR;
    dcr = P5ReadPortUchar(wPortDCR);

    if( PHASE_TERMINATE == Pdx->CurrentPhase )	{
        // We are already terminated.  This will fail if we don't
        // just bypass this mess.
        goto Terminate_ExitLabel;
    }

    // Keep Negotiated XFLAG to use for termination.
    //    xFlag,  // Technically we should have
    // cached this value from state
    // 6 of nego. This peripheral's XFlag
    // at pre state 22 should be the
    // same as state 6.
    bXFlag = P5ReadPortUchar(Controller + OFFSET_DSR) & 0x10;

    // REVISIT: Do we need to ensure the preceeding state is a valid
    //          state to terminate from.  In other words, is there there
    //          a black bar on the 1284 line for that state?


    // =============== Host State 22 Termination ===============8
    //  DIR                         = Don't Care (Possibly Low)
    //  IRQEN                       = Don't Care (Possibly Low)
    //  1284/SelectIn               = Low (Signals state 22)
    //  nReverseReq/**(ECP only)    = Don't Care (High for ECP, otherwise unused)
    //  HostAck/HostBusy/nAutoFeed  = High
    //  HostClk/nStrobe             = High
    //
    Pdx->CurrentEvent = 22;
    dcr = P5ReadPortUchar(wPortDCR);
    dcr = UPDATE_DCR(dcr, DONT_CARE, DONT_CARE, INACTIVE, DONT_CARE, ACTIVE, ACTIVE);

    //
    // Some devices start working if we add a delay here - no idea why
    // this works
    //
    // Make the delay configurable via registry setting so that devices that
    //   don't need this delay aren't penalized
    //
    if( Pdx->Event22Delay != 0 ) {
        if( Pdx->Event22Delay > 1000 ) {
            Pdx->Event22Delay = 1000;
        }
        KeStallExecutionProcessor( Pdx->Event22Delay );
    }

    P5WritePortUchar(wPortDCR, dcr);

    // Clear data lines so we don't have any random spew.
    P5WritePortUchar(Controller + OFFSET_DATA, 0);

    // *************** Periph State 23/24 Termination ***************8
    // PeriphAck/PtrBusy        = High  (Signals state 23 for ECP
    //                                   otherwise already high)
    // PeriphClk/PtrClk         = Low   (Signals state 24 for ecp
    //                                   Signals state 23 for Nibble)
    // nAckRev/AckDataReq/PE    = Don't Care
    // XFlag                    = Low  (ECP and Byte)   (State 24)
    //                          = High (Nibble)         (State 24)
    //                          = Low (All DeviceID Requests including Nibble) (State 24)
    //                          = Undefined (EPP)
    // nPeriphReq/nDataAvail    = High
    //                            Don't check nPeriphReq/nDataAvail
    //                            Since it was in a "Don't Care"
    //                            state (ie. Double bar in the spec)
    //                            until state 23 for ECP mode.
    if( Pdx->CurrentPhase == PHASE_REVERSE_IDLE || Pdx->CurrentPhase == PHASE_REVERSE_XFER) {

        // We must be in Nibble Reverse.  Let's double check!!!
        if( FAMILY_REVERSE_NIBBLE == arpReverse[Pdx->IdxReverseProtocol].ProtocolFamily ||
            FAMILY_REVERSE_BYTE   == arpReverse[Pdx->IdxReverseProtocol].ProtocolFamily )
            bUseXFlag = TRUE;   // We're in Nibble or Byte
        else
            bUseXFlag = FALSE;   // Don't know what mode we are in?

    } else {

        if (FAMILY_BECP == afpForward[Pdx->IdxForwardProtocol].ProtocolFamily ||
            FAMILY_ECP  == afpForward[Pdx->IdxForwardProtocol].ProtocolFamily )
            bUseXFlag = TRUE;   // We're in an ECP Flavor
        else
            bUseXFlag = FALSE;   // Don't know what mode we are in?
    }

    if( bUseXFlag ) {

        dsrMask = DSR_TEST_MASK( DONT_CARE, INACTIVE, DONT_CARE, bXFlag ? INACTIVE : ACTIVE, DONT_CARE );
        dsrValue = DSR_TEST_VALUE( DONT_CARE, INACTIVE, DONT_CARE, bXFlag ? INACTIVE : ACTIVE, DONT_CARE );

    } else {

        dsrMask = DSR_TEST_MASK( DONT_CARE, INACTIVE, DONT_CARE, DONT_CARE, DONT_CARE );
        dsrValue = DSR_TEST_VALUE( DONT_CARE, INACTIVE, DONT_CARE, DONT_CARE, DONT_CARE );
    }

    Pdx->CurrentEvent = 23;

    if( !CheckPort(Controller + OFFSET_DSR, dsrMask, dsrValue, IEEE_MAXTIME_TL)) {
        // We couldn't negotiate back to compatibility mode.
        // just terminate.
        DD((PCE)Pdx,DDW,"IeeeTerminate1284Mode:State 23/24 Failed: Controller %x dsr %x dcr %x\n",
           Controller, P5ReadPortUchar(Controller + OFFSET_DSR), dcr);
        goto Terminate_ExitLabel;
    }

    // =============== Host State 25 Termination ===============8
    //  DIR                         = Don't Care (Possibly Low)
    //  IRQEN                       = Don't Care (Possibly Low)
    //  1284/SelectIn               = Low
    //  nReverseReq/**(ECP only)    = Don't Care (Possibly High)
    //  HostAck/HostBusy/nAutoFeed  = Low (Signals State 25)
    //  HostClk/nStrobe             = High
    //
    Pdx->CurrentEvent = 25;
    dcr = UPDATE_DCR(dcr, DONT_CARE, DONT_CARE, INACTIVE, DONT_CARE, INACTIVE, ACTIVE);
    P5WritePortUchar(wPortDCR, dcr);

    // =============== State 26 Termination ===============8
    // Do nothing for state 26

    // =============== Periph State 27 Termination ===============8
    // PeriphAck/PtrBusy        = High
    // PeriphClk/PtrClk         = High   (Signals State 27)
    // nAckRev/AckDataReq/PE    = Don't Care  (Invalid from State 23)
    // XFlag                    = Don't Care (All Modes)   (Invlaid at State 27)
    // nPeriphReq/nDataAvial    = Don't Care (Invalid from State 26)
    // dvrh 6/16/97
    Pdx->CurrentEvent = 27;
    if( !CHECK_DSR(Controller, ACTIVE, ACTIVE, DONT_CARE, DONT_CARE, DONT_CARE, IEEE_MAXTIME_TL) ) {
        DD((PCE)Pdx,DDW,"IeeeTerminate1284Mode:State 27 Failed: Controller %x dsr %x dcr %x\n", 

⌨️ 快捷键说明

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