📄 parmode.c
字号:
// reading a non-existant ECR could have one of two results: the ECR address
// could decode on top of the DCR, so we'll read the value we are about to set.
// Alternately, we might just read a floating bus and get a random value.
dcr = SET_DCR( DIR_WRITE, IRQEN_DISABLE, INACTIVE, ACTIVE, INACTIVE, ACTIVE );
WRITE_PORT_UCHAR( wPortDCR, dcr );
ecrLast = ecr = READ_PORT_UCHAR(wPortECR);
PptDump2(PARINITDEV, ("ParMode::PptDetectEcpPort: Ecr Value After DCR write: %x\n", ecr));
// Attempt to read the ECR. If ECP hardware is present, the ECR register's
// bit 1 and bit 0 should read a 00 (some data in the FIFO), 01 (FIFO empty),
// or 10 (FIFO full). If we read a 11 (illegal combination) then we know for
// sure that no ECP hardware is present. Also, a valid ECR should never return
// 0xFF (but a nonexistant register probably would), so we'll test for that
// specific value also.
if ( ( TEST_ECR_FIFO( ecr, ECR_FIFO_MASK ) ) || ( ecrLast == 0xFF ) )
{
// ECR[1:0] returned a value of 11, so this can't be hardware ECP.
PptDump2(PARINITDEV, ("ParMode::PptDetectEcpPort: illegal FIFO status\n"));
// Restore the DCR so that all lines are inactive.
dcr = SET_DCR( DIR_WRITE, IRQEN_DISABLE, INACTIVE, ACTIVE, ACTIVE, ACTIVE );
WRITE_PORT_UCHAR( wPortDCR, dcr );
return;
}
// OK, so we got either a 00, 01, or 10 for ECR[1:0]. If it was 10, the
if ( TEST_ECR_FIFO( ecr, ECR_FIFO_FULL ) ) // Looking for ECR[1:0] of 10...
{
// The ECR[1:0] returned 10. This is a legal value, but possibly the
// hardware might have just decoded the DCR and we merely read back the
// DCR value we set earlier. Or, we might have just read back a value
// that was hanging on the bus due to bus capacitance. So, we'll change
// the DCR, read the ECR again, and see if the two registers continue to
// track each other. If they do track, we'll conclude that there is no
// ECP hardware.
// Put the DCR's nAutoFeed and nStrobe register bits back to zero.
dcr = SET_DCR( DIR_WRITE, IRQEN_DISABLE, INACTIVE, ACTIVE, ACTIVE, ACTIVE );
WRITE_PORT_UCHAR( wPortDCR, dcr );
// Read the ECR again
ecr = READ_PORT_UCHAR( wPortECR );
if ( TEST_ECR_FIFO( ecr, ECR_FIFO_SOME_DATA ) )
{
// ECR[1:0] is tracking DCR[1:0], so this can't be hardware ECP.
PptDump2(PARINITDEV, ("ParMode::PptDetectEcpPort: FIFO status follows DCR\r\n"));
// Restore the DCR so that all lines are inactive.
dcr = SET_DCR( DIR_WRITE, IRQEN_DISABLE, INACTIVE, ACTIVE, ACTIVE, ACTIVE );
WRITE_PORT_UCHAR( wPortDCR, dcr );
return;
}
}
// If we get this far, then the ECR appears to be returning something valid that
// doesn't track the DCR. It is beginning to look promising. We're going
// to take a chance, and write the ECR to put the chip in compatiblity
// mode. Doing so will reset the FIFO, so when we read FIFO status it should
// come back empty. However, if we're wrong and this isn't ECP hardware, the
// value we're about to write will turn on 1284Active (nSelectIn) and this might
// cause headaches for the peripheral.
WRITE_PORT_UCHAR( wPortECR, DEFAULT_ECR_COMPATIBILITY );
// Read the ECR again
ecr = READ_PORT_UCHAR( 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 ) )
{
PptDump2(PARINITDEV, ("ParMode::PptDetectEcpPort: FIFO shows full\n"));
// Restore the DCR so that all lines are inactive.
dcr = SET_DCR( DIR_WRITE, IRQEN_DISABLE, INACTIVE, ACTIVE, ACTIVE, ACTIVE );
WRITE_PORT_UCHAR( 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
WRITE_PORT_UCHAR(wPortECR, ecrLast);
//
// Test here for ECP capable
//
// get value from ECR reg & save it
ecrLast = READ_PORT_UCHAR( wPortECR );
ecr = (UCHAR)(ecrLast & ECR_MODE_MASK);
// Put the chip into test mode; the FIFO should start out empty
WRITE_PORT_UCHAR(wPortECR, (UCHAR)(ecr | ECR_TEST_MODE) );
PptDetermineFifoWidth(Extension);
if (0 != Extension->PnpInfo.FifoWidth)
{
Extension->PnpInfo.HardwareCapabilities |= PPT_ECP_PRESENT;
PptDetermineFifoDepth(Extension);
PptDump2(PARINITDEV, ("ParMode::PptDetectEcpPort: ECP present\n") );
}
// return ecr to original
WRITE_PORT_UCHAR( wPortECR, ecrLast);
return;
}
VOID
PptDetectEppPortIfDot3DevicePresent(
IN PDEVICE_EXTENSION Extension
)
/*++
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:
Extension - Supplies the device extension of the device we are
reporting resources for.
Return Value:
None.
--*/
{
NTSTATUS status;
PUCHAR Controller = Extension->PortInfo.Controller;
UCHAR Reverse = (UCHAR)(DCR_DIRECTION | DCR_NOT_INIT | DCR_AUTOFEED | DCR_DSTRB);
UCHAR Forward = (UCHAR)(DCR_NOT_INIT | DCR_AUTOFEED | DCR_DSTRB);
BOOLEAN daisyChainDevicePresent = FALSE;
// ULONG DisableEppTest = 0; // any value != 0 means disable the test
PARALLEL_1284_COMMAND Command;
if( 0 == Extension->PnpInfo.Ieee1284_3DeviceCount ) {
PptDump2(PARINITDEV, ("ParMode::PptDetectEppPortIfDot3DevicePresent "
"- No dot3 device present - aborting - Controller=%x\n", Controller) );
PARDD01(("-- No DOT3 Device Present\n"));
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( Extension, &Command );
if( !NT_SUCCESS( status ) ) {
// unable to select device - something is wrong - just bail out
PptDump2(PARINITDEV, ("ParMode::PptDetectEppPortIfDot3DevicePresent: "
"unable to select 1284.3 device - bailing out - Controller=%x\n",
Controller) );
return;
}
//
// do the detection for chipset EPP capability
//
PARDD01(("-- DOT3 Device Present and selected\n"));
PptDetectEppPort( Extension );
//
// Deselect 1284.3 daisy chain device
//
Command.ID = 0;
Command.Port = 0;
Command.CommandFlags = PAR_HAVE_PORT_KEEP_PORT;
status = PptDeselectDevice( Extension, &Command );
if( !NT_SUCCESS( status ) ) {
// deselect failed??? - this shouldn't happen - our daisy chain interface is likely hung
PptDump2(PARINITDEV, ("ParMode::PptDetectEppPort: deselect 1284.3 device FAILED - Controller=%x\n", Controller) );
} else {
// 1284.3 daisy chain device deselected
PARDD01(("-- DOT3 Device deselected\n"));
PptDump2(PARINITDEV, ("ParMode::PptDetectEppPort: 1284.3 device deselected - Controller=%x\n", Controller) );
}
#if DBG
if( Extension->PnpInfo.HardwareCapabilities & PPT_EPP_PRESENT ) {
PptDump2(PARINITDEV, ("ParMode::PptDetectEppPort: EPP present - Controller=%x\n", Controller) );
} else {
PptDump2(PARINITDEV, ("ParMode::PptDetectEppPort: EPP NOT present - Controller=%x\n", Controller) );
}
#endif
return;
}
VOID
PptDetectEppPortIfUserRequested(
IN PDEVICE_EXTENSION Extension
)
/*++
Routine Description:
If user explicitly requested Generic EPP detection then do the check.
Arguments:
Extension - Supplies the device extension of the device we are
reporting resources for.
Return Value:
None.
--*/
{
ULONG RequestEppTest = 0;
PptRegGetDeviceParameterDword( Extension->PhysicalDeviceObject, (PWSTR)L"RequestEppTest", &RequestEppTest );
if( RequestEppTest ) {
PARDD01(("-- User Requested EPP detection - %x\n", RequestEppTest));
PptDetectEppPort( Extension );
} else {
PARDD01(("-- User did not request EPP detection\n"));
}
return;
}
VOID
PptDetectEppPort(
IN PDEVICE_EXTENSION Extension
)
/*++
Routine Description:
This routine checks for EPP capable port after ECP was found.
Arguments:
Extension - 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);
BOOLEAN daisyChainDevicePresent = FALSE;
ULONG DisableEppTest = 0; // any value != 0 means disable the test
PARDD01(("-- PptDetectEppPort - Enter\n"));
PptDump2(PARINITDEV, ("ParMode::PptDetectEppPort: Enter\n") );
Controller = Extension->PortInfo.Controller;
// Get current DCR
dcr = READ_PORT_UCHAR( 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.
//
Extension->PnpInfo.HardwareCapabilities |= PPT_EPP_PRESENT;
// Setting EPP mode
PptDump2(PARINITDEV, ("ParMode::PptDetectEppPort: Setting EPP Mode\n") );
PptEcrSetMode( Extension, 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
WRITE_PORT_UCHAR( Controller + DCR_OFFSET, Reverse );
KeStallExecutionProcessor( 5 );
WRITE_PORT_UCHAR( Controller + EPP_OFFSET, (UCHAR)i );
// put it back into forward phase to read the byte we put out there
WRITE_PORT_UCHAR( Controller + DCR_OFFSET, Forward );
KeStallExecutionProcessor( 5 );
if ( READ_PORT_UCHAR( Controller ) != i ) {
// failure so clear EPP flag
Extension->PnpInfo.HardwareCapabilities &= ~PPT_EPP_PRESENT;
break;
}
}
// Clearing EPP Mode
PptEcrClearMode( Extension );
// Restore DCR
WRITE_PORT_UCHAR( Controller + DCR_OFFSET, dcr );
Extension->CheckedForGenericEpp = TRUE; // check is complete
if( Extension->PnpInfo.HardwareCapabilities & PPT_EPP_PRESENT ) {
PptDump2(PARINITDEV, ("ParMode::PptDetectEppPort: EPP present - Controller=%x\n", Controller) );
PARDD01(("-- PptDetectEppPort - HAVE Generic EPP\n"));
} else {
PptDump2(PARINITDEV, ("ParMode::PptDetectEppPort: EPP NOT present - Controller=%x\n", Controller) );
PARDD01(("-- PptDetectEppPort - DON'T HAVE Generic EPP\n"));
}
PARDD01(("-- PptDetectEppPort - Exit\n"));
return;
}
VOID
PptDetectBytePort(
IN PDEVICE_EXTENSION Extension
)
/*++
Routine Description:
This routine check to see if the port is Byte capable.
Arguments:
Extension - Supplies the device extension of the device we are
reporting resources for.
Return Value:
None.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PptDump2(PARINITDEV, ("ParMode::PptDetectBytePort Enter.\n" ) );
Status = PptSetByteMode( Extension, ECR_BYTE_PIO_MODE );
if ( NT_SUCCESS(Status) ) {
// Byte Mode found
PptDump2(PARINITDEV, ("ParMode::PptDetectBytePort: Byte Found\n") );
Extension->PnpInfo.HardwareCapabilities |= PPT_BYTE_PRESENT;
} else {
// Byte Mode Not Found
PptDump2(PARINITDEV, ("ParMode::PptDetectBytePort: Byte Not Found\n"));
}
(VOID)PptClearByteMode( Extension );
}
VOID PptDetermineFifoDepth(
IN PDEVICE_EXTENSION Extension
)
{
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 = Extension->PortInfo.Controller;
#if (0 == DVRH_USE_PARPORT_ECP_ADDR)
wPortECR = Controller + ECR_OFFSET;
wPortDFIFO = Controller + ECP_DFIFO_OFFSET;
#else
wPortECR = Extension->PnpInfo.EcpController+ ECR_OFFSET;
wPortDFIFO = Extension->PnpInfo.EcpController;
#endif
wFifoDepth = 0;
ecrLast = READ_PORT_UCHAR(wPortECR );
WRITE_PORT_UCHAR(wPortECR, DEFAULT_ECR_TEST );
ecr = READ_PORT_UCHAR(wPortECR );
if ( TEST_ECR_FIFO( ecr, ECR_FIFO_EMPTY ) ) {
// Write bytes into the FIFO until it indicates full.
writeFifoDepth = 0;
limitCount = 0;
while (((READ_PORT_UCHAR (wPortECR) & ECR_FIFO_MASK) != ECR_FIFO_FULL ) &&
(limitCount <= ECP_MAX_FIFO_DEPTH)) {
WRITE_PORT_UCHAR( wPortDFIFO, (UCHAR)(writeFifoDepth & 0xFF));
writeFifoDepth++;
limitCount++;
}
PptDump2(PARINITDEV, ("ParMode::PptDetermineFifoDepth:: write fifo depth = %d\r\n", writeFifoDepth ));
// Now read the bytes back, comparing what comes back.
readFifoDepth = 0;
limitCount = 0;
while (((READ_PORT_UCHAR( wPortECR ) & ECR_FIFO_MASK ) != ECR_FIFO_EMPTY ) &&
(limitCount <= ECP_MAX_FIFO_DEPTH)) {
testData = READ_PORT_UCHAR( wPortDFIFO );
if ( testData != (readFifoDepth & (UCHAR)0xFF )) {
// Data mismatch indicates problems...
// FIFO status didn't pan out, may not be an ECP chip after all
WRITE_PORT_UCHAR( wPortECR, ecrLast);
PptDump2(PARINITDEV, ("ParMode::PptDetermineFifoDepth::: data mismatch\n"));
return;
}
readFifoDepth++;
limitCount++;
}
PptDump2(PARINITDEV, ("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
WRITE_PORT_UCHAR( wPortECR, ecrLast);
PptDump2(PARINITDEV, ("ParMode::PptDetermineFifoDepth::: No Fifo\n"));
return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -