📄 parmode.c
字号:
Extension - Supplies the device extension.
Return Value:
STATUS_SUCCESS - if it was successful.
!STATUS_SUCCESS - otherwise.
--*/
{
UCHAR ecr;
PUCHAR Controller;
PUCHAR wPortECR;
Controller = Extension->PortInfo.Controller;
//
// Restore the prior mode.
//
// Get original ECR register
ecr = Extension->EcrPortData;
Extension->EcrPortData = 0;
// some chips require to change modes only after
// you put it into spp mode
#if (0 == DVRH_USE_PARPORT_ECP_ADDR)
wPortECR = Controller + ECR_OFFSET;
#else
wPortECR = Extension->PnpInfo.EcpController + ECR_OFFSET;
#endif
WRITE_PORT_UCHAR( wPortECR, (UCHAR)(ecr & ECR_MODE_MASK) );
// Back to original mode
WRITE_PORT_UCHAR( wPortECR, ecr );
return STATUS_SUCCESS;
}
NTSTATUS
PptFindNatChip(
IN PDEVICE_EXTENSION Extension
)
/*++
Routine Description:
This routine finds out if there is a National Semiconductor IO chip on
this machine. If it finds a National chip it then determines if this
instance of Parport is using this chips paralle port IO address.
Arguments:
Extension - Supplies the device extension.
Return Value:
STATUS_SUCCESS - if we were able to check for the parallel chip.
STATUS_UNSUCCESSFUL - if we were not able to check for the parallel chip.
Updates:
Extension->
NationalChecked
NationalChipFound
--*/
{
BOOLEAN found = FALSE; // return code, assumed value
BOOLEAN OkToLook = FALSE;
BOOLEAN Conflict;
PUCHAR ChipAddr[4] = { (PUCHAR)0x398, (PUCHAR)0x26e, (PUCHAR)0x15c, (PUCHAR)0x2e }; // list of valid chip addresses
PUCHAR AddrList[4] = { (PUCHAR)0x378, (PUCHAR)0x3bc, (PUCHAR)0x278, (PUCHAR)0x00 }; // List of valid Parallel Port addresses
PUCHAR PortAddr; // Chip Port Address
ULONG_PTR Port; // Chip Port Read Value
UCHAR SaveIdx; // Save the index register value
UCHAR cr; // config register value
UCHAR ii; // loop index
NTSTATUS Status; // Status of success
ULONG ResourceDescriptorCount;
ULONG ResourcesSize;
PCM_RESOURCE_LIST Resources;
ULONG NationalChecked = 0;
ULONG NationalChipFound = 0;
//
// Quick exit if we already know the answer
//
if ( Extension->NationalChecked == TRUE ) {
PptDump2(PARINITDEV, ("ParMode::PptFindNatChip: Already found NatSemi\n") );
return STATUS_SUCCESS;
}
//
// Mark extension so that we can quick exit the next time we are asked this question
//
Extension->NationalChecked = TRUE;
//
// Check the registry - we should only need to check this once per installation
//
PptRegGetDeviceParameterDword(Extension->PhysicalDeviceObject, (PWSTR)L"NationalChecked", &NationalChecked);
if( NationalChecked ) {
//
// We previously performed the NatSemi Check - extract result from registry
//
PptRegGetDeviceParameterDword(Extension->PhysicalDeviceObject, (PWSTR)L"NationalChipFound", &NationalChipFound);
if( NationalChipFound ) {
Extension->NationalChipFound = TRUE;
} else {
Extension->NationalChipFound = FALSE;
}
return STATUS_SUCCESS;
}
//
// This is our first, and hopefully last time that we need to make this check
// for this installation
//
//
// Allocate a block of memory for constructing a resource descriptor
//
// number of partial descriptors
ResourceDescriptorCount = sizeof(ChipAddr)/sizeof(ULONG);
// size of resource descriptor list + space for (n-1) more partial descriptors
// (resource descriptor list includes one partial descriptor)
ResourcesSize = sizeof(CM_RESOURCE_LIST) +
(ResourceDescriptorCount - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
Resources = (PCM_RESOURCE_LIST)ExAllocatePool(NonPagedPool, ResourcesSize);
if (Resources == NULL) {
PptDump2(PARINITDEV, ("ParMode::PptFindNatChip: No Resources Punting\n"));
// Error out
return(STATUS_UNSUCCESSFUL);
}
// zero out memory block as a precaution
RtlZeroMemory(Resources, ResourcesSize);
//
// Build the Resource List
//
Status = PptBuildResourceList( Extension,
sizeof(ChipAddr)/sizeof(ULONG),
&ChipAddr[0],
Resources
);
// Check to see if it was successful
if ( !NT_SUCCESS( Status ) )
{
PptDump2(PARINITDEV, ("ParMode::PptFindNatChip: Couldn't build Resources list. Punting\n") );
ExFreePool( Resources );
return ( Status );
}
//
// check to see if we can use the io addresses where
// national chipsets are located
//
Status = IoReportResourceUsage( NULL,
Extension->DriverObject,
Resources,
sizeof(Resources),
Extension->DeviceObject,
NULL,
0,
FALSE,
&Conflict
);
// done with resource list
ExFreePool( Resources );
// Check to see if IoReportResourceUsage was successful
if ( !NT_SUCCESS( Status ) )
{
PptDump2(PARINITDEV, ("ParMode::PptFindNatChip: Couldn't report usage. Punting\n") );
return ( Status );
}
// Check to see if it was successful
if ( Conflict )
{
PptDump2(PARINITDEV, ("ParMode::PptFindNatChip: Conflict. Punting\n"));
return ( STATUS_UNSUCCESSFUL );
}
// Was successful so now we check each of the addresses that we have
// the resources for
//
// the following for loop is a state machine that checks modes and
// port addresses.
//
// state 0: check for Pc873 at primary port address
// state 1: check for Pc873 at secondary port address
// state 2: check for Pc873 at Ter port address
// state 3: check for Pc873 at Quad port address
for ( ii = 0; !found && ii < 4; ii++ ) {
PortAddr = (PUCHAR)ChipAddr[ii];
// After power up the index register will read back an 0xAA one time only.
// So we'll check for that first.
// Then it should read back a 0 or a valid register number
if(( READ_PORT_UCHAR( PortAddr ) == 0x88 )
&& ( READ_PORT_UCHAR( PortAddr ) < 0x20 )) {
OkToLook = TRUE;
} else {
// Or it could read back a 0 or a valid register number
READ_PORT_UCHAR( PortAddr ); // may read back 0 here
cr = READ_PORT_UCHAR( PortAddr ); // valid register no.
// is it really valid?
// if( cr < 0x20 ) { - dvdr
if( cr != 0xff ) {
// does it read back the same?
if( READ_PORT_UCHAR( PortAddr ) == cr)
OkToLook = TRUE;
}
} // end else
// take a closer look by writing to the chip
if ( OkToLook ) {
OkToLook = FALSE;
// setup for ID reg
WRITE_PORT_UCHAR( PortAddr, REG_CR8 );
// read it back
cr = READ_PORT_UCHAR( PortAddr );
// does it read back the same?
if( cr == REG_CR8 ) {
// get the ID number.
cr = (UCHAR)( READ_PORT_UCHAR( PortAddr + 1 ) & 0xf0 );
// if the up. nib. is 1,3,5,6,7,9,A,B,C
if( cr == PC87332 || cr == PC87334 || cr == PC87306 || cr == PC87303 ||
cr == PC87323 || cr == PC87336 || cr == PC87338 || cr == PC873xx ) {
// we found a national chip
found = TRUE;
// setup for Address reg
WRITE_PORT_UCHAR( PortAddr, REG_CR1 );
// read it back
Port = READ_PORT_UCHAR( PortAddr + 1 ) & 0x03;
// Check the base address
if ( Extension->PortInfo.Controller == (PUCHAR)AddrList[ Port ] ) {
//
// it is using the same address that Parport is using
// so we set the flag to not use generic ECP and EPP
//
Extension->NationalChipFound = TRUE;
}
}
} // reads back ok
} // end OkToLook
// check to see if we found it
if ( !found ) {
// Check for the 307/308 chips
SaveIdx = READ_PORT_UCHAR( PortAddr );
// Setup for SID Register
WRITE_PORT_UCHAR( PortAddr, PC873_DEVICE_ID );
// Zero the ID register to start and because it is read only it will
// let us know whether it is this chip
WRITE_PORT_UCHAR( PortAddr + 1, REG_CR0 );
// get the ID number.
cr = (UCHAR)( READ_PORT_UCHAR( PortAddr + 1 ) & 0xf8 );
if ( (cr == PC87307) || (cr == PC87308) ) {
// we found a new national chip
found = TRUE;
// Set the logical device
WRITE_PORT_UCHAR( PortAddr, PC873_LOGICAL_DEV_REG );
WRITE_PORT_UCHAR( PortAddr+1, PC873_PP_LDN );
// set up for the base address MSB register
WRITE_PORT_UCHAR( PortAddr, PC873_BASE_IO_ADD_MSB );
// get the MSB of the base address
Port = (ULONG_PTR)((READ_PORT_UCHAR( PortAddr + 1 ) << 8) & 0xff00);
// Set up for the base address LSB register
WRITE_PORT_UCHAR( PortAddr, PC873_BASE_IO_ADD_LSB );
// Get the LSBs of the base address
Port |= READ_PORT_UCHAR( PortAddr + 1 );
// Check the base address
if ( Extension->PortInfo.Controller == (PUCHAR)Port ) {
//
// it is using the same address that Parport is using
// so we set the flag to not use generic ECP and EPP
//
Extension->NationalChipFound = TRUE;
}
} else {
WRITE_PORT_UCHAR( PortAddr, SaveIdx );
}
}
} // end of for ii...
//
// Check for NatSemi chip is complete - save results in registry so that we never
// have to make this check again for this port
//
{
PDEVICE_OBJECT pdo = Extension->PhysicalDeviceObject;
NationalChecked = 1;
NationalChipFound = Extension->NationalChipFound ? 1 : 0;
// we ignore status here because there is nothing we can do if the calls fail
PptRegSetDeviceParameterDword(pdo, (PWSTR)L"NationalChecked", &NationalChecked);
PptRegSetDeviceParameterDword(pdo, (PWSTR)L"NationalChipFound", &NationalChipFound);
}
//
// release the io addresses where we checked for the national chipsets
// we do this by calling IoReportResourceUsage with all NULL parameters
//
Status = IoReportResourceUsage( NULL,
Extension->DriverObject,
NULL,
0,
Extension->DeviceObject,
NULL,
0,
FALSE,
&Conflict
);
PptDump2(PARINITDEV, ("ParMode::PptFindNatChip: return isFound [%x]\n", Extension->NationalChipFound));
return ( Status );
} // end of ParFindNat()
NTSTATUS
PptBuildResourceList(
IN PDEVICE_EXTENSION Extension,
IN ULONG Partial,
IN PULONG 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:
Extension - 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 = Extension->InterfaceType;
Resources->List[0].BusNumber = Extension->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 = Addresses[i];
Resources->List[0].PartialResourceList.PartialDescriptors[i].u.Port.Length = (ULONG)2;
}
return ( STATUS_SUCCESS );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -