Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2843 lines
84 KiB

/*++
*****************************************************************************
* *
* This software contains proprietary and confidential information of *
* *
* Digi International Inc. *
* *
* By accepting transfer of this copy, Recipient agrees to retain this *
* software in confidence, to prevent disclosure to others, and to make *
* no use of this software other than that for which it was delivered. *
* This is an unpublished copyrighted work of Digi International Inc. *
* Except as permitted by federal law, 17 USC 117, copying is strictly *
* prohibited. *
* *
*****************************************************************************
Module Name:
ntxall.c
Abstract:
This module is responsible for the hardware dependent functions for
DigiBoard PC/X* and MC/X* line of products.
Revision History:
--*/
/*
* $Log: /Components/Windows/NT/Async/NTXALL/NTXALL.C $
*
* 1 3/05/96 10:18a Stana
* Miniport driver for everything but CX, EPC and XEM
* Revision 2.2 1995/09/25 16:22:02 dirkh
* Fix syntax error when build < 807.
* Revision 2.1 1995/09/19 18:26:20 dirkh
* Remove unused routines: StartIo, Read, Write, Flush, IoControl.
* Collapse to XallSuccess several identical routines (Cleanup, [Query,Set]Info, QueryVolumeInfo).
* Handle shared memory window locking more cleanly.
* Longest timeout interval is 0.1s (instead of 1s).
* Consistent init timeouts: 3s reset, 10/20s BIOS, 5/10s FEP.
* Revision 2.0 1995/09/19 14:11:16 dirkh
* Sort baud rate table.
* Declare baud rate and modem signal tables as constant arrays.
*
* Revision 1.20 1994/12/20 23:44:24 rik
* conditionally compile LargeInteger manipulations.
*
* Revision 1.19 1994/12/09 14:25:34 rik
* #if Int32x32 back to RtlLarge for NT 3.1 release
*
* Revision 1.18 1994/11/28 09:20:01 rik
* changed RtlLarge math functions to direct 64-bit manipulation.
*
* Revision 1.17 1994/09/13 07:36:47 rik
* Changed global static to just global for better debugging.
*
* Revision 1.16 1994/07/31 14:41:36 rik
* added 200 baud to baud table.
*
* Revision 1.15 1994/06/18 12:45:14 rik
* Closed files and freeing memory which wasn't happening before.
* Update DigiLogError msg's to include Line # of error.
*
* Revision 1.14 1994/05/11 13:26:16 rik
* Updated for new build version preprocessing
*
* Revision 1.13 1994/04/10 14:03:57 rik
* Converted portion of code which wasn't ported to access memory properly.
* Fixed problem with looking at wrong place on controller memory to determine
* if the buffer sizes should be resized.
*
* Revision 1.12 1994/02/23 03:25:42 rik
* Changed so the controllers firmware can be downloaded from a binary file.
* This releases some physical memory was just wasted previously.
*
* Also updated so when compiling with a Windows NT OS and tools release greater
* than 528, then pagable code is compiled into the driver. This greatly
* reduced the size of in memory code, especially the hardware specific
* miniports.
*
* Revision 1.11 1993/09/07 14:33:55 rik
* Ported memory mapped access to properly work with DEC Alpha machines.
*
* Revision 1.10 1993/08/27 10:21:22 rik
* Deleted a BreakPoint in the init code.
*
* Revision 1.9 1993/08/25 17:43:32 rik
* Added support for Microchannel controllers.
*
* Revision 1.8 1993/06/25 10:14:02 rik
* Changed Error logging to allow me to pass in up to 2 strings which
* will be dynamically inserted into the event log message.
*
* Added support for baud rates 57600 & 115200.
*
* Revision 1.7 1993/06/06 14:56:06 rik
* Removed an uninitialized variable which wasn't being used anyway.
*
* Revision 1.6 1993/05/20 21:55:06 rik
* Deleted unused variables.
* fixed problem with allocating memory for SymbolicLinkName
*
* Revision 1.5 1993/05/09 09:59:25 rik
* Made extensive changes to support the new registry configuration. Each
* of the hardware dependent driver must now read the registry and create
* a configuration for the given controller object to use upon its
* return. This new registry configuration is similiar across all
* DigiBoard controllers.
*
* Revision 1.4 1993/04/05 20:03:48 rik
* Started to add support for event logging.
*
* Revision 1.3 1993/03/15 05:07:13 rik
* Changed over to a miniport driver. This driver has an IOCTL which will
* fill in a table of function pointers which are the appropriate entry
* points in this miniport driver.
*
* Revision 1.2 1993/03/10 07:09:31 rik
* added support for PC/X* controllers. So far, I have verified that the
* changes work with the PC/8i, PC/2e, and PC/8e controllers.
*
* Revision 1.1 1993/03/08 08:40:02 rik
* Initial revision
*
*/
#include <stddef.h>
#include <ntddk.h>
#include <ntverp.h> // Include to determine what version of NT
//
// This is a fix for changes in DDK releases.
//
#ifdef VER_PRODUCTBUILD
#define rmm VER_PRODUCTBUILD
#endif
#include "ntddser.h"
#include "ntfep5.h"
#undef DbgPrint
#include "ntxall.h"
#include "ntxalllg.h"
#include "digifile.h"
#ifndef _NTXALL_DOT_C
# define _NTXALL_DOT_C
static char RCSInfo_NTXALLDotC[] = "$Header: /Components/Windows/NT/Async/NTXALL/NTXALL.C 1 3/05/96 10:18a Stana $";
#endif
static const SHORT BaudTable[NUMBER_OF_BAUD_RATES] =
{
B50, B75, B110, B134, B150, B200, B300, B600,
B1200, B1800, B2000, B2400, B3600, B4800, B7200, B9600,
B14400, B19200, B28800, B38400, B56000, B57600,
B115200, B128000, B256000, B512000
};
static const UCHAR ModemSignalTable[NUMBER_OF_SIGNALS] =
{
DTR_CONTROL, RTS_CONTROL, RESERVED1, RESERVED2,
CTS_STATUS, DSR_STATUS, RI_STATUS, DCD_STATUS
};
ULONG DigiDebugLevel = ( DIGIERRORS | DIGIMEMORY | DIGIASSERT | DIGIINIT | DIGIIOCTL );
static const PHYSICAL_ADDRESS DigiPhysicalZero = {0};
PDRIVER_OBJECT GlobalDriverObject;
USHORT MCAIOAddressTable[] = { 0x108, 0x118,
0x128, 0x208,
0x228, 0x308,
0x328, 0 };
USHORT MCA2XiIOAddressTable[] = { 0xF1F0, 0xF2F0,
0xF4F0, 0xF8F0 };
ULONG MCA2XiMemoryAddressTable[] = { 0xC0000, 0xC8000, 0xD0000, 0xD8000 };
USHORT MCAIrqTable[] = { 0, 3, 5, 7, 10, 11, 12, 15 };
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath );
NTSTATUS GetXAllConfigInfo( PUNICODE_STRING ControllerPath,
PDIGI_CONTROLLER_EXTENSION ControllerExt );
NTSTATUS XallSuccess( IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp );
NTSTATUS XallInternalIoControl( IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp );
NTSTATUS XallClose( IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp );
NTSTATUS XallCreate( IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp );
VOID XallUnload( IN PDRIVER_OBJECT DriverObject );
DIGI_MEM_COMPARES DigiMemCompare( IN PHYSICAL_ADDRESS A,
IN ULONG SpanOfA,
IN PHYSICAL_ADDRESS B,
IN ULONG SpanOfB );
VOID DigiLogError( IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT DeviceObject OPTIONAL,
IN PHYSICAL_ADDRESS P1,
IN PHYSICAL_ADDRESS P2,
IN ULONG SequenceNumber,
IN UCHAR MajorFunctionCode,
IN UCHAR RetryCount,
IN ULONG UniqueErrorValue,
IN NTSTATUS FinalStatus,
IN NTSTATUS SpecificIOStatus,
IN ULONG LengthOfInsert1,
IN PWCHAR Insert1,
IN ULONG LengthOfInsert2,
IN PWCHAR Insert2 );
NTSTATUS NtXallInitMCA( PUNICODE_STRING ControllerPath,
PDIGI_CONTROLLER_EXTENSION ControllerExt );
USHORT DigiWstrLength( IN PWSTR WStr );
NTSTATUS XallXXPrepInit( PDIGI_CONTROLLER_EXTENSION pControllerExt,
PUNICODE_STRING ControllerPath );
NTSTATUS XallXXInit( IN PDRIVER_OBJECT DriverObject,
PUNICODE_STRING ControllerPath,
PDIGI_CONTROLLER_EXTENSION pControllerExt );
VOID XallEnableWindow( IN PDIGI_CONTROLLER_EXTENSION pControllerExt,
IN USHORT Window );
VOID XallDisableWindow( IN PDIGI_CONTROLLER_EXTENSION pControllerExt );
VOID XallXXDownload( PDIGI_CONTROLLER_EXTENSION pControllerExt );
#ifdef ALLOC_PRAGMA
#pragma alloc_text( INIT, DriverEntry )
#if rmm > 528
#pragma message( "\n\\\\\n\\\\ Including PAGED CODE\n\\\\ \n" )
//DH I don't believe this is accomplishing anything.
#pragma alloc_text( PAGEDIGIXALL, XallXXPrepInit )
#pragma alloc_text( PAGEDIGIXALL, XallXXInit )
#pragma alloc_text( PAGEDIGIXALL, GetXAllConfigInfo )
#pragma alloc_text( PAGEDIGIXALL, NtXallInitMCA )
#pragma alloc_text( PAGEDIGIXALL, DigiWstrLength )
#pragma alloc_text( PAGEDIGIXALL, DigiLogError )
#pragma alloc_text( PAGEDIGIXALL, DigiMemCompare )
#pragma alloc_text( PAGEDIGIXALL, XallSuccess )
#pragma alloc_text( PAGEDIGIXALL, XallInternalIoControl )
#pragma alloc_text( PAGEDIGIXALL, XallCreate )
#pragma alloc_text( PAGEDIGIXALL, XallClose )
#pragma alloc_text( PAGEDIGIXALL, XallUnload )
#endif
#endif
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath )
/*++
Routine Description:
Entry point for loading driver.
Arguments:
DriverObject - Pointer to this drivers object.
RegistryPath - Pointer to a unicode string which points to this
drivers registry entry.
Return Value:
STATUS_SUCCESS - If the driver was successfully loaded, otherwise,
a value which indicates why it wasn't able to load.
--*/
{
NTSTATUS Status;
PDEVICE_OBJECT DeviceObject;
WCHAR XallDeviceNameBuffer[100];
UNICODE_STRING XallDeviceName;
GlobalDriverObject = DriverObject;
XallDeviceName.Length = 0;
XallDeviceName.MaximumLength = sizeof(XallDeviceNameBuffer);
XallDeviceName.Buffer = &XallDeviceNameBuffer[0];
RtlZeroMemory( XallDeviceName.Buffer, XallDeviceName.MaximumLength );
RtlAppendUnicodeToString( &XallDeviceName, L"\\Device\\ntxall" );
Status = IoCreateDevice( DriverObject,
0, &XallDeviceName,
FILE_DEVICE_SERIAL_PORT, 0, TRUE,
&DeviceObject );
if( !NT_SUCCESS(Status) )
{
DigiLogError( DriverObject,
NULL,
DigiPhysicalZero,
DigiPhysicalZero,
0,
0,
0,
__LINE__,
STATUS_INSUFFICIENT_RESOURCES,
SERIAL_INSUFFICIENT_RESOURCES,
0,
NULL,
0,
NULL );
return( STATUS_INSUFFICIENT_RESOURCES );
}
DeviceObject->Flags |= DO_BUFFERED_IO;
DriverObject->DriverUnload = XallUnload;
DriverObject->MajorFunction[IRP_MJ_CREATE] = XallCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = XallClose;
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] =
XallInternalIoControl;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] =
DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] =
DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] =
DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] =
XallSuccess;
return( STATUS_SUCCESS );
} // end DriverEntry
NTSTATUS XallXXPrepInit( PDIGI_CONTROLLER_EXTENSION pControllerExt,
PUNICODE_STRING ControllerPath )
/*++
Routine Description:
Arguments:
pControllerExt -
Return Value:
STATUS_SUCCESS
--*/
{
NTSTATUS Status=STATUS_SUCCESS;
KIRQL OldIrql;
#if rmm > 528
PVOID lockPtr;
lockPtr = MmLockPagableCodeSection( XallXXPrepInit );
#endif
//
// At this point, determine if we are using a MCA controller.
// If we are, then we need to read the POS to get the
// Memory address and I/O address.
//
if( pControllerExt->BusType == MicroChannel )
{
Status = NtXallInitMCA( ControllerPath, pControllerExt );
if( Status != STATUS_SUCCESS )
goto XallXXPrepInitExit;
}
//
// Make sure we have exclusive access to the controller
// extension
//
KeAcquireSpinLock( &pControllerExt->ControlAccess,
&OldIrql );
//
// We should really read some the following information from
// the registry.
//
pControllerExt->IOSpan = 4;
//
// Default to a 64K window if it isn't all ready assigned.
//
if( pControllerExt->WindowSize == 0 )
pControllerExt->WindowSize = 0x10000L;
pControllerExt->Global.Window = FEP_GLOBAL_WINDOW;
pControllerExt->Global.Offset = 0;
pControllerExt->EventQueue.Window = FEP_EVENT_WINDOW;
pControllerExt->EventQueue.Offset = FEP_EVENT_OFFSET;
pControllerExt->CommandQueue.Window = FEP_COMMAND_WINDOW;
pControllerExt->CommandQueue.Offset = FEP_COMMAND_OFFSET;
pControllerExt->BaudTable = &BaudTable[0];
pControllerExt->ModemSignalTable = &ModemSignalTable[0];
//
// Make sure we release exclusive access to the controller
// extension
//
KeReleaseSpinLock( &pControllerExt->ControlAccess,
OldIrql );
XallXXPrepInitExit:;
#if rmm > 528
MmUnlockPagableImageSection( lockPtr );
#endif
return( Status );
} // end XallXXPrepInit
NTSTATUS XallXXInit( IN PDRIVER_OBJECT DriverObject,
PUNICODE_STRING ControllerPath,
PDIGI_CONTROLLER_EXTENSION pControllerExt )
/*++
Routine Description:
Arguments:
ControllerPath - Unicode string with path to a controllers registry info.
pControllerExt - Pointer to the Controller extension.
Return Value:
STATUS_SUCCESS - The controller was properly initialized.
STATUS_SERIAL_NO_DEVICE_INITED - The controller couldn't be initialized
for some reason.
--*/
{
int i;
USHORT Address;
NTSTATUS Status;
UCHAR ByteValue;
UCHAR ResetByte, ResetMask;
FEPOS5_ADDRESS NTFep5Address;
ULONG MemorySegment, MemorySize;
PUCHAR fepos;
TIME Timeout;
PFEP_CHANNEL_STRUCTURE ChannelInfo;
PHYSICAL_ADDRESS TempPhyAddr;
NTSTATUS FStatus;
HANDLE BiosFHandle=0;
ULONG BiosFLength=0;
PUCHAR BiosFImage=NULL;
HANDLE FEPFHandle=0;
ULONG FEPFLength=0;
PUCHAR FEPFImage=NULL;
#if rmm > 528
PVOID lockPtr;
lockPtr = MmLockPagableCodeSection( XallXXPrepInit );
#endif
MemorySegment = 0;
Status = GetXAllConfigInfo( ControllerPath, pControllerExt );
if( !NT_SUCCESS(Status) )
{
// There was some type of problem with the configuration,
// just return.
#if rmm > 528
MmUnlockPagableImageSection( lockPtr );
#endif
return( Status );
}
//
//
// IMPORTANT NOTE:
//
// I map the Bios and FEP images in here before acquiring the
// spinlock because acquiring a spinlock raises the current IRQL
// level, and the open file, etc calls can not be access at
// the raised IRQL level because it is pageable code
//
//
//
// Open and map in the Bios and FEP images
//
RtlFillMemory( &TempPhyAddr, sizeof(TempPhyAddr), 0xFF );
DigiOpenFile( &FStatus,
&BiosFHandle,
&BiosFLength,
&pControllerExt->BiosImagePath,
TempPhyAddr );
if( FStatus == STATUS_SUCCESS )
{
DigiDump( DIGIINIT, ("NTXALL: NdisOpenFile was successful!\n") );
DigiMapFile( &FStatus,
&(PVOID)BiosFImage,
BiosFHandle );
if( FStatus == STATUS_SUCCESS )
{
DigiDump( DIGIINIT, ("NTXALL: NdisMapFile was successful!\n") );
}
else
{
DigiDump( DIGIINIT, ("NTXALL: NdisMapFile was UN-successful!\n") );
DigiLogError( GlobalDriverObject,
NULL,
DigiPhysicalZero,
DigiPhysicalZero,
0,
0,
0,
__LINE__,
STATUS_DEVICE_NOT_INITIALIZED,
SERIAL_FILE_NOT_FOUND,
pControllerExt->BiosImagePath.Length + sizeof(WCHAR),
pControllerExt->BiosImagePath.Buffer,
0,
NULL );
Status = STATUS_DEVICE_NOT_INITIALIZED;
goto XallXXInitExit;
}
}
else
{
DigiDump( DIGIINIT, ("NTXALL: NdisOpenFile was UN-successful!\n") );
DigiLogError( GlobalDriverObject,
NULL,
DigiPhysicalZero,
DigiPhysicalZero,
0,
0,
0,
__LINE__,
STATUS_DEVICE_NOT_INITIALIZED,
SERIAL_FILE_NOT_FOUND,
pControllerExt->BiosImagePath.Length + sizeof(WCHAR),
pControllerExt->BiosImagePath.Buffer,
0,
NULL );
Status = STATUS_DEVICE_NOT_INITIALIZED;
goto XallXXInitExit;
}
RtlFillMemory( &TempPhyAddr, sizeof(TempPhyAddr), 0xFF );
DigiOpenFile( &FStatus,
&FEPFHandle,
&FEPFLength,
&pControllerExt->FEPImagePath,
TempPhyAddr );
if( FStatus == STATUS_SUCCESS )
{
DigiDump( DIGIINIT, ("NTXALL: NdisOpenFile was successful!\n") );
DigiMapFile( &FStatus,
&(PVOID)FEPFImage,
FEPFHandle );
if( FStatus == STATUS_SUCCESS )
{
DigiDump( DIGIINIT, ("NTXALL: NdisMapFile was successful!\n") );
}
else
{
DigiDump( DIGIINIT, ("NTXALL: NdisMapFile was UN-successful!\n") );
DigiLogError( GlobalDriverObject,
NULL,
DigiPhysicalZero,
DigiPhysicalZero,
0,
0,
0,
__LINE__,
STATUS_DEVICE_NOT_INITIALIZED,
SERIAL_FILE_NOT_FOUND,
pControllerExt->FEPImagePath.Length + sizeof(WCHAR),
pControllerExt->FEPImagePath.Buffer,
0,
NULL );
Status = STATUS_DEVICE_NOT_INITIALIZED;
goto XallXXInitExit;
}
}
else
{
DigiDump( DIGIINIT, ("NTXALL: NdisOpenFile was UN-successful!\n") );
DigiLogError( GlobalDriverObject,
NULL,
DigiPhysicalZero,
DigiPhysicalZero,
0,
0,
0,
__LINE__,
STATUS_DEVICE_NOT_INITIALIZED,
SERIAL_FILE_NOT_FOUND,
pControllerExt->FEPImagePath.Length + sizeof(WCHAR),
pControllerExt->FEPImagePath.Buffer,
0,
NULL );
Status = STATUS_DEVICE_NOT_INITIALIZED;
goto XallXXInitExit;
}
Status = STATUS_SUCCESS;
// Ensure exclusive access to the memory area.
KeAcquireSpinLock( &pControllerExt->MemoryAccess->Lock,
&pControllerExt->MemoryAccess->OldIrql );
#if DBG
pControllerExt->MemoryAccess->LockBusy = TRUE;
#endif
//
// We need to do some sleuthing to determine which of the PC/X*
// controllers this really is. Depending on the controller, we
// will need to configure the controller memory address, and
// interrupt. This is done for the newer PC/Xe controllers. The
// older controllers, we will assume the dip switches and/or
// jumpers are set correctly.
//
//
// First, is this a MC2/Xi controller
//
if( (pControllerExt->ControllerType & CONTROLLER_TYPE_MC2XI)
== CONTROLLER_TYPE_MC2XI )
{
goto SkipBoardType;
}
//
// Reset the board and clear mask 01h.
//
WRITE_PORT_UCHAR( pControllerExt->VirtualIO, 0x04 );
// Delay 1 millisecond
#if rmm < 807
Timeout = RtlConvertLongToLargeInteger( -1 * 10000 );
#else
Timeout.QuadPart = -1 * 10000;
#endif
KeDelayExecutionThread( KernelMode, FALSE, &Timeout );
// Read the board ID.
ByteValue = READ_PORT_UCHAR( pControllerExt->VirtualIO );
if( (ByteValue & 0x01) == 0x01 )
{
// Board Type is PC/Xi
pControllerExt->ControllerType = ( CONTROLLER_TYPE_PCXI |
BASE_ENABLE_MEMORY );
if( (ByteValue & 0x30) == 0 )
{
// 64K PC/Xi
MemorySegment = 0x0000F000;
MemorySize = 0x10000;
}
else if( (ByteValue & 0x30) == 0x10 )
{
// 128K PC/Xi
MemorySegment = 0x0000E000;
MemorySize = 0x20000;
}
else if( (ByteValue & 0x30) == 0x20 )
{
// 256K PC/Xi
MemorySegment = 0x0000C000;
MemorySize = 0x40000;
}
else if( (ByteValue & 0x30) == 0x30 )
{
// 512K PC/Xi
MemorySegment = 0x00008000;
MemorySize = 0x80000;
}
}
else
{
//
// Hold Reset and set mask 0x01. The following assumes
// that the PC/Xe controllers will return a 0 regardless
// of what is written to bit mask 0x01, while the PC/Xm will always
// return what was last written to the controller.
//
// Board Type is either a PC/Xm, or PC/Xe
//
WRITE_PORT_UCHAR( pControllerExt->VirtualIO, 0x05 );
ByteValue = READ_PORT_UCHAR( pControllerExt->VirtualIO );
if( ByteValue & 0x01 )
{
// Board Type is PC/Xm
}
else
{
//
// Board Type is PC/Xe. The question now is whether the board
// is an old PC/Xe, or a new PC/Xe.
//
MemorySegment = 0x0000F000;
MemorySize = 0x10000;
if( (ByteValue & 0xC0) == 0x40 )
{
// The board is a newer PC/Xe. Determine if it should be
// configured for an 8K memory window.
//
// Reset the Window size to indicate what we will really
// be using. We don't support a PC/2e in 64K mode.
//
if( pControllerExt->WindowSize != 0x2000 )
{
DigiLogError( GlobalDriverObject,
NULL,
DigiPhysicalZero,
DigiPhysicalZero,
0,
0,
0,
__LINE__,
STATUS_SERIAL_NO_DEVICE_INITED,
SERIAL_RESIZING_WINDOW,
pControllerExt->ControllerName.Length + sizeof(WCHAR),
pControllerExt->ControllerName.Buffer,
0,
NULL );
}
pControllerExt->WindowSize = 0x2000;
pControllerExt->ControllerType = CONTROLLER_TYPE_PCXE;
Address = (USHORT)(pControllerExt->PhysicalMemoryAddress.LowPart >> 8);
Address |= 0x0010; // Enable 8K Window
WRITE_PORT_UCHAR( pControllerExt->VirtualIO+2, (UCHAR)(Address & 0x00FF) );
WRITE_PORT_UCHAR( pControllerExt->VirtualIO+3, (UCHAR)(Address >> 8) );
}
else
{
// The board is an older PC/Xe. We assume the settings
// in the registry match what the controller is configured at.
pControllerExt->ControllerType = ( CONTROLLER_TYPE_PCXE |
BASE_ENABLE_MEMORY );
}
}
}
SkipBoardType:;
//
// PC/X* Board Reset
//
if( (pControllerExt->ControllerType & CONTROLLER_TYPE_MC2XI)
== CONTROLLER_TYPE_MC2XI )
{
// reset board
WRITE_PORT_UCHAR( pControllerExt->VirtualIO, 0x40 );
}
else
{
// reset board
WRITE_PORT_UCHAR( pControllerExt->VirtualIO, 4 );
}
// Create a 0.1 second timeout interval
#if rmm < 807
Timeout = RtlConvertLongToLargeInteger( -100 * 10000 );
#else
Timeout.QuadPart = -100 * 10000;
#endif
if( (pControllerExt->ControllerType & CONTROLLER_TYPE_MC2XI)
== CONTROLLER_TYPE_MC2XI )
{
ResetByte = 0x40;
ResetMask = 0x40;
}
else
{
ResetByte = 0x04;
ResetMask = 0x0E;
}
for( i = 0; i < 30; i++ )
{
ByteValue = (READ_PORT_UCHAR( pControllerExt->VirtualIO ) & ResetMask);
if( ByteValue != ResetByte )
KeDelayExecutionThread( KernelMode, FALSE, &Timeout );
else
break;
}
DigiDump( DIGIINIT, ("Wait confirm = 0x%x, expected 0x%x.\n",
(ULONG)ByteValue, (ULONG)ResetByte ) );
if( i == 30 )
{
//
// Unable to get confirmation of the controller responding.
//
DigiLogError( GlobalDriverObject,
NULL,
DigiPhysicalZero,
DigiPhysicalZero,
0,
0,
0,
__LINE__,
STATUS_SERIAL_NO_DEVICE_INITED,
SERIAL_NO_CONTROLLER_RESET_WAIT,
pControllerExt->ControllerName.Length + sizeof(WCHAR),
pControllerExt->ControllerName.Buffer,
0,
NULL );
Status = STATUS_SERIAL_NO_DEVICE_INITED;
goto XallXXInitExit;
}
#if DBG
pControllerExt->MemoryAccess->LockBusy = FALSE;
#endif
KeReleaseSpinLock( &pControllerExt->MemoryAccess->Lock,
pControllerExt->MemoryAccess->OldIrql );
//
// Verify that memory is accessable
//
// First, turn memory on!
EnableWindow( pControllerExt, FEP_GLOBAL_WINDOW );
// Make sure we keep the controller in reset.
ByteValue = READ_PORT_UCHAR( pControllerExt->VirtualIO );
ByteValue |= ((UCHAR)ResetByte);
WRITE_PORT_UCHAR( pControllerExt->VirtualIO, ByteValue );
DigiDump( DIGIINIT, ("Dword @ VirtualAddress, before memory check = 0x%x\n",
READ_REGISTER_ULONG( (PULONG)pControllerExt->VirtualAddress )) );
WRITE_REGISTER_ULONG( (PULONG)pControllerExt->VirtualAddress,
0xA55A3CC3 );
DigiDump( DIGIINIT, ("Dword @ VirtualAddress, after memory check = 0x%x, expected 0xa55a3cc3\n",
READ_REGISTER_ULONG( (PULONG)pControllerExt->VirtualAddress )) );
DigiDump( DIGIINIT, ("Dword @ VirtualAddress+WindowSize-4, before memory check = 0x%x\n",
READ_REGISTER_ULONG( (PULONG)(pControllerExt->VirtualAddress +
pControllerExt->WindowSize -
sizeof(ULONG)) )) );
WRITE_REGISTER_ULONG( (PULONG)(pControllerExt->VirtualAddress + pControllerExt->WindowSize - sizeof(ULONG)),
0x5AA5C33C );
DigiDump( DIGIINIT, ("Dword @ VirtualAddress+WindowSize-4, after memory check = 0x%x, expected 0x5aa5c33c\n",
READ_REGISTER_ULONG( (PULONG)(pControllerExt->VirtualAddress +
pControllerExt->WindowSize -
sizeof(ULONG)) )) );
if( (READ_REGISTER_ULONG( (PULONG)pControllerExt->VirtualAddress ) != 0xA55A3CC3) ||
(READ_REGISTER_ULONG( (PULONG)(pControllerExt->VirtualAddress +
pControllerExt->WindowSize -
sizeof(ULONG)) ) != 0x5AA5C33C) )
{
DigiDump( DIGIERRORS, ("**** Board memory failure! ***\n"
" Unable to verify board memory. (%s:%d)\n",
(PUCHAR)__FILE__, (int)__LINE__) );
DigiLogError( GlobalDriverObject,
NULL,
DigiPhysicalZero,
DigiPhysicalZero,
0,
0,
0,
__LINE__,
STATUS_SERIAL_NO_DEVICE_INITED,
SERIAL_CONTROLLER_MEMORY_TEST_FAILED,
pControllerExt->ControllerName.Length + sizeof(WCHAR),
pControllerExt->ControllerName.Buffer,
0,
NULL );
Status = STATUS_SERIAL_NO_DEVICE_INITED;
goto XallXXInitExit;
}
DisableWindow( pControllerExt );
if( (pControllerExt->ControllerType & CONTROLLER_TYPE_MC2XI)
== CONTROLLER_TYPE_MC2XI )
{
//
// Be very careful here! We are jumping into the middle of code
// which expects the correct window to all ready be selected, which
// as a side-effect acquires a spinlock!
//
EnableWindow( pControllerExt, FEP_GLOBAL_WINDOW );
goto SkipBiosDownload;
}
//
// PC/X* Bios downloading
//
// Enable memory and hold board in reset
EnableWindow( pControllerExt, FEP_GLOBAL_WINDOW );
ByteValue = READ_PORT_UCHAR( pControllerExt->VirtualIO );
ByteValue |= ((UCHAR)0x04);
WRITE_PORT_UCHAR( pControllerExt->VirtualIO, ByteValue );
// Clear POSTAREA
for( i = 0; i < 15; i++ )
{
WRITE_REGISTER_UCHAR( (PUCHAR)((PUCHAR)pControllerExt->VirtualAddress +
0x0C00 + i), 0 );
}
DisableWindow( pControllerExt );
//
// Download BIOS to the X* adapter
//
{
ULONG foo;
foo = ((0xFF800 - (16 * MemorySegment)) >> 4);
Board2Fep5Address( pControllerExt, (USHORT)foo,
&NTFep5Address );
}
// Select top memory window.
EnableWindow( pControllerExt, NTFep5Address.Window );
ByteValue = READ_PORT_UCHAR( pControllerExt->VirtualIO );
// Hold board in reset
ByteValue |= ((UCHAR)0x04);
WRITE_PORT_UCHAR( pControllerExt->VirtualIO, ByteValue );
// write the BIOS from our local variable the controller.
WRITE_REGISTER_BUFFER_UCHAR( (PUCHAR)(pControllerExt->VirtualAddress +
NTFep5Address.Offset),
(PUCHAR)&BiosFImage[0],
BiosFLength );
//
// We cheat a little here. Instead of disabling the Window and
// reselecting the FEP_GLOBAL_WINDOW, we do it by hand for
// moveable windowed controllers
//
// The reason I do this is to prevent releasing the reset
// until I'm ready.
//
if( !(pControllerExt->ControllerType & BASE_ENABLE_MEMORY) )
WRITE_PORT_UCHAR( (pControllerExt->VirtualIO)+1,
(UCHAR)(FEP_GLOBAL_WINDOW | FEP_MEM_ENABLE) );
SkipBiosDownload:;
// Clear confirm word
WRITE_REGISTER_USHORT( (PUSHORT)(pControllerExt->VirtualAddress + 0x0C00),
0 );
DigiDump( DIGIINIT,
("before BIOS download memw[0C00h] = 0x%hx\n",
READ_REGISTER_USHORT( (PUSHORT)(pControllerExt->VirtualAddress+0x0C00) )) );
ByteValue = READ_PORT_UCHAR( pControllerExt->VirtualIO );
// Release reset
ByteValue &= (~(UCHAR)ResetByte);
WRITE_PORT_UCHAR( pControllerExt->VirtualIO, ByteValue );
//
// We generate a wait event for 200, 0.1 second intervals to verify
// the BIOS download.
//
// Create a 0.1 second timeout interval
#if rmm < 807
Timeout = RtlConvertLongToLargeInteger( -100 * 10000 );
#else
Timeout.QuadPart = -100 * 10000;
#endif
for( i = 0; i < 200; i++ )
{
if( READ_REGISTER_USHORT( (PUSHORT)(pControllerExt->VirtualAddress+0x0C00) )
== *(USHORT *)"GD" )
{
break;
}
KeDelayExecutionThread( KernelMode, FALSE, &Timeout );
}
if( i == 200 )
{
// The BIOS didn't initialize within 20 seconds.
DigiDump( DIGIERRORS, ("*** PC/X* BIOS did NOT initialize. ***\n") );
DigiLogError( GlobalDriverObject,
NULL,
DigiPhysicalZero,
DigiPhysicalZero,
0,
0,
0,
__LINE__,
STATUS_SERIAL_NO_DEVICE_INITED,
SERIAL_BIOS_DOWNLOAD_FAILED,
pControllerExt->ControllerName.Length + sizeof(WCHAR),
pControllerExt->ControllerName.Buffer,
0,
NULL );
Status = STATUS_SERIAL_NO_DEVICE_INITED;
goto XallXXInitExit;
}
DigiDump( DIGIINIT, ("after BIOS download memw[0C00h] = %c%c, expect %s\n",
READ_REGISTER_UCHAR( (PUCHAR)(pControllerExt->VirtualAddress+0x0C00) ),
READ_REGISTER_UCHAR( (PUCHAR)(pControllerExt->VirtualAddress+0x0C01) ),
"GD") );
DisableWindow( pControllerExt );
//
// Download FEPOS to PC/X* adapter
//
Board2Fep5Address( pControllerExt, ((USHORT)0x0200),
&NTFep5Address );
// Select Page 1 and Enable Memory
EnableWindow( pControllerExt, NTFep5Address.Window );
fepos = pControllerExt->VirtualAddress+NTFep5Address.Offset;
// write the FEPOS from our local variable the controller.
WRITE_REGISTER_BUFFER_UCHAR( fepos,
(PUCHAR)&FEPFImage[0],
FEPFLength );
DisableWindow( pControllerExt );
// Select Page 0 and Enable Memory
EnableWindow( pControllerExt, FEP_GLOBAL_WINDOW );
if( (pControllerExt->ControllerType & CONTROLLER_TYPE_MC2XI)
== CONTROLLER_TYPE_MC2XI )
{
goto SkipBiosMoveReq;
}
// Form BIOS move program request
WRITE_REGISTER_USHORT( (PUSHORT)(pControllerExt->VirtualAddress + 0x0C40),
0x0002 );
WRITE_REGISTER_USHORT( (PUSHORT)(pControllerExt->VirtualAddress + 0x0C42),
((USHORT)(MemorySegment + 0x0200)) );
WRITE_REGISTER_USHORT( (PUSHORT)(pControllerExt->VirtualAddress + 0x0C44),
0x0000 );
WRITE_REGISTER_USHORT( (PUSHORT)(pControllerExt->VirtualAddress + 0x0C46),
0x0200 );
WRITE_REGISTER_USHORT( (PUSHORT)(pControllerExt->VirtualAddress + 0x0C48),
0x0000 );
WRITE_REGISTER_USHORT( (PUSHORT)(pControllerExt->VirtualAddress + 0x0C4A),
0x2000 );
// Toggle Board Interrupt High
ByteValue = READ_PORT_UCHAR( pControllerExt->VirtualIO );
ByteValue |= ((UCHAR)0x08);
WRITE_PORT_UCHAR( pControllerExt->VirtualIO, ByteValue );
// Create a 0.1 second timeout interval
#if rmm < 807
Timeout = RtlConvertLongToLargeInteger( -100 * 10000 );
#else
Timeout.QuadPart = -100 * 10000;
#endif
for( i = 0; i < 100; i++ )
{
if( READ_REGISTER_USHORT( (PUSHORT)(pControllerExt->VirtualAddress +
0x0C40) ) == 0 )
{
break;
}
KeDelayExecutionThread( KernelMode, FALSE, &Timeout );
}
if( i == 100 )
{
// The FEPOS didn't initialize within 10 seconds.
DigiDump( DIGIERRORS, ("*** PC/X* Wait confirm for FEPOS move did NOT happen! ***\n") );
Status = STATUS_SERIAL_NO_DEVICE_INITED;
goto XallXXInitExit;
}
// Toggle Board interrupt low
ByteValue = READ_PORT_UCHAR( pControllerExt->VirtualIO );
ByteValue &= (~(UCHAR)0x08);
WRITE_PORT_UCHAR( pControllerExt->VirtualIO, ByteValue );
SkipBiosMoveReq:;
// Form BIOS execute request
WRITE_REGISTER_USHORT( (PUSHORT)(pControllerExt->VirtualAddress + 0x0C40),
0x0001 );
if( (pControllerExt->ControllerType & CONTROLLER_TYPE_MC2XI)
== CONTROLLER_TYPE_MC2XI )
{
WRITE_REGISTER_USHORT( (PUSHORT)(pControllerExt->VirtualAddress + 0x0C42),
0x2200 );
}
else
{
WRITE_REGISTER_USHORT( (PUSHORT)(pControllerExt->VirtualAddress + 0x0C42),
0x0200 );
}
WRITE_REGISTER_USHORT( (PUSHORT)(pControllerExt->VirtualAddress + 0x0C44),
0x0004 );
// Clear confirm location
WRITE_REGISTER_USHORT( (PUSHORT)(pControllerExt->VirtualAddress + 0x0D20),
0x0000 );
if( (pControllerExt->ControllerType & CONTROLLER_TYPE_MC2XI)
== CONTROLLER_TYPE_MC2XI )
{
// Toggle Board Interrupt High
ByteValue = READ_PORT_UCHAR( pControllerExt->VirtualIO );
ByteValue |= ((UCHAR)0x80);
WRITE_PORT_UCHAR( pControllerExt->VirtualIO, ByteValue );
}
else
{
// Toggle Board Interrupt High
ByteValue = READ_PORT_UCHAR( pControllerExt->VirtualIO );
ByteValue |= ((UCHAR)0x08);
WRITE_PORT_UCHAR( pControllerExt->VirtualIO, ByteValue );
}
//
// Verify FEP execution.
//
for( i = 0; i < 100; i++ )
{
if( READ_REGISTER_USHORT( (PUSHORT)(pControllerExt->VirtualAddress+0x0D20) ) == *(USHORT *)"OS" )
{
break;
}
KeDelayExecutionThread( KernelMode, FALSE, &Timeout );
}
if( i == 100 )
{
// The FEPOS didn't initialize within 10 seconds.
// For PC/X* controllers read memb[0C12h] & memb[0C14h] and
// place in the event log for diagnostic purposes.
DigiDump( DIGIERRORS, ("*** PC/X* FEPOS did NOT initialize! ***\n") );
DigiLogError( GlobalDriverObject,
NULL,
DigiPhysicalZero,
DigiPhysicalZero,
0,
0,
0,
__LINE__,
STATUS_SERIAL_NO_DEVICE_INITED,
SERIAL_FEPOS_INIT_FAILURE,
pControllerExt->ControllerName.Length + sizeof(WCHAR),
pControllerExt->ControllerName.Buffer,
0,
NULL );
Status = STATUS_SERIAL_NO_DEVICE_INITED;
goto XallXXInitExit;
}
DisableWindow( pControllerExt );
// Select Page 0 and Enable Memory
EnableWindow( pControllerExt, FEP_GLOBAL_WINDOW );
//
// If the controller has buffers which are larger than the window size,
// then reallocate the RX & TX buffers to the window size.
//
ChannelInfo = (PFEP_CHANNEL_STRUCTURE)(pControllerExt->VirtualAddress +
FEP_CHANNEL_START );
//
// We do a check based on rmax size because there is a bias in the
// controller buffer allocation scheme in favor of recieve buffers.
//
DigiDump( DIGIINIT, ("rmax = 0x%x, WindowSize = 0x%x\n",
READ_REGISTER_USHORT( (PUSHORT)( (PUCHAR)ChannelInfo +
FIELD_OFFSET(FEP_CHANNEL_STRUCTURE, rmax)) ),
pControllerExt->WindowSize) );
if( READ_REGISTER_USHORT( (PUSHORT)( (PUCHAR)ChannelInfo +
FIELD_OFFSET(FEP_CHANNEL_STRUCTURE, rmax)) )
> ((USHORT)((pControllerExt->WindowSize & 0x0000FFFF) - 1)) )
{
PCOMMAND_STRUCT CommandQ;
COMMAND_STRUCT CmdStruct;
FEP_COMMAND FepCommand;
CommandQ = ((PCOMMAND_STRUCT)(pControllerExt->VirtualAddress + FEP_CIN));
READ_REGISTER_BUFFER_UCHAR( (PUCHAR)CommandQ,
(PUCHAR)&CmdStruct,
sizeof(CmdStruct) );
//
// Put the data in the command buffer.
//
FepCommand.Command = SET_BUFFER_SPACE;
FepCommand.Port = (UCHAR)0;
FepCommand.Word = (USHORT)(pControllerExt->WindowSize * 4 / 1024);
WRITE_REGISTER_BUFFER_UCHAR( (PUCHAR)(pControllerExt->VirtualAddress +
CmdStruct.cmHead +
CmdStruct.cmStart),
(PUCHAR)&FepCommand,
sizeof(FepCommand) );
WRITE_REGISTER_USHORT( (PUSHORT)((PUCHAR)CommandQ +
FIELD_OFFSET(COMMAND_STRUCT, cmHead)),
(USHORT)((CmdStruct.cmHead + 4) & 0x3FC) );
}
XallXXInitExit:
DisableWindow( pControllerExt );
if( BiosFImage != NULL )
{
DigiUnmapFile( BiosFHandle );
DigiCloseFile( BiosFHandle );
}
if( FEPFImage != NULL )
{
DigiUnmapFile( FEPFHandle );
DigiCloseFile( FEPFHandle );
}
#if rmm > 528
MmUnlockPagableImageSection( lockPtr );
#endif
return( Status );
} // end XallXXInit
VOID XallEnableWindow( IN PDIGI_CONTROLLER_EXTENSION pControllerExt,
IN USHORT Window )
/*++
Routine Description:
Arguments:
pControllerExt - Pointer to the Controller extension.
Window - Indicates the window to enable on a controller.
Return Value:
--*/
{
#if DBG
BOOLEAN wasBusy = pControllerExt->MemoryAccess->LockBusy;
#endif
// Ensure exclusive access to the memory area.
KeAcquireSpinLock( &pControllerExt->MemoryAccess->Lock,
&pControllerExt->MemoryAccess->OldIrql );
#if DBG
if( wasBusy )
++pControllerExt->MemoryAccess->LockContention;
pControllerExt->MemoryAccess->LockBusy = TRUE;
#endif
if( (pControllerExt->ControllerType & CONTROLLER_TYPE_MC2XI)
== CONTROLLER_TYPE_MC2XI )
{
Window |= 4;
}
if( pControllerExt->ControllerType & (BASE_ENABLE_MEMORY) )
{
WRITE_PORT_UCHAR( (pControllerExt->VirtualIO),
(UCHAR)(0x02) );
}
else
{
WRITE_PORT_UCHAR( (pControllerExt->VirtualIO)+1,
(UCHAR)(Window | FEP_MEM_ENABLE) );
}
} // XallEnableWindow
VOID XallDisableWindow( IN PDIGI_CONTROLLER_EXTENSION pControllerExt )
/*++
Routine Description:
Arguments:
pControllerExt - Pointer to the Controller extension.
Return Value:
--*/
{
if( pControllerExt->ControllerType & (BASE_ENABLE_MEMORY) )
{
WRITE_PORT_UCHAR( (pControllerExt->VirtualIO), 0 );
}
else
{
WRITE_PORT_UCHAR( (pControllerExt->VirtualIO)+1, 0 );
}
#if DBG
pControllerExt->MemoryAccess->LockBusy = FALSE;
#endif
// Release exclusive access to the memory area.
KeReleaseSpinLock( &pControllerExt->MemoryAccess->Lock,
pControllerExt->MemoryAccess->OldIrql );
} // end XallDisableWindow
VOID XallXXDownload( PDIGI_CONTROLLER_EXTENSION pControllerExt )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
return;
} // end XallXXDownload
NTSTATUS XallBoard2Fep5Address( PDIGI_CONTROLLER_EXTENSION ControllerExt,
USHORT ControllerAddress,
PFEPOS5_ADDRESS FepAddress )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
ULONG Temp;
if( (ControllerExt->ControllerType & CONTROLLER_TYPE_MC2XI)
== CONTROLLER_TYPE_MC2XI )
{
ControllerAddress -= 0x2000;
Temp = ((ULONG)ControllerAddress & 0x0000FFFF) << 4;
}
else
{
Temp = ((ULONG)ControllerAddress & 0x00000FFF) << 4;
}
FepAddress->Window = (USHORT)((Temp / ControllerExt->WindowSize) & 0xFFFF);
FepAddress->Offset = (USHORT)(Temp -
( FepAddress->Window * (USHORT)(ControllerExt->WindowSize) ));
return( STATUS_SUCCESS );
} // end XallBoard2Fep5Address
LARGE_INTEGER XallDiagnose(PDIGI_CONTROLLER_EXTENSION pControllerExt);
//
// XallDiagnose will examine and return info about a particular card, and also
// try to fix the card if possible.
//
LARGE_INTEGER XallDiagnose(PDIGI_CONTROLLER_EXTENSION pControllerExt)
{
LARGE_INTEGER Result;
Result.HighPart = 0;
Result.LowPart = 0;
Result.LowPart += pControllerExt->BusType;
return Result;
}
NTSTATUS GetXAllConfigInfo( PUNICODE_STRING ControllerPath,
PDIGI_CONTROLLER_EXTENSION ControllerExt )
{
UNICODE_STRING ParametersPath, LinePath, ConcentratorPath, PortPath;
UNICODE_STRING CurNtNameForPort, CurSymbolicLinkName;
PWSTR ParametersString=L"Parameters";
NTSTATUS Status=STATUS_SUCCESS;
PRTL_QUERY_REGISTRY_TABLE TableInfo = NULL;
PDIGI_CONFIG_INFO NewConfigInfo;
OBJECT_ATTRIBUTES ParametersAttributes;
HANDLE ParametersHandle;
ULONG x, y, z;
RtlInitUnicodeString( &ParametersPath, NULL );
RtlInitUnicodeString( &LinePath, NULL );
RtlInitUnicodeString( &ConcentratorPath, NULL );
RtlInitUnicodeString( &PortPath, NULL );
RtlInitUnicodeString( &CurNtNameForPort, NULL );
RtlInitUnicodeString( &CurSymbolicLinkName, NULL );
// Allocate memory for creating a path to the Parameters
// folder
ParametersPath.MaximumLength = ControllerPath->Length +
(sizeof(WCHAR) * 20);
ParametersPath.Buffer = DigiAllocMem( PagedPool,
ParametersPath.MaximumLength );
if( !ParametersPath.Buffer )
{
DigiDump( DIGIERRORS, ("NTXALL: Could not allocate string for Parameters path\n"
"----- to LineX for %wZ\n",
ControllerPath) );
Status = STATUS_INSUFFICIENT_RESOURCES;
goto GetXAllConfigInfoExit;
}
RtlZeroMemory( ParametersPath.Buffer, ParametersPath.MaximumLength );
RtlCopyUnicodeString( &ParametersPath, ControllerPath );
RtlAppendUnicodeToString( &ParametersPath, L"\\" );
RtlAppendUnicodeToString( &ParametersPath, ParametersString );
// Allocate memory for creating a path to the Parameters\LineX
// folder
LinePath.MaximumLength = ControllerPath->Length +
(sizeof(WCHAR) * 257);
LinePath.Buffer = DigiAllocMem( PagedPool,
LinePath.MaximumLength );
if( !LinePath.Buffer )
{
DigiDump( DIGIERRORS, ("NTXALL: Could not allocate string for path\n"
"----- to LineX for %wZ\n",
ControllerPath) );
Status = STATUS_INSUFFICIENT_RESOURCES;
goto GetXAllConfigInfoExit;
}
RtlZeroMemory( LinePath.Buffer, LinePath.MaximumLength );
// Allocate memory for creating a path to the
// Parameters\LineX\ConcentratorY folder
ConcentratorPath.MaximumLength = ControllerPath->Length +
(sizeof(WCHAR) * 257);
ConcentratorPath.Buffer = DigiAllocMem( PagedPool,
ConcentratorPath.MaximumLength );
if( !ConcentratorPath.Buffer )
{
DigiDump( DIGIERRORS, ("NTXALL: Could not allocate string for path\n"
"----- to LineX\\ConcentratorY for %wZ\n",
ControllerPath) );
Status = STATUS_INSUFFICIENT_RESOURCES;
goto GetXAllConfigInfoExit;
}
RtlZeroMemory( ConcentratorPath.Buffer,
ConcentratorPath.MaximumLength );
PortPath.MaximumLength = ControllerPath->Length +
(sizeof(WCHAR) * 257);
PortPath.Buffer = DigiAllocMem( PagedPool,
PortPath.MaximumLength );
if( !PortPath.Buffer )
{
DigiDump( DIGIERRORS, ("NTXALL: Could not allocate string for path\n"
"----- to LineX\\ConcentratorY\\PortZ for %wZ",
ControllerPath) );
Status = STATUS_INSUFFICIENT_RESOURCES;
goto GetXAllConfigInfoExit;
}
RtlZeroMemory( PortPath.Buffer, PortPath.MaximumLength );
CurNtNameForPort.MaximumLength = ControllerPath->Length +
(sizeof(WCHAR) * 257);
CurNtNameForPort.Buffer = DigiAllocMem( PagedPool,
CurNtNameForPort.MaximumLength );
if( !CurNtNameForPort.Buffer )
{
DigiDump( DIGIERRORS, ("NTXALL: Could not allocate string for NtNameForPort.\n") );
Status = STATUS_INSUFFICIENT_RESOURCES;
goto GetXAllConfigInfoExit;
}
RtlZeroMemory( CurNtNameForPort.Buffer,
CurNtNameForPort.MaximumLength );
CurSymbolicLinkName.MaximumLength = ControllerPath->Length +
(sizeof(WCHAR) * 257);
CurSymbolicLinkName.Buffer = DigiAllocMem( PagedPool,
CurSymbolicLinkName.MaximumLength );
if( !CurSymbolicLinkName.Buffer )
{
DigiDump( DIGIERRORS, ("NTXALL: Could not allocate string for NtNameForPort.\n") );
Status = STATUS_INSUFFICIENT_RESOURCES;
goto GetXAllConfigInfoExit;
}
RtlZeroMemory( CurSymbolicLinkName.Buffer,
CurSymbolicLinkName.MaximumLength );
TableInfo = DigiAllocMem( PagedPool,
sizeof( RTL_QUERY_REGISTRY_TABLE ) * 4 );
if( !TableInfo )
{
DigiDump( DIGIERRORS, ("NTXALL: Could not allocate table for rtl query\n"
"----- to for %wZ\n",
ControllerPath ) );
Status = STATUS_INSUFFICIENT_RESOURCES;
goto GetXAllConfigInfoExit;
}
RtlZeroMemory( TableInfo, sizeof(RTL_QUERY_REGISTRY_TABLE) * 4 );
InitializeObjectAttributes( &ParametersAttributes,
&ParametersPath,
OBJ_CASE_INSENSITIVE,
NULL, NULL );
if( !NT_SUCCESS( Status = ZwOpenKey( &ParametersHandle, MAXIMUM_ALLOWED,
&ParametersAttributes ) ) )
{
DigiDump( DIGIERRORS, ("NTXALL: Could not open the drivers Parameters key %wZ\n",
&ParametersPath ) );
goto GetXAllConfigInfoExit;
}
//
// Look for Line1 only
//
for( x = 1; x < 2; x++ )
{
OBJECT_ATTRIBUTES LineAttributes;
HANDLE LineHandle;
PWSTR LineString=L"Line";
UNICODE_STRING LineNumberUString;
WCHAR LineNumberBuffer[8];
NTSTATUS LocalScopeStatus;
RtlInitUnicodeString( &LineNumberUString, NULL );
LineNumberUString.MaximumLength = sizeof(LineNumberBuffer);
LineNumberUString.Buffer = &LineNumberBuffer[0];
RtlIntegerToUnicodeString( x, 10, &LineNumberUString );
RtlZeroMemory( LinePath.Buffer, LinePath.MaximumLength );
RtlCopyUnicodeString( &LinePath, &ParametersPath );
RtlAppendUnicodeToString( &LinePath, L"\\" );
RtlAppendUnicodeToString( &LinePath, LineString );
RtlAppendUnicodeStringToString( &LinePath, &LineNumberUString );
InitializeObjectAttributes( &LineAttributes,
&LinePath,
OBJ_CASE_INSENSITIVE,
NULL, NULL );
if( !NT_SUCCESS( ZwOpenKey( &LineHandle,
KEY_READ,
&LineAttributes )))
{
//
// This Line entry does not exist, look for the next.
//
continue;
}
//
// We should have a registry path something like:
// ..\<AdapterName>\Parameters\Line1
//
LocalScopeStatus = STATUS_SUCCESS;
if( NT_SUCCESS(LocalScopeStatus) )
{
ULONG NumberOfPorts;
//
// Some data may have been found. Let's process it.
//
DigiDump( DIGIINIT, ("NTXALL: %wZ registry info\n",
&LinePath) );
// Look for up 1 Concentrator
for( y = 1; y < 2; y++ )
{
OBJECT_ATTRIBUTES ConcentratorAttributes;
HANDLE ConcentratorHandle;
PWSTR ConcentratorString=L"Concentrator";
UNICODE_STRING ConcentratorNumberUString;
WCHAR ConcentratorNumberBuffer[8];
RtlInitUnicodeString( &ConcentratorNumberUString, NULL );
ConcentratorNumberUString.MaximumLength = sizeof(ConcentratorNumberBuffer);
ConcentratorNumberUString.Buffer = &ConcentratorNumberBuffer[0];
RtlIntegerToUnicodeString( y, 10, &ConcentratorNumberUString );
RtlZeroMemory( ConcentratorPath.Buffer, ConcentratorPath.MaximumLength );
RtlCopyUnicodeString( &ConcentratorPath, &LinePath );
RtlAppendUnicodeToString( &ConcentratorPath, L"\\" );
RtlAppendUnicodeToString( &ConcentratorPath,
ConcentratorString );
RtlAppendUnicodeStringToString( &ConcentratorPath,
&ConcentratorNumberUString );
DigiDump( DIGIINIT, ("NTXALL: Attempting to open key:\n %wZ\n",
&ConcentratorPath) );
InitializeObjectAttributes( &ConcentratorAttributes,
&ConcentratorPath,
OBJ_CASE_INSENSITIVE,
NULL, NULL );
if( !NT_SUCCESS( ZwOpenKey( &ConcentratorHandle,
KEY_READ,
&ConcentratorAttributes ) ) )
{
DigiDump( DIGIERRORS, ("NTXALL: Could not open the drivers %wZ key.\n",
&ConcentratorPath ) );
// Unlike the LineX key, we assume our configuration is
// such that our Concentrator entries are numerically
// ordered at all times.
break;
}
LocalScopeStatus = STATUS_SUCCESS;
if( NT_SUCCESS(LocalScopeStatus) )
{
// Look for up to 16 ports on the current concentrator
for( z = 1; z < 17; z++ )
{
OBJECT_ATTRIBUTES PortAttributes;
HANDLE PortHandle;
NTSTATUS KeyExists;
PWSTR PortString=L"Port";
UNICODE_STRING PortNumberUString;
WCHAR PortNumberBuffer[8];
RtlInitUnicodeString( &PortNumberUString, NULL );
PortNumberUString.MaximumLength = sizeof(PortNumberBuffer);
PortNumberUString.Buffer = &PortNumberBuffer[0];
RtlIntegerToUnicodeString( z, 10, &PortNumberUString );
RtlZeroMemory( PortPath.Buffer, PortPath.MaximumLength );
RtlCopyUnicodeString( &PortPath, &ConcentratorPath );
RtlAppendUnicodeToString( &PortPath, L"\\" );
RtlAppendUnicodeToString( &PortPath, PortString );
RtlAppendUnicodeStringToString( &PortPath,
&PortNumberUString );
DigiDump( DIGIINIT, ("NTXALL: Checking for key:\n %wZ\n",
&PortPath) );
KeyExists = RtlCheckRegistryKey( RTL_REGISTRY_ABSOLUTE,
PortPath.Buffer );
if( !NT_SUCCESS(KeyExists) )
{
// I assume the PortZ keys are numberically ordered,
// so when a given PortZ entry is not found, it
// indicates the end of the number of ports
break;
}
RtlZeroMemory( CurNtNameForPort.Buffer,
CurNtNameForPort.MaximumLength );
RtlCopyUnicodeString( &CurNtNameForPort,
&ControllerExt->ControllerName );
RtlAppendUnicodeToString( &CurNtNameForPort,
LineString );
RtlAppendUnicodeStringToString( &CurNtNameForPort,
&LineNumberUString );
RtlAppendUnicodeToString( &CurNtNameForPort,
ConcentratorString );
RtlAppendUnicodeStringToString( &CurNtNameForPort,
&ConcentratorNumberUString );
RtlAppendUnicodeToString( &CurNtNameForPort, PortString );
RtlAppendUnicodeStringToString( &CurNtNameForPort,
&PortNumberUString );
DigiDump( DIGIINIT, ("NTXALL: CurNtNameForPort = %wZ\n",
&CurNtNameForPort) );
InitializeObjectAttributes( &PortAttributes,
&PortPath,
OBJ_CASE_INSENSITIVE,
NULL, NULL );
LocalScopeStatus = ZwOpenKey( &PortHandle,
KEY_READ,
&PortAttributes );
if( !NT_SUCCESS(Status) )
{
DigiDump( DIGIINIT, ("NTXALL: Error opening key:\n %wZ\n",
&PortPath) );
continue;
}
//
// We need to reset the CurSymbolicLinkName.MaximumLength
// to the appropriate value because of a "feature" in
// the RtlQueryRegistryValues call. If an entry is not
// found and the EntryContext is to a Unicode string, then
// Rtl function will reassign the MaximumLength to 0.
//
CurSymbolicLinkName.MaximumLength = ControllerPath->Length +
(sizeof(WCHAR) * 257);
RtlZeroMemory( CurSymbolicLinkName.Buffer,
CurSymbolicLinkName.MaximumLength );
// Read the registry for the DosDevices Name to use
TableInfo[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
TableInfo[0].Name = DEFAULT_DIRECTORY;
TableInfo[0].EntryContext = &CurSymbolicLinkName;
Status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE,
PortPath.Buffer,
TableInfo,
NULL, NULL );
if( !NT_SUCCESS(Status) )
{
// Assign a bogus Name if a DosDevices Value
// is not found!
Status = Status;
DigiDump( DIGIINIT, ("NTXALL: Bogus SymbolicLinkName\n") );
}
else
{
DigiDump( DIGIINIT, ("NTXALL: CurSymbolicLinkName = %wZ\n",
&CurSymbolicLinkName) );
}
DigiDump( DIGIINIT, ("NTXALL: After RtlQueryRegistryValues, CurSymbolicLinkName.MaxLength = %u\n",
CurSymbolicLinkName.MaximumLength) );
ZwClose( PortHandle );
// Setup and initialize the config information
NewConfigInfo = DigiAllocMem( PagedPool,
sizeof(DIGI_CONFIG_INFO) );
if( !NewConfigInfo )
{
DigiDump( DIGIERRORS, ("NTXALL: Could not allocate DIGI_CONFIG_INFO structure\n"
"----- for %wZ\n",
&PortPath ) );
break;
}
RtlInitUnicodeString( &NewConfigInfo->SymbolicLinkName, NULL );
NewConfigInfo->SymbolicLinkName.MaximumLength =
CurSymbolicLinkName.MaximumLength;
#if DBG
NewConfigInfo->SymbolicLinkName.Buffer =
DigiAllocMem( NonPagedPool,
NewConfigInfo->SymbolicLinkName.MaximumLength );
#else
NewConfigInfo->SymbolicLinkName.Buffer =
DigiAllocMem( PagedPool,
NewConfigInfo->SymbolicLinkName.MaximumLength );
#endif
if( !NewConfigInfo->SymbolicLinkName.Buffer )
{
DigiDump( DIGIERRORS, ("NTXALL: Could not allocate memory for SymbolicLinkName buffer\n"
"----- for %wZ\n",
&PortPath ) );
break;
}
RtlInitUnicodeString( &NewConfigInfo->NtNameForPort, NULL );
NewConfigInfo->NtNameForPort.MaximumLength =
CurNtNameForPort.MaximumLength;
NewConfigInfo->NtNameForPort.Buffer =
DigiAllocMem( PagedPool,
NewConfigInfo->NtNameForPort.MaximumLength );
if( !NewConfigInfo->NtNameForPort.Buffer )
{
DigiDump( DIGIERRORS, ("NTXALL: Could not allocate memory for NtNameForPort buffer\n"
"----- for %wZ\n",
&PortPath ) );
break;
}
ControllerExt->NumberOfPorts++;
RtlCopyUnicodeString( &NewConfigInfo->NtNameForPort,
&CurNtNameForPort );
RtlCopyUnicodeString( &NewConfigInfo->SymbolicLinkName,
&CurSymbolicLinkName );
InsertTailList( &ControllerExt->ConfigList,
&NewConfigInfo->ListEntry );
} // end for( z = 1; z < 129; z++ )
NumberOfPorts = z - 1;
}
ZwClose( ConcentratorHandle );
} // end for( x = 1; x < 16; x++ )
ZwClose( LineHandle );
}
else
{
// DigiDump( DIGIINIT, ("NTXALL: %wZ registry DEFAULT info\n"
// "----- return value = 0x%x\n",
// &LinePath, LocalScopeStatus) );
}
} // end for( i = 1; i < 3; i++ )
ZwClose( ParametersHandle );
GetXAllConfigInfoExit:;
if( ParametersPath.Buffer )
DigiFreeMem( ParametersPath.Buffer );
if( LinePath.Buffer )
DigiFreeMem( LinePath.Buffer );
if( ConcentratorPath.Buffer )
DigiFreeMem( ConcentratorPath.Buffer );
if( PortPath.Buffer )
DigiFreeMem( PortPath.Buffer );
if( CurNtNameForPort.Buffer )
DigiFreeMem( CurNtNameForPort.Buffer );
if( CurSymbolicLinkName.Buffer )
DigiFreeMem( CurSymbolicLinkName.Buffer );
if( TableInfo )
DigiFreeMem( TableInfo );
return( Status );
} // end GetXAllConfigInfo
NTSTATUS XallSuccess( IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp )
/*++
Services XallCleanup, XallQueryInformation, XallSetInformation,
and XallQueryVolumeInformation requests.
--*/
{
DigiDump( DIGIFLOW, ("Entering XallSuccess\n") );
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
DigiDump( DIGIFLOW, ("Exiting XallSuccess\n") );
return( STATUS_SUCCESS );
} // end XallSuccess
NTSTATUS XallInternalIoControl( IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp )
/*++
Routine Description:
This routine process private IOCTL requests which should only be called
from kernel level, i.e. other drivers.
Arguments:
DeviceObject - Pointer to this devices object.
Irp - Pointer to the open IRP request.
Return Value:
--*/
{
PIO_STACK_LOCATION IrpSp;
NTSTATUS Status=STATUS_INVALID_PARAMETER;
#if rmm > 528
PVOID lockPtr;
lockPtr = MmLockPagableCodeSection( XallXXPrepInit );
#endif
IrpSp = IoGetCurrentIrpStackLocation( Irp );
Irp->IoStatus.Information = 0L;
switch( IrpSp->Parameters.DeviceIoControl.IoControlCode )
{
case IOCTL_DIGI_GET_ENTRY_POINTS:
{
PDIGI_MINIPORT_ENTRY_POINTS EntryPoints;
DigiDump( DIGIIOCTL, ( "Dummy: IOCTL_DIGI_GET_ENTRY_POINTS\n" ));
if( IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(DIGI_MINIPORT_ENTRY_POINTS) )
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
EntryPoints = (PDIGI_MINIPORT_ENTRY_POINTS)Irp->AssociatedIrp.SystemBuffer;
EntryPoints->XXPrepInit = XallXXPrepInit;
EntryPoints->XXInit = XallXXInit;
EntryPoints->EnableWindow = XallEnableWindow;
EntryPoints->DisableWindow = XallDisableWindow;
EntryPoints->XXDownload = XallXXDownload;
EntryPoints->Board2Fep5Address = XallBoard2Fep5Address;
EntryPoints->Diagnose = XallDiagnose;
Irp->IoStatus.Information = sizeof(DIGI_MINIPORT_ENTRY_POINTS);
Status = STATUS_SUCCESS;
break;
}
}
Irp->IoStatus.Status = Status;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
#if rmm > 528
MmUnlockPagableImageSection( lockPtr );
#endif
return( Status );
} // end XallInternalIoControl
NTSTATUS XallCreate( IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp )
/*++
Routine Description:
This routine is called to open the device associated with DeviceObject.
We will always allow the driver to be opened.
Arguments:
DeviceObject - Pointer to this devices object.
Irp - Pointer to the open IRP request.
Return Value:
STATUS_SUCCESS
--*/
{
#if rmm > 528
PVOID lockPtr;
lockPtr = MmLockPagableCodeSection( XallXXPrepInit );
#endif
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
#if rmm > 528
MmUnlockPagableImageSection( lockPtr );
#endif
return( STATUS_SUCCESS );
} // end XallCreate
NTSTATUS XallClose( IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp )
/*++
Routine Description:
This routine is called to close the device associated with DeviceObject.
We will always close the device successfully.
Arguments:
DeviceObject - Pointer to this devices object.
Irp - Pointer to the open IRP request.
Return Value:
STATUS_SUCCESS
--*/
{
#if rmm > 528
PVOID lockPtr;
lockPtr = MmLockPagableCodeSection( XallXXPrepInit );
#endif
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
#if rmm > 528
MmUnlockPagableImageSection( lockPtr );
#endif
return( STATUS_SUCCESS );
} // end XallClose
VOID XallUnload( IN PDRIVER_OBJECT DriverObject )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
#if rmm > 528
PVOID lockPtr;
lockPtr = MmLockPagableCodeSection( XallXXPrepInit );
#endif
IoDeleteDevice( DriverObject->DeviceObject );
#if rmm > 528
MmUnlockPagableImageSection( lockPtr );
#endif
return;
} // end XallUnload
DIGI_MEM_COMPARES DigiMemCompare( IN PHYSICAL_ADDRESS A,
IN ULONG SpanOfA,
IN PHYSICAL_ADDRESS B,
IN ULONG SpanOfB )
/*++
Routine Description:
Compare two phsical address.
Arguments:
A - One half of the comparison.
SpanOfA - In units of bytes, the span of A.
B - One half of the comparison.
SpanOfB - In units of bytes, the span of B.
Return Value:
The result of the comparison.
--*/
{
LARGE_INTEGER a;
LARGE_INTEGER b;
LARGE_INTEGER lower;
ULONG lowerSpan;
LARGE_INTEGER higher;
#if rmm < 807
a.LowPart = A.LowPart;
a.HighPart = A.HighPart;
b.LowPart = B.LowPart;
b.HighPart = B.HighPart;
if (RtlLargeIntegerEqualTo(
a,
b
)) {
return AddressesAreEqual;
}
if (RtlLargeIntegerGreaterThan(
a,
b
)) {
higher = a;
lower = b;
lowerSpan = SpanOfB;
} else {
higher = b;
lower = a;
lowerSpan = SpanOfA;
}
if (RtlLargeIntegerGreaterThanOrEqualTo(
RtlLargeIntegerSubtract(
higher,
lower
),
RtlConvertUlongToLargeInteger(lowerSpan)
)) {
return AddressesAreDisjoint;
}
#else
a = A;
b = B;
if (a.QuadPart == b.QuadPart) {
return AddressesAreEqual;
}
if (a.QuadPart > b.QuadPart) {
higher = a;
lower = b;
lowerSpan = SpanOfB;
} else {
higher = b;
lower = a;
lowerSpan = SpanOfA;
}
if ((higher.QuadPart - lower.QuadPart) >= lowerSpan) {
return AddressesAreDisjoint;
}
#endif
return AddressesOverlap;
} // end DigiMemCompare
VOID DigiLogError( IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT DeviceObject OPTIONAL,
IN PHYSICAL_ADDRESS P1,
IN PHYSICAL_ADDRESS P2,
IN ULONG SequenceNumber,
IN UCHAR MajorFunctionCode,
IN UCHAR RetryCount,
IN ULONG UniqueErrorValue,
IN NTSTATUS FinalStatus,
IN NTSTATUS SpecificIOStatus,
IN ULONG LengthOfInsert1,
IN PWCHAR Insert1,
IN ULONG LengthOfInsert2,
IN PWCHAR Insert2 )
/*++
Routine Description:
This routine allocates an error log entry, copies the supplied data
to it, and requests that it be written to the error log file.
Arguments:
DriverObject - A pointer to the driver object for the device.
DeviceObject - A pointer to the device object associated with the
device that had the error, early in initialization, one may not
yet exist.
P1,P2 - If phyical addresses for the controller ports involved
with the error are available, put them through as dump data.
SequenceNumber - A ulong value that is unique to an IRP over the
life of the irp in this driver - 0 generally means an error not
associated with an irp.
MajorFunctionCode - If there is an error associated with the irp,
this is the major function code of that irp.
RetryCount - The number of times a particular operation has been
retried.
UniqueErrorValue - A unique long word that identifies the particular
call to this function.
FinalStatus - The final status given to the irp that was associated
with this error. If this log entry is being made during one of
the retries this value will be STATUS_SUCCESS.
SpecificIOStatus - The IO status for a particular error.
LengthOfInsert1 - The length in bytes (including the terminating NULL)
of the first insertion string.
Insert1 - The first insertion string.
LengthOfInsert2 - The length in bytes (including the terminating NULL)
of the second insertion string. NOTE, there must
be a first insertion string for their to be
a second insertion string.
Insert2 - The second insertion string.
Return Value:
None.
--*/
{
PIO_ERROR_LOG_PACKET errorLogEntry;
PVOID objectToUse;
SHORT dumpToAllocate = 0;
PUCHAR ptrToFirstInsert;
PUCHAR ptrToSecondInsert;
if( ARGUMENT_PRESENT(DeviceObject) )
{
objectToUse = DeviceObject;
}
else
{
objectToUse = DriverObject;
}
if( DigiMemCompare( P1, (ULONG)1,
DigiPhysicalZero, (ULONG)1 ) != AddressesAreEqual )
{
dumpToAllocate = (SHORT)sizeof(PHYSICAL_ADDRESS);
}
if( DigiMemCompare( P2, (ULONG)1,
DigiPhysicalZero, (ULONG)1 ) != AddressesAreEqual )
{
dumpToAllocate += (SHORT)sizeof(PHYSICAL_ADDRESS);
}
errorLogEntry = IoAllocateErrorLogEntry( objectToUse,
(UCHAR)(sizeof(IO_ERROR_LOG_PACKET) +
dumpToAllocate + LengthOfInsert1 +
LengthOfInsert2) );
if( errorLogEntry != NULL )
{
errorLogEntry->ErrorCode = SpecificIOStatus;
errorLogEntry->SequenceNumber = SequenceNumber;
errorLogEntry->MajorFunctionCode = MajorFunctionCode;
errorLogEntry->RetryCount = RetryCount;
errorLogEntry->UniqueErrorValue = UniqueErrorValue;
errorLogEntry->FinalStatus = FinalStatus;
errorLogEntry->DumpDataSize = dumpToAllocate;
if( dumpToAllocate )
{
RtlCopyMemory( &errorLogEntry->DumpData[0],
&P1, sizeof(PHYSICAL_ADDRESS) );
if( dumpToAllocate > sizeof(PHYSICAL_ADDRESS) )
{
RtlCopyMemory( ((PUCHAR)&errorLogEntry->DumpData[0]) +
sizeof(PHYSICAL_ADDRESS),
&P2,
sizeof(PHYSICAL_ADDRESS) );
ptrToFirstInsert =
((PUCHAR)&errorLogEntry->DumpData[0]) +
(2*sizeof(PHYSICAL_ADDRESS));
}
else
{
ptrToFirstInsert =
((PUCHAR)&errorLogEntry->DumpData[0]) +
sizeof(PHYSICAL_ADDRESS);
}
}
else
{
ptrToFirstInsert = (PUCHAR)&errorLogEntry->DumpData[0];
}
ptrToSecondInsert = ptrToFirstInsert + LengthOfInsert1;
if( LengthOfInsert1 )
{
errorLogEntry->NumberOfStrings = 1;
errorLogEntry->StringOffset = (USHORT)(ptrToFirstInsert -
(PUCHAR)errorLogEntry);
RtlCopyMemory( ptrToFirstInsert, Insert1, LengthOfInsert1 );
if( LengthOfInsert2 )
{
errorLogEntry->NumberOfStrings = 2;
RtlCopyMemory( ptrToSecondInsert, Insert2, LengthOfInsert2 );
}
}
IoWriteErrorLogEntry(errorLogEntry);
}
} // end DigiLogError
NTSTATUS NtXallInitMCA( PUNICODE_STRING ControllerPath,
PDIGI_CONTROLLER_EXTENSION ControllerExt )
/*++
Routine Description:
This routine will be called if it is determined the type of bus
is MCA. We verify that the controller is actually a DigiBoard
X* controller, read the POS to determine the I/O address and
Memory Mapped address, so the initialization process can continue.
Arguments:
ControllerPath - pointer to the registry path where this controllers
configuration information is kept.
ControllerExt - pointer to this controller extension information
where the I/O and Memory address should be stored.
Return Value:
STATUS_SUCCESS - If we were able to complete successfully
?? - We were not able to get the information required to continue.
--*/
{
PWSTR ParametersString=L"Parameters";
PWSTR MCAPosIdString=L"McaPosId";
PWSTR SlotNumberString=L"SlotNumber";
ULONG MCAPosId;
LONG SlotNumber;
USHORT ActualPosId, POSConfig = 0;
USHORT IOPortOffset;
USHORT IRQAddress;
ULONG MemoryAddress;
OBJECT_ATTRIBUTES ControllerAttributes;
HANDLE ControllerHandle;
PRTL_QUERY_REGISTRY_TABLE MCAInfo = NULL;
PHYSICAL_ADDRESS TempAddress;
NTSTATUS Status = STATUS_SUCCESS;
UCHAR OneByte;
//
// We need to read the POS Adapter ID and make sure the controller
// is one of ours. Get the Slot number and the POS ID we
// installed during configuration from the registry.
//
MCAInfo = DigiAllocMem( PagedPool,
sizeof( RTL_QUERY_REGISTRY_TABLE ) * 4 );
if( !MCAInfo )
{
DigiDump( DIGIERRORS, ("NTXALL: Could not allocate table for rtl query\n"
"----- to for %wZ\n",
ControllerPath ) );
Status = STATUS_INSUFFICIENT_RESOURCES;
goto NtXallInitMCAExit;
}
RtlZeroMemory( MCAInfo, sizeof(RTL_QUERY_REGISTRY_TABLE) * 4 );
MCAInfo[0].QueryRoutine = NULL;
MCAInfo[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
MCAInfo[0].Name = ParametersString;
MCAInfo[1].Flags = RTL_QUERY_REGISTRY_REQUIRED |
RTL_QUERY_REGISTRY_DIRECT;
MCAInfo[1].Name = MCAPosIdString;
MCAInfo[1].EntryContext = &MCAPosId;
MCAInfo[2].Flags = RTL_QUERY_REGISTRY_REQUIRED |
RTL_QUERY_REGISTRY_DIRECT;
MCAInfo[2].Name = SlotNumberString;
MCAInfo[2].EntryContext = &SlotNumber;
RtlZeroMemory( &MCAPosId, sizeof(MCAPosId) );
SlotNumber = -1;
InitializeObjectAttributes( &ControllerAttributes,
ControllerPath,
OBJ_CASE_INSENSITIVE,
NULL, NULL );
if( !NT_SUCCESS( Status = ZwOpenKey( &ControllerHandle, MAXIMUM_ALLOWED,
&ControllerAttributes ) ) )
{
DigiDump( DIGIERRORS, ("NTXALL: Could not open the drivers DigiBoard key %wZ\n",
ControllerPath ) );
// DigiLogError( GlobalDriverObject,
// NULL,
// DigiPhysicalZero,
// DigiPhysicalZero,
// 0,
// 0,
// 0,
// 8,
// Status,
// SERIAL_UNABLE_TO_OPEN_KEY,
// ControllerPath->Length + sizeof(WCHAR),
// ControllerPath->Buffer,
// 0,
// NULL );
goto NtXallInitMCAExit;
}
DigiDump( DIGIINIT, ("NTXALL: registry path = %wZ\n",
ControllerPath) );
Status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE,
ControllerPath->Buffer,
MCAInfo,
NULL, NULL );
if( !NT_SUCCESS(Status) )
{
if( !MCAPosId )
{
DigiDump( DIGIERRORS, ("NTXALL: Could not get %ws from registry.\n",
MCAPosIdString) );
DigiLogError( GlobalDriverObject,
NULL,
DigiPhysicalZero,
DigiPhysicalZero,
0,
0,
0,
__LINE__,
Status,
SERIAL_REGISTRY_VALUE_NOT_FOUND,
DigiWstrLength(MCAPosIdString) + sizeof(WCHAR),
MCAPosIdString,
0,
NULL );
}
if( SlotNumber == -1 )
{
DigiDump( DIGIERRORS, ("NTXALL: Could not get %ws from registry.\n",
SlotNumberString) );
DigiLogError( GlobalDriverObject,
NULL,
DigiPhysicalZero,
DigiPhysicalZero,
0,
0,
0,
__LINE__,
Status,
SERIAL_REGISTRY_VALUE_NOT_FOUND,
DigiWstrLength(SlotNumberString) + sizeof(WCHAR),
SlotNumberString,
0,
NULL );
}
goto NtXallInitMCAExit;
}
DigiDump( DIGIINIT, ("NTXALL: %wZ registry info\n"
"--------- MCAPosId: 0x%x\n",
ControllerPath, MCAPosId) );
DigiDump( DIGIINIT, ("--------- SlotNumber: 0x%x\n",
SlotNumber) );
// Enable the POS information for the slot we are interested in.
WRITE_PORT_UCHAR( ControllerExt->VirtualPOSBaseAddress, (UCHAR)(SlotNumber + 7) );
OneByte = READ_PORT_UCHAR( ControllerExt->VirtualPOSInfoAddress + 1 );
ActualPosId = ((USHORT)OneByte << 8);
OneByte = READ_PORT_UCHAR( ControllerExt->VirtualPOSInfoAddress );
ActualPosId |= OneByte;
DigiDump( DIGIINIT, ("POS Adapter ID = 0x%hx\n", ActualPosId) );
TempAddress.LowPart = ActualPosId;
TempAddress.HighPart = 0;
//
// Is this a new MC/2e, MC/4e, or MC/8e?
//
if( ActualPosId == MCA_XPORT_POS_ID )
{
//
// This is a new controller.
//
OneByte = READ_PORT_UCHAR( ControllerExt->VirtualPOSInfoAddress + 3 );
POSConfig = ((USHORT)OneByte << 8);
OneByte = READ_PORT_UCHAR( ControllerExt->VirtualPOSInfoAddress + 2 );
POSConfig |= OneByte;
OneByte = READ_PORT_UCHAR( ControllerExt->VirtualPOSInfoAddress + 5 );
OneByte &= 0x60;
IOPortOffset = (POSConfig & MCA_IO_PORT_MASK) >> 4;
MemoryAddress = ((ULONG)(POSConfig & MCA_MEMORY_MASK) << 8);
MemoryAddress |= ( ((ULONG)OneByte << 8) & 0x00006000 );
DigiDump( DIGIINIT, ("POS config read = 0x%hx\n"
" IOPortOffset = 0x%hx, MemoryAddress = 0x%x,"
" IOPort = 0x%hx\n",
POSConfig, IOPortOffset, MemoryAddress,
MCAIOAddressTable[IOPortOffset]) );
//
// If the 8K window is not enable, enable it!
//
OneByte = READ_PORT_UCHAR( ControllerExt->VirtualPOSInfoAddress + 5 );
if( !(OneByte & 0x0010) )
{
DigiLogError( GlobalDriverObject,
NULL,
TempAddress,
DigiPhysicalZero,
0,
0,
0,
__LINE__,
STATUS_SERIAL_NO_DEVICE_INITED,
SERIAL_RESIZING_WINDOW,
ControllerExt->ControllerName.Length + sizeof(WCHAR),
ControllerExt->ControllerName.Buffer,
0,
NULL );
}
//
// If interrupts are enabled, we disable them for now.
//
IRQAddress = (USHORT)(POSConfig & MCA_IRQ_MASK);
if( IRQAddress )
{
OneByte = READ_PORT_UCHAR( ControllerExt->VirtualPOSInfoAddress + 2 );
OneByte &= ~MCA_IRQ_MASK;
WRITE_PORT_UCHAR( ControllerExt->VirtualPOSInfoAddress, OneByte );
}
ControllerExt->PhysicalIOPort.LowPart = MCAIOAddressTable[IOPortOffset];
ControllerExt->PhysicalIOPort.HighPart = 0;
ControllerExt->PhysicalMemoryAddress.LowPart = MemoryAddress;
ControllerExt->PhysicalMemoryAddress.HighPart = 0;
}
else
{
USHORT MemoryOffset;
//
// Check and make sure this is only a 32K controller.
//
if( (ActualPosId & 0x7F90) != 0x7F90 )
{
//
// This must be a 128K controller. Log an error message and
// return.
//
DigiLogError( GlobalDriverObject,
NULL,
TempAddress,
DigiPhysicalZero,
0,
0,
0,
__LINE__,
STATUS_SERIAL_NO_DEVICE_INITED,
SERIAL_UNSUPPORTED_CONTROLLER,
ControllerExt->ControllerName.Length + sizeof(WCHAR),
ControllerExt->ControllerName.Buffer,
0,
NULL );
Status = STATUS_SERIAL_NO_DEVICE_INITED;
goto NtXallInitMCAExit;
}
//
// Assume this is an older MC2/Xi controller.
//
OneByte = READ_PORT_UCHAR( ControllerExt->VirtualPOSInfoAddress + 2);
MemoryOffset = (USHORT)((OneByte & 0x06) >> 1);
IOPortOffset = (USHORT)((OneByte & 0x18) >> 3);
MemoryAddress = MCA2XiMemoryAddressTable[MemoryOffset];
DigiDump( DIGIINIT, ("POS config read = 0x%hx\n"
" IOPortOffset = 0x%hx, MemoryOffset = 0x%hx\n"
" MemoryAddress = 0x%x, IOPort = 0x%hx\n",
POSConfig, IOPortOffset, MemoryOffset, MemoryAddress,
MCA2XiIOAddressTable[IOPortOffset]) );
ControllerExt->PhysicalIOPort.LowPart = MCA2XiIOAddressTable[IOPortOffset];
ControllerExt->PhysicalIOPort.HighPart = 0;
ControllerExt->PhysicalMemoryAddress.LowPart = MemoryAddress;
ControllerExt->PhysicalMemoryAddress.HighPart = 0;
//
// Set the window size to 32K.
//
ControllerExt->WindowSize = 0x8000;
//
// Indicate this controller is an MC2/Xi
//
ControllerExt->ControllerType = ( CONTROLLER_TYPE_MC2XI );
}
// Disable the POS information.
WRITE_PORT_UCHAR( ControllerExt->VirtualPOSBaseAddress, 0 );
NtXallInitMCAExit:;
if( MCAInfo )
DigiFreeMem( MCAInfo );
return( Status );
}
USHORT DigiWstrLength( IN PWSTR Wstr )
{
USHORT Length=0;
while( *Wstr++ )
{
Length += sizeof(WCHAR);
}
return( Length );
} // end DigiWstrLength