Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / devices / pcie_bus / include / pcie_bus.h
/*
* ========== Copyright Header Begin ==========================================
*
* OpenSPARC T2 Processor File: pcie_bus.h
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
*
* The above named program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License version 2 as published by the Free Software Foundation.
*
* The above named program is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*
* ========== Copyright Header End ============================================
*/
#ifndef _PCIE_BUS_NEW_IMPL_H
#define _PCIE_BUS_NEW_IMPL_H
#include <list>
#include <map>
#include <stdio.h>
#include "pcie.h"
#include "arg.h"
using namespace std;
class pcieBus:public Module, public pcieBusIf{
public:
struct pcieDevInfo{
const char * name;
mmi_instance_t instance;
genericPcieDevIf * devIf;
int device;
int function;
pcieDevInfo(){
name = 0;
devIf = 0;
device = function = -1;
}
pcieDevInfo(const char * n, mmi_instance_t i, genericPcieDevIf * dI, int d, int f = 0){
name = n;
device = d;
function = f;
instance = i;
devIf = dI;
}
void print(){
printf("name <%s>, dev <%d>, fun <%d>",name, device, function);
}
};
struct pcieRange{
uint64_t base;
uint64_t end; // base + size - 1
pcieDevInfo * devInfo; // pointer to the info struct for this device
pcieRange(){
base = end = -1;
devInfo = 0;
}
pcieRange(uint64_t b, uint64_t e, pcieDevInfo * di){
base = b; end = e; devInfo = di;
}
void print(){
devInfo->print();
printf(" base <%llx> end <%llx>\n", base, end);
}
};
//comparison function (reverse than normal default case)
class compare{
public:
bool operator()(uint64_t key1, uint64_t key2)const{
return key1 > key2;
}
};
private:
typedef map<uint64_t , pcieRange *,compare> pcieDevMap;
typedef map<uint64_t , pcieRange *,compare>::iterator pcieDevMapIterator;
pcieDevInfo *searchDevInfoListByName(const char * name){
list<pcieDevInfo *>::iterator i;
for(i = devInfoList.begin(); i != devInfoList.end(); i++)
if(!strcmp(name, (*i)->name))
return *i;
return 0;
}
pcieDevInfo *searchDevInfoListByDevFun(int dev, int fun){
list<pcieDevInfo *>::iterator i;
for(i = devInfoList.begin(); i != devInfoList.end(); i++)
if(((*i)->device == dev) && ((*i)->function == fun))
return *i;
return 0;
}
bool addSpace(pcieRange * pI,pcie_space space){
pcieDevMapIterator dmIter;
for(dmIter = pcieAddrSpace[space].begin(); dmIter != pcieAddrSpace[space].end(); dmIter++){
if(pI->base >= dmIter->second->base && pI->base <= dmIter->second->end || // pI base within dmIter
pI->end >= dmIter->second->base && pI->end <= dmIter->second->end || // pI end within dmIter
pI->base <= dmIter->second->base && pI->end >= dmIter->second->end){ // pI encloses dmIter
if(strcmp(pI->devInfo->name,dmIter->second->devInfo->name)){
printf("%s add Space error : Conflicting ranges\n",getName());
printf("Existing device -->"); dmIter->second->print();
printf("Conflicting device -->"); pI->print();
}
return false; //range conflict
}
}
pcieAddrSpace[space][pI->base] = pI;
return true;
}
bool removeMap(pcieDevInfo * pI){ //remove all the mappings for device with info struct pI
pcieDevMapIterator dmIter;
for(uint8_t i = 0; i < PCI_NSPACES; i++)
for(dmIter = pcieAddrSpace[i].begin(); dmIter != pcieAddrSpace[i].end(); dmIter++)
if(dmIter->second->devInfo == pI){
pcieDevMapIterator dmIter1 = ++dmIter;
pcieAddrSpace[i].erase(--dmIter);
dmIter = dmIter1;
}
return true;
}
bool removeSpace(uint64_t base, pcie_space space){
return pcieAddrSpace[space].erase(base);
}
static const char * pcie_space_name(pcie_space space){
switch(space){
case PCIE_CFG:
return "PCIE config";
case PCIE_IO:
return "PCIE IO";
case PCIE_MEM:
return "PCIE MEM";
default:
return "Unknow Pcie Space!!";
}
}
list<pcieDevInfo*> devInfoList; //list of devices present on the pci Bus
pcieDevMap pcieAddrSpace[3]; // map in only PCIE_CFG, PCIE_IO, PCIE_MEM
const char * bridgeName;
mmi_instance_t bridgeMod;
genericPcieDevIf * bridgeIf;
uint16_t getBridgeId(){ return PCIE_REQUESTER_ID(bridgeIf->devif_getPriBusNo(),\
bridgeIf->devif_getDevice(),bridgeIf->devif_getFunction());}
public:
pcieBus(const char *_modname, const char *_instance_name);
~pcieBus();
void modinfo();
bool parse_arg(const char *arg);
void module_added(mmi_instance_t , const char *target_name);
void module_deleted(mmi_instance_t, const char *target_name);
void * get_interface(const char *name);
bool check_args();
const char * get_help();
void setBridgeIf(genericPcieDevIf * i){bridgeIf = i;}
bool busif_addDevice(const char *devname, int device, int function);
bool busif_deleteDevice(const char *devname);
bool busif_map(const char *devname, pcie_space, uint64_t base, uint64_t size);
bool busif_unmap(const char *devname, pcie_space, uint64_t base);
int busif_getBusno();
bool dump(const char * dir, const char* file){return true;}
bool restore(const char * dir, const char* file){return true;}
// get the mmi instance based upon device and function
mmi_instance_t getDevInstance(int dev,int fun);
int devif_getBusNo();
// access the mem, io, conf space addresses under this bus hierarchy.
pcieCompleter busif_access(pcie_space, bool wr, uint64_t addr, void * data, \
uint16_t length, uint8_t be, uint16_t reqId, addrMd_xactnType , SAM_DeviceId *samId, tlp_X args);
// addr is a 64 bit flat address into one of the mem/io/conf spaces.
// the bus would call one of the devif functions based upon the space.
pcieCompleter busif_msgAccess(uint8_t messageCode, msgRouting route,uint16_t reqId, SAM_DeviceId *samId,\
uint64_t tarIdOrAddr, /*msg tlp*/ \
void * data, uint16_t length, /* msgd tlp*/ \
uint16_t vendor, uint32_t vendor_data, tlp_X args = dont_care_attrs); /* vendor defined msg*/
};
#endif