|
|
/*++
Copyright (C) Microsoft Corporation, 1993 - 1999
Module Name:
util.c
Abstract:
This module contains utility code used by other 1284 modules.
Author:
Robbie Harris (Hewlett-Packard) 20-May-1998
Environment:
Kernel mode
Revision History :
--*/
#include "pch.h"
#include "ecp.h"
//============================================================================
// NAME: BusReset()
//
// Performs a bus reset as defined in Chapter 7.2 of the
// 1284-1994 spec.
//
// PARAMETERS:
// DCRController - Supplies the base address of of the DCR.
//
// RETURNS:
// nothing
//============================================================================
void BusReset( IN PUCHAR DCRController ) { UCHAR dcr;
dcr = READ_PORT_UCHAR(DCRController); // Set 1284 and nInit low.
dcr = UPDATE_DCR(dcr, DONT_CARE, DONT_CARE, INACTIVE, INACTIVE, DONT_CARE, DONT_CARE); WRITE_PORT_UCHAR(DCRController, dcr); KeStallExecutionProcessor(100); // Legacy Zip will hold what looks to be
// a bus reset for 9us. Since this proc is used
// to trigger a logic analyzer... let's hold
// for 100us
}
BOOLEAN CheckPort( IN PUCHAR wPortAddr, IN UCHAR bMask, IN UCHAR bValue, IN USHORT msTimeDelay ) /*++
Routine Description: This routine will loop for a given time period (actual time is passed in as an arguement) and wait for the dsr to match predetermined value (dsr value is passed in).
Arguments: wPortAddr - Supplies the base address of the parallel port + some offset. This will have us point directly to the dsr (controller + 1). bMask - Mask used to determine which bits we are looking at bValue - Value we are looking for. msTimeDelay - Max time to wait for peripheral response (in ms)
Return Value: TRUE if a dsr match was found. FALSE if the time period expired before a match was found. --*/
{ UCHAR dsr; LARGE_INTEGER Wait; LARGE_INTEGER Start; LARGE_INTEGER End;
// Do a quick check in case we have one stinkingly fast peripheral!
dsr = READ_PORT_UCHAR(wPortAddr); if ((dsr & bMask) == bValue) return TRUE;
Wait.QuadPart = (msTimeDelay * 10 * 1000) + KeQueryTimeIncrement(); KeQueryTickCount(&Start);
CheckPort_Start: KeQueryTickCount(&End); dsr = READ_PORT_UCHAR(wPortAddr); if ((dsr & bMask) == bValue) return TRUE;
if ((End.QuadPart - Start.QuadPart) * KeQueryTimeIncrement() > Wait.QuadPart) { // We timed out!!!
// do one last check
dsr = READ_PORT_UCHAR(wPortAddr); if ((dsr & bMask) == bValue) return TRUE;
#if DVRH_BUS_RESET_ON_ERROR
BusReset(wPortAddr+1); // Pass in the dcr address
#endif
#if DBG
ParDump2(PARERRORS, ("CheckPort: Timeout\n")); ParDump2(PARERRORS, ("<==========================================================\n")); { int i;
for (i = 3; i < 8; i++) { if ((bMask >> i) & 1) { if (((bValue >> i) & 1) != ((dsr >> i) & 1)) { ParDump2(PARERRORS, ("\t\t Bit %d is %d and should be %d!!!\n", i, (dsr >> i) & 1, (bValue >> i) & 1)); } } } } ParDump2(PARERRORS, ("<==========================================================\n")); #endif
goto CheckPort_TimeOut; } goto CheckPort_Start;
CheckPort_TimeOut:
return FALSE; }
BOOLEAN CheckTwoPorts( PUCHAR pPortAddr1, UCHAR bMask1, UCHAR bValue1, PUCHAR pPortAddr2, UCHAR bMask2, UCHAR bValue2, USHORT msTimeDelay ) { int i; UCHAR bPort1; UCHAR bPort2; LARGE_INTEGER Wait; LARGE_INTEGER Start; LARGE_INTEGER End;
// Do a quick check in case we have one stinkingly fast peripheral!
bPort1 = READ_PORT_UCHAR( pPortAddr1 ); if ( ( bPort1 & bMask1 ) == bValue1 ) { return TRUE; } bPort2 = READ_PORT_UCHAR( pPortAddr2 ); if ( ( bPort2 & bMask2 ) == bValue2 ) { return FALSE; }
Wait.QuadPart = (msTimeDelay * 10 * 1000) + KeQueryTimeIncrement(); KeQueryTickCount(&Start);
CheckTwoPorts_Start: KeQueryTickCount(&End);
bPort1 = READ_PORT_UCHAR( pPortAddr1 ); if ( ( bPort1 & bMask1 ) == bValue1 ) { return TRUE; } bPort2 = READ_PORT_UCHAR( pPortAddr2 ); if ( ( bPort2 & bMask2 ) == bValue2 ) { return FALSE; }
if ((End.QuadPart - Start.QuadPart) * KeQueryTimeIncrement() > Wait.QuadPart) { // We timed out!!!
// Recheck the values
bPort1 = READ_PORT_UCHAR( pPortAddr1 ); if ( ( bPort1 & bMask1 ) == bValue1 ) { return TRUE; } bPort2 = READ_PORT_UCHAR( pPortAddr2 ); if ( ( bPort2 & bMask2 ) == bValue2 ) { return FALSE; }
#if DVRH_BUS_RESET_ON_ERROR
BusReset(pPortAddr1+1); // Pass in the dcr address
#endif
// Device never responded, return timeout status.
return FALSE; } goto CheckTwoPorts_Start;
return FALSE; } // CheckPort2...
PWSTR ParCreateWideStringFromUnicodeString(PUNICODE_STRING UnicodeString) /*++
Routine Description:
Create a UNICODE_NULL terminated WSTR given a UNICODE_STRING.
This function allocates PagedPool, copies the UNICODE_STRING buffer to the allocation, and appends a UNICODE_NULL to terminate the WSTR *** This function allocates pool. ExFreePool must be called to free the allocation when the buffer is no longer needed.
Arguments:
UnicodeString - The source
Return Value:
PWSTR - if successful
NULL - otherwise
--*/ { PWSTR buffer; ULONG length = UnicodeString->Length;
buffer = ExAllocatePool( PagedPool, length + sizeof(UNICODE_NULL) ); if(!buffer) { return NULL; // unable to allocate pool, bail out
} else { RtlCopyMemory(buffer, UnicodeString->Buffer, length); buffer[length/2] = UNICODE_NULL; return buffer; } }
NTSTATUS ParCreateDevice( IN PDRIVER_OBJECT DriverObject, IN ULONG DeviceExtensionSize, IN PUNICODE_STRING DeviceName OPTIONAL, IN DEVICE_TYPE DeviceType, IN ULONG DeviceCharacteristics, IN BOOLEAN Exclusive, OUT PDEVICE_OBJECT *DeviceObject ) { NTSTATUS status; status = IoCreateDevice( DriverObject, DeviceExtensionSize, DeviceName, DeviceType, (DeviceCharacteristics | FILE_DEVICE_SECURE_OPEN), Exclusive, DeviceObject ); return status; }
VOID ParInitializeExtension1284Info( IN PDEVICE_EXTENSION Extension ) // make this a function since it is now called from two places:
// - 1) when initializing a new devobj
// - 2) from CreateOpen
{ USHORT i;
Extension->Connected = FALSE; if (DefaultModes) { USHORT rev = (USHORT) (DefaultModes & 0xffff); USHORT fwd = (USHORT)((DefaultModes & 0xffff0000)>>16); switch (fwd) { case BOUNDED_ECP: Extension->IdxForwardProtocol = BOUNDED_ECP_FORWARD; break; case ECP_HW_NOIRQ: case ECP_HW_IRQ: Extension->IdxForwardProtocol = ECP_HW_FORWARD_NOIRQ; break; case ECP_SW: Extension->IdxForwardProtocol = ECP_SW_FORWARD; break; case EPP_HW: Extension->IdxForwardProtocol = EPP_HW_FORWARD; break; case EPP_SW: Extension->IdxForwardProtocol = EPP_SW_FORWARD; break; case IEEE_COMPATIBILITY: Extension->IdxForwardProtocol = IEEE_COMPAT_MODE; break; case CENTRONICS: default: Extension->IdxForwardProtocol = CENTRONICS_MODE; break; } switch (rev) { case BOUNDED_ECP: Extension->IdxReverseProtocol = BOUNDED_ECP_REVERSE; break; case ECP_HW_NOIRQ: case ECP_HW_IRQ: Extension->IdxReverseProtocol = ECP_HW_REVERSE_NOIRQ; break; case ECP_SW: Extension->IdxReverseProtocol = ECP_SW_REVERSE; break; case EPP_HW: Extension->IdxReverseProtocol = EPP_HW_REVERSE; break; case EPP_SW: Extension->IdxReverseProtocol = EPP_SW_REVERSE; break; case BYTE_BIDIR: Extension->IdxReverseProtocol = BYTE_MODE; break; case CHANNEL_NIBBLE: case NIBBLE: default: Extension->IdxReverseProtocol = NIBBLE_MODE; break; } } else { Extension->IdxReverseProtocol = NIBBLE_MODE; Extension->IdxForwardProtocol = CENTRONICS_MODE; } Extension->bShadowBuffer = FALSE; Extension->ProtocolModesSupported = 0; Extension->BadProtocolModes = 0; Extension->IsCritical = FALSE; #if (1 == DVRH_USE_CORRECT_PTRS)
Extension->fnRead = NULL; Extension->fnWrite = NULL; // Extension->fnRead = arpReverse[Extension->IdxReverseProtocol].fnRead;
// Extension->fnWrite = afpForward[Extension->IdxForwardProtocol].fnWrite;
#endif
Extension->ForwardInterfaceAddress = DEFAULT_ECP_CHANNEL; Extension->ReverseInterfaceAddress = DEFAULT_ECP_CHANNEL; Extension->SetForwardAddress = FALSE; Extension->SetReverseAddress = FALSE; Extension->bIsHostRecoverSupported = FALSE; Extension->IsIeeeTerminateOk = FALSE;
for (i = FAMILY_NONE; i < FAMILY_MAX; i++) { Extension->ProtocolData[i] = 0; } }
#if (1 == DVRH_DELAY_THEORY)
void DVRH_Diagnostic_Delay() { LARGE_INTEGER Interval;
//in 100ns increments
Interval.QuadPart = 1000; KeDelayExecutionThread( KernelMode, FALSE, &Interval ); } #endif
VOID ParGetDriverParameterDword( IN PUNICODE_STRING ServicePath, IN PWSTR ParameterName, IN OUT PULONG ParameterValue ) /*++
Read registry DWORD from <ServicePath>\Parameters
--*/ { NTSTATUS status; RTL_QUERY_REGISTRY_TABLE paramTable[2]; PWSTR suffix = L"\\Parameters"; ULONG defaultValue; UNICODE_STRING path = {0,0,0}; ULONG length;
//
// Sanity check parameters
//
if( ( NULL == ServicePath->Buffer ) || ( NULL == ParameterName ) || ( NULL == ParameterValue ) ) { return; }
//
// set up table entries for call to RtlQueryRegistryValues
//
RtlZeroMemory( paramTable, sizeof(paramTable));
defaultValue = *ParameterValue;
paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; paramTable[0].Name = ParameterName; paramTable[0].EntryContext = ParameterValue; paramTable[0].DefaultType = REG_DWORD; paramTable[0].DefaultData = &defaultValue; paramTable[0].DefaultLength = sizeof(ULONG);
//
// leave paramTable[2] as all zeros - this terminates the table
//
//
// compute the size of the path including the "parameters" suffix
//
length = ( sizeof(WCHAR) * wcslen( suffix ) ) + sizeof(UNICODE_NULL); length += RegistryPath.Length;
//
// construct the path as: <ServiceName>\Parameters
//
path.Buffer = ExAllocatePool( PagedPool, length ); if( NULL == path.Buffer ) { return; }
RtlZeroMemory( path.Buffer, length ); path.MaximumLength = (USHORT)length; RtlCopyUnicodeString( &path, &RegistryPath ); RtlAppendUnicodeToString( &path, suffix ); ParDump2(PARREG,("util::ParGetDriverParameterDword - path = <%wZ>\n", &path));
ParDump2(PARREG,("util::ParGetDriverParameterDword - pre-query value = %x\n", *ParameterValue));
//
// query registry
//
status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, path.Buffer, ¶mTable[0], NULL, NULL); RtlFreeUnicodeString( &path );
ParDump2(PARREG,("util::ParGetDriverParameterDword - post-query value = %x\n", *ParameterValue)); ParDump2(PARREG,("util::ParGetDriverParameterDword - status from RtlQueryRegistryValues on SubKey = %x\n", status) );
return; }
|