📄 parmode.c
字号:
/*++
Copyright (C) Microsoft Corporation, 1993 - 1999
Module Name:
parmode.c
Abstract:
This is the main module for Extended Parallel Port (ECP) and
Enhanced Parallel Port (EPP) detection. This module
will detect for invalid chipshets and do ECR detection
for ECP and EPP hardware support if the invalid chipset
is not found.
Author:
Don Redford (v-donred) 4-Mar-1998
Environment:
Kernel mode
Revision History :
--*/
#include "pch.h"
#include "parmode.h"
#define USE_PARCHIP_ECRCONTROLLER 1
NTSTATUS
PptDetectChipFilter(
IN PDEVICE_EXTENSION Extension
)
/*++
Routine Description:
This routine is called once per DeviceObject to see if the filter driver
for detecting parallel chip capabilities is there and to get the chip
capabilities if there of the port in question.
Arguments:
Extension - Supplies the device extension.
Return Value:
STATUS_SUCCESS - if we were able detect the chip and modes possible.
!STATUS_SUCCESS - otherwise.
--*/
{
NTSTATUS Status = STATUS_NO_SUCH_DEVICE;
PIRP Irp;
KEVENT Event;
IO_STATUS_BLOCK IoStatus;
UCHAR ecrLast;
PUCHAR Controller, EcpController;
Controller = Extension->PortInfo.Controller;
EcpController = Extension->PnpInfo.EcpController;
PptDumpV( ("PptDetectChipFilter(...)\n") );
// Setting variable to FALSE to make sure we do not acidentally succeed
Extension->ChipInfo.success = FALSE;
// Setting the Address to send to the filter driver to check the chips
Extension->ChipInfo.Controller = Controller;
// Setting the Address to send to the filter driver to check the chips
Extension->ChipInfo.EcrController = EcpController;
#ifndef USE_PARCHIP_ECRCONTROLLER
// if there is not value in the ECR controller then PARCHIP and PARPORT
// will conflict and PARCHIP will not work with PARPORT unless we
// use the ECR controller found by PARCHIP.
if ( !EcpController ) {
return Status;
}
#endif
//
// Initialize
//
KeInitializeEvent(&Event, NotificationEvent, FALSE);
// Send a Pointer to the ChipInfo structure to and from the filter
Irp = IoBuildDeviceIoControlRequest( IOCTL_INTERNAL_PARCHIP_CONNECT,
Extension->ParentDeviceObject,
&Extension->ChipInfo,
sizeof(PARALLEL_PARCHIP_INFO),
&Extension->ChipInfo,
sizeof(PARALLEL_PARCHIP_INFO),
TRUE, &Event, &IoStatus);
if (!Irp) {
// couldn't create an IRP
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Call down to our parent and see if Filter is present
//
PptDumpV( ("PptDetectChipFilter: ready to call IoCallDriver\n") );
Status = IoCallDriver(Extension->ParentDeviceObject, Irp);
if (Status == STATUS_PENDING) {
KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
Status = Irp->IoStatus.Status;
}
//
// If successful then we have a filter driver and we need to get the modes supported
//
if ( NT_SUCCESS(Status) ) {
PptDumpV( ("PptDetectChipFilter(...) Found A Filter Driver\n") );
//
// check to see if the filter driver was able to determine the I/O chip
//
if ( Extension->ChipInfo.success ) {
PptDumpV( ("PptDetectChipFilter(...) Found A Filter Driver and detected the chip.\n") );
Extension->PnpInfo.HardwareCapabilities = Extension->ChipInfo.HardwareModes;
#ifdef USE_PARCHIP_ECRCONTROLLER
// only replace it if defined
PptDumpV( ("PptDetectChipFilter(...) BEFORE CHIP FILTER ECR address is %x.\n", Extension->PnpInfo.EcpController) );
if ( Extension->PnpInfo.EcpController != Extension->ChipInfo.EcrController ) {
Extension->PnpInfo.EcpController = Extension->ChipInfo.EcrController;
EcpController = Extension->PnpInfo.EcpController;
PptDumpV( ("PptDetectChipFilter(...) AFTER CHIP FILTER ECR address is %x.\n", Extension->PnpInfo.EcpController) );
}
#endif
// Set variable to say we have a filter driver
Extension->FilterMode = TRUE;
} else {
PptDumpV( ("PptDetectChipFilter(...) Found A Filter Driver NOT able to detect the chip.\n") );
}
}
// if there is a filter and ECP capable we need to get the Fifo Size
if ( Extension->FilterMode && Extension->PnpInfo.HardwareCapabilities & PPT_ECP_PRESENT ) {
PptDumpV( ("PptDetectChipFilter(...) ECP is present Determining Fifo size.\n") );
Status = Extension->ChipInfo.ParChipSetMode ( Extension->ChipInfo.Context, ECR_ECP_MODE );
// if able to set ECP mode
if ( NT_SUCCESS( Status ) ) {
PUCHAR wPortECR;
PptDumpV( ("PptDetectChipFilter(...) Able to set chip into ECP mode.\n") );
#if (0 == DVRH_USE_PARPORT_ECP_ADDR)
wPortECR = Controller + ECR_OFFSET;
#else
wPortECR = EcpController + ECR_OFFSET;
#endif
// get value from ECR reg & save it
ecrLast = READ_PORT_UCHAR( wPortECR );
// Determining Fifo Size
PptDetermineFifoWidth(Extension);
PptDetermineFifoDepth(Extension);
// return ecr to original
WRITE_PORT_UCHAR( wPortECR, ecrLast);
Status = Extension->ChipInfo.ParChipClearMode ( Extension->ChipInfo.Context, ECR_ECP_MODE );
}
}
PptDumpV( ("Leaving PptDetectChipFilter(...) with Status 0x%x\n", Status) );
return Status;
}
NTSTATUS
PptDetectPortType(
IN PDEVICE_EXTENSION Extension
)
/*++
Routine Description:
This routine is called once per DeviceObject to detect the type of
parallel chip capabilities of the port in question.
Arguments:
Extension - Supplies the device extension.
Return Value:
STATUS_SUCCESS - if we were able detect the chip and modes possible.
!STATUS_SUCCESS - otherwise.
--*/
{
NTSTATUS Status;
UNICODE_STRING ParportPath;
RTL_QUERY_REGISTRY_TABLE RegTable[2];
ULONG IdentifierHex = 12169;
ULONG zero = 0;
PptDumpV( ("PARPORT: Enter PptDetectPortType().\n") );
//
// -- May want to get detection order from Registry.
// -- May also want to store/retrieve last known good configuration in/from registry.
// -- Finally we should set a registry flag during dection so that we'll know
// if we crashed while attempting to detect and not try it again.
//
RtlInitUnicodeString(&ParportPath, (PWSTR)L"Parport");
// Setting up to get the Parport info
RtlZeroMemory( RegTable, sizeof(RegTable) );
RegTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT |
RTL_QUERY_REGISTRY_REQUIRED;
RegTable[0].Name = (PWSTR)L"ModeCheckedStalled";
RegTable[0].EntryContext = &IdentifierHex;
RegTable[0].DefaultType = REG_DWORD;
RegTable[0].DefaultData = &zero;
RegTable[0].DefaultLength = sizeof(ULONG);
//
// Querying the registry for Parport to see if we tried to go check mode and we crashed
// the registry key would still be there
//
Status = RtlQueryRegistryValues(
RTL_REGISTRY_SERVICES,
ParportPath.Buffer,
RegTable,
NULL,
NULL );
PptDump2(PARINITDEV, ("PptDetectPortType: Query Register returned : %x.\n", Status) );
PptDump2(PARINITDEV, ("PptDetectPortType: IdentifierHex is : %x.\n", IdentifierHex) );
//
// if registry key is there then we will just check ECP and Byte
//
// if ( !NT_SUCCESS( Status ) || (IdentifierHex == zero)) {
if ( !(NT_SUCCESS( Status ) && IdentifierHex == 0) && (Status != STATUS_OBJECT_NAME_NOT_FOUND) ) {
PptDump2(PARINITDEV, ("PptDetectPortType: Found Registry value so we locked up last time.\n") );
// dvtw, Check for ECP anyway! We just won't turn it on
PptDump2(PARINITDEV, ("PptDetectPortType: Only check ECP and Byte.\n") );
PptDetectEcpPort(Extension);
PptDetectBytePort(Extension);
if (Extension->PnpInfo.HardwareCapabilities &
(PPT_ECP_PRESENT | PPT_BYTE_PRESENT) ) {
return ( STATUS_SUCCESS );
} else {
return ( STATUS_NO_SUCH_DEVICE );
}
}
IdentifierHex = 12169;
// Write the registry key out there just in case we crash
Status = RtlWriteRegistryValue(
RTL_REGISTRY_SERVICES,
ParportPath.Buffer,
(PWSTR)L"ModeCheckedStalled",
REG_DWORD,
&IdentifierHex,
sizeof(ULONG) );
//
// Now we can start detecting the parallel port chip capabilities
//
PptDumpV( ("PARPORT: PptDetectPortType() Calling PptDetectPortCapablities().\n") );
Status = PptDetectPortCapabilities( Extension );
PptDumpV( ("PARPORT: PptDetectPortType() PptDetectPortCapablities returned %x.\n", Status) );
// Delete the registry key out there since we finished
Status = RtlDeleteRegistryValue(
RTL_REGISTRY_SERVICES,
ParportPath.Buffer,
(PWSTR)L"ModeCheckedStalled"
);
PptDumpV( ("PARPORT: Leave PptDetectPortType() with Status %x.\n", Status) );
return Status;
}
NTSTATUS
PptDetectPortCapabilities(
IN PDEVICE_EXTENSION Extension
)
/*++
Routine Description:
This is the "default" detection code, which looks for an ECR. If the ECR
is present it tries to set mode 100b in <7:5>. If it sticks we'll call it
EPP.
Arguments:
Extension - Supplies the device extension.
Return Value:
STATUS_SUCCESS - if the port type was detected.
!STATUS_SUCCESS - otherwise.
--*/
{
NTSTATUS Status;
PptDump2(PARINITDEV, ("Entering PptDetectPortCapablilities\n") );
PptDump2(PARINITDEV, ("PptDetectPortCapablilities(): Detecting ECP\n") );
PptDetectEcpPort( Extension );
// dvdr
//
// if we did not detect an ECR for ECP mode and ECP mode failed
// EPP mode would fail also
// Also cannot have EPP mode at an address that ends with a "C"
//
if ( (Extension->PnpInfo.HardwareCapabilities & PPT_ECP_PRESENT)
&& (((ULONG_PTR)Extension->PortInfo.Controller & 0x0F) != 0x0C) ) {
PptDump2(PARINITDEV, ("PptDetectPortCapablilities ECP Found Detecting for National Chipset\n") );
// Need to check for National chipsets before trying EPP mode
// dvdr - need to add detection for old Winbond
Status = PptFindNatChip( Extension );
if ( NT_SUCCESS( Status ) ) {
if ( !Extension->NationalChipFound ) {
// National chipset was NOT found so we can see if generic EPP is supported
PptDump2(PARINITDEV, ("National chipset not found on %lx\n", Extension->PortInfo.Controller) );
PptDump2(PARINITDEV, ("PptDetectPortCapablilities Detecting EPP\n") );
PARDD01(("-- !NationalChipFound\n"));
PARDD01(("-- pre PptDetectEppPortIfDot3DevicePresent\n"));
PptDetectEppPortIfDot3DevicePresent( Extension );
PARDD01(("-- post PptDetectEppPortIfDot3DevicePresent\n"));
if( !Extension->CheckedForGenericEpp ) {
// we didn't have a dot3 device to use for screening, do check anyway
// if user has explicitly requested EPP detection
PARDD01(("-- no dot3 device - perhaps user requested that we check for EPP anyway?\n"));
PARDD01(("-- pre PptDetectEppPortIfUserRequested\n"));
PptDetectEppPortIfUserRequested( Extension );
PARDD01(("-- post PptDetectEppPortIfUserRequested\n"));
}
} else {
// National chipset was found so can't do generic EPP
PptDump2(PARINITDEV, ("National chipset found\n") );
PARDD01(("-- NationalChipFound\n"));
Extension->CheckedForGenericEpp = TRUE; // check is complete - generic EPP is unsafe
}
}
} else {
// ECP failed no check for Generic EPP
PptDump2(PARINITDEV, ("ECP on port %lx Failed Not Checking EPP\n", Extension->PortInfo.Controller) );
PARDD01(("-- !ECP\n"));
Extension->CheckedForGenericEpp = TRUE; // check is complete - generic EPP is unsafe
}
PptDump2(PARINITDEV, ("PptDetectPortCapablilities Detecting BYTE\n") );
PptDetectBytePort( Extension );
if (Extension->PnpInfo.HardwareCapabilities &
(PPT_ECP_PRESENT | PPT_EPP_PRESENT | PPT_BYTE_PRESENT) ) {
PptDump2(PARINITDEV, ("Leaving PptDetectPortCapablilities was successful\n") );
return STATUS_SUCCESS;
}
PptDump2(PARINITDEV, ("Leaving PptDetectPortCapablilities no Device found\n") );
return STATUS_NO_SUCH_DEVICE;
}
VOID
PptDetectEcpPort(
IN PDEVICE_EXTENSION Extension
)
/*++
Routine Description:
This routine looks for the presence of an ECR register to determine that
it has ECP.
Arguments:
Extension - Supplies the device extension of the device we are
reporting resources for.
Return Value:
None.
--*/
{
PUCHAR Controller;
PUCHAR wPortDCR; // IO address of Device Control Register (DCR)
PUCHAR wPortECR; // IO address of Extended Control Register (ECR)
UCHAR ecrLast, ecr, dcr;
Controller = Extension->PortInfo.Controller;
wPortDCR = Controller + DCR_OFFSET;
#if (0 == DVRH_USE_PARPORT_ECP_ADDR)
wPortECR = Controller + OFFSET_ECR;
#else
if( 0 == Extension->PnpInfo.EcpController ) {
//
// PnP didn't give us an ECP Register set - we're done here
//
PptDump2(PARINITDEV, ("ParMode::PptDetectEcpPort: Start\n"));
return;
}
wPortECR = Extension->PnpInfo.EcpController + ECR_OFFSET;
#endif
PptDump2(PARINITDEV, ("ParMode::PptDetectEcpPort: Start\n"));
PptDump2(PARINITDEV, ("ParMode::PptDetectEcpPort: Ecr port : %x\n", wPortECR));
ecrLast = ecr = READ_PORT_UCHAR(wPortECR);
PptDump2(PARINITDEV, ("ParMode::PptDetectEcpPort: Ecr Value before DCR write: %x\n", ecr));
// Initialize the DCR's nAutoFeed and nStrobe to a harmless combination
// that could be returned by the ECR, but is not likely to be returned if
// the ECR isn't present. Depending on the host's address decode logic,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -