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.
 
 
 
 
 
 

1344 lines
42 KiB

#include "precomp.h"
/////////////////////////////////////////////////////////////////////////////////////
// This file contains all functions that are needed to integrate between the
// generic PnP code and the product specific code.
/////////////////////////////////////////////////////////////////////////////////////
#define FILE_ID SPD_PNP_C // File ID for Event Logging see SPD_DEFS.H for values.
// Prototypes
// End of Prototypes
NTSTATUS
XXX_CardGetResources(IN PDEVICE_OBJECT pDevObject,
IN PCM_RESOURCE_LIST PResList,
IN PCM_RESOURCE_LIST PTrResList)
/* ++
Routine Description:
Stores resources given to us by the PnP manager
in the card's device extension.
Arguments:
pDevObject - Pointer to the device object.
PResList - Pointer to the untranslated resources requested.
PTrResList - Pointer to the translated resources requested.
Return Value:
STATUS_SUCCESS.
--*/
{
PCARD_DEVICE_EXTENSION pCard = pDevObject->DeviceExtension;
NTSTATUS status = STATUS_NOT_IMPLEMENTED;
CHAR szErrorMsg[MAX_ERROR_LOG_INSERT]; // Limited to 51 characters + 1 null
ULONG count = 0;
ULONG i = 0;
USHORT MemoryResource = 0;
USHORT IOResource = 0;
PCM_FULL_RESOURCE_DESCRIPTOR pFullResourceDesc = NULL;
PCM_PARTIAL_RESOURCE_LIST pPartialResourceList = NULL;
PCM_PARTIAL_RESOURCE_DESCRIPTOR pPartialResourceDesc = NULL;
PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL
SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Entering XXX_CardGetResources for Card %d.\n",
PRODUCT_NAME, pCard->CardNumber));
SpxDbgMsg(SPX_MISC_DBG, ("%s: Resource pointer is 0x%X\n", PRODUCT_NAME, PResList));
SpxDbgMsg(SPX_MISC_DBG, ("%s: Translated resource pointer is 0x%X\n", PRODUCT_NAME, PTrResList));
if((PResList == NULL) || (PTrResList == NULL))
{
// This shouldn't happen in theory
ASSERT(PResList != NULL);
ASSERT(PTrResList != NULL);
sprintf(szErrorMsg, "Card %d has been given no resources.", pCard->CardNumber);
Spx_LogMessage( STATUS_SEVERITY_ERROR,
pCard->DriverObject, // Driver Object
pCard->DeviceObject, // Device Object (Optional)
PhysicalZero, // Physical Address 1
PhysicalZero, // Physical Address 2
0, // SequenceNumber
0, // Major Function Code
0, // RetryCount
FILE_ID | __LINE__, // UniqueErrorValue
STATUS_SUCCESS, // FinalStatus
szErrorMsg); // Error Message
// This status is as appropriate as I can think of
return STATUS_INSUFFICIENT_RESOURCES;
}
// Each resource list should have only one set of resources
ASSERT(PResList->Count == 1);
ASSERT(PTrResList->Count == 1);
// Find out the card type...
if((pCard->CardType = SpxGetNtCardType(pCard->DeviceObject)) == -1)
{
sprintf(szErrorMsg, "Card %d is unrecognised.", pCard->CardNumber);
Spx_LogMessage( STATUS_SEVERITY_ERROR,
pCard->DriverObject, // Driver Object
pCard->DeviceObject, // Device Object (Optional)
PhysicalZero, // Physical Address 1
PhysicalZero, // Physical Address 2
0, // SequenceNumber
0, // Major Function Code
0, // RetryCount
FILE_ID | __LINE__, // UniqueErrorValue
STATUS_SUCCESS, // FinalStatus
szErrorMsg); // Error Message
return(STATUS_DEVICE_DOES_NOT_EXIST);
}
// Find out which raw resources have been given to us.
pFullResourceDesc = &PResList->List[0];
if(pFullResourceDesc)
{
pPartialResourceList = &pFullResourceDesc->PartialResourceList;
pPartialResourceDesc = pPartialResourceList->PartialDescriptors;
count = pPartialResourceList->Count; // Number of Partial Resource Descriptors
// Pull out the stuff that is in the full descriptor.
pCard->InterfaceType = pFullResourceDesc->InterfaceType;
pCard->BusNumber = pFullResourceDesc->BusNumber;
// Now run through the partial resource descriptors looking for the port and interrupt.
for(i = 0; i < count; i++, pPartialResourceDesc++)
{
switch(pPartialResourceDesc->Type)
{
case CmResourceTypeMemory:
break;
case CmResourceTypePort:
{
switch(pCard->CardType)
{
case Fast4_Isa:
case Fast8_Isa:
case Fast16_Isa:
case Fast4_Pci:
case Fast8_Pci:
case Fast16_Pci:
case Fast16FMC_Pci:
case RAS4_Pci:
case RAS8_Pci:
pCard->PhysAddr = pPartialResourceDesc->u.Memory.Start;
pCard->SpanOfController = pPartialResourceDesc->u.Memory.Length;
break;
default: // Speed cards
break;
}
IOResource++;
break;
}
case CmResourceTypeInterrupt:
{
pCard->OriginalIrql = pPartialResourceDesc->u.Interrupt.Level;
pCard->OriginalVector = pPartialResourceDesc->u.Interrupt.Vector;
pCard->ProcessorAffinity= pPartialResourceDesc->u.Interrupt.Affinity;
if(pPartialResourceDesc->Flags & CM_RESOURCE_INTERRUPT_LATCHED)
pCard->InterruptMode = Latched;
else
pCard->InterruptMode = LevelSensitive;
switch(pPartialResourceDesc->ShareDisposition)
{
case CmResourceShareDeviceExclusive:
pCard->InterruptShareable = FALSE;
break;
case CmResourceShareDriverExclusive:
pCard->InterruptShareable = FALSE;
break;
case CmResourceShareShared:
default:
pCard->InterruptShareable = TRUE;
break;
}
break;
}
default:
break;
}
}
}
// Do the same for the translated resources.
pFullResourceDesc = &PTrResList->List[0];
if(pFullResourceDesc)
{
pPartialResourceList = &pFullResourceDesc->PartialResourceList;
pPartialResourceDesc = pPartialResourceList->PartialDescriptors;
count = pPartialResourceList->Count; // Number of Partial Resource Descriptors
// Pull out the stuff that is in the full descriptor.
pCard->InterfaceType = pFullResourceDesc->InterfaceType;
pCard->BusNumber = pFullResourceDesc->BusNumber;
// Now run through the partial resource descriptors looking for the interrupt,
for(i = 0; i < count; i++, pPartialResourceDesc++)
{
switch(pPartialResourceDesc->Type)
{
case CmResourceTypeMemory:
{
switch(pCard->CardType)
{
case Fast4_Isa:
case Fast8_Isa:
case Fast16_Isa:
break; // No Memory resource for these
case Fast4_Pci:
case Fast8_Pci:
case Fast16_Pci:
case Fast16FMC_Pci:
case RAS4_Pci:
case RAS8_Pci:
{ // Must be config space
pCard->PCIConfigRegisters = pPartialResourceDesc->u.Memory.Start;
pCard->SpanOfPCIConfigRegisters = pPartialResourceDesc->u.Memory.Length;
break;
}
default: // Speed cards
{
if(MemoryResource == 0)
{
pCard->PhysAddr = pPartialResourceDesc->u.Memory.Start;
pCard->SpanOfController = pPartialResourceDesc->u.Memory.Length;
}
else
{ // Must be config space
pCard->PCIConfigRegisters = pPartialResourceDesc->u.Memory.Start;
pCard->SpanOfPCIConfigRegisters = pPartialResourceDesc->u.Memory.Length;
}
break;
}
}
MemoryResource++;
break;
}
case CmResourceTypePort:
break;
case CmResourceTypeInterrupt:
{
pCard->TrIrql = (KIRQL) pPartialResourceDesc->u.Interrupt.Level;
pCard->TrVector = pPartialResourceDesc->u.Interrupt.Vector;
pCard->ProcessorAffinity = pPartialResourceDesc->u.Interrupt.Affinity;
break;
}
default:
break;
}
}
}
// If we have 1 Mem or 1 I/O Resources and an interrupt the resource allocation most probably succeeded.
if(((MemoryResource >= 1) || (IOResource >= 1)) && (pCard->TrVector))
status = STATUS_SUCCESS;
return status;
}
NTSTATUS
XXX_CardInit(IN PCARD_DEVICE_EXTENSION pCard)
{
NTSTATUS status = STATUS_SUCCESS;
PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL
SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Entering XXX_CardInit for Card %d.\n",
PRODUCT_NAME, pCard->CardNumber));
pCard->OurIsr = SerialISR;
pCard->OurIsrContext = pCard;
return status;
}
NTSTATUS
XXX_CardStart(IN PCARD_DEVICE_EXTENSION pCard)
{
NTSTATUS status = STATUS_SUCCESS;
UCHAR CardID = 0;
CHAR szErrorMsg[MAX_ERROR_LOG_INSERT]; // Limited to 51 characters + 1 null
BOOLEAN bInterruptConnnected = FALSE;
PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL
SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Entering XXX_CardStart for Card %d.\n",
PRODUCT_NAME, pCard->CardNumber));
switch(pCard->CardType)
{
case Fast4_Isa:
case Fast4_Pci:
case RAS4_Pci:
pCard->UARTOffset = 8; // I/O address offset between UARTs
pCard->UARTRegStride = 1;
pCard->NumberOfPorts = 4;
pCard->ClockRate = CLOCK_FREQ_7M3728Hz; // 7.3728 MHz
pCard->Controller = (PUCHAR) pCard->PhysAddr.LowPart;
if(UL_InitUartLibrary(&pCard->UartLib, UL_LIB_16C65X_UART) != UL_STATUS_SUCCESS) // Init table of UART library functions pointers.
goto Error;
break;
case Fast8_Isa:
case Fast8_Pci:
case RAS8_Pci:
pCard->UARTOffset = 8; // I/O address offset between UARTs
pCard->UARTRegStride = 1;
pCard->NumberOfPorts = 8;
pCard->ClockRate = CLOCK_FREQ_7M3728Hz; // 7.3728 MHz
pCard->Controller = (PUCHAR) pCard->PhysAddr.LowPart;
if(UL_InitUartLibrary(&pCard->UartLib, UL_LIB_16C65X_UART) != UL_STATUS_SUCCESS) // Init table of UART library functions pointers.
goto Error;
break;
case Fast16_Isa:
case Fast16_Pci:
case Fast16FMC_Pci:
pCard->UARTOffset = 8; // I/O address offset between UARTs
pCard->UARTRegStride = 1;
pCard->NumberOfPorts = 16;
pCard->ClockRate = CLOCK_FREQ_7M3728Hz; // 7.3728 MHz
pCard->Controller = (PUCHAR) pCard->PhysAddr.LowPart;
if(UL_InitUartLibrary(&pCard->UartLib, UL_LIB_16C65X_UART) != UL_STATUS_SUCCESS) // Init table of UART library functions pointers.
goto Error;
break;
case Speed2_Pci:
pCard->UARTOffset = OXPCI_INTERNAL_MEM_OFFSET; // Memory address offset between internal UARTs
pCard->UARTRegStride = 4;
pCard->NumberOfPorts = 2;
pCard->ClockRate = CLOCK_FREQ_1M8432Hz; // 1.8432 MHz
pCard->Controller = MmMapIoSpace(pCard->PhysAddr, pCard->SpanOfController, FALSE); // Map in the card's memory base address
if(UL_InitUartLibrary(&pCard->UartLib, UL_LIB_16C95X_UART) != UL_STATUS_SUCCESS) // Init table of UART library functions pointers.
goto Error;
break;
case Speed2P_Pci:
pCard->UARTOffset = OXPCI_INTERNAL_MEM_OFFSET; // Memory address offset between internal UARTs
pCard->UARTRegStride = 4;
pCard->NumberOfPorts = 2;
pCard->ClockRate = CLOCK_FREQ_14M7456Hz; // 14.7456 MHz
pCard->Controller = MmMapIoSpace(pCard->PhysAddr, pCard->SpanOfController, FALSE); // Map in the card's memory base address
if(UL_InitUartLibrary(&pCard->UartLib, UL_LIB_16C95X_UART) != UL_STATUS_SUCCESS) // Init table of UART library functions pointers.
goto Error;
break;
case Speed4_Pci:
pCard->UARTOffset = OXPCI_INTERNAL_MEM_OFFSET; // Memory address offset between internal UARTs
pCard->UARTRegStride = 4;
pCard->NumberOfPorts = 4;
pCard->ClockRate = CLOCK_FREQ_1M8432Hz; // 1.8432 MHz
pCard->Controller = MmMapIoSpace(pCard->PhysAddr, pCard->SpanOfController, FALSE); // Map in the card's memory base address
if(UL_InitUartLibrary(&pCard->UartLib, UL_LIB_16C95X_UART) != UL_STATUS_SUCCESS) // Init table of UART library functions pointers.
goto Error;
break;
case Speed4P_Pci:
pCard->UARTOffset = OXPCI_INTERNAL_MEM_OFFSET; // Memory address offset between internal UARTs
pCard->UARTRegStride = 4;
pCard->NumberOfPorts = 4;
pCard->ClockRate = CLOCK_FREQ_14M7456Hz; // 14.7456 MHz
pCard->Controller = MmMapIoSpace(pCard->PhysAddr, pCard->SpanOfController, FALSE); // Map in the card's memory base address
if(UL_InitUartLibrary(&pCard->UartLib, UL_LIB_16C95X_UART) != UL_STATUS_SUCCESS) // Init table of UART library functions pointers.
goto Error;
break;
case Speed2and4_Pci_8BitBus:
pCard->UARTOffset = OXPCI_LOCAL_MEM_OFFSET; // Memory address offset between local bus UARTs
pCard->UARTRegStride = 4;
pCard->NumberOfPorts = 0; // No ports.
pCard->ClockRate = CLOCK_FREQ_1M8432Hz;
pCard->Controller = MmMapIoSpace(pCard->PhysAddr, pCard->SpanOfController, FALSE); // Map in the card's memory base address
break;
case Speed2P_Pci_8BitBus:
case Speed4P_Pci_8BitBus:
pCard->UARTOffset = OXPCI_LOCAL_MEM_OFFSET; // Memory address offset between local bus UARTs
pCard->UARTRegStride = 4;
pCard->NumberOfPorts = 0; // No ports on a Speed2/4+ card.
pCard->ClockRate = CLOCK_FREQ_14M7456Hz;
pCard->Controller = MmMapIoSpace(pCard->PhysAddr, pCard->SpanOfController, FALSE); // Map in the card's memory base address
break;
default:
pCard->NumberOfPorts = 0; // Default = No ports.
break;
}
// Map in the card's memory base address
if(!pCard->Controller)
{
status = STATUS_INSUFFICIENT_RESOURCES;
goto Error;
}
// Map in the card's Local Configuration Registers...
if(pCard->InterfaceType == PCIBus) // If we have some PCI config registers
{
pCard->LocalConfigRegisters = MmMapIoSpace(pCard->PCIConfigRegisters, pCard->SpanOfPCIConfigRegisters, FALSE);
if(!pCard->LocalConfigRegisters)
{
status = STATUS_INSUFFICIENT_RESOURCES;
goto Error;
}
}
// Try to connect to interrupt.
if(SPX_SUCCESS(status = IoConnectInterrupt(&pCard->Interrupt, // Interrupt object
pCard->OurIsr, // Service routine
pCard->OurIsrContext, // Service context
NULL, // SpinLock (optional)
pCard->TrVector, // Vector
pCard->TrIrql, // IRQL
pCard->TrIrql, // Synchronize IRQL
pCard->InterruptMode, // Mode (Latched/Level Sensitive)
pCard->InterruptShareable, // Sharing mode
pCard->ProcessorAffinity, // Processors to handle ints
FALSE))) // Floating point save
{
bInterruptConnnected = TRUE; // Set Interrupt Connected flag.
}
else
{
// Tell user the problem
sprintf(szErrorMsg, "Card at %08X%08X: Interrupt unavailable.", pCard->PhysAddr.HighPart, pCard->PhysAddr.LowPart);
Spx_LogMessage( STATUS_SEVERITY_ERROR,
pCard->DriverObject, // Driver Object
pCard->DeviceObject, // Device Object (Optional)
PhysicalZero, // Physical Address 1
PhysicalZero, // Physical Address 2
0, // SequenceNumber
0, // Major Function Code
0, // RetryCount
FILE_ID | __LINE__, // UniqueErrorValue
STATUS_SUCCESS, // FinalStatus
szErrorMsg); // Error Message
goto Error;
}
switch(pCard->CardType)
{
case Fast4_Isa: // If ISA card try to verify the card is present at selected address
case Fast8_Isa: // by trying to verify first UART on the Card.
case Fast16_Isa:
{
INIT_UART InitUart = {0};
// Set base address of 1st UART
InitUart.UartNumber = 0;
InitUart.BaseAddress = pCard->Controller;
InitUart.RegisterStride = pCard->UARTRegStride;
InitUart.ClockFreq = pCard->ClockRate;
pCard->pFirstUart = NULL;
// Init a UART structure.
if(pCard->UartLib.UL_InitUart_XXXX(&InitUart, pCard->pFirstUart, &(pCard->pFirstUart)) != UL_STATUS_SUCCESS)
{
status = STATUS_INSUFFICIENT_RESOURCES;
goto Error;
}
// Reset and try to verify the UART.
if(!KeSynchronizeExecution(pCard->Interrupt, SerialResetAndVerifyUart, pCard->DeviceObject)) // Verify UART exists.
{
SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Failed to find 1st UART on Card %d.\n", PRODUCT_NAME, pCard->CardNumber));
pCard->UartLib.UL_DeInitUart_XXXX(pCard->pFirstUart); // DeInit UART
status = STATUS_DEVICE_DOES_NOT_EXIST;
goto Error;
}
// DeInit the UART structure.
pCard->UartLib.UL_DeInitUart_XXXX(pCard->pFirstUart); // DeInit UART
pCard->pFirstUart = NULL;
}
default:
break;
}
switch(pCard->CardType)
{
case Speed2and4_Pci_8BitBus:
case Speed2P_Pci_8BitBus:
case Speed4P_Pci_8BitBus:
break;
default:
GetCardSettings(pCard->DeviceObject); // Get Card settings if present.
#ifdef WMI_SUPPORT
// Register for WMI
SpeedCard_WmiInitializeWmilibContext(&pCard->WmiLibInfo);
IoWMIRegistrationControl(pCard->DeviceObject, WMIREG_ACTION_REGISTER);
#endif
break;
}
return status;
Error:
if(bInterruptConnnected)
IoDisconnectInterrupt(pCard->Interrupt); // Disconnect Interrupt.
switch(pCard->CardType)
{
case Fast4_Isa:
case Fast8_Isa:
case Fast16_Isa:
case Fast4_Pci:
case Fast8_Pci:
case Fast16_Pci:
case Fast16FMC_Pci:
case RAS4_Pci:
case RAS8_Pci:
pCard->Controller = NULL;
break;
default: // Speed cards
if(pCard->Controller) // If mapped in.
{
MmUnmapIoSpace(pCard->Controller, pCard->SpanOfController); // Unmap.
pCard->Controller = NULL;
}
break;
}
if(pCard->LocalConfigRegisters) // If PCI Config registers are mapped in.
{
MmUnmapIoSpace(pCard->LocalConfigRegisters, pCard->SpanOfPCIConfigRegisters); // Unmap.
pCard->LocalConfigRegisters = NULL;
}
UL_DeInitUartLibrary(&pCard->UartLib); // DeInit table of UART library functions pointers.
switch(status)
{
case STATUS_DEVICE_DOES_NOT_EXIST:
case STATUS_UNSUCCESSFUL:
{
sprintf(szErrorMsg, "Card at %08X%08X: Unrecognised or malfunctioning.", pCard->PhysAddr.HighPart, pCard->PhysAddr.LowPart);
Spx_LogMessage( STATUS_SEVERITY_ERROR,
pCard->DriverObject, // Driver Object
pCard->DeviceObject, // Device Object (Optional)
PhysicalZero, // Physical Address 1
PhysicalZero, // Physical Address 2
0, // SequenceNumber
0, // Major Function Code
0, // RetryCount
FILE_ID | __LINE__, // UniqueErrorValue
STATUS_SUCCESS, // FinalStatus
szErrorMsg); // Error Message
break;
}
case STATUS_INSUFFICIENT_RESOURCES:
{
sprintf(szErrorMsg, "Card at %08X%08X: Insufficient resources.", pCard->PhysAddr.HighPart, pCard->PhysAddr.LowPart);
Spx_LogMessage( STATUS_SEVERITY_ERROR,
pCard->DriverObject, // Driver Object
pCard->DeviceObject, // Device Object (Optional)
PhysicalZero, // Physical Address 1
PhysicalZero, // Physical Address 2
0, // SequenceNumber
0, // Major Function Code
0, // RetryCount
FILE_ID | __LINE__, // UniqueErrorValue
STATUS_SUCCESS, // FinalStatus
szErrorMsg); // Error Message
break;
}
default:
break;
}
return status;
}
NTSTATUS
XXX_CardStop(IN PCARD_DEVICE_EXTENSION pCard)
{
NTSTATUS status = STATUS_SUCCESS;
PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL
SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Entering XXX_CardStop for Card %d.\n",
PRODUCT_NAME, pCard->CardNumber));
// Stop Card from interrupting
IoDisconnectInterrupt(pCard->Interrupt); // Disconnect from Interrupt.
#ifdef WMI_SUPPORT
switch(pCard->CardType)
{
case Speed2and4_Pci_8BitBus:
case Speed2P_Pci_8BitBus:
case Speed4P_Pci_8BitBus:
break;
default:
// Deregister for WMI
IoWMIRegistrationControl(pCard->DeviceObject, WMIREG_ACTION_DEREGISTER);
break;
}
#endif
switch(pCard->CardType)
{
case Fast4_Isa:
case Fast8_Isa:
case Fast16_Isa:
case Fast4_Pci:
case Fast8_Pci:
case Fast16_Pci:
case Fast16FMC_Pci:
case RAS4_Pci:
case RAS8_Pci:
pCard->Controller = NULL;
break;
default: // Speed cards
if(pCard->Controller) // If mapped in.
{
MmUnmapIoSpace(pCard->Controller, pCard->SpanOfController); // Unmap.
pCard->Controller = NULL;
}
break;
}
// Unmap PCI card's Local Configuration Registers...
if(pCard->LocalConfigRegisters) // If mapped in.
{
MmUnmapIoSpace(pCard->LocalConfigRegisters, pCard->SpanOfPCIConfigRegisters);
pCard->LocalConfigRegisters = NULL;
}
UL_DeInitUartLibrary(&pCard->UartLib); // DeInit table of UART library functions pointers.
pCard->InterfaceType = InterfaceTypeUndefined;
pCard->PhysAddr = PhysicalZero;
pCard->SpanOfController = 0;
pCard->OriginalIrql = 0;
pCard->OriginalVector = 0;
pCard->ProcessorAffinity = 0;
pCard->TrIrql = 0;
pCard->TrVector = 0;
pCard->Controller = NULL;
pCard->LocalConfigRegisters = NULL;
pCard->SpanOfPCIConfigRegisters = 0;
return status;
}
NTSTATUS
XXX_CardDeInit(IN PCARD_DEVICE_EXTENSION pCard)
{
NTSTATUS status = STATUS_SUCCESS;
PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL
SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Entering XXX_CardDeInit for Card %d.\n",
PRODUCT_NAME, pCard->CardNumber));
pCard->OurIsr = NULL;
pCard->OurIsrContext = NULL;
pCard->pFirstUart = NULL;
return status;
}
NTSTATUS
XXX_PortInit(IN PPORT_DEVICE_EXTENSION pPort)
{
// Initialise port device extension.
PCARD_DEVICE_EXTENSION pCard = pPort->pParentCardExt;
NTSTATUS status = STATUS_SUCCESS;
SHORT PortType = 0;
CHAR szTemp[50]; // Space to hold string
CHAR szCard[10]; // Space to hold card type string
SHORT i = 0;
int Result = 0;
INIT_UART InitUart;
PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL
SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Entering XXX_PortInit for Port %d.\n",
PRODUCT_NAME, pPort->PortNumber));
#ifndef BUILD_SPXMINIPORT
// Form an InstanceID for the port.
if(!SPX_SUCCESS(status = Spx_CreatePortInstanceID(pPort)))
return status;
#endif
switch(pCard->CardType)
{
case Fast4_Isa:
case Fast4_Pci:
sprintf(szCard, "FAST"); // Fast card
PortType = FAST_8PIN_RJ45; // 8 pin RJ45 ports with Chase pinouts
break;
case Fast8_Isa:
case Fast8_Pci:
sprintf(szCard, "FAST"); // Fast card
PortType = FAST_8PIN_XXXX; // 8 pin ports
break;
case Fast16_Isa:
case Fast16_Pci:
sprintf(szCard, "FAST"); // Fast card
PortType = FAST_6PIN_XXXX; // 6 pin ports
break;
case Fast16FMC_Pci:
sprintf(szCard, "FAST"); // Fast card
PortType = FAST_8PIN_XXXX; // 8 pin Full Modem Control (FMC) ports
break;
case RAS4_Pci:
case RAS8_Pci:
sprintf(szCard, "SPDRAS"); // RAS card
PortType = MODEM_PORT; // Modem Ports
break;
case Speed2_Pci:
sprintf(szCard, "SPD2"); // Speed 2 card
PortType = SPD_8PIN_RJ45; // 8 pin RJ45 ports
break;
case Speed2P_Pci:
sprintf(szCard, "SPD2P"); // Speed 2+ card
PortType = SPD_10PIN_RJ45; // 10 pin RJ45 ports
break;
case Speed4_Pci:
sprintf(szCard, "SPD4"); // Speed 4 card
PortType = SPD_8PIN_RJ45; // 8 pin RJ45 ports
break;
case Speed4P_Pci:
sprintf(szCard, "SPD4P"); // Speed 4+ card
PortType = SPD_10PIN_RJ45; // 10 pin RJ45 ports
break;
default:
sprintf(szCard, "XXX"); // Unknown card type
break;
}
// Initialise device identifiers...
switch(PortType)
{
case FAST_8PIN_RJ45:
sprintf(szTemp,"FAST\\%s&8PINRJ45", szCard);
Spx_InitMultiString(FALSE, &pPort->DeviceID, szTemp, NULL);
sprintf(szTemp,"FAST\\%s&8PINRJ45", szCard);
Spx_InitMultiString(TRUE, &pPort->HardwareIDs, szTemp, NULL);
sprintf(szTemp,"Perle FAST Serial Port %d", pPort->PortNumber+1);
Spx_InitMultiString(FALSE, &pPort->DevDesc, szTemp, NULL);
break;
case FAST_8PIN_XXXX:
sprintf(szTemp,"FAST\\%s&8PINXXXX", szCard);
Spx_InitMultiString(FALSE, &pPort->DeviceID, szTemp, NULL);
sprintf(szTemp,"FAST\\%s&8PINXXXX", szCard);
Spx_InitMultiString(TRUE, &pPort->HardwareIDs, szTemp, NULL);
sprintf(szTemp,"Perle FAST Serial Port %d", pPort->PortNumber+1);
Spx_InitMultiString(FALSE, &pPort->DevDesc, szTemp, NULL);
break;
case FAST_6PIN_XXXX:
sprintf(szTemp,"FAST\\%s&6PINXXXX", szCard);
Spx_InitMultiString(FALSE, &pPort->DeviceID, szTemp, NULL);
sprintf(szTemp,"FAST\\%s&6PINXXXX", szCard);
Spx_InitMultiString(TRUE, &pPort->HardwareIDs, szTemp, NULL);
sprintf(szTemp,"Perle FAST Serial Port %d", pPort->PortNumber+1);
Spx_InitMultiString(FALSE, &pPort->DevDesc, szTemp, NULL);
break;
case MODEM_PORT:
sprintf(szTemp,"SPDRAS\\RASPort");
Spx_InitMultiString(FALSE, &pPort->DeviceID, szTemp, NULL);
sprintf(szTemp,"SPDRAS\\RASPort");
Spx_InitMultiString(TRUE, &pPort->HardwareIDs, szTemp, NULL);
sprintf(szTemp,"Perle RAS Port %d", pPort->PortNumber+1);
Spx_InitMultiString(FALSE, &pPort->DevDesc, szTemp, NULL);
break;
case SPD_8PIN_RJ45:
sprintf(szTemp,"SPEED\\%s&8PINRJ45", szCard);
Spx_InitMultiString(FALSE, &pPort->DeviceID, szTemp, NULL);
sprintf(szTemp,"SPEED\\%s&8PINRJ45", szCard);
Spx_InitMultiString(TRUE, &pPort->HardwareIDs, szTemp, NULL);
sprintf(szTemp,"Perle SPEED Serial Port %d", pPort->PortNumber+1);
Spx_InitMultiString(FALSE, &pPort->DevDesc, szTemp, NULL);
break;
case SPD_10PIN_RJ45:
sprintf(szTemp,"SPEED\\%s&10PINRJ45", szCard);
Spx_InitMultiString(FALSE, &pPort->DeviceID, szTemp, NULL);
sprintf(szTemp,"SPEED\\%s&10PINRJ45", szCard);
Spx_InitMultiString(TRUE, &pPort->HardwareIDs, szTemp, NULL);
sprintf(szTemp,"Perle SPEED Serial Port %d", pPort->PortNumber+1);
Spx_InitMultiString(FALSE, &pPort->DevDesc, szTemp, NULL);
break;
default:
sprintf(szTemp,"SPEED\\%s&XXXXXXXX", szCard);
Spx_InitMultiString(FALSE, &pPort->DeviceID, szTemp, NULL);
sprintf(szTemp,"SPEED\\%s&XXXXXXXX", szCard);
Spx_InitMultiString(TRUE, &pPort->HardwareIDs, szTemp, NULL);
sprintf(szTemp,"Perle Serial Port %d of Unknown Type.", pPort->PortNumber + 1);
Spx_InitMultiString(FALSE, &pPort->DevDesc, szTemp, NULL);
status = STATUS_UNSUCCESSFUL;
break;
}
/* Not required as we are using INF file
i = sprintf(szTemp, "Port %d on ", pPort->PortNumber + 1);
sprintf(szTemp+i, "PCI Card 0x%08lX", pCard->PhysAddr);
Spx_InitMultiString(FALSE, &pPort->DevLocation, szTemp, NULL);
*/
pPort->pUartLib = &pCard->UartLib; // Store pointer to UART library functions in port.
// Set base address of port
InitUart.UartNumber = pPort->PortNumber;
InitUart.BaseAddress = pCard->Controller + (pPort->PortNumber * pCard->UARTOffset);
InitUart.RegisterStride = pCard->UARTRegStride;
InitUart.ClockFreq = pCard->ClockRate;
if(pPort->pUartLib->UL_InitUart_XXXX(&InitUart, pCard->pFirstUart, &(pPort->pUart)) != UL_STATUS_SUCCESS)
{
pPort->pUartLib = NULL; // NULL pointer to UART library functions.
return STATUS_UNSUCCESSFUL;
}
pPort->pUartLib->UL_SetAppBackPtr_XXXX(pPort->pUart, pPort); // Set back ptr.
if(pCard->pFirstUart == NULL)
pCard->pFirstUart = pPort->pUart;
pPort->Interrupt = pCard->Interrupt;
/* pPort->RFLAddress = pCard->LocalConfigRegisters + URL + pPort->PortNumber;
pPort->TFLAddress = pCard->LocalConfigRegisters + UTL + pPort->PortNumber;
// pPort->InterruptStatus = pCard->LocalConfigRegisters
*/
return status;
}
NTSTATUS
XXX_PortStart(IN PPORT_DEVICE_EXTENSION pPort)
{
NTSTATUS status = STATUS_SUCCESS;
PCARD_DEVICE_EXTENSION pCard = pPort->pParentCardExt;
SET_BUFFER_SIZES BufferSizes;
UART_INFO UartInfo;
PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL
SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Entering XXX_PortStart for Port %d.\n",
PRODUCT_NAME, pPort->PortNumber));
if(!KeSynchronizeExecution(pPort->Interrupt, SerialResetAndVerifyUart, pPort->DeviceObject)) // Verify UART exists.
{
SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Failed to find 16Cx5x Port %d.\n", PRODUCT_NAME, pPort->PortNumber));
return STATUS_UNSUCCESSFUL;
}
SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Found 16Cx5x Port %d.\n", PRODUCT_NAME, pPort->PortNumber));
KeSynchronizeExecution(pPort->Interrupt, SerialReset, pPort); // Resets the port
pPort->pUartLib->UL_GetUartInfo_XXXX(pPort->pUart, &UartInfo); // Get UART Capabilities
switch(pCard->CardType)
{
case Fast4_Isa:
case Fast4_Pci:
case Fast8_Isa:
case Fast8_Pci:
case Fast16_Isa:
case Fast16_Pci:
case Fast16FMC_Pci:
case RAS4_Pci:
case RAS8_Pci:
{
pPort->MaxTxFIFOSize = UartInfo.MaxTxFIFOSize; // Max Tx FIFO Size.
pPort->MaxRxFIFOSize = UartInfo.MaxRxFIFOSize; // Max Rx FIFO Size.
pPort->TxFIFOSize = pPort->MaxTxFIFOSize; // Default Tx FIFO Size.
pPort->RxFIFOSize = pPort->MaxRxFIFOSize; // Default Rx FIFO Size.
pPort->TxFIFOTrigLevel = 8; // Default Tx FIFO Trigger Level.
pPort->RxFIFOTrigLevel = 56; // Default Rx FIFO Trigger Level.
pPort->LoFlowCtrlThreshold = 16; // Default Low Flow Control Threshold.
pPort->HiFlowCtrlThreshold = 60; // Default High Flow Control Threshold.
break;
}
case Speed2_Pci:
case Speed2P_Pci:
case Speed4_Pci:
case Speed4P_Pci:
{
pPort->MaxTxFIFOSize = UartInfo.MaxTxFIFOSize; // Max Tx FIFO Size.
pPort->MaxRxFIFOSize = UartInfo.MaxRxFIFOSize; // Max Rx FIFO Size.
pPort->TxFIFOSize = pPort->MaxTxFIFOSize; // Default Tx FIFO Size.
pPort->RxFIFOSize = pPort->MaxRxFIFOSize; // Default Rx FIFO Size.
pPort->TxFIFOTrigLevel = 16; // Default Tx FIFO Trigger Level.
pPort->RxFIFOTrigLevel = 100; // Default Rx FIFO Trigger Level.
pPort->LoFlowCtrlThreshold = 16; // Default Low Flow Control Threshold.
pPort->HiFlowCtrlThreshold = 112; // Default High Flow Control Threshold.
break;
}
default:
break;
}
#ifdef WMI_SUPPORT
// Store Default FIFO settings for WMI
pPort->SpeedWmiFifoProp.MaxTxFiFoSize = pPort->MaxTxFIFOSize;
pPort->SpeedWmiFifoProp.MaxRxFiFoSize = pPort->MaxRxFIFOSize;
pPort->SpeedWmiFifoProp.DefaultTxFiFoLimit = pPort->TxFIFOSize;
pPort->SpeedWmiFifoProp.DefaultTxFiFoTrigger = pPort->TxFIFOTrigLevel;
pPort->SpeedWmiFifoProp.DefaultRxFiFoTrigger = pPort->RxFIFOTrigLevel;
pPort->SpeedWmiFifoProp.DefaultLoFlowCtrlThreshold = pPort->LoFlowCtrlThreshold;
pPort->SpeedWmiFifoProp.DefaultHiFlowCtrlThreshold = pPort->HiFlowCtrlThreshold;
#endif
GetPortSettings(pPort->DeviceObject); // Get Saved Port Settings if present.
// Initialize the list heads for the read, write, and mask queues...
InitializeListHead(&pPort->ReadQueue);
InitializeListHead(&pPort->WriteQueue);
InitializeListHead(&pPort->MaskQueue);
InitializeListHead(&pPort->PurgeQueue);
// Initialize the spinlock associated with fields read (& set) by IO Control functions...
KeInitializeSpinLock(&pPort->ControlLock);
// Initialize the timers used to timeout operations...
KeInitializeTimer(&pPort->ReadRequestTotalTimer);
KeInitializeTimer(&pPort->ReadRequestIntervalTimer);
KeInitializeTimer(&pPort->WriteRequestTotalTimer);
KeInitializeTimer(&pPort->ImmediateTotalTimer);
KeInitializeTimer(&pPort->XoffCountTimer);
KeInitializeTimer(&pPort->LowerRTSTimer);
// Initialise the dpcs that will be used to complete or timeout various IO operations...
KeInitializeDpc(&pPort->CommWaitDpc, SerialCompleteWait, pPort);
KeInitializeDpc(&pPort->CompleteReadDpc, SerialCompleteRead, pPort);
KeInitializeDpc(&pPort->CompleteWriteDpc, SerialCompleteWrite, pPort);
KeInitializeDpc(&pPort->TotalImmediateTimeoutDpc, SerialTimeoutImmediate, pPort);
KeInitializeDpc(&pPort->TotalReadTimeoutDpc, SerialReadTimeout, pPort);
KeInitializeDpc(&pPort->IntervalReadTimeoutDpc, SerialIntervalReadTimeout, pPort);
KeInitializeDpc(&pPort->TotalWriteTimeoutDpc, SerialWriteTimeout, pPort);
KeInitializeDpc(&pPort->CommErrorDpc, SerialCommError, pPort);
KeInitializeDpc(&pPort->CompleteImmediateDpc, SerialCompleteImmediate, pPort);
KeInitializeDpc(&pPort->XoffCountTimeoutDpc, SerialTimeoutXoff, pPort);
KeInitializeDpc(&pPort->XoffCountCompleteDpc, SerialCompleteXoff, pPort);
KeInitializeDpc(&pPort->StartTimerLowerRTSDpc, SerialStartTimerLowerRTS, pPort);
KeInitializeDpc(&pPort->PerhapsLowerRTSDpc, SerialInvokePerhapsLowerRTS, pPort);
// Default device control fields...
pPort->SpecialChars.XonChar = SERIAL_DEF_XON;
pPort->SpecialChars.XoffChar = SERIAL_DEF_XOFF;
pPort->HandFlow.ControlHandShake = SERIAL_DTR_CONTROL;
pPort->HandFlow.FlowReplace = SERIAL_RTS_CONTROL;
// Define which baud rates can be supported...
pPort->SupportedBauds = SERIAL_BAUD_USER;
pPort->UartConfig.TxBaud = 75;
if(KeSynchronizeExecution(pPort->Interrupt, SerialSetBaud, pPort) == TRUE)
pPort->SupportedBauds |= SERIAL_BAUD_075;
pPort->UartConfig.TxBaud = 110;
if(KeSynchronizeExecution(pPort->Interrupt, SerialSetBaud, pPort) == TRUE)
pPort->SupportedBauds |= SERIAL_BAUD_110;
pPort->UartConfig.TxBaud = 134;
if(KeSynchronizeExecution(pPort->Interrupt, SerialSetBaud, pPort) == TRUE)
pPort->SupportedBauds |= SERIAL_BAUD_134_5;
pPort->UartConfig.TxBaud = 150;
if(KeSynchronizeExecution(pPort->Interrupt, SerialSetBaud, pPort) == TRUE)
pPort->SupportedBauds |= SERIAL_BAUD_150;
pPort->UartConfig.TxBaud = 300;
if(KeSynchronizeExecution(pPort->Interrupt, SerialSetBaud, pPort) == TRUE)
pPort->SupportedBauds |= SERIAL_BAUD_300;
pPort->UartConfig.TxBaud = 600;
if(KeSynchronizeExecution(pPort->Interrupt, SerialSetBaud, pPort) == TRUE)
pPort->SupportedBauds |= SERIAL_BAUD_600;
pPort->UartConfig.TxBaud = 1200;
if(KeSynchronizeExecution(pPort->Interrupt, SerialSetBaud, pPort) == TRUE)
pPort->SupportedBauds |= SERIAL_BAUD_1200;
pPort->UartConfig.TxBaud = 1800;
if(KeSynchronizeExecution(pPort->Interrupt, SerialSetBaud, pPort) == TRUE)
pPort->SupportedBauds |= SERIAL_BAUD_1800;
pPort->UartConfig.TxBaud = 2400;
if(KeSynchronizeExecution(pPort->Interrupt, SerialSetBaud, pPort) == TRUE)
pPort->SupportedBauds |= SERIAL_BAUD_2400;
pPort->UartConfig.TxBaud = 4800;
if(KeSynchronizeExecution(pPort->Interrupt, SerialSetBaud, pPort) == TRUE)
pPort->SupportedBauds |= SERIAL_BAUD_4800;
pPort->UartConfig.TxBaud = 7200;
if(KeSynchronizeExecution(pPort->Interrupt, SerialSetBaud, pPort) == TRUE)
pPort->SupportedBauds |= SERIAL_BAUD_7200;
pPort->UartConfig.TxBaud = 9600;
if(KeSynchronizeExecution(pPort->Interrupt, SerialSetBaud, pPort) == TRUE)
pPort->SupportedBauds |= SERIAL_BAUD_9600;
pPort->UartConfig.TxBaud = 14400;
if(KeSynchronizeExecution(pPort->Interrupt, SerialSetBaud, pPort) == TRUE)
pPort->SupportedBauds |= SERIAL_BAUD_14400;
pPort->UartConfig.TxBaud = 19200;
if(KeSynchronizeExecution(pPort->Interrupt, SerialSetBaud, pPort) == TRUE)
pPort->SupportedBauds |= SERIAL_BAUD_19200;
pPort->UartConfig.TxBaud = 38400;
if(KeSynchronizeExecution(pPort->Interrupt, SerialSetBaud, pPort) == TRUE)
pPort->SupportedBauds |= SERIAL_BAUD_38400;
pPort->UartConfig.TxBaud = 56000;
if(KeSynchronizeExecution(pPort->Interrupt, SerialSetBaud, pPort) == TRUE)
pPort->SupportedBauds |= SERIAL_BAUD_56K;
pPort->UartConfig.TxBaud = 57600;
if(KeSynchronizeExecution(pPort->Interrupt, SerialSetBaud, pPort) == TRUE)
pPort->SupportedBauds |= SERIAL_BAUD_57600;
pPort->UartConfig.TxBaud = 115200;
if(KeSynchronizeExecution(pPort->Interrupt, SerialSetBaud, pPort) == TRUE)
pPort->SupportedBauds |= SERIAL_BAUD_115200;
pPort->UartConfig.TxBaud = 128000;
if(KeSynchronizeExecution(pPort->Interrupt, SerialSetBaud, pPort) == TRUE)
pPort->SupportedBauds |= SERIAL_BAUD_128K;
// Default line configuration: 1200,E,7,1
pPort->UartConfig.TxBaud = 1200;
pPort->LineControl = SERIAL_EVEN_PARITY | SERIAL_7_DATA | SERIAL_1_STOP;
pPort->ValidDataMask = 0x7F;
// Set Frame Config
pPort->UartConfig.FrameConfig = (pPort->UartConfig.FrameConfig & ~UC_FCFG_DATALEN_MASK) | UC_FCFG_DATALEN_7;
pPort->UartConfig.FrameConfig = (pPort->UartConfig.FrameConfig & ~UC_FCFG_PARITY_MASK) | UC_FCFG_EVEN_PARITY;
pPort->UartConfig.FrameConfig = (pPort->UartConfig.FrameConfig & ~UC_FCFG_STOPBITS_MASK) | UC_FCFG_STOPBITS_1;
// Mark this device as not being opened by anyone. We keep a variable
// around so that spurious interrupts are easily dismissed by the ISR.
pPort->DeviceIsOpen = FALSE;
// pPort->UartConfig.SpecialMode |= UC_SM_LOOPBACK_MODE; // Internal Loopback mode
// Set up values for interval timing...
// Store values into the extension for interval timing. If the interval
// timer is less than a second then come in with a short "polling" loop.
// For large (> then 2 seconds) use a 1 second poller.
pPort->ShortIntervalAmount.QuadPart = -1;
pPort->LongIntervalAmount.QuadPart = -10000000;
pPort->CutOverAmount.QuadPart = 200000000;
#ifdef WMI_SUPPORT
//
// Fill in WMI hardware data
//
pPort->WmiHwData.IrqNumber = pCard->TrIrql;
pPort->WmiHwData.IrqVector = pCard->TrVector;
pPort->WmiHwData.IrqLevel = pCard->TrIrql;
pPort->WmiHwData.IrqAffinityMask = pCard->ProcessorAffinity;
if(pCard->InterruptMode == Latched)
pPort->WmiHwData.InterruptType = SERIAL_WMI_INTTYPE_LATCHED;
else
pPort->WmiHwData.InterruptType = SERIAL_WMI_INTTYPE_LEVEL;
pPort->WmiHwData.BaseIOAddress = (ULONG_PTR)pCard->Controller;
//
// Fill in WMI device state data (as defaults)
//
pPort->WmiCommData.BaudRate = pPort->UartConfig.TxBaud;
UPDATE_WMI_LINE_CONTROL(pPort->WmiCommData, pPort->LineControl);
UPDATE_WMI_XON_XOFF_CHARS(pPort->WmiCommData, pPort->SpecialChars);
UPDATE_WMI_XMIT_THRESHOLDS(pPort->WmiCommData, pPort->HandFlow);
pPort->WmiCommData.MaximumBaudRate = 115200U; // 115200k baud max
pPort->WmiCommData.MaximumOutputBufferSize = (UINT32)((ULONG)-1);
pPort->WmiCommData.MaximumInputBufferSize = (UINT32)((ULONG)-1);
pPort->WmiCommData.Support16BitMode = FALSE;
pPort->WmiCommData.SupportDTRDSR = TRUE;
pPort->WmiCommData.SupportIntervalTimeouts = TRUE;
pPort->WmiCommData.SupportParityCheck = TRUE;
pPort->WmiCommData.SupportRTSCTS = TRUE;
pPort->WmiCommData.SupportXonXoff = TRUE;
pPort->WmiCommData.SettableBaudRate = TRUE;
pPort->WmiCommData.SettableDataBits = TRUE;
pPort->WmiCommData.SettableFlowControl = TRUE;
pPort->WmiCommData.SettableParity = TRUE;
pPort->WmiCommData.SettableParityCheck = TRUE;
pPort->WmiCommData.SettableStopBits = TRUE;
pPort->WmiCommData.IsBusy = FALSE;
// Fill in wmi perf data (all zero's)
RtlZeroMemory(&pPort->WmiPerfData, sizeof(pPort->WmiPerfData));
//
// Register for WMI
//
SpeedPort_WmiInitializeWmilibContext(&pPort->WmiLibInfo);
IoWMIRegistrationControl(pPort->DeviceObject, WMIREG_ACTION_REGISTER);
#endif
// Initialise the port hardware...
KeSynchronizeExecution(pPort->Interrupt, SerialReset, pPort); // Resets the port
KeSynchronizeExecution(pPort->Interrupt, ApplyInitialPortSettings, pPort); // Apply settings
KeSynchronizeExecution(pPort->Interrupt, SerialMarkClose, pPort); // Disables the FIFO
KeSynchronizeExecution(pPort->Interrupt, SerialClrRTS, pPort); // Clear RTS signal
KeSynchronizeExecution(pPort->Interrupt, SerialClrDTR, pPort); // Clear DTR signal
return status;
}
NTSTATUS
XXX_PortStop(IN PPORT_DEVICE_EXTENSION pPort)
{
NTSTATUS status = STATUS_SUCCESS;
PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL
SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Entering XXX_PortStop for Port %d.\n",
PRODUCT_NAME, pPort->PortNumber));
#ifdef WMI_SUPPORT
IoWMIRegistrationControl(pPort->DeviceObject, WMIREG_ACTION_DEREGISTER);
RtlZeroMemory(&pPort->WmiLibInfo, sizeof(WMILIB_CONTEXT));
#endif
// Cancel timers...
KeCancelTimer(&pPort->ReadRequestTotalTimer);
KeCancelTimer(&pPort->ReadRequestIntervalTimer);
KeCancelTimer(&pPort->WriteRequestTotalTimer);
KeCancelTimer(&pPort->ImmediateTotalTimer);
KeCancelTimer(&pPort->XoffCountTimer);
KeCancelTimer(&pPort->LowerRTSTimer);
// Cancel pending DPCs...
KeRemoveQueueDpc(&pPort->CommWaitDpc);
KeRemoveQueueDpc(&pPort->CompleteReadDpc);
KeRemoveQueueDpc(&pPort->CompleteWriteDpc);
KeRemoveQueueDpc(&pPort->TotalReadTimeoutDpc);
KeRemoveQueueDpc(&pPort->IntervalReadTimeoutDpc);
KeRemoveQueueDpc(&pPort->TotalWriteTimeoutDpc);
KeRemoveQueueDpc(&pPort->CommErrorDpc);
KeRemoveQueueDpc(&pPort->CompleteImmediateDpc);
KeRemoveQueueDpc(&pPort->TotalImmediateTimeoutDpc);
KeRemoveQueueDpc(&pPort->XoffCountTimeoutDpc);
KeRemoveQueueDpc(&pPort->XoffCountCompleteDpc);
KeRemoveQueueDpc(&pPort->StartTimerLowerRTSDpc);
KeRemoveQueueDpc(&pPort->PerhapsLowerRTSDpc);
KeSynchronizeExecution(pPort->Interrupt, SerialReset, pPort); // Resets the port
return status;
}
NTSTATUS
XXX_PortDeInit(IN PPORT_DEVICE_EXTENSION pPort)
{
PCARD_DEVICE_EXTENSION pCard = pPort->pParentCardExt;
NTSTATUS status = STATUS_SUCCESS;
PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL
SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Entering XXX_PortDeInit for Port %d.\n",
PRODUCT_NAME, pPort->PortNumber));
// If we are about to DeInit the first UART object to be serviced next
// Make the pFirstUart point to the next UART in the list.
if(pPort->pUart == pCard->pFirstUart)
pCard->pFirstUart = pCard->UartLib.UL_GetUartObject_XXXX(pPort->pUart, UL_OP_GET_NEXT_UART);
pCard->UartLib.UL_DeInitUart_XXXX(pPort->pUart); // DeInit UART
pPort->pUart = NULL;
pPort->pUartLib = NULL; // NULL pointer to UART library functions.
// Free identifier string allocations...
if(pPort->DeviceID.Buffer != NULL)
ExFreePool(pPort->DeviceID.Buffer);
if(pPort->InstanceID.Buffer != NULL)
ExFreePool(pPort->InstanceID.Buffer);
if(pPort->HardwareIDs.Buffer != NULL)
ExFreePool(pPort->HardwareIDs.Buffer);
if(pPort->DevDesc.Buffer != NULL)
ExFreePool(pPort->DevDesc.Buffer);
if(pPort->DevLocation.Buffer != NULL)
ExFreePool(pPort->DevLocation.Buffer);
return status;
}