/*++
*******************************************************************************
* Copyright (c) 1990-98 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				*
*																										*
*******************************************************************************

Module Name:

   dxbpci.c

Abstract:

   This module contains routines common to all pci adapters. 

Author:

   Michael Zarns

--*/
#include "digidxb.h"

#if !NT5_BUILD

NTSTATUS
dxbPciGetAdapterInfo( 
	IN ULONG BusNumber,
	IN ULONG SlotNumber,
	OUT PULONG pVendorId OPTIONAL,
	OUT PULONG pDeviceId OPTIONAL,
	OUT PULONG pSubVendorId OPTIONAL,
	OUT PULONG pSubSystemId OPTIONAL )
{
	PCI_COMMON_CONFIG PciConfig = { 0 };
	NTSTATUS Status;
	ULONG cbRead;

	cbRead = HalGetBusData( PCIConfiguration, BusNumber, SlotNumber, 
	                        &PciConfig, sizeof PciConfig );

	if ( cbRead == 0 )
	{
		Status = STATUS_UNSUCCESSFUL;
		DigiDump( DIGIERROR, ( "DXB: Invalid BusNumber 0x%x!\n", BusNumber ) );
		goto Exit;
	}

	if ( cbRead == 2 )
	{
		Status = STATUS_UNSUCCESSFUL;
		DigiDump( DIGIERROR, ( "DXB: PCI Slot 0x%x is empty!\n", SlotNumber ) );
		goto Exit;
	}

	DigiDump( DIGIPCI, 
	          ("\tVendorID 0x%x\n"
	           "\tDeviceID 0x%x\n"
	           "\tCommand 0x%x\n"
	           "\tStatus 0x%x\n"
	           "\tRevisionID 0x%x\n"
	           "\tProgIf 0x%x\n"
	           "\tSubClass 0x%x\n"
	           "\tBaseClass 0x%x\n"
	           "\tCacheLineSize 0x%x\n"
	           "\tLatencyTimer 0x%x\n"
	           "\tHeaderType 0x%x\n"
	           "\tBIST 0x%x\n"
	           "\tu.type0\n"
	           "\t   BaseAddresses\n"
	           "\t      0x%x\n"
	           "\t      0x%x\n"
	           "\t      0x%x\n"
	           "\t      0x%x\n"
	           "\t      0x%x\n"
	           "\t      0x%x\n"
	           "\t   CIS 0x%x\n"
				  "\t   SubVendorID 0x%x\n"
				  "\t   SubSystemID 0x%x\n"
	           "\t   ROMBaseAddress 0x%x\n"
	           "\t   Reserved2 0x%x 0x%x\n"
	           "\t   InterruptLine 0x%x\n"
	           "\t   InterruptPin 0x%x\n"
	           "\t   MinimumGrant 0x%x\n"
	           "\t   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 ) );

	if ( pVendorId )
		*pVendorId = PciConfig.VendorID;

	if ( pDeviceId )
		*pDeviceId = PciConfig.DeviceID;

	if ( pSubVendorId )
		*pSubVendorId = PciConfig.u.type0.SubVendorID;

	if ( pSubSystemId )
		*pSubSystemId = PciConfig.u.type0.SubSystemID;

	Status = STATUS_SUCCESS;

Exit:
	return Status;
}


NTSTATUS
dxbPciVerifyAdapter( 
	IN ULONG BusNumber,
	IN ULONG SlotNumber,
	IN ULONG VendorId,
	IN ULONG DeviceId,
	IN ULONG SubVendorId,
	IN ULONG SubDeviceId )
{
	PCI_COMMON_CONFIG PciConfig = { 0 };
	NTSTATUS Status;
	ULONG cbRead;

	cbRead = HalGetBusData( PCIConfiguration, BusNumber, SlotNumber, 
	                        &PciConfig, sizeof PciConfig );

	if ( cbRead == 0 )
	{
		Status = STATUS_UNSUCCESSFUL;
		DigiDump( DIGIERROR, ( "DXB: Invalid BusNumber 0x%x!\n", BusNumber ) );
		goto Exit;
	}

	if ( cbRead == 2 )
	{
		Status = STATUS_UNSUCCESSFUL;
		DigiDump( DIGIERROR, ( "DXB: PCI Slot 0x%x is empty!\n", SlotNumber ) );
		goto Exit;
	}

	if ( PciConfig.VendorID != VendorId || PciConfig.DeviceID != DeviceId )
	{
		DigiDump( DIGIERROR, ( "DXB: Adapter mismatch in slot %d!\n"
		                     "       Found    VendorId 0x%x, DeviceId 0x%x\n"
		                     "       Expected VendorId 0x%x, DeviceId 0x%x\n", 
		                     SlotNumber, PciConfig.VendorID, PciConfig.DeviceID, 
		                     VendorId, DeviceId ) );
		Status = STATUS_UNSUCCESSFUL;
		goto Exit;
	}

	if ( ( SubVendorId && PciConfig.u.type0.SubVendorID != SubVendorId ) || 
	     ( SubDeviceId && PciConfig.u.type0.SubSystemID != SubDeviceId ) )
	{
		DigiDump( DIGIERROR, ( "DXB: Adapter subsystem mismatch in slot %d!\n"
		                     "       Found    SubVendorId 0x%x, SubVendorId 0x%x\n"
		                     "       Expected SubDeviceId 0x%x, SubDeviceId 0x%x\n", 
		                     SlotNumber, PciConfig.u.type0.SubVendorID, PciConfig.u.type0.SubSystemID, 
		                     SubVendorId, SubDeviceId ) );
		Status = STATUS_UNSUCCESSFUL;
		goto Exit;
	}

	DigiDump( DIGIPCI, 
	          ("\tVendorID 0x%x\n"
	           "\tDeviceID 0x%x\n"
	           "\tCommand 0x%x\n"
	           "\tStatus 0x%x\n"
	           "\tRevisionID 0x%x\n"
	           "\tProgIf 0x%x\n"
	           "\tSubClass 0x%x\n"
	           "\tBaseClass 0x%x\n"
	           "\tCacheLineSize 0x%x\n"
	           "\tLatencyTimer 0x%x\n"
	           "\tHeaderType 0x%x\n"
	           "\tBIST 0x%x\n"
	           "\tu.type0\n"
	           "\t   BaseAddresses\n"
	           "\t      0x%x\n"
	           "\t      0x%x\n"
	           "\t      0x%x\n"
	           "\t      0x%x\n"
	           "\t      0x%x\n"
	           "\t      0x%x\n"
	           "\t   CIS 0x%x\n"
				  "\t   SubVendorID 0x%x\n"
				  "\t   SubSystemID 0x%x\n"
	           "\t   ROMBaseAddress 0x%x\n"
	           "\t   InterruptLine 0x%x\n"
	           "\t   InterruptPin 0x%x\n"
	           "\t   MinimumGrant 0x%x\n"
	           "\t   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.InterruptLine,
				  PciConfig.u.type0.InterruptPin,
				  PciConfig.u.type0.MinimumGrant,
				  PciConfig.u.type0.MaximumLatency ) );

	Status = STATUS_SUCCESS;

Exit:
	return Status;
}
#endif
