📄 ieee1284.c
字号:
/*++
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 + -