Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / devices / pci_bus / include / pci_bus.h
/*
* ========== Copyright Header Begin ==========================================
*
* OpenSPARC T2 Processor File: pci_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 _PCI_BUS_NEW_IMPL_H
#define _PCI_BUS_NEW_IMPL_H
#include <list>
#include <map>
#include <stdio.h>
#include "pci.h"
#include "arg.h"
using namespace std;
class pciBus:public Module, pciBusIf{
public:
struct pciDevInfo{
const char * name;
mmi_instance_t instance;
genericPciDevIf * devIf;
uint8_t device;
uint8_t function;
pciDevInfo(){
name = 0;
devIf = 0;
device = function = -1;
}
pciDevInfo(const char * n, mmi_instance_t i, genericPciDevIf * dI, uint8_t d, uint8_t f = 0){
name = n;
device = d;
function = f;
instance = i;
devIf = dI;
}
void print(){
printf("name <%s>, dev <%d>, fun <%d>\n",name, device, function);
}
};
struct pciRange{
uint64_t base;
uint64_t end; // base + size - 1
pciDevInfo * devInfo; // pointer to the info struct for this device
pciRange(){
base = end = -1;
devInfo = 0;
}
pciRange(uint64_t b, uint64_t e, pciDevInfo * 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 , pciRange *,compare> pciDevMap;
typedef map<uint64_t , pciRange *,compare>::iterator pciDevMapIterator;
pciDevInfo *searchDevInfoListByName(const char * name){
list<pciDevInfo *>::iterator i;
for(i = devInfoList.begin(); i != devInfoList.end(); i++)
if(!strcmp(name, (*i)->name))
return *i;
return 0;
}
pciDevInfo *searchDevInfoListByDevFun(uint8_t dev, uint8_t fun){
list<pciDevInfo *>::iterator i;
for(i = devInfoList.begin(); i != devInfoList.end(); i++)
if(((*i)->device == dev) && ((*i)->function == fun))
return *i;
return 0;
}
bool addSpace(pciRange * pI,pci_space_t space){
pciDevMapIterator dmIter;
dmIter = pciAddrSpace[space].lower_bound(pI->base);
for(dmIter = pciAddrSpace[space].begin(); dmIter != pciAddrSpace[space].end(); dmIter++){
if(pI->base >= dmIter->second->base && pI->base <= dmIter->second->end || \
pI->end >= dmIter->second->base && pI->end <= dmIter->second->end || \
pI->base <= dmIter->second->base && pI->end >= dmIter->second->end){
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
}
}
pciAddrSpace[space][pI->base] = pI;
return true;
}
bool removeMap(pciDevInfo * pI){ //remove all the mappings for device with info struct pI
pciDevMapIterator dmIter;
for(uint8_t i = 0; i < PCI_NSPACES; i++)
for(dmIter = pciAddrSpace[i].begin(); dmIter != pciAddrSpace[i].end(); dmIter++)
if(dmIter->second->devInfo == pI){
pciDevMapIterator dmIter1 = ++dmIter;
pciAddrSpace[i].erase(--dmIter);
dmIter = dmIter1;
}
return true;
}
bool removeSpace(uint64_t base, pci_space_t space){
return pciAddrSpace[space].erase(base);
}
static const char * pci_space_name(pci_space_t space){
switch(space){
case PCI_CFG:
return "PCI config";
case PCI_IO:
return "PCI IO";
case PCI_MEM32:
return "PCI MEM32";
case PCI_MEM64:
return "PCI MEM64";
default:
return "Unknow!!";
}
}
list<pciDevInfo*> devInfoList; //list of devices present on the pci Bus
pciDevMap pciAddrSpace[PCI_NSPACES];
const char * bridgeName;
//mmi_instance_t bridgeMod;
mmi_instance_t bridgeMod;
pciBridgeIf * bridgeIf;
public:
pciBus(const char *_modname, const char *_instance_name);
~pciBus();
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();
bool busif_add_device(const char *devname, uint8_t device, uint8_t function);
bool busif_delete_device(const char *devname);
bool busif_map(const char *devname, pci_space_t, uint64_t base, uint64_t size);
bool busif_unmap(const char *devname, pci_space_t, uint64_t base);
int busif_add_interrupt(int device, int dev_type, int slot_irl[], bool isMulti = false);
int busif_free_interrupt(int device);
bool busif_interrupt_in(bool set, int dev_number, int line, SAM_DeviceId *samId);
uint64_t busif_get_lowest_base(pci_space_t, uint64_t sz);
pciXactnStatus busif_dma(bool wr, uint64_t vaddr, void *data, long count, SAM_DeviceId *samId);
pciXactnStatus busif_special_cycle(uint16_t mssg, uint16_t data);
pciXactnStatus busif_intr_ack(uint64_t * data);
pciXactnStatus busif_access_w_size(pci_space_t, uint64_t paddr, uint64_t offset, bool_t wr, uint64_t* buf, uint8_t size, SAM_DeviceId * samId);
pciXactnStatus busif_access_w_byte_enables(pci_space_t, uint64_t paddr, uint64_t offset, bool_t wr, uint64_t* buf, uint8_t byte_enable, SAM_DeviceId * samId);
int busif_get_busno(){return bridgeIf->busif_get_secondary_busno();}
};
#endif