Leaked source code of windows server 2003
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.
 
 
 
 
 
 

667 lines
16 KiB

/*++
Module Name:
Mxenum.C
Abstract:
This module contains contains the entry points
for a serial port bus enumerator PNP / WDM driver.
Environment:
kernel mode only
Notes:
Revision History:
--*/
#include <ntddk.h>
#include <devioctl.h>
#include <initguid.h>
#include <wdmguid.h>
#include <ntddser.h>
#include "mxenum.h"
static const PHYSICAL_ADDRESS SerialPhysicalZero = {0};
PWSTR BoardDesc[5]={
L"C218Turbo",
L"C218Turbo/PCI",
L"C320Turbo",
L"C320Turbo/PCI",
L"CP-204J"
};
PWSTR DownloadErrMsg[7]={
L"Fimware file not found or bad",
L"Board not found",
L"CPU module not found",
L"Download fail",
L"Download fail",
L"CPU module download fail",
L"UART module fail"
};
ULONG NumBoardInstalled;
//
// Declare some entry functions as pageable, and make DriverEntry
// discardable
//
NTSTATUS DriverEntry(PDRIVER_OBJECT, PUNICODE_STRING);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(PAGE, MxenumDriverUnload)
#pragma alloc_text(PAGE,MxenumLogError)
#endif
NTSTATUS
DriverEntry (
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING UniRegistryPath
)
/*++
Routine Description:
Initialize the entry points of the driver.
--*/
{
ULONG i;
#if !DBG
UNREFERENCED_PARAMETER (UniRegistryPath);
#endif
MxenumKdPrint (MXENUM_DBG_TRACE,("Driver Entry\n"));
MxenumKdPrint (MXENUM_DBG_TRACE, ("RegPath: %ws\n", UniRegistryPath->Buffer));
//
// Set ever slot to initially pass the request through to the lower
// device object
//
for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) {
DriverObject->MajorFunction[i] = MxenumDispatchPassThrough;
}
DriverObject->MajorFunction [IRP_MJ_INTERNAL_DEVICE_CONTROL]
= MxenumInternIoCtl;
DriverObject->MajorFunction [IRP_MJ_PNP] = MxenumPnPDispatch;
DriverObject->MajorFunction [IRP_MJ_POWER] = MxenumPowerDispatch;
DriverObject->DriverUnload = MxenumDriverUnload;
DriverObject->DriverExtension->AddDevice = MxenumAddDevice;
NumBoardInstalled = 0;
return STATUS_SUCCESS;
}
NTSTATUS
MxenumSyncCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp,
IN PKEVENT SerenumSyncEvent)
{
UNREFERENCED_PARAMETER(DeviceObject);
UNREFERENCED_PARAMETER(Irp);
KeSetEvent(SerenumSyncEvent, IO_NO_INCREMENT, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
MxenumInternIoCtl (
PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
--*/
{
PIO_STACK_LOCATION pIrpStack;
NTSTATUS status;
PCOMMON_DEVICE_DATA commonData;
PPDO_DEVICE_DATA pdoData;
PFDO_DEVICE_DATA fdoData;
// PAGED_CODE();
status = STATUS_SUCCESS;
pIrpStack = IoGetCurrentIrpStackLocation (Irp);
// ASSERT (IRP_MJ_INTERNAL_DEVICE_CONTROL == pIrpStack->MajorFunction);
commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension;
pdoData = (PPDO_DEVICE_DATA) DeviceObject->DeviceExtension;
//
// We only take Internal Device Control requests for the PDO.
// That is the objects on the bus (representing the serial ports)
if (commonData->IsFDO) {
status = STATUS_ACCESS_DENIED;
} else if (pdoData->Removed) {
//
// This bus has received the PlugPlay remove IRP. It will no longer
// respond to external requests.
//
status = STATUS_DELETE_PENDING;
} else {
switch (pIrpStack->Parameters.DeviceIoControl.IoControlCode) {
case IOCTL_MOXA_INTERNAL_BASIC_SETTINGS :
{
PDEVICE_SETTINGS pSettings;
long len;
MxenumKdPrint(MXENUM_DBG_TRACE, ("Get Settings\n"));
//
// Check the buffer size
//
if (pIrpStack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(DEVICE_SETTINGS)) {
MxenumKdPrint(MXENUM_DBG_TRACE, ("Output buffer too small\n"));
status = STATUS_BUFFER_TOO_SMALL;
break;
}
Irp->IoStatus.Information = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
pSettings = (PDEVICE_SETTINGS)Irp->AssociatedIrp.SystemBuffer;
fdoData = (PFDO_DEVICE_DATA)(pdoData->ParentFdo->DeviceExtension);
pSettings->BoardIndex = fdoData->BoardIndex;
pSettings->PortIndex = pdoData->PortIndex;
pSettings->BoardType = fdoData->BoardType;
pSettings->NumPorts = fdoData->NumPorts;
pSettings->InterfaceType = fdoData->InterfaceType;
pSettings->BusNumber = fdoData->BusNumber;
RtlCopyMemory(&pSettings->OriginalAckPort,&fdoData->OriginalAckPort,sizeof(PHYSICAL_ADDRESS));
RtlCopyMemory(&pSettings->OriginalBaseAddress,&fdoData->OriginalBaseAddress,sizeof(PHYSICAL_ADDRESS));
pSettings->BaseAddress = fdoData->BaseAddress;
pSettings->AckPort = fdoData->AckPort;
pSettings->Interrupt.Level = fdoData->Interrupt.Level;
pSettings->Interrupt.Vector = fdoData->Interrupt.Vector;
pSettings->Interrupt.Affinity = fdoData->Interrupt.Affinity;
status = STATUS_SUCCESS;
MxenumKdPrint(MXENUM_DBG_TRACE, ("OK\n"));
break;
}
case IOCTL_MOXA_INTERNAL_BOARD_READY :
{
MxenumKdPrint(MXENUM_DBG_TRACE, ("Get board ready\n"));
//
// Check the buffer size
//
if (pIrpStack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(ULONG)) {
MxenumKdPrint(MXENUM_DBG_TRACE, ("Output buffer too small\n"));
status = STATUS_BUFFER_TOO_SMALL;
break;
}
Irp->IoStatus.Information = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
fdoData = (PFDO_DEVICE_DATA)(pdoData->ParentFdo->DeviceExtension);
if (fdoData->Started == TRUE) {
*(PULONG)Irp->AssociatedIrp.SystemBuffer = 1;
MxenumKdPrint(MXENUM_DBG_TRACE, ("This board is ready\n"));
}
else {
*(PULONG)Irp->AssociatedIrp.SystemBuffer = 0;
MxenumKdPrint(MXENUM_DBG_TRACE, ("This board is not ready\n"));
}
break;
}
default:
status = STATUS_INVALID_PARAMETER;
}
}
Irp->IoStatus.Status = status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return status;
}
VOID
MxenumDriverUnload (
IN PDRIVER_OBJECT Driver
)
/*++
Routine Description:
Clean up everything we did in driver entry.
--*/
{
UNREFERENCED_PARAMETER (Driver);
PAGED_CODE();
MxenumKdPrint(MXENUM_DBG_TRACE, ("Driver unload\n"));
//
// All the device objects should be gone.
//
// ASSERT (NULL == Driver->DeviceObject);
//
// Here we free any resources allocated in DriverEntry
//
return;
}
NTSTATUS
MxenumIncIoCount (
PFDO_DEVICE_DATA Data
)
{
InterlockedIncrement (&Data->OutstandingIO);
if (Data->Removed) {
if (0 == InterlockedDecrement (&Data->OutstandingIO)) {
KeSetEvent (&Data->RemoveEvent, 0, FALSE);
}
return STATUS_DELETE_PENDING;
}
return STATUS_SUCCESS;
}
VOID
MxenumDecIoCount (
PFDO_DEVICE_DATA Data
)
{
if (0 == InterlockedDecrement (&Data->OutstandingIO)) {
KeSetEvent (&Data->RemoveEvent, 0, FALSE);
}
}
NTSTATUS
MxenumDispatchPassThrough(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Passes a request on to the lower driver.
--*/
{
PIO_STACK_LOCATION IrpStack =
IoGetCurrentIrpStackLocation( Irp );
#if 0
MxenumKdPrint(MXENUM_DBG_TRACE,
("[MxenumDispatchPassThrough] "
"IRP: %8x; "
"MajorFunction: %d\n",
Irp,
IrpStack->MajorFunction ));
#endif
//
// Pass the IRP to the target
//
IoSkipCurrentIrpStackLocation (Irp);
// BUGBUG: VERIFY THIS FUNCTIONS CORRECTLY!!!
if (((PPDO_DEVICE_DATA) DeviceObject->DeviceExtension)->IsFDO) {
return IoCallDriver(
((PFDO_DEVICE_DATA) DeviceObject->DeviceExtension)->TopOfStack,
Irp );
} else {
return IoCallDriver(
((PFDO_DEVICE_DATA) ((PPDO_DEVICE_DATA) DeviceObject->
DeviceExtension)->ParentFdo->DeviceExtension)->TopOfStack,
Irp );
}
}
MXENUM_MEM_COMPARES
MxenumMemCompare(
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;
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;
}
return AddressesOverlap;
}
VOID
MxenumLogError(
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 (MxenumMemCompare(
P1,
(ULONG)1,
SerialPhysicalZero,
(ULONG)1
) != AddressesAreEqual) {
dumpToAllocate = (SHORT)sizeof(PHYSICAL_ADDRESS);
}
if (MxenumMemCompare(
P2,
(ULONG)1,
SerialPhysicalZero,
(ULONG)1
) != AddressesAreEqual) {
dumpToAllocate += (SHORT)sizeof(PHYSICAL_ADDRESS);
}
errorLogEntry = IoAllocateErrorLogEntry(
objectToUse,
(UCHAR)(sizeof(IO_ERROR_LOG_PACKET) +
dumpToAllocate + LengthOfInsert1 +
LengthOfInsert2)
);
if ( errorLogEntry != NULL ) {
RtlZeroMemory(
(PUCHAR)errorLogEntry,
(UCHAR)(sizeof(IO_ERROR_LOG_PACKET) +
dumpToAllocate + LengthOfInsert1 +
LengthOfInsert2)
);
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);
}
}
VOID
MxenumHexToString(PWSTR buffer, int port)
{
unsigned short io;
buffer[0] = '0';
buffer[1] = 'x';
io = (USHORT)port;
io >>= 12;
io &= 0x000F;
buffer[2] = (WCHAR)('0' + io);
if ( io >= 0x000A )
buffer[2] += (WCHAR)('A' - '9' - 1);
io = (USHORT)port;
io >>= 8;
io &= 0x000F;
buffer[3] = (WCHAR)('0' + io);
if ( io >= 0x000A )
buffer[3] += (WCHAR)('A' - '9' - 1);
io = (USHORT)port;
io >>= 4;
io &= 0x000F;
buffer[4] = (WCHAR)('0' + io);
if ( io >= 0x000A )
buffer[4] += (WCHAR)('A' - '9' - 1);
io = (USHORT)port;
io &= 0x000F;
buffer[5] = (WCHAR)('0' + io);
if ( io >= 0x000A )
buffer[5] += (WCHAR)('A' - '9' - 1);
buffer[6] = (WCHAR)0;
}