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.
 
 
 
 
 
 

702 lines
22 KiB

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
init.c
Abstract:
DriverEntry initialization code for pnp isa bus extender.
Author:
Shie-Lin Tzong (shielint) 29-Apr-1996
Environment:
Kernel mode only.
Revision History:
--*/
#include "busp.h"
#include "pnpisa.h"
//
// Internal References
//
PVOID
PipGetMappedAddress(
IN INTERFACE_TYPE BusType,
IN ULONG BusNumber,
IN PHYSICAL_ADDRESS IoAddress,
IN ULONG NumberOfBytes,
IN ULONG AddressSpace,
OUT PBOOLEAN MappedAddress
);
NTSTATUS
PipAcquirePortResources(
IN PPI_BUS_EXTENSION BusExtension,
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath,
IN PHYSICAL_ADDRESS BaseAddressLow,
IN PHYSICAL_ADDRESS BaseAddressHi,
IN ULONG Alignment,
IN ULONG PortLength,
OUT PCM_RESOURCE_LIST *CmResourceList
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT,DriverEntry)
#pragma alloc_text(INIT,PipAcquirePortResources)
#pragma alloc_text(INIT,PipGetMappedAddress)
#endif
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
This is a temporary driver. It isolates all the PNP ISA cards. For each
Pnp Isa device, if its driver is installed, we retrieve user specified
resource information to configure the card and turn on the device.
Otherwise, we create a device instance for the device and record its resource
requirements list.
All the work is done in the Init/DriverEntry routine. So, this driver always
return failure to let itself be unloaded.
Arguments:
DriverObject - specifies the driver object for the bus extender.
RegistryPath - supplies a pointer to a unicode string of the service key name in
the CurrentControlSet\Services key for the bus extender.
Return Value:
Always return STATUS_UNSUCCESSFUL.
--*/
{
NTSTATUS status;
ULONG size, i, j, csn, cardDetected, maxCardDetected = 0;
PHYSICAL_ADDRESS baseAddrHi, baseAddrLow;
PUCHAR readDataPort = NULL;
PCM_RESOURCE_LIST cmResource, maxCmResource = NULL;
PCM_PARTIAL_RESOURCE_DESCRIPTOR cmResourceDescriptor;
BOOLEAN gotResource = FALSE;
PipDriverObject = DriverObject;
//
// In the first pass, we try to isolate pnpisa cards in the machine
// using read data port from each predefined ranges. One some machine
// different number of isapnp cards can be detected. We will choose
// the read data port which gives the max number of pnpisa cards.
//
for (i = 0; i < READ_DATA_PORT_RANGE_CHOICES; i++) {
baseAddrLow.LowPart = PipReadDataPortRanges[i].MinimumAddress;
baseAddrLow.HighPart = 0;
baseAddrHi.LowPart = PipReadDataPortRanges[i].MaximumAddress;
baseAddrHi.HighPart = 0;
status = PipAcquirePortResources(
&PipBusExtension,
DriverObject,
RegistryPath,
baseAddrLow,
baseAddrHi,
PipReadDataPortRanges[i].Alignment,
4,
&cmResource
);
if (!NT_SUCCESS(status)) {
continue;
}
gotResource = TRUE;
//
// Perform Pnp isolation process. This will assign card select number for each
// Pnp Isa card isolated by the system. All the isolated cards will be put into
// wait-for-key state.
//
PipIsolateCards(&csn);
//
// send initiation key to put cards into sleep state
//
PipLFSRInitiation ();
//
// For each card selected, make sure it returns valid card resource data
//
cardDetected = 0;
for (j = 1; j <= csn; j++) {
ULONG noDevices, dataLength;
PUCHAR cardData;
status = PipReadCardResourceData (
j,
&noDevices,
&cardData,
&dataLength);
if (!NT_SUCCESS(status)) {
continue;
} else {
ExFreePool(cardData);
cardDetected++;
}
}
//
// Finaly put all cards into wait for key state.
//
PipWriteAddress(CONFIG_CONTROL_PORT);
PipWriteData(CONTROL_WAIT_FOR_KEY);
if ((cardDetected != 0) && (cardDetected >= maxCardDetected)) {
maxCardDetected = cardDetected;
readDataPort = PipReadDataPort;
if (maxCmResource) {
ExFreePool(maxCmResource);
}
maxCmResource = cmResource;
} else {
ExFreePool(cmResource);
}
}
if (!gotResource) {
//
// If we did not get any port resource to assign to read data port
// log the error.
//
PipLogError(PNPISA_INSUFFICIENT_PORT_RESOURCES,
PNPISA_INIT_ACQUIRE_PORT_RESOURCE,
STATUS_INSUFFICIENT_RESOURCES,
NULL,
0,
0,
NULL
);
}
//
// Log an error to indicate there is no availble IO port for read data port
//
if (readDataPort != NULL) {
if (readDataPort != PipReadDataPort) {
if (PipReadDataPort) {
if (PipBusExtension.DataPortMapped) {
MmUnmapIoSpace(PipReadDataPort - 3, 4);
}
PipReadDataPort = NULL;
}
cmResourceDescriptor =
&maxCmResource->List->PartialResourceList.PartialDescriptors[0];
PipReadDataPort = PipGetMappedAddress(
Isa, // InterfaceType
0, // BusNumber,
cmResourceDescriptor->u.Port.Start,
cmResourceDescriptor->u.Port.Length,
cmResourceDescriptor->Flags,
&PipBusExtension.DataPortMapped
);
if (PipReadDataPort) {
PipReadDataPort += 3;
ASSERT(readDataPort == PipReadDataPort);
PipBusExtension.ReadDataPort = PipReadDataPort;
} else {
ULONG dumpData[3];
dumpData[0] = cmResourceDescriptor->u.Port.Start.LowPart;
dumpData[1] = cmResourceDescriptor->u.Port.Length;
dumpData[2] = (ULONG)cmResourceDescriptor->Flags;
PipLogError(PNPISA_REGISTER_NOT_MAPPED,
PNPISA_INIT_MAP_PORT,
STATUS_INSUFFICIENT_RESOURCES,
dumpData,
3,
0,
NULL
);
goto exit;
}
}
//
// Perform initial bus check to find all the PnP ISA devices
//
PipCheckBus(&PipBusExtension);
ASSERT(PipBusExtension.NumberCSNs == maxCardDetected);
//
// Perform PnP ISA device check to see if we should enable it.
//
PipCheckDevices(RegistryPath, &PipBusExtension);
//
// Delete all the device info structures and card info structures
//
PipDeleteCards(&PipBusExtension);
}
//
// Release address, command and read data port resources.
//
exit:
if (maxCmResource) {
ExFreePool(maxCmResource);
}
if (PipCommandPort && PipBusExtension.CmdPortMapped) {
MmUnmapIoSpace(PipCommandPort, 1);
}
if (PipAddressPort && PipBusExtension.AddrPortMapped) {
MmUnmapIoSpace(PipAddressPort, 1);
}
if (PipReadDataPort && PipBusExtension.DataPortMapped) {
MmUnmapIoSpace(PipReadDataPort - 3, 4);
}
IoAssignResources(RegistryPath,
NULL,
DriverObject,
NULL,
NULL,
NULL);
//
// Scan through every pnpisa device instance. If the device instance's
// FoundAtEnum is FALSE and no driver is installed, we will delete the
// device instance key.
//
PipCleanupDeviceInstances();
//
// Finally, return failure to get ourself unloaded.
//
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
PipAcquirePortResources(
IN PPI_BUS_EXTENSION BusExtension,
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath,
IN PHYSICAL_ADDRESS BaseAddressLow,
IN PHYSICAL_ADDRESS BaseAddressHi,
IN ULONG Alignment,
IN ULONG PortLength,
OUT PCM_RESOURCE_LIST *CmResourceList
)
/*++
Routine Description:
This routine acquires specified port resources.
Arguments:
BusExtension - Supplies a pointer to the pnp bus extension.
BaseAddressLow,
BaseAddressHi - Supplies the read data port base address range to be mapped.
Alignment - supplies the port allignment.
PortLength = Number of ports required.
Return Value:
NTSTATUS code.
--*/
{
#if 1
PCM_RESOURCE_LIST cmResource;
PCM_PARTIAL_RESOURCE_DESCRIPTOR cmResourceDescriptor;
NTSTATUS status;
ULONG size;
PIO_RESOURCE_REQUIREMENTS_LIST ioResource;
ULONG i;
PHYSICAL_ADDRESS physicalAddress;
ULONG dumpData[3];
*CmResourceList = NULL;
//
// Create a static Io resource requirements list and
// Call I/O mgr to get address, command and read data port addresses assigned.
//
size = sizeof(IO_RESOURCE_REQUIREMENTS_LIST);
ioResource = (PIO_RESOURCE_REQUIREMENTS_LIST) ExAllocatePool(PagedPool, size);
RtlZeroMemory(ioResource, size);
ioResource->ListSize = size;
ioResource->InterfaceType = Isa;
ioResource->AlternativeLists = 1;
ioResource->List[0].Version = 1;
ioResource->List[0].Revision = 1;
ioResource->List[0].Count = 1;
ioResource->List[0].Descriptors[0].Type = CmResourceTypePort;
ioResource->List[0].Descriptors[0].ShareDisposition = CmResourceShareDeviceExclusive;
ioResource->List[0].Descriptors[0].Flags = CM_RESOURCE_PORT_IO;
ioResource->List[0].Descriptors[0].u.Port.Length = PortLength;
ioResource->List[0].Descriptors[0].u.Port.Alignment = Alignment;
ioResource->List[0].Descriptors[0].u.Port.MinimumAddress = BaseAddressLow;
ioResource->List[0].Descriptors[0].u.Port.MaximumAddress = BaseAddressHi;
status = IoAssignResources(RegistryPath,
NULL,
DriverObject,
NULL,
ioResource,
&cmResource);
ExFreePool(ioResource);
if (!NT_SUCCESS(status)) {
DebugPrint((DEBUG_MESSAGE,"PnpIsa: IoAssignResources failed\n"));
return status;
}
//
// Map port addr to memory addr if necessary.
//
if (PipAddressPort == NULL) {
physicalAddress.LowPart = ADDRESS_PORT;
physicalAddress.HighPart = 0;
BusExtension->AddressPort =
PipAddressPort = PipGetMappedAddress(
Isa, // InterfaceType
0, // BusNumber,
physicalAddress,
1,
CM_RESOURCE_PORT_IO,
&BusExtension->AddrPortMapped
);
if (PipAddressPort == NULL) {
dumpData[0] = ADDRESS_PORT;
dumpData[1] = 1;
dumpData[2] = CM_RESOURCE_PORT_IO;
PipLogError(PNPISA_REGISTER_NOT_MAPPED,
PNPISA_ACQUIREPORTRESOURCE_1,
STATUS_INSUFFICIENT_RESOURCES,
dumpData,
3,
0,
NULL
);
goto exit0;
}
}
if (PipCommandPort == NULL) {
physicalAddress.LowPart = COMMAND_PORT;
physicalAddress.HighPart = 0;
BusExtension->CommandPort =
PipCommandPort = PipGetMappedAddress(
Isa, // InterfaceType
0, // BusNumber,
physicalAddress,
1,
CM_RESOURCE_PORT_IO,
&BusExtension->CmdPortMapped
);
if (PipCommandPort == NULL) {
dumpData[0] = COMMAND_PORT;
dumpData[1] = 1;
dumpData[2] = CM_RESOURCE_PORT_IO;
PipLogError(PNPISA_REGISTER_NOT_MAPPED,
PNPISA_ACQUIREPORTRESOURCE_2,
STATUS_INSUFFICIENT_RESOURCES,
dumpData,
3,
0,
NULL
);
goto exit0;
}
}
cmResourceDescriptor =
&cmResource->List->PartialResourceList.PartialDescriptors[0];
if ((cmResourceDescriptor->u.Port.Start.LowPart & 0xf) == 0) {
//
// Some cards (e.g. 3COM elnkiii) do not response to 0xyy3 addr.
//
DebugPrint((DEBUG_BREAK, "PnpIsa:ReadDataPort is at yy3\n"));
goto exit0;
}
if (PipReadDataPort && BusExtension->DataPortMapped) {
MmUnmapIoSpace(PipReadDataPort - 3, 4);
PipReadDataPort = NULL;
BusExtension->DataPortMapped = FALSE;
}
PipReadDataPort = PipGetMappedAddress(
Isa, // InterfaceType
0, // BusNumber,
cmResourceDescriptor->u.Port.Start,
cmResourceDescriptor->u.Port.Length,
cmResourceDescriptor->Flags,
&BusExtension->DataPortMapped
);
if (PipReadDataPort) {
PipReadDataPort += 3;
PipBusExtension.ReadDataPort = PipReadDataPort;
} else {
dumpData[0] = cmResourceDescriptor->u.Port.Start.LowPart;
dumpData[1] = cmResourceDescriptor->u.Port.Length;
dumpData[2] = cmResourceDescriptor->Flags;
PipLogError(PNPISA_REGISTER_NOT_MAPPED,
PNPISA_ACQUIREPORTRESOURCE_3,
STATUS_INSUFFICIENT_RESOURCES,
dumpData,
3,
0,
NULL
);
}
exit0:
//ExFreePool(cmResource);
if (PipReadDataPort && PipCommandPort && PipAddressPort) {
*CmResourceList = cmResource;
return STATUS_SUCCESS;
} else {
return STATUS_INSUFFICIENT_RESOURCES;
}
#else
PCM_RESOURCE_LIST cmResource;
PCM_PARTIAL_RESOURCE_DESCRIPTOR cmResourceDescriptor;
NTSTATUS status;
ULONG size;
PIO_RESOURCE_REQUIREMENTS_LIST ioResource;
ULONG i;
//
// Create a static Io resource requirements list and
// Call I/O mgr to get address, command and read data port addresses assigned.
//
size = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) +
sizeof (IO_RESOURCE_DESCRIPTOR) * 2;
ioResource = (PIO_RESOURCE_REQUIREMENTS_LIST) ExAllocatePool(PagedPool, size);
RtlZeroMemory(ioResource, size);
ioResource->ListSize = size;
ioResource->InterfaceType = Isa;
ioResource->AlternativeLists = 1;
ioResource->List[0].Version = 1;
ioResource->List[0].Revision = 1;
ioResource->List[0].Count = 3;
ioResource->List[0].Descriptors[0].Type = CmResourceTypePort;
ioResource->List[0].Descriptors[0].ShareDisposition = CmResourceShareDeviceExclusive;
ioResource->List[0].Descriptors[0].Flags = CM_RESOURCE_PORT_IO;
ioResource->List[0].Descriptors[0].u.Port.Length = PortLength;
ioResource->List[0].Descriptors[0].u.Port.Alignment = Alignment;
ioResource->List[0].Descriptors[0].u.Port.MinimumAddress = BaseAddressLow;
ioResource->List[0].Descriptors[0].u.Port.MaximumAddress = BaseAddressHi;
ioResource->List[0].Descriptors[1].Type = CmResourceTypePort;
ioResource->List[0].Descriptors[1].ShareDisposition = CmResourceShareDeviceExclusive;
ioResource->List[0].Descriptors[1].Flags = CM_RESOURCE_PORT_IO;
ioResource->List[0].Descriptors[1].u.Port.Length = 1;
ioResource->List[0].Descriptors[1].u.Port.Alignment = 1;
ioResource->List[0].Descriptors[1].u.Port.MinimumAddress.LowPart = ADDRESS_PORT;
ioResource->List[0].Descriptors[1].u.Port.MaximumAddress.LowPart = ADDRESS_PORT;
ioResource->List[0].Descriptors[2].Type = CmResourceTypePort;
ioResource->List[0].Descriptors[2].ShareDisposition = CmResourceShareDeviceExclusive;
ioResource->List[0].Descriptors[2].Flags = CM_RESOURCE_PORT_IO;
ioResource->List[0].Descriptors[2].u.Port.Length = 1;
ioResource->List[0].Descriptors[2].u.Port.Alignment = 1;
ioResource->List[0].Descriptors[2].u.Port.MinimumAddress.LowPart = COMMAND_PORT;
ioResource->List[0].Descriptors[2].u.Port.MaximumAddress.LowPart = COMMAND_PORT;
status = IoAssignResources(RegistryPath,
NULL,
DriverObject,
NULL,
ioResource,
&cmResource);
ExFreePool(ioResource);
if (!NT_SUCCESS(status)) {
DebugPrint((DEBUG_MESSAGE,"PnpIsa: IoAssignResources failed\n"));
return status;
}
//
// Map port addr to memory addr if necessary.
//
ASSERT(cmResource->List->PartialResourceList.Count == 3);
for (i = 0; i < cmResource->List->PartialResourceList.Count; i++) {
cmResourceDescriptor =
&cmResource->List->PartialResourceList.PartialDescriptors[i];
ASSERT(cmResourceDescriptor->Type == CmResourceTypePort);
if (cmResourceDescriptor->u.Port.Start.LowPart == ADDRESS_PORT) {
if (PipAddressPort == NULL) {
BusExtension->AddressPort =
PipAddressPort = PipGetMappedAddress(
Isa, // InterfaceType
0, // BusNumber,
cmResourceDescriptor->u.Port.Start,
cmResourceDescriptor->u.Port.Length,
cmResourceDescriptor->Flags,
&BusExtension->AddrPortMapped
);
}
} else if (cmResourceDescriptor->u.Port.Start.LowPart == COMMAND_PORT) {
if (PipCommandPort == NULL) {
BusExtension->CommandPort =
PipCommandPort = PipGetMappedAddress(
Isa, // InterfaceType
0, // BusNumber,
cmResourceDescriptor->u.Port.Start,
cmResourceDescriptor->u.Port.Length,
cmResourceDescriptor->Flags,
&BusExtension->CmdPortMapped
);
}
} else {
if ((cmResourceDescriptor->u.Port.Start.LowPart & 0xf) == 0) {
//
// Some cards (e.g. 3COM elnkiii) do not response to 0xyy3 addr.
//
DebugPrint((DEBUG_BREAK, "PnpIsa:ReadDataPort is at yy3\n"));
goto exit0;
}
if (PipReadDataPort && BusExtension->DataPortMapped) {
MmUnmapIoSpace(PipReadDataPort, 4);
PipReadDataPort = NULL;
BusExtension->DataPortMapped = FALSE;
}
PipReadDataPort = PipGetMappedAddress(
Isa, // InterfaceType
0, // BusNumber,
cmResourceDescriptor->u.Port.Start,
cmResourceDescriptor->u.Port.Length,
cmResourceDescriptor->Flags,
&BusExtension->DataPortMapped
);
if (PipReadDataPort) {
PipReadDataPort += 3;
PipBusExtension.ReadDataPort = PipReadDataPort;
}
}
}
exit0:
ExFreePool(cmResource);
if (PipReadDataPort && PipCommandPort && PipAddressPort) {
return STATUS_SUCCESS;
} else {
IoAssignResources(RegistryPath,
NULL,
DriverObject,
NULL,
NULL,
NULL);
return STATUS_INSUFFICIENT_RESOURCES;
}
#endif // 1
}
PVOID
PipGetMappedAddress(
IN INTERFACE_TYPE BusType,
IN ULONG BusNumber,
IN PHYSICAL_ADDRESS IoAddress,
IN ULONG NumberOfBytes,
IN ULONG AddressSpace,
OUT PBOOLEAN MappedAddress
)
/*++
Routine Description:
This routine maps an IO address to system address space.
Arguments:
BusType - Supplies the type of bus - eisa, mca, isa...
IoBusNumber - Supplies the bus number.
IoAddress - Supplies the base device address to be mapped.
NumberOfBytes - Supplies the number of bytes for which the address is
valid.
AddressSpace - Supplies whether the address is in io space or memory.
MappedAddress - Supplies whether the address was mapped. This only has
meaning if the address returned is non-null.
Return Value:
The mapped address.
--*/
{
PHYSICAL_ADDRESS cardAddress;
PVOID address;
HalTranslateBusAddress(BusType, BusNumber, IoAddress, &AddressSpace,
&cardAddress);
//
// Map the device base address into the virtual address space
// if the address is in memory space.
//
if (!AddressSpace) {
address = MmMapIoSpace(cardAddress, NumberOfBytes, FALSE);
*MappedAddress = (address ? TRUE : FALSE);
} else {
address = (PVOID) cardAddress.LowPart;
*MappedAddress = FALSE;
}
return address;
}