/*++
 * Copyright (c) 1990-96 Digi International Inc., All Rights Reserved
 * 
 * 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.
 * 
 * Restricted Rights Legend
 *
 * Use, duplication, or disclosure by the Government is subject to
 * restrictions set forth in sub-paragraph (c)(1)(ii) of The Rights in
 * Technical Data and Computer Software clause at DFARS 252.227-7031 or
 * subparagraphs (c)(1) and (2) of the Commercial Computer Software -
 * Restricted Rights at 48 CFR 52.227-19, as applicable.
 *
 * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
 *
 *
 * Last Update: $Date: 10/22/97 11:56a $
 *
 * $Header: /Components/Windows/NT/Sync/Build/Mp570/hw_pci.c 6     10/22/97 11:56a Darinh $
 *
 * Revision History:
 * $Log: /Components/Windows/NT/Sync/Build/Mp570/hw_pci.c $
 * 
 * 6     10/22/97 11:56a Darinh
 * Changes to make multiple board installations work better.
 * 
 * 5     9/08/97 3:44p Darinh
 * A variety of changes, including Data General fixes are included.
 * 
 * 4     7/15/97 1:05p Darinh
 * Added DigiLogError statements and message file, altered code to function
 * in DStreams environment and SNA environment with a conditional
 * compilation.
 * 
 * 3     6/06/97 1:47p Darinh
 * Everything seems functional, but more testing is required.
 * 
 * 2     4/08/97 4:55p Darinh
 * Changes made to correspond to the new DigiUtil library.  It
 * successfully transmits data!  I don't know about receiving data yet.
 * 
 * 1     4/02/97 10:08a Darinh
 * Initial checkin; ISA cards initialize, but do not pass data.
 * 
--*/

#include <ntddk.h>
#include "digilib.h"
#include "def570.h"
#include "board.h"
#include "mpisr.h"
#include "proto.h"
#include "io.h"
#include "debug.h"
#include "hwutils.h"
#include "hw570.h"
#include "digilog.h"




#if NT5_BUILD

NTSTATUS
SetupPciAdapter (
	IN PDRIVER_OBJECT	pDriverObject,
	IN PCONTROLLER_EXT	pControllerExt)
/*++

Routine Description:

	Find resources needed for this adapter, map and claim them.

Return Value:

	STATUS_SUCCESS if adapter found and resources claimed, otherwise error.

--*/
{
	ULONG				AddressSpace = 0;
	volatile	UCHAR	iBusMemoryCommType;	


	DigiDump (DIGIFLOW, ("Entering SetupPciAdapter()\n"));

	pControllerExt->PlxRegistersSpan = 0x80;

	//
	//  Now map in the PLX Runtime Registers
	//
	pControllerExt->VirtualPlxRegisters = Dg570GetMappedAddress (
		pControllerExt->BusType,
		pControllerExt->BusNumber,
		pControllerExt->PhysPlxRegisters,
		pControllerExt->PlxRegistersSpan,
		CM_RESOURCE_PORT_MEMORY,
		&pControllerExt->UnMapVirtualPlxRegisters);

	DigiDump (DIGIINIT,
		("pControllerExt->UnMapVirtualPlxRegisters returned %s\n",
		pControllerExt->UnMapVirtualPlxRegisters ? "TRUE" : "FALSE"));

	if (!pControllerExt->VirtualPlxRegisters)
	{
		DigiDump (DIGIERRORS,
			("*** Could not map PLX Registers. (%s:%d)\n",
			__FILE__, __LINE__));

		DigiLogError (pDriverObject,
			MP570_MEMORY_NOT_MAPPED,
			13,
			NULL, 0,
			pControllerExt->Name.Buffer, pControllerExt->Name.Length + sizeof (WCHAR),
			NULL, 0);

		return (STATUS_NONE_MAPPED);
	}

	pControllerExt->WindowSize		= 0x40000;	//  256 KB
	pControllerExt->NumberOfWindows = 1;

	DigiDump (DIGIVERYLOUD, ("WindowSize = 0x%x  NumberOfWindows = 0x%x\n",
		pControllerExt->WindowSize, pControllerExt->NumberOfWindows));

	//
	//  Now map in the Adapter's Shared Memory
	//
	pControllerExt->VirtualWindow = Dg570GetMappedAddress (
		pControllerExt->BusType,
		pControllerExt->BusNumber,
		pControllerExt->PhysWindowAddress,
		pControllerExt->WindowSize + 0x40000,	//  add 256 KB for SCA Registers
		CM_RESOURCE_PORT_MEMORY,
		&pControllerExt->UnMapVirtualWindow);

	DigiDump (DIGIINIT,
		("pControllerExt->UnMapVirtualWindow returned %s\n",
		pControllerExt->UnMapVirtualWindow ? "TRUE" : "FALSE"));

	if (!pControllerExt->VirtualWindow)
	{
		DigiDump (DIGIERRORS,
			("*** Could not map memory for Device memory. (%s:%d)\n",
			__FILE__, __LINE__));

		DigiLogError (pDriverObject,
			MP570_MEMORY_NOT_MAPPED,
			14,
			NULL, 0,
			pControllerExt->Name.Buffer,
			pControllerExt->Name.Length + sizeof (WCHAR),
			NULL, 0);

		return (STATUS_NONE_MAPPED);
	}

	//  The SCA registers are mapped in above the 256KB of card memory
	pControllerExt->VirtualSca = pControllerExt->VirtualWindow + 0x40000;

	//  SCA registers are mapped into memory in the PCI Sync/570 cards
	pControllerExt->VirtualIO = pControllerExt->VirtualWindow + 0x41000;

	DigiDump (DIGIINIT, ("pControllerExt (0x%p): "
		"VirtualWindow = 0x%p  VirtualIO = 0x%p\n",
			pControllerExt,
			pControllerExt->VirtualWindow,
			pControllerExt->VirtualIO));

	// Set the I/O Routine addresses
	pControllerExt->pIO_IN	= fnReadMem;
	pControllerExt->pIO_OUT = fnWriteMem;

	//
	//  Get the Bus, Memory, and Communications Interface Type information
	//  This information is used later in GetInterfaceId ().
	//
	//  *********************  NOTE ****************************************
	//
	//  The following code may look sttrange because it is.  We had a 
	//  problem with a certain type of machine (Siemens Sinergy) that
	//  would not boot with a 2.0 compliant 570 board (REV F).  REV D
	//  boards (2.1 Compliant) worked.  We observed that this first
	//  access to the boards registers did not work.  The second one
	//  did.
	//
	iBusMemoryCommType =  
		(*pControllerExt->pIO_IN) (pControllerExt->VirtualIO +
			REG570PCI_BUS_MEM_INTERF);
	iBusMemoryCommType =  
		(*pControllerExt->pIO_IN) (pControllerExt->VirtualIO +
			REG570PCI_BUS_MEM_INTERF);
	pControllerExt->iBusMemoryCommType = iBusMemoryCommType;

	DigiDump (DIGIFLOW, ("Exiting SetupPciAdapter()\n"));

	return (STATUS_SUCCESS);
}

#else

VOID
FindPCIAdapters (
	PCONTROLLER_EXT		pControllerExt);

NTSTATUS
SetupPciAdapter (
	IN PUNICODE_STRING	RegistryPath,
	IN PDRIVER_OBJECT	pDriverObject,
	IN PCONTROLLER_EXT	pControllerExt)
/*++

Routine Description:

	Find resources needed for this adapter, map and claim them.

Return Value:

	STATUS_SUCCESS if adapter found and resources claimed, otherwise error.

--*/
{
	ULONG				SlotNumber;
	ULONG				AddressSpace = 0;
	BOOLEAN				Found;
	PCI_COMMON_CONFIG	PciConfig;
	NTSTATUS			Status;
	ULONG				BytesRead;
	PCM_RESOURCE_LIST	pAllocatedResources = NULL;
	ULONG				i;
	volatile	UCHAR	iBusMemoryCommType;	
	DIGI_RESOURCE_LIST  Resources = {0};


	DigiDump (DIGIFLOW, ("Entering SetupPciAdapter()\n"));


	//
	//  Read the card info for the given slot and bus
	//
	BytesRead = HalGetBusData (PCIConfiguration,
		pControllerExt->BusNumber,
		pControllerExt->SlotNumber,
		&PciConfig,
		sizeof (PCI_COMMON_CONFIG));

	switch (BytesRead)
	{
	default:
		DigiDump (DIGIVERYLOUD, ("PCI Card found in bus: %d, slot: %d\n",
			pControllerExt->BusNumber, pControllerExt->SlotNumber));
		break;

	case 0:
		// PCIBus BusNumber does not exist.  Report an error, and exit.
		DigiDump (DIGIERRORS, ("*** PCI bus %d does not exist.  (%s:%d)\n",
			pControllerExt->BusNumber, __FILE__, __LINE__));

		DigiLogError (pGlobalDriverObject,
			MP570PCI_CARD_NOT_FOUND,
			9,
			NULL, 0,
			pControllerExt->Name.Buffer,
			pControllerExt->Name.Length + sizeof (WCHAR),
			NULL, 0);

		FindPCIAdapters (pControllerExt);
		goto AnErrorOccurred;

	case 2:
		DigiDump (DIGIERRORS, ("*** PCI slot %d is empty.  (%s:%d)\n",
			pControllerExt->SlotNumber, __FILE__, __LINE__));

		DigiLogError (pGlobalDriverObject,
			MP570PCI_CARD_NOT_FOUND,
			10,
			NULL, 0,
			pControllerExt->Name.Buffer, pControllerExt->Name.Length + sizeof (WCHAR),
			NULL, 0);

		FindPCIAdapters (pControllerExt);
		goto AnErrorOccurred;
	}


	//  Found an adapter,  Is it a Sync570?
	if (((PciConfig.VendorID == DIGI_PCI_VENDOR_ID) ||
		(PciConfig.VendorID == DIGI_PCI_VENDOR_ID_NEW)) &&
		((PciConfig.DeviceID == DIGI_PCI_SYNC570I_2PORT_LIN) ||
		(PciConfig.DeviceID == DIGI_PCI_SYNC570I_4PORT_LIN)))
	{
		DigiDump (DIGIVERYLOUD, ("Digi Sync570 found!\n"));

		//  Save this device's ID for later
		pControllerExt->DeviceID = PciConfig.DeviceID;

		pControllerExt->pIO_IN = fnReadMem;
		pControllerExt->pIO_OUT = fnWriteMem;
	}
	else
	{

		WCHAR			DeviceIdBuffer[16];
		UNICODE_STRING	uniDeviceId;
		WCHAR			VendorIdBuffer[16];
		UNICODE_STRING	uniVendorId;

		// Convert the PCI Vendor ID to a string
		RtlZeroMemory( VendorIdBuffer, sizeof( VendorIdBuffer ) );
		uniVendorId.Length = 0;
		uniVendorId.Buffer = VendorIdBuffer;
		uniVendorId.MaximumLength = sizeof( VendorIdBuffer );
		RtlIntegerToUnicodeString(PciConfig.VendorID,16,&uniVendorId);

		// Convert the PCI Device ID to a string
		RtlZeroMemory( DeviceIdBuffer, sizeof( DeviceIdBuffer ) );
		uniDeviceId.Length = 0;
		uniDeviceId.Buffer = DeviceIdBuffer;
		uniDeviceId.MaximumLength = sizeof( DeviceIdBuffer );
		RtlIntegerToUnicodeString(PciConfig.DeviceID,16,&uniDeviceId);

		//  Not a Sync570, exit with error.
		DigiDump (DIGIERRORS, ("*** PCI Sync/570i not found.  (%s:%d)\n",
			__FILE__, __LINE__));

		DigiLogError (pGlobalDriverObject,
			MP570PCI_UNSUPPORTED_CARD_FOUND,
			11,
			NULL, 0,
			uniVendorId.Buffer,
			uniVendorId.Length + sizeof (WCHAR),
			uniDeviceId.Buffer,
			uniDeviceId.Length + sizeof (WCHAR));

		goto AnErrorOccurred;
	}

	Status = DigiAssignPciSlotResources (
		pDriverObject,
		RegistryPath,
		pControllerExt->BusNumber,
		pControllerExt->SlotNumber,
		&pAllocatedResources,
		&Resources);

	if (!NT_SUCCESS (Status))
	{
		// Couldn't assign resources (i/o, memory, or irq)
		DigiDump (DIGIERRORS,
			("*** (0x%x) Couldn't assign resources for this adapter. (%s:%d)\n",
				Status, __FILE__, __LINE__));

		DigiLogError (pGlobalDriverObject,
			MP570_REGISTERS_NOT_MAPPED,
			12,
			NULL, 0,
			pControllerExt->Name.Buffer, pControllerExt->Name.Length + sizeof (WCHAR),
			NULL, 0);

		return (Status);
	}


	//
	// Check if all the resources were assigned.
	//
	if ((PciConfig.u.type0.BaseAddresses[1] & 0xFFFFFFFC) &&
		(PciConfig.u.type0.BaseAddresses[2] & 0xFFFFFFF0) ||
		(PciConfig.u.type0.InterruptLine))
	{
		pControllerExt->PhysPlxRegisters.LowPart =
			(PciConfig.u.type0.BaseAddresses[0] & 0xFFFFFFFC);

		pControllerExt->PhysWindowAddress.LowPart =
			PciConfig.u.type0.BaseAddresses[2] & 0xFFFFFFF0;
	}
	else
	{
		Status = STATUS_UNSUCCESSFUL;
		DigiDump (DIGIERRORS, ("*** Resources NOT assigned!!!\n"));
		goto AnErrorOccurred;
	}


	pControllerExt->PlxRegistersSpan = 0x80;

	//
	//  Now map in the PLX Runtime Registers
	//
	pControllerExt->VirtualPlxRegisters = Dg570GetMappedAddress (
		pControllerExt->BusType,
		pControllerExt->BusNumber,
		pControllerExt->PhysPlxRegisters,
		pControllerExt->PlxRegistersSpan,
		CM_RESOURCE_PORT_MEMORY,
		&pControllerExt->UnMapVirtualPlxRegisters);

	DigiDump (DIGIINIT,
		("pControllerExt->UnMapVirtualPlxRegisters returned %s\n",
		pControllerExt->UnMapVirtualPlxRegisters ? "TRUE" : "FALSE"));

	if (!pControllerExt->VirtualPlxRegisters)
	{
		DigiDump (DIGIERRORS,
			("*** Could not map PLX Registers. (%s:%d)\n",
			__FILE__, __LINE__));

		DigiLogError (pGlobalDriverObject,
			MP570_MEMORY_NOT_MAPPED,
			13,
			NULL, 0,
			pControllerExt->Name.Buffer, pControllerExt->Name.Length + sizeof (WCHAR),
			NULL, 0);

		return (STATUS_NONE_MAPPED);
	}

	pControllerExt->WindowSize = 0x40000;	//  256 KB
	pControllerExt->NumberOfWindows = 1;

	DigiDump (DIGIVERYLOUD, ("WindowSize = 0x%x  NumberOfWindows = 0x%x\n",
		pControllerExt->WindowSize, pControllerExt->NumberOfWindows));

	//
	//  Now map in the Adapter's Shared Memory
	//
	pControllerExt->VirtualWindow = Dg570GetMappedAddress (
		pControllerExt->BusType,
		pControllerExt->BusNumber,
		pControllerExt->PhysWindowAddress,
		pControllerExt->WindowSize + 0x40000,	//  add 256 KB for SCA Registers
		CM_RESOURCE_PORT_MEMORY,
		&pControllerExt->UnMapVirtualWindow);

	DigiDump (DIGIINIT,
		("pControllerExt->UnMapVirtualWindow returned %s\n",
		pControllerExt->UnMapVirtualWindow ? "TRUE" : "FALSE"));

	if (!pControllerExt->VirtualWindow)
	{
		DigiDump (DIGIERRORS,
			("*** Could not map memory for Device memory. (%s:%d)\n",
			__FILE__, __LINE__));

		DigiLogError (pGlobalDriverObject,
			MP570_MEMORY_NOT_MAPPED,
			14,
			NULL, 0,
			pControllerExt->Name.Buffer,
			pControllerExt->Name.Length + sizeof (WCHAR),
			NULL, 0);

		return (STATUS_NONE_MAPPED);
	}

	//  The SCA registers are mapped in above the 256KB of card memory
	pControllerExt->VirtualSca = pControllerExt->VirtualWindow + 0x40000;

	//  SCA registers are mapped into memory in the PCI Sync/570 cards
	pControllerExt->VirtualIO = pControllerExt->VirtualWindow + 0x41000;

	DigiDump (DIGIINIT, ("pControllerExt (0x%x): "
		"VirtualWindow = 0x%x  VirtualIO = 0x%x\n",
			(ULONG) pControllerExt,
			(ULONG) pControllerExt->VirtualWindow,
			(ULONG) pControllerExt->VirtualIO));


	//
	//  Get the Bus, Memory, and Communications Interface Type information
	//  This information is used later in GetInterfaceId ().
	//
	//  *********************  NOTE ****************************************
	//
	//  The following code may look sttrange because it is.  We had a 
	//  problem with a certain type of machine (Siemens Sinergy) that
	//  would not boot with a 2.0 compliant 570 board (REV F).  REV D
	//  boards (2.1 Compliant) worked.  We observed that this first
	//  access to the boards registers did not work.  The second one
	//  did.
	//
	iBusMemoryCommType =  
		(*pControllerExt->pIO_IN) (pControllerExt->VirtualIO +
			REG570PCI_BUS_MEM_INTERF);
	iBusMemoryCommType =  
		(*pControllerExt->pIO_IN) (pControllerExt->VirtualIO +
			REG570PCI_BUS_MEM_INTERF);
	pControllerExt->iBusMemoryCommType = iBusMemoryCommType;

	// Save Interrupt information
	pControllerExt->InterruptLevelOriginal = PciConfig.u.type0.InterruptLine;

	DigiDump (DIGIFLOW, ("Exiting SetupPciAdapter()\n"));

	return (STATUS_SUCCESS);

AnErrorOccurred:

	return (STATUS_NOT_FOUND);
}

#endif // NT5_BUILD

NTSTATUS
PciConnectToInterrupt (
	IN PCONTROLLER_EXT	pControllerExt)
{
	BOOLEAN		ConflictDetected;
	NTSTATUS	Status = STATUS_SUCCESS;


	DigiDump (DIGIFLOW, ("Entering ConnectToInterrupt()\n"));

	//
	//  Disabling Interrupts on the card
	//
	DigiDump (DIGIVERYLOUD, ("  Disabling Interrupts.\n"));
	WRT_REG_UCHAR (pControllerExt->VirtualPlxRegisters + 0x69, 0);

	pControllerExt->InterruptMode = LevelSensitive;
	pControllerExt->InterruptShareable = TRUE;

#if !NT5_BUILD

	DigiDump (DIGIINIT, ("  Int Level Orig: 0x%x  Int Mode: LevelSensitive, "
		"Int is Shareable\n",
		pControllerExt->InterruptLevelOriginal));

	//
	//  Get system assigned Interrupt Vector
	//
	pControllerExt->InterruptVector = HalGetInterruptVector (
		pControllerExt->BusType,
		pControllerExt->BusNumber,
		pControllerExt->InterruptLevelOriginal,
		pControllerExt->InterruptLevelOriginal,
		&(pControllerExt->InterruptLevel),
		&(pControllerExt->ProcessorAffinity) );

#endif

	//
	//  We need to connect to a H/W interrupt.
	//
	Status = IoConnectInterrupt (&pControllerExt->InterruptObject,
		fnISR,
		pControllerExt,
		NULL,
		pControllerExt->InterruptVector,
		pControllerExt->InterruptLevel,
		pControllerExt->InterruptLevel,
		pControllerExt->InterruptMode,
		pControllerExt->InterruptShareable,
		pControllerExt->ProcessorAffinity,
		FALSE);

	if (!NT_SUCCESS (Status))
	{
		DigiDump (DIGIERRORS,
			("*** Could not claim interrupt vector.  (%s:%d)\n",
				__FILE__, __LINE__));

		DigiLogError (pGlobalDriverObject,
			MP570_INTERRUPT_RESOURCE_CONFLICT,
			15,
			NULL, 0,
			pControllerExt->Name.Buffer, pControllerExt->Name.Length + sizeof (WCHAR),
			NULL, 0);

		//
		//  Disable Interrupts on the card
		//
		DigiDump (DIGIVERYLOUD, ("  Disabling Interrupts.\n"));
		WRT_REG_UCHAR (pControllerExt->VirtualPlxRegisters + 0x69, 0);

		return (Status);
	}

	DigiDump (DIGIVERYLOUD, ("  Connected to the interrupt successfully.\n"));

	//
	//  Enable Interrupts on the card
	//
	DigiDump (DIGIVERYLOUD, ("  Enabling Interrupts.\n"));
	WRT_REG_UCHAR (pControllerExt->VirtualPlxRegisters + 0x69, 0x09);


	DigiDump (DIGIFLOW, ("Exiting ConnectToInterrupt()\n"));

	return (Status);
}


#if !NT5_BUILD

VOID
FindPCIAdapters (
	PCONTROLLER_EXT		pControllerExt)
{
	ULONG				SlotNumber, BusNumber;
	BOOLEAN				Found;
	PCI_COMMON_CONFIG	PciConfig;
	NTSTATUS			Status;
	ULONG				BytesRead;


	DigiDump (DIGIERRORS, ("*** PCI Resources on bus %d\n",
		pControllerExt->BusNumber));


	for (BusNumber = 0; BusNumber < 8; BusNumber++)
	{
		for (SlotNumber = 0; SlotNumber < 16; SlotNumber++)
		{
			BytesRead = HalGetBusData (PCIConfiguration,
				BusNumber,
				SlotNumber,
				&PciConfig,
				sizeof (PCI_COMMON_CONFIG));

			if (!BytesRead)
			{
				// PCI Bus BusNumber does not exist.
				continue;
			}

			DigiDump (DIGIERRORS, ("*** Slot %d\n", SlotNumber));

			if (BytesRead == 2)
			{
				// This slot is empty.  Move on to the next slot.
				continue;
			}

			DigiDump (DIGIERRORS,
				("***VendorID 0x%x\n"
					"   DeviceID 0x%x\n"
					"   Command 0x%x\n"
					"   Status 0x%x\n"
					"   RevisionID 0x%x\n"
					"   ProgIf 0x%x\n"
					"   SubClass 0x%x\n"
					"   BaseClass 0x%x\n"
					"   CacheLineSize 0x%x\n"
					"   LatencyTimer 0x%x\n"
					"   HeaderType 0x%x\n"
					"   BIST 0x%x\n"
					"   u.type0\n"
					"      BaseAddresses\n"
					"         0x%x\n"
					"         0x%x\n"
					"         0x%x\n"
					"         0x%x\n"
					"         0x%x\n"
					"         0x%x\n"
					"      CIS 0x%x\n"
					"      SubVendorID 0x%x\n"
					"      SubSystemID 0x%x\n"
					"      ROMBaseAddress 0x%x\n"
					"      Reserved2 0x%x 0x%x\n"
					"      InterruptLine 0x%x\n"
					"      InterruptPin 0x%x\n"
					"      MinimumGrant 0x%x\n"
					"      MaximumLatency 0x%x\n",
					PciConfig.VendorID,
					PciConfig.DeviceID,
					PciConfig.Command,
					PciConfig.Status,
					PciConfig.RevisionID,
					PciConfig.ProgIf,
					PciConfig.SubClass,
					PciConfig.BaseClass,
					PciConfig.CacheLineSize,
					PciConfig.LatencyTimer,
					PciConfig.HeaderType,
					PciConfig.BIST,
					PciConfig.u.type0.BaseAddresses[0],
					PciConfig.u.type0.BaseAddresses[1],
					PciConfig.u.type0.BaseAddresses[2],
					PciConfig.u.type0.BaseAddresses[3],
					PciConfig.u.type0.BaseAddresses[4],
					PciConfig.u.type0.BaseAddresses[5],
					PciConfig.u.type0.CIS,
					PciConfig.u.type0.SubVendorID,
					PciConfig.u.type0.SubSystemID,
					PciConfig.u.type0.ROMBaseAddress,
					PciConfig.u.type0.Reserved2[0],
					PciConfig.u.type0.Reserved2[1],
					PciConfig.u.type0.InterruptLine,
					PciConfig.u.type0.InterruptPin,
					PciConfig.u.type0.MinimumGrant,
					PciConfig.u.type0.MaximumLatency));
		}
	}
}


#endif


#pragma alloc_text( PAGE, Dg570GetMappedAddress )
PVOID 
Dg570GetMappedAddress (
	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 - what type of bus - eisa, mca, isa, pci
	BusNumber - which IO bus (for machines with multiple buses).
	IoAddress - base device address to be mapped.
	NumberOfBytes - number of bytes for which address is valid.
	AddressSpace - Denotes whether the address is in io space or memory.
	MappedAddress - indicates whether the address was mapped.
                    This only has meaning if the address returned
                    is non-null.

Return Value:

	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 == CM_RESOURCE_PORT_MEMORY)
	{
		Address = MmMapIoSpace (cardAddress,
			NumberOfBytes,
			FALSE);

		*MappedAddress = (BOOLEAN) ((Address) ? (TRUE) : (FALSE));
	}
	else
	{
		Address = (PVOID) cardAddress.LowPart;
		*MappedAddress = FALSE;
	}

	return (Address);

}