navienginebsp/naviengine_assp/pci/pci-ne.cpp
changeset 0 5de814552237
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/navienginebsp/naviengine_assp/pci/pci-ne.cpp	Tue Sep 28 18:00:05 2010 +0100
@@ -0,0 +1,773 @@
+/*
+* Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  
+*
+*/
+
+
+
+#include "pci-ne.h"
+#include "../naviengine_pci.h"
+#include <naviengine_priv.h>
+#include <naviengine.h>
+
+
+_LIT(KTConfigSpace, "TConfigSpace");
+TConfigSpace::TConfigSpace(TPciFunction& aFunction, DPciBridge& aBridge)
+	:TAddrSpace(KCfgSpaceSize, KTConfigSpace), iFunction(aFunction), iBridge(aBridge)
+	{
+	}
+
+/**
+Read 1 byte from config space. Config space is 256 bytes long
+out of range access will fault the kernel.
+*/
+EXPORT_C TUint8 TConfigSpace::Read8(TUint32 aOffset)
+	{
+	CheckAccess(E1Byte, aOffset);
+
+	return iBridge.ReadConfig8(
+			iFunction.Bus(),
+			iFunction.Device(),
+			iFunction.Function(),
+			aOffset
+			);
+	}
+
+EXPORT_C TUint16 TConfigSpace::Read16(TUint32 aOffset)
+	{
+	CheckAccess(E2Byte, aOffset);
+
+	return iBridge.ReadConfig16(
+			iFunction.Bus(),
+			iFunction.Device(),
+			iFunction.Function(),
+			aOffset
+			);
+	}
+
+EXPORT_C TUint32 TConfigSpace::Read32(TUint32 aOffset)
+	{
+	CheckAccess(E4Byte, aOffset);
+
+	return iBridge.ReadConfig32(
+			iFunction.Bus(),
+			iFunction.Device(),
+			iFunction.Function(),
+			aOffset
+			);
+	}
+
+EXPORT_C void TConfigSpace::Write8(TUint32 aOffset, TUint8 aValue)
+	{
+	CheckAccess(E1Byte, aOffset);
+
+	iBridge.WriteConfig8(
+			iFunction.Bus(),
+			iFunction.Device(),
+			iFunction.Function(),
+			aOffset,
+			aValue
+			);
+	}
+
+EXPORT_C void TConfigSpace::Write16(TUint32 aOffset, TUint16 aValue)
+	{
+	CheckAccess(E2Byte, aOffset);
+
+	iBridge.WriteConfig16(
+			iFunction.Bus(),
+			iFunction.Device(),
+			iFunction.Function(),
+			aOffset,
+			aValue
+			);
+	}
+
+EXPORT_C void TConfigSpace::Write32(TUint32 aOffset, TUint32 aValue)
+	{
+	CheckAccess(E4Byte, aOffset);
+
+	iBridge.WriteConfig32(
+			iFunction.Bus(),
+			iFunction.Device(),
+			iFunction.Function(),
+			aOffset,
+			aValue
+			);
+	}
+
+EXPORT_C void TConfigSpace::Modify8(TUint32 aOffset, TUint8 aClearMask, TUint8 aSetMask)
+	{
+	CheckAccess(E1Byte, aOffset);
+
+	iBridge.ModifyConfig8(
+			iFunction.Bus(),
+			iFunction.Device(),
+			iFunction.Function(),
+			aOffset,
+			aClearMask,
+			aSetMask
+			);
+	}
+
+EXPORT_C void TConfigSpace::Modify16(TUint32 aOffset, TUint16 aClearMask, TUint16 aSetMask)
+	{
+	CheckAccess(E2Byte, aOffset);
+
+	iBridge.ModifyConfig16(
+			iFunction.Bus(),
+			iFunction.Device(),
+			iFunction.Function(),
+			aOffset,
+			aClearMask,
+			aSetMask
+			);
+	}
+
+EXPORT_C void TConfigSpace::Modify32(TUint32 aOffset, TUint32 aClearMask, TUint32 aSetMask)
+	{
+	CheckAccess(E4Byte, aOffset);
+
+	iBridge.ModifyConfig32(
+			iFunction.Bus(),
+			iFunction.Device(),
+			iFunction.Function(),
+			aOffset,
+			aClearMask,
+			aSetMask
+			);
+	}
+
+DNaviEnginePciBridge::DNaviEnginePciBridge(TUint aBaseAddress, TUint32 aVirtualWindow)
+	:DPciBridge(), iBaseAddr(aBaseAddress),
+	iVirtualWindow(aVirtualWindow),
+	iAllocator(KPciAddressSpaceSize),
+	iMapMan(KNeBridgeNumberOfBars, iAllocator, iBaseAddr),
+	iChunkMan(iMapMan),
+	iVid(AsspRegister::Read16(iBaseAddr+KHoPciVid)),
+	iDid(AsspRegister::Read16(iBaseAddr+KHoPciDid))
+	{
+	}
+
+TInt DNaviEnginePciBridge::Initialise()
+	{
+	__KTRACE_OPT(KPCI, Kern::Printf("Initialising Naviengine bridge: Base address: %x", iBaseAddr)) ;
+	InitialiseRegisters();
+	return SetupInterrupts();
+	}
+
+DNaviEnginePciBridge::~DNaviEnginePciBridge()
+	{
+	}
+
+/**
+Create a DPlatChunkHw which will be accessble to PCI devices under this bridge.
+
+@param aSize Amount of memory visible from PCI in bytes.
+This will be rounded up to the next power of 2 in kilobytes
+.eg 1K, 2K, 4K etc. @note The actual amount of memory allocated
+will always be a multiple of the page size (4K), but any excess
+will not be visible to the PCI bus.
+@param aPciAddress On success, will be a PCI address by which the chunk may be accessed
+@return
+	- KErrNone - On Success
+	- KErrInUse - aChunk was not NULL
+	- KErrNotFound - All of Bridge's BARS have been used up. Free one with RemoveChunk
+	- KErrArgument - aSize was less than 1.
+*/
+TInt DNaviEnginePciBridge::CreateChunk(DPlatChunkHw*& aChunk, TInt aSize, TUint aAttributes, TUint32& aPciAddress)
+	{
+	if(aChunk!=NULL)
+		return KErrInUse;
+	if(aSize<1)
+		return KErrArgument;
+
+	return iChunkMan.AddChunk(aChunk, aSize, aAttributes, aPciAddress);
+	}
+
+/**
+Create a DChunk which will be accessble to PCI devices under this bridge.
+
+@param aSize Amount of memory to be allocated to chunk.
+This will be rounded up to at least the next power of 2 in kilobytes
+.eg 1K, 2K, 4K, 8k etc.
+@param aPciAddress On success, will be a PCI address by which the chunk may be accessed
+@return
+	- KErrNone - On Success
+	- KErrInUse - aChunk was not NULL
+	- KErrNotFound - All of Bridge's BARS have been used up. Free one with RemoveChunk
+	- KErrArgument - aSize was less than 1.
+*/
+TInt DNaviEnginePciBridge::CreateChunk(DChunk*& aChunk, TChunkCreateInfo &aAttributes, TUint aOffset, TUint aSize, TUint32& aPciAddress)
+	{
+	if(aChunk!=NULL)
+		return KErrInUse;
+	if(aSize<1)
+		return KErrArgument;
+
+	return iChunkMan.AddChunk(aChunk, aAttributes, aOffset, aSize, aPciAddress);
+	}
+
+
+TInt DNaviEnginePciBridge::RemoveChunk(DPlatChunkHw* aChunk)
+	{
+	return iChunkMan.RemoveChunk(aChunk);
+	}
+
+TInt DNaviEnginePciBridge::CreateMapping(TUint32 aPhysicalAddress, TInt aSize, TUint32& aPciAddress)
+	{
+	if(aSize<1)
+		return KErrArgument;
+
+	return iMapMan.CreateMapping(aPhysicalAddress, aSize, aPciAddress);
+	}
+
+TInt DNaviEnginePciBridge::RemoveMapping(TUint32 aPhysicalAddress)
+	{
+	return iMapMan.RemoveMapping(aPhysicalAddress);
+	}
+
+TInt DNaviEnginePciBridge::GetPciAddress(TUint32 aPhysicalAddress, TUint32& aPciAddress)
+	{
+	return iMapMan.GetPciAddress(aPhysicalAddress, aPciAddress);
+	}
+
+TInt DNaviEnginePciBridge::GetPhysicalAddress(TUint32 aPciAddress, TUint32& aPhysicalAddress)
+	{
+	return iMapMan.GetPhysicalAddress(aPciAddress, aPhysicalAddress);
+	}
+
+/**
+Attempt to access function at this location. If it exists then scan its
+bars to create required PCI memory space.
+Create and return a complete TPciFunction
+*/
+TPciFunction* DNaviEnginePciBridge::Function(TInt aBus, TInt aDevice, TInt aFunction)
+	{
+	const TUint32 val = ReadConfig32(aBus, aDevice, aFunction, 0x0);
+
+	//the function does not exist.
+	if(val == 0xFFFFFFFF)
+		return NULL;
+
+	const TInt16 vid=val&0xFFFF;
+	TInt16 did=(val>>16)&0xFFFF;
+
+	//don't give access to the bridge its self
+	if(vid==iVid && did==iDid)
+		return NULL;
+
+	TPciFunction* func= new TPciFunction(aBus, aDevice, aFunction, vid, did, *this);
+	if(NULL==func)
+		return func;
+
+	TAddrSpace& configSpace=*func->GetConfigSpace();
+
+	TInt r=KErrNone;
+	//scan each of the bars
+	for(TInt i=0; i<KPciNumberOfBars; ++i)
+		{
+		const TInt barOffset=KPciBar0+(4*i);
+		const TUint32 size= ProbeBar(configSpace, barOffset);
+
+		if(NULL==size)
+			continue;
+
+		//allocate pci address range
+		TUint32 pciAddress=0;
+		r=iAllocator.Allocate(pciAddress, size);
+		if(r!=KErrNone)
+			break;
+
+		//tell the function what its address is.
+		r = func->AddMemorySpace(size, pciAddress+iVirtualWindow, i);
+		if(r!=KErrNone)
+			break;
+
+		//modify bar.
+		configSpace.Write32(barOffset, pciAddress);
+		}
+
+	if(r==KErrNone)
+		{
+		configSpace.Modify16(KHoPciCmd, NULL, KHtPcicmd_Memen);
+		return func;
+		}
+	else
+		{
+		delete func;
+		return NULL;
+		}
+
+	}
+
+void DNaviEnginePciBridge::ConfigurationComplete()
+	{
+	//state that config is complete and allow subsequent master aborts
+	//to trigger the error interrupt
+	AsspRegister::Modify32(iBaseAddr+KHoPciCtrlH, NULL, KHtPciCtrlH_CnfigDone| KHtPciCtrlH_Mase);
+	Interrupt::Enable(EIntPciInt);
+	}
+
+
+void DNaviEnginePciBridge::ErrorPrint()
+	{
+	Kern::Printf("Pci Errors:");
+
+	Kern::Printf(" Status Register");
+	volatile TUint16 status=AsspRegister::Read16(iBaseAddr+KHoPciStatus);
+	if(status & KHtPciStatus_ParityError)
+		Kern::Printf("  Parity Error");
+	if(status & KHtPciStatus_SystemError)
+		Kern::Printf("  System Error");
+	if(status & KHtPciStatus_MasterAbrtRcvd)
+		Kern::Printf("  MasterAbrtRcvd");
+	if(status & KHtPciStatus_TargetAbrtRcvd)
+		Kern::Printf("  TargetAbrtRcvd");
+	if(status & KHtPciStatus_DPErrorAsserted)
+		Kern::Printf("  PERR# asserted");
+
+	Kern::Printf(" Err1 Register:");
+	volatile TUint32 error=AsspRegister::Read32(iBaseAddr+KHoError1);
+	if(error & KHtError1_SystemError)
+		Kern::Printf("  System Error");
+	if(error & KHtError1_AMEr)
+		Kern::Printf("  AHB master error");
+
+	Kern::Printf(" PciCtrlHi Register");
+
+	volatile TUint32 pciCtrlH=AsspRegister::Read32(iBaseAddr+KHoPciCtrlH);
+	if(pciCtrlH & KHtPciCtrlH_Aper)
+		Kern::Printf("  Address Parity error");
+	if(pciCtrlH & KHtPciCtrlH_Dtep)
+		Kern::Printf("  Discard time out");
+	if(pciCtrlH & KHtPciCtrlH_Dper)
+		Kern::Printf("  Data parity error");
+	if(pciCtrlH & KHtPciCtrlH_Rlex)
+		Kern::Printf("  Retry limit exceeded");
+	if(pciCtrlH & KHtPciCtrlH_Mabo)
+		Kern::Printf("  Master abort");
+	if(pciCtrlH & KHtPciCtrlH_Tabo)
+		Kern::Printf("  Target abort");
+
+	}
+/**
+@param aOffset A DWord index (32 bit)
+@return A value sutiable for writing to the bridge's CNFIG_ADDR register
+*/
+TCnfgAddr DNaviEnginePciBridge::MakeConfigAddress(TInt aBus, TInt aDevice, TInt aFunction, TUint aDwordOffset)
+	{
+	using namespace ConfigAddress;
+	const TUint32 bus=(aBus<<KHsBus);
+	const TUint32 device=(aDevice<<KHsDevice);
+	const TUint32 function=(aFunction<<KHsFunction);
+	const TUint32 offset=(aDwordOffset<<KHsOffset);
+
+	__NK_ASSERT_DEBUG( (bus & (~KHmBus)) == NULL);
+	__NK_ASSERT_DEBUG( (device & (~KHmDevice)) == NULL);
+	__NK_ASSERT_DEBUG( (function & (~KHmFunction)) == NULL);
+	__NK_ASSERT_DEBUG( (offset & (~KHmOffset)) == NULL);
+
+	return (KHtCnfigEnable|
+			(bus & KHmBus)|
+			(device & KHmDevice)|
+			(function & KHmFunction)|
+			(offset & KHmOffset)
+		   );
+	}
+
+/**
+Probes the specified bar to see whether it is implemented, if so
+then return the amount of memory space required.
+
+@note Driver does not currently support devices which request IO-space
+or 64-bit bars.
+*/
+TUint DNaviEnginePciBridge::ProbeBar(TAddrSpace& aCs, TUint32 aBarOffset)
+	{
+	__KTRACE_OPT(KPCI, Kern::Printf("DNaviEnginePciBridge::ProbeBar Probing BAR at Offset %d", aBarOffset));
+
+	//ignore any writable bits in positions [0:2]
+	//they shouldn't be writable but are for the NaviEngine host
+	//bridge
+	const TUint32 KHmIgnore= Bar::KHtMemSpaceType|Bar::KHmType|Bar::KHtPreFetchable;
+
+	aCs.Write32(aBarOffset, 0x00000000);
+	TUint32 initial= aCs.Read32(aBarOffset);
+	aCs.Write32(aBarOffset, KMaxTUint32);
+	TUint32 bar = aCs.Read32(aBarOffset);
+
+	//reset after probing
+	aCs.Write32(aBarOffset, 0x00000000);
+
+	if( (bar&(~KHmIgnore)) == (initial&(~KHmIgnore)) )
+		{
+		__KTRACE_OPT(KPCI, Kern::Printf(" Function doesn't implement BAR"));
+		return NULL;
+		}
+	if(bar & Bar::KHtMemSpaceType)
+		{
+		__KTRACE_OPT(KPCI, Kern::Printf(" IOSpace is not supported") );
+		return NULL;
+		}
+
+	if(bar & Bar::KHmType )
+		{
+		__KTRACE_OPT(KPCI, Kern::Printf(" Only support 32 bit address space") );
+		return NULL;
+		}
+
+	TUint size= (bar<<1)^(bar);
+	__KTRACE_OPT(KPCI, Kern::Printf(" Address space: %08x bytes", size));
+	return size;
+	}
+
+
+
+TUint8 DNaviEnginePciBridge::ReadConfig8(TInt aBus, TInt aDevice, TInt aFunction, TUint aOffset) const
+	{
+	const TUint dwordOffset = aOffset>>2; //divide by 4
+	const TUint byteOffset = aOffset%4;
+
+	const TCnfgAddr location = MakeConfigAddress(aBus, aDevice, aFunction, dwordOffset);
+
+	Wait();
+	AsspRegister::Write32(KHoCnfig_addr+iBaseAddr, location);
+	volatile TUint8 value = AsspRegister::Read8(iBaseAddr+KHoCnfig_data+byteOffset);
+	Signal();
+	return value;
+	}
+
+TUint16 DNaviEnginePciBridge::ReadConfig16(TInt aBus, TInt aDevice, TInt aFunction, TUint aOffset) const
+	{
+	const TUint dwordOffset = aOffset>>2; //divide by 4
+	const TUint byteOffset = aOffset%4;
+
+	const TCnfgAddr location = MakeConfigAddress(aBus, aDevice, aFunction, dwordOffset);
+
+	Wait();
+	AsspRegister::Write32(KHoCnfig_addr+iBaseAddr, location);
+	volatile TUint16 value = AsspRegister::Read16(iBaseAddr+KHoCnfig_data+byteOffset);
+	Signal();
+	return value;
+	}
+
+/**
+@param aOffset A byte index
+*/
+TUint32 DNaviEnginePciBridge::ReadConfig32(TInt aBus, TInt aDevice, TInt aFunction, TUint aOffset) const
+	{
+	TUint dwordOffset = aOffset>>2; //divide by 4
+
+	const TCnfgAddr location = MakeConfigAddress(aBus, aDevice, aFunction, dwordOffset);
+
+	Wait();
+	AsspRegister::Write32(KHoCnfig_addr+iBaseAddr, location);
+	volatile TInt32 value = AsspRegister::Read32(KHoCnfig_data+iBaseAddr);
+	Signal();
+	return value;
+	}
+
+void DNaviEnginePciBridge::WriteConfig8(TInt aBus, TInt aDevice, TInt aFunction, TUint aOffset, TUint8 aValue)
+	{
+	TUint dwordOffset = aOffset>>2; //divide by 4
+	const TUint byteOffset = aOffset%4;
+
+	const TCnfgAddr location = MakeConfigAddress(aBus, aDevice, aFunction, dwordOffset);
+
+	Wait();
+	AsspRegister::Write32(KHoCnfig_addr+iBaseAddr, location);
+	AsspRegister::Write8(KHoCnfig_data+iBaseAddr+byteOffset, aValue);
+	Signal();
+	}
+
+void DNaviEnginePciBridge::WriteConfig16(TInt aBus, TInt aDevice, TInt aFunction, TUint aOffset, TUint16 aValue)
+	{
+	TUint dwordOffset = aOffset>>2; //divide by 4
+	const TUint byteOffset = aOffset%4;
+
+	const TCnfgAddr location = MakeConfigAddress(aBus, aDevice, aFunction, dwordOffset);
+
+	Wait();
+	AsspRegister::Write32(KHoCnfig_addr+iBaseAddr, location);
+	AsspRegister::Write16(KHoCnfig_data+iBaseAddr+byteOffset, aValue);
+	Signal();
+	}
+
+/**
+@param aOffset A byte index
+*/
+void DNaviEnginePciBridge::WriteConfig32(TInt aBus, TInt aDevice, TInt aFunction, TUint aOffset, TUint32 aValue)
+	{
+	//__KTRACE_OPT(KPCI, Kern::Printf("PCI: WriteConfig32: %x:%x:%x os=%x, val=%x ", aBus,aDevice, aFunction, aOffset, aValue));
+	TUint dwordOffset = aOffset>>2; //divide by 4
+	const TCnfgAddr location = MakeConfigAddress(aBus, aDevice, aFunction, dwordOffset);
+
+	Wait();
+	AsspRegister::Write32(KHoCnfig_addr+iBaseAddr, location);
+	AsspRegister::Write32(KHoCnfig_data+iBaseAddr, aValue);
+	Signal();
+	}
+
+void DNaviEnginePciBridge::ModifyConfig8(TInt aBus, TInt aDevice, TInt aFunction, TUint aOffset, TUint8 aClearMask, TUint8 aSetMask)
+	{
+	//__KTRACE_OPT(KPCI, Kern::Printf("PCI: ModifyConfig32: %x:%x:%x os=%x, clear=%x, set=%x ",aBus,aDevice, aFunction, aOffset, aClearMask, aSetMask));
+	TUint dwordOffset = aOffset>>2; //divide by 4 (and trunctate)
+	const TUint byteOffset = aOffset%4;
+
+	const TCnfgAddr location = MakeConfigAddress(aBus, aDevice, aFunction, dwordOffset);
+
+	Wait();
+	AsspRegister::Write32(KHoCnfig_addr+iBaseAddr, location);
+	AsspRegister::Modify8(KHoCnfig_data+iBaseAddr+byteOffset, aClearMask, aSetMask);
+	Signal();
+	}
+
+void DNaviEnginePciBridge::ModifyConfig16(TInt aBus, TInt aDevice, TInt aFunction, TUint aOffset, TUint16 aClearMask, TUint16 aSetMask)
+	{
+	//__KTRACE_OPT(KPCI, Kern::Printf("PCI: ModifyConfig32: %x:%x:%x os=%x, clear=%x, set=%x ",aBus,aDevice, aFunction, aOffset, aClearMask, aSetMask));
+	TUint dwordOffset = aOffset>>2; //divide by 4 (and trunctate)
+	const TUint byteOffset = aOffset%4;
+
+	const TCnfgAddr location = MakeConfigAddress(aBus, aDevice, aFunction, dwordOffset);
+
+	Wait();
+	AsspRegister::Write32(KHoCnfig_addr+iBaseAddr, location);
+	AsspRegister::Modify16(KHoCnfig_data+iBaseAddr+byteOffset, aClearMask, aSetMask);
+	Signal();
+	}
+
+void DNaviEnginePciBridge::ModifyConfig32(TInt aBus, TInt aDevice, TInt aFunction, TUint aOffset, TUint32 aClearMask, TUint32 aSetMask)
+	{
+	//__KTRACE_OPT(KPCI, Kern::Printf("PCI: ModifyConfig32: %x:%x:%x os=%x, clear=%x, set=%x ",aBus,aDevice, aFunction, aOffset, aClearMask, aSetMask));
+	TUint dwordOffset = aOffset>>2; //divide by 4 (and trunctate)
+
+	const TCnfgAddr location = MakeConfigAddress(aBus, aDevice, aFunction, dwordOffset);
+
+	Wait();
+	AsspRegister::Write32(KHoCnfig_addr+iBaseAddr, location);
+	AsspRegister::Modify32(KHoCnfig_data+iBaseAddr, aClearMask, aSetMask);
+	Signal();
+	}
+
+void DNaviEnginePciBridge::InitialiseRegisters()
+	{
+	ClearRegisters();
+
+	//make the bridge a PCI master and respond as a target
+	AsspRegister::Modify16(iBaseAddr+KHoPciCmd, 0x0, KHtPcicmd_Bmasen|KHtPcicmd_Memen|KHtPcicmd_Peren|KHtPcicmd_Seren);
+
+	//set up inbound access to PCI through window 1.
+	const TUint32 window1Register =
+		0| //window points to address 0 of PCI
+		(0x13<<Initiator::KHsA2PCAMask)| //modify incomming AHB address above 8k
+		(0x3<<Initiator::KHsType)| //incomming accesses will perform memory read/memory write
+		0x1; //enable incomming address conversion
+	AsspRegister::Write32(iBaseAddr+Initiator::KHoReg1, window1Register);
+
+	AsspRegister::Write32(iBaseAddr+KHoBarEnable, 0); //disable all BARs, don't yet want access from PCI to AHB
+
+	AsspRegister::Modify32(iBaseAddr+KHoPciCtrlH ,NULL,
+			KHtPciCtrlH_Aerse|
+			KHtPciCtrlH_Dtimse|
+			KHtPciCtrlH_Perse|
+			KHtPciCtrlH_Rtyse|
+			KHtPciCtrlH_Tase
+			);
+	//report errors from PCI bus to AHB64PCI_ERR pin
+	//report errror on AHB to AHB64PCI_ERR pin
+	AsspRegister::Modify32(iBaseAddr+KHoError1, NULL,
+			KHtError1_PEEn|
+			KHtError1_AMEn
+			);
+
+	}
+
+void DNaviEnginePciBridge::ClearRegisters()
+	{
+	ClearErrors();
+
+	AsspRegister::Modify16(iBaseAddr+KHoPciCmd,
+			KHtPcicmd_Bmasen|
+			KHtPcicmd_Memen|
+			KHtPcicmd_Peren|
+			KHtPcicmd_Seren,
+			NULL);
+
+	AsspRegister::Modify32(iBaseAddr+KHoPciCtrlH ,
+			KHtPciCtrlH_CnfigDone|
+			KHtPciCtrlH_Aerse|
+			KHtPciCtrlH_Dtimse|
+			KHtPciCtrlH_Perse|
+			KHtPciCtrlH_Rtyse|
+			KHtPciCtrlH_Mase|
+			KHtPciCtrlH_Tase,
+			NULL
+			);
+
+	AsspRegister::Modify32(iBaseAddr+KHoError1,
+			KHtError1_PEEn|
+			KHtError1_AMEn,
+			NULL
+			);
+
+	AsspRegister::Write32(KHoCnfig_addr+iBaseAddr, 0x0);
+
+	AsspRegister::Write32(iBaseAddr+Initiator::KHoReg1, 0x0);
+	AsspRegister::Write32(iBaseAddr+Initiator::KHoReg2, 0x0);
+	}
+
+//Clear latched bits by wriring 1 to them
+void DNaviEnginePciBridge::ClearErrors()
+	{
+	AsspRegister::Modify16(iBaseAddr+KHoPciStatus, NULL,
+		KHtPciStatus_ParityError|
+		KHtPciStatus_SystemError|
+		KHtPciStatus_MasterAbrtRcvd|
+		KHtPciStatus_TargetAbrtRcvd|
+		KHtPciStatus_DPErrorAsserted
+		);
+
+	AsspRegister::Modify32(iBaseAddr+KHoError1, NULL,
+			KHtError1_SystemError|
+			KHtError1_AMEr
+			);
+
+	AsspRegister::Modify32(iBaseAddr+KHoPciCtrlH, NULL,
+			KHtPciCtrlH_Aper|
+			KHtPciCtrlH_Dtep|
+			KHtPciCtrlH_Dper|
+			KHtPciCtrlH_Rlex|
+			KHtPciCtrlH_Mabo|
+			KHtPciCtrlH_Tabo
+			);
+
+	}
+
+
+TInt DNaviEnginePciBridge::SetupInterrupts()
+	{
+	__KTRACE_OPT(KPCI, Kern::Printf("DNaviEnginePciBridge: SetupInterrupts()"));
+	TInt r = KErrNone;
+
+	__KTRACE_OPT(KPCI, Kern::Printf("  Binding EIntPciPErrB"));
+	r = Interrupt::Bind(EIntPciPErrB, ParityErrorISR, this);
+	__KTRACE_OPT(KPCI, Kern::Printf("  r=%d", r));
+
+	__KTRACE_OPT(KPCI, Kern::Printf("  Binding EIntPciSErrB"));
+	r = Interrupt::Bind(EIntPciSErrB, SystemErrorISR, this);
+	__KTRACE_OPT(KPCI, Kern::Printf("  r=%d", r));
+
+	__KTRACE_OPT(KPCI, Kern::Printf("  Binding EIntPciInt"));
+	r = Interrupt::Bind(EIntPciInt, PciISR, this);
+	__KTRACE_OPT(KPCI, Kern::Printf("  r=%d", r));
+
+	__KTRACE_OPT(KPCI, Kern::Printf("  Enabling EIntPciPErrB"));
+	r = Interrupt::Enable(EIntPciPErrB);
+	__KTRACE_OPT(KPCI, Kern::Printf("  r=%d", r));
+
+	__KTRACE_OPT(KPCI, Kern::Printf("  Enabling EIntPciSErrB"));
+	r = Interrupt::Enable(EIntPciSErrB);
+	__KTRACE_OPT(KPCI, Kern::Printf("  r=%d", r));
+
+	__KTRACE_OPT(KPCI, Kern::Printf("  Enabling EIntPciInt"));
+	Interrupt::Clear(EIntPciInt);
+	//r = Interrupt::Enable(EIntPciInt);
+	__KTRACE_OPT(KPCI, Kern::Printf("  r=%d", r));
+	return r;
+	}
+
+void DNaviEnginePciBridge::ParityErrorISR(void* aP)
+	{
+	Interrupt::Clear(EIntPciPErrB);
+	Kern::Fault("PCI Parity error",0);
+	}
+
+void DNaviEnginePciBridge::SystemErrorISR(void* aP)
+	{
+	Interrupt::Clear(EIntPciSErrB);
+	Kern::Fault("PCI System error",0);
+	}
+
+/**
+This interrupt is raised when a bus error has occured, if the
+appropriate bit has been set (KHtPciCtrlH_Mase).
+It will also be raised if a peripheral uses one of the
+native PCI interrupt lines - but this not yet supported.
+*/
+void DNaviEnginePciBridge::PciISR(void* aP)
+	{
+	Interrupt::Clear(EIntPciInt);
+	DNaviEnginePciBridge* bridge = static_cast<DNaviEnginePciBridge*>(aP);
+	__KTRACE_OPT(KPCI,
+			Kern::Printf("Pci interrupt line: Bridge Base address 0x%08x",bridge->iBaseAddr);
+			bridge->ErrorPrint();
+			);
+
+	volatile TUint16 status=AsspRegister::Read16((bridge->iBaseAddr)+KHoPciStatus);
+	if(status & KHtPciStatus_SystemError)
+		{
+		Kern::Fault("PCI System Error: Fatal",0);
+		}
+	bridge->ClearErrors();
+	}
+
+//
+// TNaviEngineChunkCleanup //
+//
+
+TNaviEngineChunkCleanup::TNaviEngineChunkCleanup(TChunkManager& aChunkMan, TUint32 aPhysicalAddress)
+	:TChunkCleanup(), iChunkMan(aChunkMan), iPhysicalAddress(aPhysicalAddress)
+	{
+	}
+
+TNaviEngineChunkCleanup::~TNaviEngineChunkCleanup()
+	{
+	}
+
+void TNaviEngineChunkCleanup::Destroy()
+	{
+	iChunkMan.RemoveChunk(iPhysicalAddress);
+	}
+
+
+DECLARE_STANDARD_EXTENSION()
+	{
+	__KTRACE_OPT(KEXTENSION, Kern::Printf("Pci Extension starting..."));
+
+	DPciBridge* internBridge = new DNaviEnginePciBridge(KHwPciBridgeUsb, KHwUsbHWindow);
+
+	if(internBridge == NULL)
+		return KErrNoMemory;
+
+	TInt r = internBridge->Initialise();
+	if(r !=KErrNone)
+		return r;
+
+	r = internBridge->Register();
+	if(r !=KErrNone)
+		{
+		delete internBridge;
+		return r;
+		}
+
+	r = Pci::Enumerate();
+	return r;
+	}
+
+
+
+
+