/*++
 * 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_isa.c 5     10/22/97 11:56a Darinh $
 *
 * Revision History:
 * $Log: /Components/Windows/NT/Sync/Build/Mp570/hw_isa.c $
 * 
 * 5     10/22/97 11:56a Darinh
 * Changes to make multiple board installations work better.
 * 
 * 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 "digilib.h"

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



NTSTATUS
SetupIsaAdapter (
	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.

--*/
{
	UCHAR		MemoryMultiplier = 0;
	NTSTATUS	Status = STATUS_SUCCESS;


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


	//  16 bytes of I/O space are needed for Sync/570i ISA cards
	pControllerExt->IOSpan = 16;

	//  16KB of memory space are required for Sync/570i ISA adapters
	pControllerExt->WindowSize = 0x4000;

#if !NT5_BUILD

	// Report the resources before using them
	Status = IsaReportResources(pControllerExt);
	if (!NT_SUCCESS (Status)) 
	{
		return Status;
	}

#endif

	//  Setup the I/O function pointers
	pControllerExt->pIO_IN = fnReadIO;
	pControllerExt->pIO_OUT = fnWriteIO;

	// Setup access to IO Ports
	pControllerExt->VirtualIO = Dg570GetMappedAddress (
		pControllerExt->BusType,
		pControllerExt->BusNumber,
		pControllerExt->PhysIOPort,
		pControllerExt->IOSpan,
		CM_RESOURCE_PORT_IO,
		&pControllerExt->UnMapVirtualIO);

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

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

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

		return (STATUS_NONE_MAPPED);
	}

	DigiDump (DIGIINIT, ("Base I/O address: 0x%x  IOSpan: 0x%x\n",
		pControllerExt->VirtualIO, pControllerExt->IOSpan));

	//
	//  Verify the card is a 570, at the specified I/O address
	//
	Status = fnQueryAdapterExistence (pControllerExt);

	if (!NT_SUCCESS (Status))
	{
		DigiDump (DIGIERRORS, ("*** Card was not present at IO Addr: 0x%x\n",
			pControllerExt->PhysIOPort.LowPart));

		DigiLogError (pGlobalDriverObject,
					  MP570_CARD_NOT_FOUND,
					  5,
					  NULL, 0,
					  NULL, 0,
					  NULL, 0);

		return (Status);
	}

	//  Calculate the total memory on the card
	pControllerExt->iBusMemoryCommType =
		READ_PORT_UCHAR (pControllerExt->VirtualIO + REG570_BUS_MEM_INTERF);
	DigiDump (DIGIINIT, ("Bus, Mem, Comm Register 0x%x\n",
		pControllerExt->iBusMemoryCommType)) ;

	MemoryMultiplier = (pControllerExt->iBusMemoryCommType >> 2) & 7;

	//
	//  Total memory on the card is NumberOfWindows * WindowSize
	//
	pControllerExt->NumberOfWindows = 4 << MemoryMultiplier;

	DigiDump (DIGIINIT, (
		"NumberOfWindows: 0x%x  WindowSize: 0x%x  Card Memory Size: 0x%x\n",
		pControllerExt->NumberOfWindows,
		pControllerExt->WindowSize,
		pControllerExt->NumberOfWindows * pControllerExt->WindowSize));

	//  Setup the card to use the configured memory address and IRQ
	fnSetupAdapter (pControllerExt);

	//  Setup access to the adapter's shared memory window
	pControllerExt->VirtualWindow = Dg570GetMappedAddress (
		pControllerExt->BusType,
		pControllerExt->BusNumber,
		pControllerExt->PhysWindowAddress,
		pControllerExt->WindowSize,
		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,
			        6,
					NULL, 0,
					pControllerExt->Name.Buffer, pControllerExt->Name.Length + sizeof (WCHAR),
					NULL, 0);

		return (STATUS_NONE_MAPPED);
	}

	//  We don't have separate address space for the SCA registers on this card
	pControllerExt->VirtualSca = pControllerExt->VirtualWindow;

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

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

	return (Status);
}


NTSTATUS
IsaConnectToInterrupt (
	IN PCONTROLLER_EXT	pControllerExt)
{
	NTSTATUS	Status = STATUS_UNSUCCESSFUL;

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

	//  Connect to the interrupt.
	if (pControllerExt->PhysInterruptNumber.LowPart)
	{
		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_RESOURCE_CONFLICT,
				7,
				NULL, 0,
				pControllerExt->Name.Buffer, pControllerExt->Name.Length + sizeof (WCHAR),
				NULL, 0);

		}
	}

	DigiDump (DIGIFLOW, ("Exiting IsaConnectToInterrupt() Status =%08x\n",Status));

	return (Status);
}

#if !NT5_BUILD

NTSTATUS
IsaReportResources (
	IN PCONTROLLER_EXT	pControllerExt)

{
	BOOLEAN		ConflictDetected;
	NTSTATUS	Status = STATUS_SUCCESS;

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

	//  Setup interrupt
	pControllerExt->InterruptMode = Latched;
	pControllerExt->InterruptShareable = FALSE;

	if (pControllerExt->PhysInterruptNumber.LowPart)
	{
		pControllerExt->InterruptLevelOriginal =
			pControllerExt->PhysInterruptNumber.LowPart;

		//
		//  Get system Interrupt vector for this card.
		//
		pControllerExt->InterruptVector = HalGetInterruptVector (
			pControllerExt->BusType,
			pControllerExt->BusNumber,
			pControllerExt->InterruptLevelOriginal,
			pControllerExt->InterruptLevelOriginal,
			&(pControllerExt->InterruptLevel),
			&(pControllerExt->ProcessorAffinity) );
	}

	DigiDump (DIGIINIT, ("BusType                 = %d\n",pControllerExt->BusType));
	DigiDump (DIGIINIT, ("PhysIOPort              = 0x%x\n",pControllerExt->PhysIOPort));
	DigiDump (DIGIINIT, ("IOSpan                  = %d\n",pControllerExt->IOSpan));
	DigiDump (DIGIINIT, ("PhysWindowAddress       = 0x%x\n",pControllerExt->PhysWindowAddress));
	DigiDump (DIGIINIT, ("WindowSize              = 0x%x\n",pControllerExt->WindowSize));
	DigiDump (DIGIINIT, ("InterruptLevelOriginal  = %d\n",pControllerExt->InterruptLevelOriginal));
	DigiDump (DIGIINIT, ("ProcessorAffinity       = %d\n",pControllerExt->ProcessorAffinity));

	// Report resources *before* trying to access any of them.
	DigiReportResources (pGlobalDriverObject,
		pControllerExt->BusType,
		pControllerExt->BusNumber,
		&pControllerExt->PhysIOPort,
		pControllerExt->IOSpan,
		&pControllerExt->PhysWindowAddress,
		pControllerExt->WindowSize,
		pControllerExt->InterruptLevelOriginal,
		pControllerExt->InterruptLevelOriginal,
		pControllerExt->ProcessorAffinity,
		pControllerExt->InterruptMode,
		&ConflictDetected,
		&pControllerExt->hReportedResources);

	if (ConflictDetected)
	{
		DigiLogError (pGlobalDriverObject,
			MP570_RESOURCE_CONFLICT,
			8,
			NULL, 0,
			pControllerExt->Name.Buffer, pControllerExt->Name.Length + sizeof (WCHAR),
			NULL, 0);

		Status = STATUS_INSUFFICIENT_RESOURCES;
	}

	DigiDump (DIGIFLOW, ("Exiting IsaReportResources() Status =%08x\n",Status));

	return (Status);
}

#endif
