📄 datalink.c
字号:
/*++
Copyright (C) Microsoft Corporation, 1993 - 1999
Module Name:
p12843dl.c
Abstract:
This module contains utility code used by 1284.3 Data Link.
Author:
Robbie Harris (Hewlett-Packard) 10-September-1998
Environment:
Kernel mode
Revision History :
--*/
#include "pch.h"
UCHAR Dot3_StartOfFrame1 = 0x55;
UCHAR Dot3_StartOfFrame2 = 0xaa;
UCHAR Dot3_EndOfFrame1 = 0x00;
UCHAR Dot3_EndOfFrame2 = 0xff;
NTSTATUS
ParDot3Connect(
IN PPDO_EXTENSION Pdx
)
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG ParFwdSkip = 0, ParRevSkip = 0;
ULONG ParResetChannel = (ULONG)~0, ParResetByteCount = 4, ParResetByte = 0;
ULONG ParSkipDefault = 0;
ULONG ParResetChannelDefault = (ULONG)~0;
// If an MLC device hangs we can sometimes wake it up by wacking it with
// 4 Zeros sent to the reset channel (typically 78 or 0x4E). Make this
// configurable via registry setting.
ULONG ParResetByteCountDefault = 4; // from MLC spec
ULONG ParResetByteDefault = 0; // from MLC spec
BOOLEAN bConsiderEppDangerous = FALSE;
DD((PCE)Pdx,DDT,"ParDot3Connect: enter\n");
if (P12843DL_OFF == Pdx->P12843DL.DataLinkMode) {
DD((PCE)Pdx,DDT,"ParDot3Connect: Neither Dot3 or MLC are supported - FAIL request\n");
return STATUS_UNSUCCESSFUL;
}
if (Pdx->P12843DL.bEventActive) {
DD((PCE)Pdx,DDT,"ParDot3Connect: Already connected - FAIL request\n");
return STATUS_UNSUCCESSFUL;
}
// Let's get a Device Id so we can pull settings for this device
ParTerminate(Pdx);
{ // local block
PCHAR buffer = NULL;
ULONG bufferLength;
UCHAR resultString[MAX_ID_SIZE];
ANSI_STRING AnsiIdString;
UNICODE_STRING UnicodeTemp;
RTL_QUERY_REGISTRY_TABLE paramTable[6];
UNICODE_STRING Dot3Key;
USHORT Dot3NameSize;
NTSTATUS status;
RtlZeroMemory(resultString, MAX_ID_SIZE);
// ask the device how large of a buffer is needed to hold it's raw device id
if ( Pdx->Ieee1284Flags & ( 1 << Pdx->Ieee1284_3DeviceId ) ) {
buffer = Par3QueryDeviceId(Pdx, NULL, 0, &bufferLength, FALSE, TRUE);
} else{
buffer = Par3QueryDeviceId(Pdx, NULL, 0, &bufferLength, FALSE, FALSE);
}
if( !buffer ) {
DD((PCE)Pdx,DDT,"ParDot3Connect - Couldn't alloc pool for DevId - FAIL request\n");
return STATUS_UNSUCCESSFUL;
}
DD((PCE)Pdx,DDT,"ParDot3Connect - 1284 ID string = <%s>\n",buffer);
// extract the part of the ID that we want from the raw string
// returned by the hardware
Status = ParPnpGetId( buffer, BusQueryDeviceID, (PCHAR)resultString, NULL );
StringSubst( (PCHAR)resultString, ' ', '_', (USHORT)strlen((const PCHAR)resultString) );
DD((PCE)Pdx,DDT,"ParDot3Connect: resultString Post StringSubst = <%s>\n",resultString);
// were we able to extract the info that we want from the raw ID string?
if( !NT_SUCCESS(Status) ) {
DD((PCE)Pdx,DDT,"ParDot3Connect - Call to ParPnpGetId Failed - FAIL request\n");
if( buffer ) {
ExFreePool( buffer );
}
return STATUS_UNSUCCESSFUL;
}
// Does the ID that we just retrieved from the device match the one
// that we previously saved in the device extension?
if(0 != strcmp( (const PCHAR)Pdx->DeviceIdString, (const PCHAR)resultString)) {
DD((PCE)Pdx,DDT,"ParDot3Connect - strcmp shows NO MATCH\n");
// DVDF - we may want to trigger a reenumeration since we know that the device changed
}
// Ok, now we have what we need to look in the registry
// and pull some prefs.
RtlZeroMemory(¶mTable[0], sizeof(paramTable));
paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
paramTable[0].Name = (PWSTR)L"ParFwdSkip";
paramTable[0].EntryContext = &ParFwdSkip;
paramTable[0].DefaultType = REG_DWORD;
paramTable[0].DefaultData = &ParSkipDefault;
paramTable[0].DefaultLength = sizeof(ULONG);
paramTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
paramTable[1].Name = (PWSTR)L"ParRevSkip";
paramTable[1].EntryContext = &ParRevSkip;
paramTable[1].DefaultType = REG_DWORD;
paramTable[1].DefaultData = &ParSkipDefault;
paramTable[1].DefaultLength = sizeof(ULONG);
paramTable[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
paramTable[2].Name = (PWSTR)L"ParRC";
paramTable[2].EntryContext = &ParResetChannel;
paramTable[2].DefaultType = REG_DWORD;
paramTable[2].DefaultData = &ParResetChannelDefault;
paramTable[2].DefaultLength = sizeof(ULONG);
paramTable[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
paramTable[3].Name = (PWSTR)L"ParRBC";
paramTable[3].EntryContext = &ParResetByteCount;
paramTable[3].DefaultType = REG_DWORD;
paramTable[3].DefaultData = &ParResetByteCountDefault;
paramTable[3].DefaultLength = sizeof(ULONG);
paramTable[4].Flags = RTL_QUERY_REGISTRY_DIRECT;
paramTable[4].Name = (PWSTR)L"ParRBD";
paramTable[4].EntryContext = &ParResetByte;
paramTable[4].DefaultType = REG_DWORD;
paramTable[4].DefaultData = &ParResetByteDefault;
paramTable[4].DefaultLength = sizeof(ULONG);
Dot3Key.Buffer = NULL;
Dot3Key.Length = 0;
Dot3NameSize = sizeof(L"Dot3\\") + sizeof(UNICODE_NULL);
Dot3Key.MaximumLength = (USHORT)( Dot3NameSize + (sizeof(resultString) * sizeof(WCHAR)) );
Dot3Key.Buffer = ExAllocatePool(PagedPool,
Dot3Key.MaximumLength);
if( !Dot3Key.Buffer ) {
DD((PCE)Pdx,DDT,"ParDot3Connect - ExAllocatePool for Registry Check failed - FAIL request\n");
if( buffer ) {
ExFreePool( buffer );
}
return STATUS_UNSUCCESSFUL;
}
DD((PCE)Pdx,DDT,"ParDot3Connect: ready to Zero buffer, &Dot3Key= %x , MaximumLength=%d\n",&Dot3Key, Dot3Key.MaximumLength);
RtlZeroMemory(Dot3Key.Buffer, Dot3Key.MaximumLength);
status = RtlAppendUnicodeToString(&Dot3Key, (PWSTR)L"Dot3\\");
ASSERT( NT_SUCCESS(status) );
DD((PCE)Pdx,DDT,"ParDot3Connect:\"UNICODE\" Dot3Key S = <%S>\n",Dot3Key.Buffer);
DD((PCE)Pdx,DDT,"ParDot3Connect:\"UNICODE\" Dot3Key wZ = <%wZ>\n",&Dot3Key);
DD((PCE)Pdx,DDT,"ParDot3Connect:\"RAW\" resultString string = <%s>\n",resultString);
RtlInitAnsiString(&AnsiIdString,(const PCHAR)resultString);
status = RtlAnsiStringToUnicodeString(&UnicodeTemp,&AnsiIdString,TRUE);
if( NT_SUCCESS( status ) ) {
DD((PCE)Pdx,DDT,"ParDot3Connect:\"UNICODE\" UnicodeTemp = <%S>\n",UnicodeTemp.Buffer);
Dot3Key.Buffer[(Dot3NameSize / sizeof(WCHAR)) - 1] = UNICODE_NULL;
DD((PCE)Pdx,DDT,"ParDot3Connect:\"UNICODE\" Dot3Key (preappend) = <%S>\n",Dot3Key.Buffer);
status = RtlAppendUnicodeStringToString(&Dot3Key, &UnicodeTemp);
if( NT_SUCCESS( status ) ) {
DD((PCE)Pdx,DDT,"ParDot3Connect: ready to call RtlQuery...\n");
Status = RtlQueryRegistryValues( RTL_REGISTRY_CONTROL, Dot3Key.Buffer, ¶mTable[0], NULL, NULL);
DD((PCE)Pdx,DDT,"ParDot3Connect: RtlQueryRegistryValues Status = %x\n",Status);
}
RtlFreeUnicodeString(&UnicodeTemp);
}
if( Dot3Key.Buffer ) {
ExFreePool (Dot3Key.Buffer);
}
// no longer needed
ExFreePool(buffer);
if (!NT_SUCCESS(Status)) {
// registry read failed
DD((PCE)Pdx,DDT,"ParDot3Connect: No Periph Defaults in Registry\n");
DD((PCE)Pdx,DDT,"ParDot3Connect: No Periph Defaults in Registry\n");
// registry read failed, use defaults and consider EPP to be dangerous
ParRevSkip = ParFwdSkip = ParSkipDefault;
bConsiderEppDangerous = TRUE;
}
DD((PCE)Pdx,DDT,"ParDot3Connect: pre IeeeNegotiateBestMode\n");
// if we don't have registry overrides then use what the
// peripheral told us otherwise stick with defaults.
if (ParSkipDefault == ParRevSkip) {
ParRevSkip = Pdx->P12843DL.RevSkipMask;
} else {
Pdx->P12843DL.RevSkipMask = (USHORT)ParRevSkip;
}
if (ParSkipDefault == ParFwdSkip) {
ParFwdSkip = Pdx->P12843DL.FwdSkipMask;
} else {
Pdx->P12843DL.FwdSkipMask = (USHORT)ParFwdSkip;
}
if( bConsiderEppDangerous ) {
ParFwdSkip |= EPP_ANY;
ParRevSkip |= EPP_ANY;
}
Status = IeeeNegotiateBestMode(Pdx, (USHORT)ParRevSkip, (USHORT)ParFwdSkip);
if( !NT_SUCCESS(Status) ) {
DD((PCE)Pdx,DDT,"ParDot3Connect - Peripheral Negotiation Failed - FAIL dataLink connect\n");
return Status;
}
Pdx->ForwardInterfaceAddress = Pdx->P12843DL.DataChannel;
if (Pdx->P12843DL.DataLinkMode == P12843DL_MLC_DL) {
if (ParResetChannel != ParResetChannelDefault) {
Pdx->P12843DL.ResetByte = (UCHAR) ParResetByte & 0xff;
Pdx->P12843DL.ResetByteCount = (UCHAR) ParResetByteCount & 0xff;
if (ParResetChannel == PAR_COMPATIBILITY_RESET) {
Pdx->P12843DL.fnReset = ParMLCCompatReset;
} else {
// Max ECP channel is 127 so let's mask off bogus bits.
Pdx->P12843DL.ResetChannel = (UCHAR) ParResetChannel & 0x7f;
Pdx->P12843DL.fnReset = ParMLCECPReset;
}
}
}
if (Pdx->P12843DL.fnReset) {
DD((PCE)Pdx,DDT,"ParDot3Connect: MLCReset is supported on %x\n",Pdx->P12843DL.ResetChannel);
Status = ((PDOT3_RESET_ROUTINE) (Pdx->P12843DL.fnReset))(Pdx);
} else {
DD((PCE)Pdx,DDT,"ParDot3Connect - MLCReset is not supported\n");
Status = ParSetFwdAddress(Pdx);
}
if( !NT_SUCCESS(Status) ) {
DD((PCE)Pdx,DDT,"ParDot3Connect - Couldn't Set Address - FAIL request\n");
return Status;
}
// Check to make sure we are ECP, BECP, or EPP
DD((PCE)Pdx,DDT,"ParDot3Connect: pre check of ECP, BECP, EPP\n");
if (afpForward[Pdx->IdxForwardProtocol].ProtocolFamily != FAMILY_BECP &&
afpForward[Pdx->IdxForwardProtocol].ProtocolFamily != FAMILY_ECP &&
afpForward[Pdx->IdxForwardProtocol].ProtocolFamily != FAMILY_EPP) {
DD((PCE)Pdx,DDT,"ParDot3Connect - We did not reach ECP or EPP - FAIL request\n");
return STATUS_UNSUCCESSFUL;
}
} // end local block
if (Pdx->P12843DL.DataLinkMode == P12843DL_DOT3_DL) {
DD((PCE)Pdx,DDT,"ParDot3Connect - P12843DL_DOT3_DL\n");
Pdx->P12843DL.fnRead = arpReverse[Pdx->IdxReverseProtocol].fnRead;
Pdx->P12843DL.fnWrite = afpForward[Pdx->IdxForwardProtocol].fnWrite;
Pdx->fnRead = ParDot3Read;
Pdx->fnWrite = ParDot3Write;
}
DD((PCE)Pdx,DDT,"ParDot3Connect - Exit with status %x\n",Status);
return Status;
}
VOID
ParDot3CreateObject(
IN PPDO_EXTENSION Pdx,
IN PCHAR DOT3DL,
IN PCHAR DOT3C
)
{
Pdx->P12843DL.DataLinkMode = P12843DL_OFF;
Pdx->P12843DL.fnReset = NULL;
DD((PCE)Pdx,DDT,"ParDot3CreateObject - DOT3DL [%s] DOT3C\n",DOT3DL, DOT3C);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -