1316 lines
37 KiB
C
1316 lines
37 KiB
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"
|
||
|
||
#define USE_PARCHIP_ECRCONTROLLER 1
|
||
|
||
|
||
NTSTATUS
|
||
PptDetectChipFilter(
|
||
IN PFDO_EXTENSION Fdx
|
||
)
|
||
|
||
/*++
|
||
|
||
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:
|
||
|
||
Fdx - 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 = Fdx->PortInfo.Controller;
|
||
EcpController = Fdx->PnpInfo.EcpController;
|
||
|
||
// Setting variable to FALSE to make sure we do not acidentally succeed
|
||
Fdx->ChipInfo.success = FALSE;
|
||
|
||
// Setting the Address to send to the filter driver to check the chips
|
||
Fdx->ChipInfo.Controller = Controller;
|
||
|
||
// Setting the Address to send to the filter driver to check the chips
|
||
Fdx->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,
|
||
Fdx->ParentDeviceObject,
|
||
&Fdx->ChipInfo,
|
||
sizeof(PARALLEL_PARCHIP_INFO),
|
||
&Fdx->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
|
||
//
|
||
Status = IoCallDriver(Fdx->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) ) {
|
||
|
||
//
|
||
// check to see if the filter driver was able to determine the I/O chip
|
||
//
|
||
if ( Fdx->ChipInfo.success ) {
|
||
Fdx->PnpInfo.HardwareCapabilities = Fdx->ChipInfo.HardwareModes;
|
||
#ifdef USE_PARCHIP_ECRCONTROLLER
|
||
// only replace it if defined
|
||
if ( Fdx->PnpInfo.EcpController != Fdx->ChipInfo.EcrController ) {
|
||
Fdx->PnpInfo.EcpController = Fdx->ChipInfo.EcrController;
|
||
EcpController = Fdx->PnpInfo.EcpController;
|
||
}
|
||
#endif
|
||
// Set variable to say we have a filter driver
|
||
Fdx->FilterMode = TRUE;
|
||
}
|
||
}
|
||
|
||
// if there is a filter and ECP capable we need to get the Fifo Size
|
||
if ( Fdx->FilterMode && Fdx->PnpInfo.HardwareCapabilities & PPT_ECP_PRESENT ) {
|
||
|
||
Status = Fdx->ChipInfo.ParChipSetMode ( Fdx->ChipInfo.Context, ECR_ECP_MODE );
|
||
|
||
// if able to set ECP mode
|
||
if ( NT_SUCCESS( Status ) ) {
|
||
PUCHAR wPortECR;
|
||
|
||
wPortECR = EcpController + ECR_OFFSET;
|
||
|
||
// get value from ECR reg & save it
|
||
ecrLast = P5ReadPortUchar( wPortECR );
|
||
|
||
// Determining Fifo Size
|
||
PptDetermineFifoWidth(Fdx);
|
||
PptDetermineFifoDepth(Fdx);
|
||
|
||
// return ecr to original
|
||
P5WritePortUchar( wPortECR, ecrLast);
|
||
|
||
Status = Fdx->ChipInfo.ParChipClearMode ( Fdx->ChipInfo.Context, ECR_ECP_MODE );
|
||
}
|
||
|
||
}
|
||
|
||
return Status;
|
||
}
|
||
|
||
NTSTATUS
|
||
PptDetectPortType(
|
||
IN PFDO_EXTENSION Fdx
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is called once per DeviceObject to detect the type of
|
||
parallel chip capabilities of the port in question.
|
||
|
||
Arguments:
|
||
|
||
Fdx - 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;
|
||
|
||
//
|
||
// -- 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 );
|
||
|
||
//
|
||
// if registry key is there then we will just check ECP and Byte
|
||
//
|
||
if ( !(NT_SUCCESS( Status ) && IdentifierHex == 0) && (Status != STATUS_OBJECT_NAME_NOT_FOUND) ) {
|
||
|
||
// dvtw, Check for ECP anyway! We just won't turn it on
|
||
|
||
PptDetectEcpPort(Fdx);
|
||
PptDetectBytePort(Fdx);
|
||
|
||
if( Fdx->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
|
||
//
|
||
Status = PptDetectPortCapabilities( Fdx );
|
||
|
||
// Delete the registry key out there since we finished
|
||
Status = RtlDeleteRegistryValue( RTL_REGISTRY_SERVICES, ParportPath.Buffer, (PWSTR)L"ModeCheckedStalled" );
|
||
return Status;
|
||
}
|
||
|
||
NTSTATUS
|
||
PptDetectPortCapabilities(
|
||
IN PFDO_EXTENSION Fdx
|
||
)
|
||
|
||
/*++
|
||
|
||
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:
|
||
|
||
Fdx - Supplies the device extension.
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS - if the port type was detected.
|
||
!STATUS_SUCCESS - otherwise.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status;
|
||
|
||
PptDetectEcpPort( Fdx );
|
||
|
||
// 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 ( (Fdx->PnpInfo.HardwareCapabilities & PPT_ECP_PRESENT) &&
|
||
(((ULONG_PTR)Fdx->PortInfo.Controller & 0x0F) != 0x0C) ) {
|
||
|
||
// Need to check for National chipsets before trying EPP mode
|
||
// dvdr - need to add detection for old Winbond
|
||
|
||
Status = PptFindNatChip( Fdx );
|
||
|
||
if ( NT_SUCCESS( Status ) ) {
|
||
if ( !Fdx->NationalChipFound ) {
|
||
// National chipset was NOT found so we can see if generic EPP is supported
|
||
|
||
PptDetectEppPortIfDot3DevicePresent( Fdx );
|
||
|
||
if( !Fdx->CheckedForGenericEpp ) {
|
||
// we didn't have a dot3 device to use for screening, do check anyway
|
||
// if user has explicitly requested EPP detection
|
||
PptDetectEppPortIfUserRequested( Fdx );
|
||
}
|
||
} else {
|
||
// National chipset was found so can't do generic EPP
|
||
Fdx->CheckedForGenericEpp = TRUE; // check is complete - generic EPP is unsafe
|
||
}
|
||
}
|
||
} else {
|
||
// ECP failed no check for Generic EPP
|
||
Fdx->CheckedForGenericEpp = TRUE; // check is complete - generic EPP is unsafe
|
||
}
|
||
|
||
PptDetectBytePort( Fdx );
|
||
|
||
if (Fdx->PnpInfo.HardwareCapabilities & (PPT_ECP_PRESENT | PPT_EPP_PRESENT | PPT_BYTE_PRESENT) ) {
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
return STATUS_NO_SUCH_DEVICE;
|
||
}
|
||
|
||
VOID
|
||
PptDetectEcpPort(
|
||
IN PFDO_EXTENSION Fdx
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine looks for the presence of an ECR register to determine that
|
||
it has ECP.
|
||
|
||
Arguments:
|
||
|
||
Fdx - 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 = Fdx->PortInfo.Controller;
|
||
wPortDCR = Controller + DCR_OFFSET;
|
||
|
||
if( 0 == Fdx->PnpInfo.EcpController ) {
|
||
// PnP didn't give us an ECP Register set - we're done here
|
||
return;
|
||
}
|
||
wPortECR = Fdx->PnpInfo.EcpController + ECR_OFFSET;
|
||
|
||
ecrLast = ecr = P5ReadPortUchar(wPortECR);
|
||
|
||
// 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,
|
||
// 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 );
|
||
P5WritePortUchar( wPortDCR, dcr );
|
||
|
||
ecrLast = ecr = P5ReadPortUchar(wPortECR);
|
||
|
||
|
||
// 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.
|
||
DD((PCE)Fdx,DDT,"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 );
|
||
P5WritePortUchar( 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 );
|
||
P5WritePortUchar( wPortDCR, dcr );
|
||
|
||
// Read the ECR again
|
||
ecr = P5ReadPortUchar( 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.
|
||
|
||
// Restore the DCR so that all lines are inactive.
|
||
dcr = SET_DCR( DIR_WRITE, IRQEN_DISABLE, INACTIVE, ACTIVE, ACTIVE, ACTIVE );
|
||
P5WritePortUchar( 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.
|
||
P5WritePortUchar( wPortECR, DEFAULT_ECR_COMPATIBILITY );
|
||
|
||
// 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;
|
||
|
||
goto ExitSetChipModeNoChange;
|
||
}
|
||
|
||
// need to find out what mode it was and try to take it out of it
|
||
|
||
// Check to see if we need to use the filter to set the mode
|
||
if ( Fdx->FilterMode ) {
|
||
Status = Fdx->ChipInfo.ParChipSetMode ( Fdx->ChipInfo.Context, ChipMode );
|
||
} else {
|
||
|
||
// If asked for ECP check to see if we can do it
|
||
if ( EcrMode == ECR_ECP_MODE ) {
|
||
if ((Fdx->PnpInfo.HardwareCapabilities & PPT_ECP_PRESENT) ^ PPT_ECP_PRESENT) {
|
||
// ECP Not Present
|
||
return STATUS_NO_SUCH_DEVICE;
|
||
}
|
||
Status = PptEcrSetMode ( Fdx, ChipMode );
|
||
goto ExitSetChipModeWithChanges;
|
||
}
|
||
|
||
// If asked for EPP check to see if we can do it
|
||
if ( EcrMode == ECR_EPP_MODE ) {
|
||
if ((Fdx->PnpInfo.HardwareCapabilities & PPT_EPP_PRESENT) ^ PPT_EPP_PRESENT) {
|
||
// EPP Not Present
|
||
return STATUS_NO_SUCH_DEVICE;
|
||
}
|
||
Status = PptEcrSetMode ( Fdx, ChipMode );
|
||
goto ExitSetChipModeWithChanges;
|
||
}
|
||
|
||
// If asked for Byte Mode check to see if it is still enabled
|
||
if ( EcrMode == ECR_BYTE_MODE ) {
|
||
if ((Fdx->PnpInfo.HardwareCapabilities & PPT_BYTE_PRESENT) ^ PPT_BYTE_PRESENT) {
|
||
// BYTE Not Present
|
||
return STATUS_NO_SUCH_DEVICE;
|
||
}
|
||
Status = PptSetByteMode ( Fdx, ChipMode );
|
||
goto ExitSetChipModeWithChanges;
|
||
}
|
||
}
|
||
|
||
ExitSetChipModeWithChanges:
|
||
|
||
if ( NT_SUCCESS(Status) ) {
|
||
Fdx->PnpInfo.CurrentMode = EcrMode;
|
||
} else {
|
||
DD((PCE)Fdx,DDW,"PptSetChipMode - failed w/status = %x\n",Status);
|
||
}
|
||
|
||
ExitSetChipModeNoChange:
|
||
|
||
return Status;
|
||
}
|
||
|
||
NTSTATUS
|
||
PptClearChipMode (
|
||
IN PFDO_EXTENSION Fdx,
|
||
IN UCHAR ChipMode
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine Clears the Given chip mode.
|
||
|
||
Arguments:
|
||
|
||
Fdx - Supplies the device extension.
|
||
ChipMode - The given mode to clear from the Chip
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS - if the port type was detected.
|
||
!STATUS_SUCCESS - otherwise.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||
ULONG EcrMode = ChipMode & ~ECR_MODE_MASK;
|
||
|
||
// make sure we have a mode to clear
|
||
if ( EcrMode != Fdx->PnpInfo.CurrentMode ) {
|
||
|
||
DD((PCE)Fdx,DDW,"ParMode::PptClearChipMode: Mode to Clear != CurrentModen");
|
||
|
||
// Current mode is not the same as requested to take it out of
|
||
Status = STATUS_INVALID_DEVICE_STATE;
|
||
|
||
goto ExitClearChipModeNoChange;
|
||
}
|
||
|
||
// need to find out what mode it was and try to take it out of it
|
||
|
||
// check to see if we used the filter to set the mode
|
||
if ( Fdx->FilterMode ) {
|
||
Status = Fdx->ChipInfo.ParChipClearMode ( Fdx->ChipInfo.Context, ChipMode );
|
||
} else {
|
||
|
||
// If ECP mode check to see if we can clear it
|
||
if ( EcrMode == ECR_ECP_MODE ) {
|
||
Status = PptEcrClearMode( Fdx );
|
||
goto ExitClearChipModeWithChanges;
|
||
}
|
||
|
||
// If EPP mode check to see if we can clear it
|
||
if ( EcrMode == ECR_EPP_MODE ) {
|
||
Status = PptEcrClearMode( Fdx );
|
||
goto ExitClearChipModeWithChanges;
|
||
}
|
||
|
||
// If BYTE mode clear it if use ECR register
|
||
if ( EcrMode == ECR_BYTE_MODE ) {
|
||
Status = PptClearByteMode( Fdx );
|
||
goto ExitClearChipModeWithChanges;
|
||
}
|
||
}
|
||
|
||
ExitClearChipModeWithChanges:
|
||
|
||
if( NT_SUCCESS(Status) ) {
|
||
Fdx->PnpInfo.CurrentMode = INITIAL_MODE;
|
||
}
|
||
|
||
ExitClearChipModeNoChange:
|
||
|
||
return Status;
|
||
}
|
||
|
||
NTSTATUS
|
||
PptEcrSetMode(
|
||
IN PFDO_EXTENSION Fdx,
|
||
IN UCHAR ChipMode
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine enables EPP mode through the ECR register.
|
||
|
||
Arguments:
|
||
|
||
Fdx - Supplies the device extension.
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS - if the port type was detected.
|
||
!STATUS_SUCCESS - otherwise.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
UCHAR ecr;
|
||
PUCHAR Controller;
|
||
PUCHAR wPortECR;
|
||
|
||
Controller = Fdx->PortInfo.Controller;
|
||
|
||
//
|
||
// Store the prior mode.
|
||
//
|
||
wPortECR = Fdx->PnpInfo.EcpController + ECR_OFFSET;
|
||
|
||
ecr = P5ReadPortUchar( wPortECR );
|
||
Fdx->EcrPortData = ecr;
|
||
|
||
// get rid of prior mode which is the top three bits
|
||
ecr &= ECR_MODE_MASK;
|
||
|
||
// Write out SPP mode first to the chip
|
||
P5WritePortUchar( wPortECR, (UCHAR)(ecr | ECR_BYTE_MODE) );
|
||
|
||
// Write new mode to ECR register
|
||
P5WritePortUchar( wPortECR, ChipMode );
|
||
|
||
return STATUS_SUCCESS;
|
||
|
||
}
|
||
|
||
NTSTATUS
|
||
PptSetByteMode(
|
||
IN PFDO_EXTENSION Fdx,
|
||
IN UCHAR ChipMode
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine enables Byte mode either through the ECR register
|
||
(if available). Or just checks it to see if it works
|
||
|
||
Arguments:
|
||
|
||
Fdx - Supplies the device extension.
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS - if the port type was detected.
|
||
!STATUS_SUCCESS - otherwise.
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS Status;
|
||
|
||
// Checking to see if ECR register is there and if there use it
|
||
if ( Fdx->PnpInfo.HardwareCapabilities & PPT_ECP_PRESENT ) {
|
||
Status = PptEcrSetMode( Fdx, ChipMode );
|
||
}
|
||
|
||
Status = PptCheckByteMode( Fdx );
|
||
|
||
return Status;
|
||
|
||
}
|
||
|
||
NTSTATUS
|
||
PptClearByteMode(
|
||
IN PFDO_EXTENSION Fdx
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine Clears Byte mode through the ECR register if there otherwise
|
||
just returns success because nothing needs to be done.
|
||
|
||
Arguments:
|
||
|
||
Fdx - Supplies the device extension.
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS - if the port type was detected.
|
||
!STATUS_SUCCESS - otherwise.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
||
// Put ECR register back to original if it was there
|
||
if ( Fdx->PnpInfo.HardwareCapabilities & PPT_ECP_PRESENT ) {
|
||
Status = PptEcrClearMode( Fdx );
|
||
}
|
||
|
||
return Status;
|
||
}
|
||
|
||
NTSTATUS
|
||
PptCheckByteMode(
|
||
IN PFDO_EXTENSION Fdx
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine checks to make sure we are still Byte capable before doing
|
||
any transfering of data.
|
||
|
||
Arguments:
|
||
|
||
Fdx - Supplies the device extension of the device we are
|
||
reporting resources for.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
PUCHAR Controller;
|
||
UCHAR dcr;
|
||
|
||
Controller = Fdx->PortInfo.Controller;
|
||
|
||
//
|
||
// run the test again to make sure somebody didn't take us out of a
|
||
// bi-directional capable port.
|
||
//
|
||
// 1. put in extended read mode.
|
||
// 2. write data pattern
|
||
// 3. read data pattern
|
||
// 4. if bi-directional capable, then data patterns will be different.
|
||
// 5. if patterns are the same, then check one more pattern.
|
||
// 6. if patterns are still the same, then port is NOT bi-directional.
|
||
//
|
||
|
||
// get the current control port value for later restoration
|
||
dcr = P5ReadPortUchar( Controller + DCR_OFFSET );
|
||
|
||
// put port into extended read mode
|
||
P5WritePortUchar( Controller + DCR_OFFSET, (UCHAR)(dcr | DCR_DIRECTION) );
|
||
|
||
// write the first pattern to the port
|
||
P5WritePortUchar( Controller, (UCHAR)0x55 );
|
||
if ( P5ReadPortUchar( Controller ) == (UCHAR)0x55 ) {
|
||
// same pattern, try the second pattern
|
||
P5WritePortUchar( Controller, (UCHAR)0xaa );
|
||
if ( P5ReadPortUchar( Controller ) == (UCHAR)0xaa ) {
|
||
// the port is NOT bi-directional capable
|
||
return STATUS_UNSUCCESSFUL;
|
||
}
|
||
}
|
||
|
||
// restore the control port to its original value
|
||
P5WritePortUchar( Controller + DCR_OFFSET, (UCHAR)dcr );
|
||
|
||
return STATUS_SUCCESS;
|
||
|
||
}
|
||
|
||
NTSTATUS
|
||
PptEcrClearMode(
|
||
IN PFDO_EXTENSION Fdx
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine disables EPP or ECP mode whichever one the chip
|
||
was in through the ECR register.
|
||
|
||
Arguments:
|
||
|
||
Fdx - Supplies the device extension.
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS - if it was successful.
|
||
!STATUS_SUCCESS - otherwise.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
UCHAR ecr;
|
||
PUCHAR Controller;
|
||
PUCHAR wPortECR;
|
||
|
||
Controller = Fdx->PortInfo.Controller;
|
||
|
||
//
|
||
// Restore the prior mode.
|
||
//
|
||
|
||
// Get original ECR register
|
||
ecr = Fdx->EcrPortData;
|
||
Fdx->EcrPortData = 0;
|
||
|
||
// some chips require to change modes only after
|
||
// you put it into spp mode
|
||
|
||
wPortECR = Fdx->PnpInfo.EcpController + ECR_OFFSET;
|
||
|
||
P5WritePortUchar( wPortECR, (UCHAR)(ecr & ECR_MODE_MASK) );
|
||
|
||
// Back to original mode
|
||
P5WritePortUchar( wPortECR, ecr );
|
||
|
||
return STATUS_SUCCESS;
|
||
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
PptBuildResourceList(
|
||
IN PFDO_EXTENSION Fdx,
|
||
IN ULONG Partial,
|
||
IN PUCHAR *Addresses,
|
||
OUT PCM_RESOURCE_LIST Resources
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine Builds a CM_RESOURCE_LIST with 1 Full Resource
|
||
Descriptor and as many Partial resource descriptors as you want
|
||
with the same parameters for the Full. No Interrupts or anything
|
||
else just IO addresses.
|
||
|
||
Arguments:
|
||
|
||
Fdx - Supplies the device extension.
|
||
Partial - Number (array size) of partial descriptors in Addresses[]
|
||
Addresses - Pointer to an Array of addresses of the partial descriptors
|
||
Resources - The returned CM_RESOURCE_LIST
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS - if the building of the list was successful.
|
||
STATUS_UNSUCCESSFUL - otherwise.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
UCHAR i;
|
||
|
||
//
|
||
// Number of Full Resource descriptors
|
||
//
|
||
Resources->Count = 1;
|
||
|
||
Resources->List[0].InterfaceType = Fdx->InterfaceType;
|
||
Resources->List[0].BusNumber = Fdx->BusNumber;
|
||
Resources->List[0].PartialResourceList.Version = 0;
|
||
Resources->List[0].PartialResourceList.Revision = 0;
|
||
Resources->List[0].PartialResourceList.Count = Partial;
|
||
|
||
//
|
||
// Going through the loop for each partial descriptor
|
||
//
|
||
for ( i = 0; i < Partial ; i++ ) {
|
||
|
||
//
|
||
// Setup port
|
||
//
|
||
Resources->List[0].PartialResourceList.PartialDescriptors[i].Type = CmResourceTypePort;
|
||
Resources->List[0].PartialResourceList.PartialDescriptors[i].ShareDisposition = CmResourceShareDriverExclusive;
|
||
Resources->List[0].PartialResourceList.PartialDescriptors[i].Flags = CM_RESOURCE_PORT_IO;
|
||
Resources->List[0].PartialResourceList.PartialDescriptors[i].u.Port.Start.QuadPart = (ULONG_PTR)Addresses[i];
|
||
Resources->List[0].PartialResourceList.PartialDescriptors[i].u.Port.Length = (ULONG)2;
|
||
|
||
}
|
||
|
||
|
||
return ( STATUS_SUCCESS );
|
||
|
||
}
|