📄 chipmode.c
字号:
// Read the ECR again
ecr = P5ReadPortUchar( wPortECR );
// Now test the ECR snapshot to see if the FIFO status is correct. The FIFO
// should test empty.
if (!TEST_ECR_FIFO( ecr, ECR_FIFO_EMPTY ) )
{
// Restore the DCR so that all lines are inactive.
dcr = SET_DCR( DIR_WRITE, IRQEN_DISABLE, INACTIVE, ACTIVE, ACTIVE, ACTIVE );
P5WritePortUchar( wPortDCR, dcr );
return;
}
// OK, it looks very promising. Perform a couple of additional tests that
// will give us a lot of confidence, as well as providing some information
// we need about the ECP chip.
// return ecr to original
P5WritePortUchar(wPortECR, ecrLast);
//
// Test here for ECP capable
//
// get value from ECR reg & save it
ecrLast = P5ReadPortUchar( wPortECR );
ecr = (UCHAR)(ecrLast & ECR_MODE_MASK);
// Put the chip into test mode; the FIFO should start out empty
P5WritePortUchar(wPortECR, (UCHAR)(ecr | ECR_TEST_MODE) );
PptDetermineFifoWidth(Fdx);
if( 0 != Fdx->PnpInfo.FifoWidth) {
Fdx->PnpInfo.HardwareCapabilities |= PPT_ECP_PRESENT;
PptDetermineFifoDepth( Fdx );
if( 0 == Fdx->PnpInfo.FifoDepth ) {
// Probe for FIFO depth failed - mark ECP as bad chip mode
Fdx->PnpInfo.HardwareCapabilities &= ~(PPT_ECP_PRESENT);
}
}
// return ecr to original
P5WritePortUchar( wPortECR, ecrLast );
return;
}
VOID
PptDetectEppPortIfDot3DevicePresent(
IN PFDO_EXTENSION Fdx
)
/*++
Routine Description:
If a 1284.3 daisy chain device is present, use the dot3 device to screen
any printer from signal leakage while doing EPP detection. Otherwise
abort detection.
Arguments:
Fdx - Supplies the device extension of the device we are
reporting resources for.
Return Value:
None.
--*/
{
NTSTATUS status;
PUCHAR Controller = Fdx->PortInfo.Controller;
PARALLEL_1284_COMMAND Command;
if( 0 == Fdx->PnpInfo.Ieee1284_3DeviceCount ) {
// No dot3 DC device present - aborting - unsafe for some printers if we check for EPP here
return;
}
//
// 1284.3 daisy chain device is present. Use device to screen printer from
// possible signal leakage.
//
//
// Select 1284.3 daisy chain device
//
Command.ID = 0;
Command.Port = 0;
Command.CommandFlags = PAR_HAVE_PORT_KEEP_PORT;
status = PptTrySelectDevice( Fdx, &Command );
if( !NT_SUCCESS( status ) ) {
// unable to select device - something is wrong - just bail out
return;
}
//
// do the detection for chipset EPP capability
//
// DOT3 Device Present and selected
PptDetectEppPort( Fdx );
//
// Deselect 1284.3 daisy chain device
//
Command.ID = 0;
Command.Port = 0;
Command.CommandFlags = PAR_HAVE_PORT_KEEP_PORT;
status = PptDeselectDevice( Fdx, &Command );
if( !NT_SUCCESS( status ) ) {
// deselect failed??? - this shouldn't happen - our daisy chain interface is likely hung
DD((PCE)Fdx,DDE,"PptDetectEppPort - deselect of 1284.3 device FAILED - Controller=%x\n", Controller);
}
return;
}
VOID
PptDetectEppPortIfUserRequested(
IN PFDO_EXTENSION Fdx
)
/*++
Routine Description:
If user explicitly requested Generic EPP detection then do the check.
Arguments:
Fdx - Supplies the device extension of the device we are
reporting resources for.
Return Value:
None.
--*/
{
ULONG RequestEppTest = 0;
PptRegGetDeviceParameterDword( Fdx->PhysicalDeviceObject, (PWSTR)L"RequestEppTest", &RequestEppTest );
if( RequestEppTest ) {
DD((PCE)Fdx,DDT,"-- User Requested EPP detection - %x\n", RequestEppTest);
PptDetectEppPort( Fdx );
} else {
DD((PCE)Fdx,DDT,"-- User did not request EPP detection\n");
}
return;
}
VOID
PptDetectEppPort(
IN PFDO_EXTENSION Fdx
)
/*++
Routine Description:
This routine checks for EPP capable port after ECP was found.
Arguments:
Fdx - Supplies the device extension of the device we are
reporting resources for.
Return Value:
None.
--*/
{
PUCHAR Controller;
UCHAR dcr, i;
UCHAR Reverse = (UCHAR)(DCR_DIRECTION | DCR_NOT_INIT | DCR_AUTOFEED | DCR_DSTRB);
UCHAR Forward = (UCHAR)(DCR_NOT_INIT | DCR_AUTOFEED | DCR_DSTRB);
ASSERTMSG(FALSE, "PptDetectEppPort shouldn't be called in current driver version");
DD((PCE)Fdx,DDT,"-- PptDetectEppPort - Enter\n");
DD((PCE)Fdx,DDT,"ParMode::PptDetectEppPort: Enter\n");
Controller = Fdx->PortInfo.Controller;
// Get current DCR
dcr = P5ReadPortUchar( Controller + DCR_OFFSET );
//
// Temporarily set capability to true to bypass PptEcrSetMode validity
// check. We'll clear the flag before we return if EPP test fails.
//
Fdx->PnpInfo.HardwareCapabilities |= PPT_EPP_PRESENT;
// Setting EPP mode
DD((PCE)Fdx,DDT,"ParMode::PptDetectEppPort: Setting EPP Mode\n");
PptEcrSetMode( Fdx, ECR_EPP_PIO_MODE );
//
// Testing the hardware for EPP capable
//
for ( i = 0x01; i <= 0x02; i++ ) {
// Put it into reverse phase so it doesn't talk to a device
P5WritePortUchar( Controller + DCR_OFFSET, Reverse );
KeStallExecutionProcessor( 5 );
P5WritePortUchar( Controller + EPP_OFFSET, (UCHAR)i );
// put it back into forward phase to read the byte we put out there
P5WritePortUchar( Controller + DCR_OFFSET, Forward );
KeStallExecutionProcessor( 5 );
if ( P5ReadPortUchar( Controller ) != i ) {
// failure so clear EPP flag
Fdx->PnpInfo.HardwareCapabilities &= ~PPT_EPP_PRESENT;
break;
}
}
// Clearing EPP Mode
PptEcrClearMode( Fdx );
// Restore DCR
P5WritePortUchar( Controller + DCR_OFFSET, dcr );
Fdx->CheckedForGenericEpp = TRUE; // check is complete
if( Fdx->PnpInfo.HardwareCapabilities & PPT_EPP_PRESENT ) {
DD((PCE)Fdx,DDT,"ParMode::PptDetectEppPort: EPP present - Controller=%x\n", Controller);
DD((PCE)Fdx,DDT,"-- PptDetectEppPort - HAVE Generic EPP\n");
} else {
DD((PCE)Fdx,DDT,"ParMode::PptDetectEppPort: EPP NOT present - Controller=%x\n", Controller);
DD((PCE)Fdx,DDT,"-- PptDetectEppPort - DON'T HAVE Generic EPP\n");
}
DD((PCE)Fdx,DDT,"-- PptDetectEppPort - Exit\n");
return;
}
VOID
PptDetectBytePort(
IN PFDO_EXTENSION Fdx
)
/*++
Routine Description:
This routine check to see if the port is Byte capable.
Arguments:
Fdx - Supplies the device extension of the device we are
reporting resources for.
Return Value:
None.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
DD((PCE)Fdx,DDT,"ParMode::PptDetectBytePort Enter.\n" );
Status = PptSetByteMode( Fdx, ECR_BYTE_PIO_MODE );
if ( NT_SUCCESS(Status) ) {
// Byte Mode found
DD((PCE)Fdx,DDT,"ParMode::PptDetectBytePort: Byte Found\n");
Fdx->PnpInfo.HardwareCapabilities |= PPT_BYTE_PRESENT;
} else {
// Byte Mode Not Found
DD((PCE)Fdx,DDT,"ParMode::PptDetectBytePort: Byte Not Found\n");
}
(VOID)PptClearByteMode( Fdx );
}
VOID PptDetermineFifoDepth(
IN PFDO_EXTENSION Fdx
)
{
PUCHAR Controller;
PUCHAR wPortECR; // IO address of Extended Control Register (ECR)
PUCHAR wPortDFIFO;
UCHAR ecr, ecrLast;
ULONG wFifoDepth;
UCHAR writeFifoDepth; // Depth calculated while writing FIFO
UCHAR readFifoDepth; // Depth calculated while reading FIFO
ULONG limitCount; // Prevents infinite looping on FIFO status
UCHAR testData;
Controller = Fdx->PortInfo.Controller;
wPortECR = Fdx->PnpInfo.EcpController+ ECR_OFFSET;
wPortDFIFO = Fdx->PnpInfo.EcpController;
wFifoDepth = 0;
ecrLast = P5ReadPortUchar(wPortECR );
P5WritePortUchar(wPortECR, DEFAULT_ECR_TEST );
ecr = P5ReadPortUchar(wPortECR );
if ( TEST_ECR_FIFO( ecr, ECR_FIFO_EMPTY ) ) {
// Write bytes into the FIFO until it indicates full.
writeFifoDepth = 0;
limitCount = 0;
while (((P5ReadPortUchar (wPortECR) & ECR_FIFO_MASK) != ECR_FIFO_FULL ) &&
(limitCount <= ECP_MAX_FIFO_DEPTH)) {
P5WritePortUchar( wPortDFIFO, (UCHAR)(writeFifoDepth & 0xFF) );
writeFifoDepth++;
limitCount++;
}
DD((PCE)Fdx,DDT,"ParMode::PptDetermineFifoDepth:: write fifo depth = %d\r\n", writeFifoDepth);
// Now read the bytes back, comparing what comes back.
readFifoDepth = 0;
limitCount = 0;
while (((P5ReadPortUchar( wPortECR ) & ECR_FIFO_MASK ) != ECR_FIFO_EMPTY ) &&
(limitCount <= ECP_MAX_FIFO_DEPTH)) {
testData = P5ReadPortUchar( wPortDFIFO );
if ( testData != (readFifoDepth & (UCHAR)0xFF )) {
// Data mismatch indicates problems...
// FIFO status didn't pan out, may not be an ECP chip after all
P5WritePortUchar( wPortECR, ecrLast);
DD((PCE)Fdx,DDT,"ParMode::PptDetermineFifoDepth::: data mismatch\n");
return;
}
readFifoDepth++;
limitCount++;
}
DD((PCE)Fdx,DDT,"ParMode::PptDetermineFifoDepth::: read fifo depth = %d\r\n", readFifoDepth);
// The write depth should match the read depth...
if ( writeFifoDepth == readFifoDepth ) {
wFifoDepth = readFifoDepth;
} else {
// Assume no FIFO
P5WritePortUchar( wPortECR, ecrLast);
DD((PCE)Fdx,DDT,"ParMode::PptDetermineFifoDepth::: No Fifo\n");
return;
}
} else {
// FIFO status didn't pan out, may not be an ECP chip after all
DD((PCE)Fdx,DDT,"ParMode::PptDetermineFifoDepth:: Bad Fifo\n");
P5WritePortUchar(wPortECR, ecrLast);
return;
}
// put chip into spp mode
P5WritePortUchar( wPortECR, ecrLast );
Fdx->PnpInfo.FifoDepth = wFifoDepth;
}
VOID
PptDetermineFifoWidth(
IN PFDO_EXTENSION Fdx
)
{
PUCHAR Controller;
UCHAR bConfigA;
PUCHAR wPortECR;
DD((PCE)Fdx,DDT,"ParMode::PptDetermineFifoWidth: Start\n");
Controller = Fdx->PortInfo.Controller;
wPortECR = Fdx->PnpInfo.EcpController + ECR_OFFSET;
// Put chip into configuration mode so we can access the ConfigA register
P5WritePortUchar( wPortECR, DEFAULT_ECR_CONFIGURATION );
// The FIFO width is bits <6:4> of the ConfigA register.
bConfigA = P5ReadPortUchar( Fdx->PnpInfo.EcpController );
Fdx->PnpInfo.FifoWidth = (ULONG)(( bConfigA & CNFGA_IMPID_MASK ) >> CNFGA_IMPID_SHIFT);
// Put the chip back in compatibility mode.
P5WritePortUchar(wPortECR, DEFAULT_ECR_COMPATIBILITY );
return;
}
NTSTATUS
PptSetChipMode (
IN PFDO_EXTENSION Fdx,
IN UCHAR ChipMode
)
/*++
Routine Description:
This function will put the current parallel chip into the
given mode if supported. The determination of supported mode
was in the PptDetectPortType function.
Arguments:
Fdx - Supplies the device extension.
Return Value:
STATUS_SUCCESS - if the port type was detected.
!STATUS_SUCCESS - otherwise.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
UCHAR EcrMode = (UCHAR)( ChipMode & ~ECR_MODE_MASK );
// Also allow PptSetChipMode from PS/2 mode - we need this for HWECP
// bus flip from Forward to Reverse in order to meet the required
// sequence specified in the Microsoft ECP Port Spec version 1.06,
// July 14, 1993, to switch directly from PS/2 mode with output
// drivers disabled (direction bit set to "read") to HWECP via
// the ECR. Changed 2000-02-11.
if ( Fdx->PnpInfo.CurrentMode != INITIAL_MODE && Fdx->PnpInfo.CurrentMode != ECR_BYTE_MODE ) {
DD((PCE)Fdx,DDW,"PptSetChipMode - CurrentMode invalid\n");
// Current mode is not valid to put in EPP or ECP mode
Status = STATUS_INVALID_DEVICE_STATE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -