// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: pcie_bridge.cc
// 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 ============================================
static const char * pcieToPcieBridge_help
= "\n\
SAM functional model for PCIE-PCIE bridge component of PLX 8532\n\
The switch is composed by sysconf'ing individual pcie bridges\n\
connected by an internal pcie bus (also sysconf'ed)\n\
The following illustrates a sample configuration with the buses\n\
numbered in DFS order.\n\
|--------------PCIE Bridge----------------|\n\
_____________________________|______________________\n\
| internal bus [1]____________|_________________ |PCIE switch\n\
| downstream port1 port2 (downstream) ... |\n\
|________________|____________|______________________|\n\
bus [2] ___|___ ___|___ bus [5]\n\
PCIE-PCI[E] bridge/PCIE device\n\
Sysconf format for individual pcie bridge is: \n\
sysconf pcie_bridge <instance name> bus=<upstream bus> secbus=<downstream bus>\n\
dev=<device number> [upstream]\n\
\'bus\' is the upstream bus for this bridge instance\n\
\'secbus\' is the secondary bus of this bridge instance\n\
\'dev\' is the device number on the upstream bus\n\
\'upstream\' is boolean parameter that designates the bridge as a switch\n\
upstream port. If absent the bridge is a downstream port\n\
Example switch config - port 0 as upstream and 1 2 8 9 as downstream\n\
{NOTE: port is same as dev here. Can also add ports 3 10 11 as well}\n\
#upstream port - pcie_a is primary bus of upstream bridge\n\
sysconf pcie_bridge b0 bus=pcie_a dev=0 fun=0 secbus=pcie_int upstream\n\
#internal virtual pcie bus\n\
sysconf pcie_bus pcie_int bridge=b0\n\
#downstream ports connected at upstream to pcie_int\n\
sysconf pcie_bridge b1 bus=pcie_int dev=1 secbus=pcie_b\n\
sysconf pcie_bridge b2 bus=pcie_int dev=2 secbus=pcie_c\n\
sysconf pcie_bridge b3 bus=pcie_int dev=8 secbus=pcie_d\n\
sysconf pcie_bridge b4 bus=pcie_int dev=9 secbus=pcie_e\n\
#downstream pcie buses\n\
sysconf pcie_bus pcie_b bridge=b1\n\
sysconf pcie_bus pcie_c bridge=b2\n\
sysconf pcie_bus pcie_d bridge=b3\n\
sysconf pcie_bus pcie_e bridge=b4\n\
For UI help type <instance name>\n\
For module specific info type \'modinfo <instance name>\'\n";
Module::get_help_string(){
return pcieToPcieBridge_help
;
Module::create(const char *_modname
, const char *_instance_name
){
return new PcieBridge(_modname
, _instance_name
);
pcieToPcieBridge_ui_cmd (void * obj
, int argc
, char * argv
[]){
PcieBridge
* i
= dynamic_cast<PcieBridge
*>((Module
*)obj
);
i
->handle_ui(argc
, argv
);
PcieBridge::PcieBridge(const char* modname
, const char * instance_name
)
: Module(modname
, instance_name
){
debug_info("PCIE-PCIE bridge: creating instance %s\n", instance_name
);
mem32_base
= mem32_limit
= 0;
mem64_base
= mem64_limit
= 0;
mmi_register_instance_cmd(getInstance(),pcieToPcieBridge_help
,pcieToPcieBridge_ui_cmd
);
pendingIntr
[0] = pendingIntr
[1] = pendingIntr
[2] = pendingIntr
[3] = false;
assert(pthread_mutex_init(&intMutex
,0) == 0);
dump_version1_0
= strdup("v1.0"); // never change
current_dump_version
= dump_version1_0
; // change if when dump format changes,
// i.e. point current to new version
PcieBridge::~PcieBridge(){
debug_info("%s: destructor\n", HERE
);
return Module::get_help_string();
PcieBridge::dump(FILE * fp
) {
char *dumpDir
= DR_get_dir();
bool ret
= genericPcieDev::dump (dumpDir
, getName());
const int bufsize
= 64 * 1024;
// dump the port/device numbers of downstream ports/devices
fprintf(fp
,"%s\n",current_dump_version
);
fprintf(fp
,"downstream ports/devices with pending interrupts\n");
for(int i
= 0; i
< 4; i
++){
sprintf(buf
,"Int%c ",'A' + i
);
list
<int>::iterator listIt
;
for(listIt
= intLine
[i
].begin(); listIt
!= intLine
[i
].end(); listIt
++){
sprintf(tbuf
,"0x%x ",*listIt
);
fwrite(buf
,strlen(buf
),1,fp
);
fwrite("\n",strlen("\n"),1,fp
);
// now dump the intx pending status
fprintf(fp
,"Pending interrupts to upstream bridge\n");
for(char i
= 0; i
< 4; i
++)
fprintf(fp
,"int%c-%s\n", i
+'A', pendingIntr
[i
]? "Asserted":"Deasserted");
PcieBridge::restore(FILE * fp
) {
char *dumpDir
= DR_get_dir();
bool ret
= genericPcieDev::restore (dumpDir
, getName());
const int bufsize
= 64 * 1024;
// read the version string.
if(!strcmp(current_dump_version
,buf
)){
printf("%s: dump version unknown\n",getName());
// throw away the comment line
for(int i
= 0; i
< 4; i
++){
strtok(buf
," "); // intr line number, ignore
while( port_val
= strtok(0," ") ){
uint64_t val
= strtoull(port_val
,0,0);
intLine
[i
].push_back(val
);
// ignore the other dump data as it can be derived from data above
snprintf(reg_descr
, 100, "%s-%s Vender ID", devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
, 2,0x10b5,0x0,0x0),PCI_CONF_VENID
);
snprintf(reg_descr
, 100, "%s-%s Device ID", devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
, 2,0x8532,0x0,0x0),PCI_CONF_DEVID
);
snprintf(reg_descr
, 100, "%s-%s command register", devif_getName(),busName
);
confSpace
->addConfReg(new bridgeCommandReg(reg_descr
,(genericPcieDev
*)this,0x547,0x0),PCI_CONF_COMM
);// write mask = 0x547
snprintf(reg_descr
,100,"%s-%s Primary device status reg", devif_getName(),busName
);
confSpace
->addConfReg(new pcieStatusReg(reg_descr
,(genericPcieDev
*)this,0x0010,0xc900),PCI_CONF_STAT
);//write mask = 0xc900
// this reg has some rw1c bit fields. over-ride the pciStatusReg class r/w functions in case OS ever complains.
snprintf(reg_descr
,100,"%s-%s revision id", devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0xbb,0x0),PCI_CONF_REVID
);// rev id = 0xBB, the latest silicon revision, ro
snprintf(reg_descr
,100,"%s-%s prog interface",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x0,0x0),PCI_CONF_PROGCLASS
);//0x00, ro
snprintf(reg_descr
,100,"%s-%s sub class",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x4,0x0),PCI_CONF_SUBCLASS
);//0x04, ro
snprintf(reg_descr
,100,"%s-%s base class",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x06,0x0),PCI_CONF_BASCLASS
);//0x06, ro
snprintf(reg_descr
,100,"%s-%s cache line size",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x0,0xff),PCI_CONF_CACHE_LINESZ
);//0x00,
snprintf(reg_descr
,100,"%s-%s latency timer",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x0,0x0),PCI_CONF_LATENCY_TIMER
);//0x00,
snprintf(reg_descr
,100,"%s-%s Header type",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x01,0x00),PCI_CONF_HEADER
);
snprintf(reg_descr
,100,"%s-%s Base Address 0",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,4,0x0,0xfffe0000),PCI_CONF_BASE0
); // Base Address writable
confSpace
->addConfReg(new pciConfReg(reg_descr
,4,0x0,0x0),PCI_CONF_BASE0
); // Base Address read only
snprintf(reg_descr
,100,"%s-%s Base Address 1",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,4,0x0,0xffffffff),PCI_CONF_BASE1
); // Base Address writable
confSpace
->addConfReg(new pciConfReg(reg_descr
,4,0x0,0x0),PCI_CONF_BASE1
); // Base Address read only
snprintf(reg_descr
,100,"%s-%s Primary Bus No",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x00,0xff),PCI_BCNF_PRIBUS
);//0x00, rw
snprintf(reg_descr
,100,"%s-%s Secondary Bus No",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x00,0xff),PCI_BCNF_SECBUS
);//0x00, rw
snprintf(reg_descr
,100,"%s-%s Subordinate Bus No",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x00,0xff),PCI_BCNF_SUBBUS
);//0x00, rw
snprintf(reg_descr
,100,"%s-%s Secondary Latency Timer",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x0,0x0),PCI_BCNF_LATENCY_TIMER
);//0x0, RO
snprintf(reg_descr
,100,"%s-%s I/O Base",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0xf1,0xf0),PCI_BCNF_IO_BASE_LOW
);//0xf1, rw
snprintf(reg_descr
,100,"%s-%s I/O Limit",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x01,0xf0),PCI_BCNF_IO_LIMIT_LOW
);//0x01, rw
snprintf(reg_descr
,100,"%s-%s Secondary Status",devif_getName(),busName
);
confSpace
->addConfReg(new pciSecondaryStatusReg(0,0xc100,0,reg_descr
),PCI_BCNF_SEC_STATUS
);//0x0, rw
snprintf(reg_descr
,100,"%s-%s Memory Base",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,2,0xfff0,0xfff0),PCI_BCNF_MEM_BASE
);//0xfff0, rw
snprintf(reg_descr
,100,"%s-%s Memory Limit",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,2,0x00,0xfff0),PCI_BCNF_MEM_LIMIT
);//0x00, rw
snprintf(reg_descr
,100,"%s-%s Prefetchable Memory Base",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,2,0xfff1,0xfff0),PCI_BCNF_PF_BASE_LOW
);//0xfff1, rw
snprintf(reg_descr
,100,"%s-%s Prefetchable Memory Limit",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,2,0x01,0xfff0),PCI_BCNF_PF_LIMIT_LOW
);//0x01, rw
snprintf(reg_descr
,100,"%s-%s Prefetchable Memory Base Upper Portion",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,4,0x0,0xffffffff),PCI_BCNF_PF_BASE_HIGH
);//0x0, rw
snprintf(reg_descr
,100,"%s-%s Prefetchable Memory Limit Upper Portion",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,4,0x0,0xffffffff),PCI_BCNF_PF_LIMIT_HIGH
);//0x0, rw
snprintf(reg_descr
,100,"%s-%s I/O Base High",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,2,0xffff,0xffff),PCI_BCNF_IO_BASE_HI
); //0xffff, rw
snprintf(reg_descr
,100,"%s-%s I/O Limit High",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,2,0x0,0xffff),PCI_BCNF_IO_LIMIT_HI
); //0x0, rw
snprintf(reg_descr
,100,"%s-%s Capabilities List Pointer",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x40,0x0),PCI_BCNF_CAP_PTR
); //0x40, RO
snprintf(reg_descr
,100,"%s-%s Interrupt Line",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x0,0xff),PCI_BCNF_ILINE
); //0x0, RW
snprintf(reg_descr
,100,"%s-%s Interrupt Pin",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x1,0x0),PCI_BCNF_IPIN
); //0x1, RO
snprintf(reg_descr
,100,"%s-%s Bridge control",devif_getName(),busName
);
confSpace
->addConfReg(new pciBridgeControlReg(0x0,0x5f,0,reg_descr
),PCI_BCNF_BCNTRL
); //0x0, RW
snprintf(reg_descr
,100,"%s-%s Power Management Capability ID",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x01,0x00),BRIDGE_POWER_CAP_ADDR
); //0x01, RO
snprintf(reg_descr
,100,"%s-%s Next Capability Pointer",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x48,0x00),BRIDGE_POWER_CAP_ADDR
+1); //0x48, RO
snprintf(reg_descr
,100,"%s-%s ower Management Version",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,2,0xc802,0x00),BRIDGE_POWER_CAP_ADDR
+2); //0xc802, RO
addMsiCap(BRIDGE_PCIE_CAP_ADDR
, BRIDGE_MSI_CAP_ADDR
, 0x80);
snprintf(reg_descr
,100,"%s PCI Express Capability Identifier",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x10,0x00),BRIDGE_PCIE_CAP_ADDR
+ PCI_EXP_CAP_ID_OFFSET
);
snprintf(reg_descr
,100,"%s Next Item Pointer",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x0,0x0),BRIDGE_PCIE_CAP_ADDR
+ PCI_EXP_NXT_CAP_PTR_OFFSET
);
snprintf(reg_descr
,100,"%s PCI Express Capability",getName());
confSpace
->addConfReg(new pciExpCapReg(0x51,0x0,0,reg_descr
),BRIDGE_PCIE_CAP_ADDR
+ PCI_EXP_CAP_REG_OFFSET
);
confSpace
->addConfReg(new pciExpCapReg(0x161,0x0,0,reg_descr
),BRIDGE_PCIE_CAP_ADDR
+ PCI_EXP_CAP_REG_OFFSET
);
snprintf(reg_descr
,100,"%s PCI Express Device Capabilities Register",getName());
confSpace
->addConfReg(new pciExpDevCapReg(0x7001,0x0,0,reg_descr
),BRIDGE_PCIE_CAP_ADDR
+ PCI_EXP_DEV_CAP_OFFSET
);
confSpace
->addConfReg(new pciExpDevCapReg(0x1,0x0,0,reg_descr
),BRIDGE_PCIE_CAP_ADDR
+ PCI_EXP_DEV_CAP_OFFSET
);
snprintf(reg_descr
,100,"%s PCI Express Device Control Register",getName());
confSpace
->addConfReg(new pciExpDevCntrlReg(0x0,0xef,0,reg_descr
),BRIDGE_PCIE_CAP_ADDR
+ PCI_EXP_DEV_CTRL_OFFSET
);
snprintf(reg_descr
,100,"%s PCI Express Device Status Register",getName());
confSpace
->addConfReg(new pciExpDevStatReg(0x0,0xf,0,reg_descr
),BRIDGE_PCIE_CAP_ADDR
+ PCI_EXP_DEV_STAT_OFFSET
);
snprintf(reg_descr
,100,"%s PCI Express Link Capabilities Register",getName());
confSpace
->addConfReg(new pciExpLnkCapReg(device
<< 24 | 0x2dc41,0x0,0x0,reg_descr
),BRIDGE_PCIE_CAP_ADDR
+ PCI_EXP_LINK_CAP_OFFSET
);
snprintf(reg_descr
,100,"%s PCI Express Link Control Register",getName());
confSpace
->addConfReg(new pciExpLnkCntrlReg(0x0,0xc3,0x0,reg_descr
),BRIDGE_PCIE_CAP_ADDR
+ PCI_EXP_LINK_CONT_OFFSET
);
confSpace
->addConfReg(new pciExpLnkCntrlReg(0x0,0xf3,0x0,reg_descr
),BRIDGE_PCIE_CAP_ADDR
+ PCI_EXP_LINK_CONT_OFFSET
);
snprintf(reg_descr
,100,"%s PCI Express Link Status Register",getName());
confSpace
->addConfReg(new pciExpLnkStatReg(0x11,0x0,0x0,reg_descr
),BRIDGE_PCIE_CAP_ADDR
+ PCI_EXP_LINK_STAT_OFFSET
);
snprintf(reg_descr
,100,"%s PCI Express Slot Capabilities Register",getName());
confSpace
->addConfReg(new pciExpSlotCapReg(0x0,0x0,0x0,reg_descr
),BRIDGE_PCIE_CAP_ADDR
+ PCI_EXP_SLOT_CAP_OFFSET
);
confSpace
->addConfReg(new pciExpSlotCapReg(0xcdf,0x0,0x0,reg_descr
),BRIDGE_PCIE_CAP_ADDR
+ PCI_EXP_SLOT_CAP_OFFSET
);
snprintf(reg_descr
,100,"%s PCI Express Slot Control Register",getName());
confSpace
->addConfReg(new pciExpSlotCntrlReg(0x0,0x0,0x0,reg_descr
),BRIDGE_PCIE_CAP_ADDR
+ PCI_EXP_SLOT_CTRL_OFFSET
);
confSpace
->addConfReg(new pciExpSlotCntrlReg(0x7c0,0x7ff,0x0,reg_descr
),BRIDGE_PCIE_CAP_ADDR
+ PCI_EXP_SLOT_CTRL_OFFSET
);
snprintf(reg_descr
,100,"%s PCI Express Slot Status Register",getName());
confSpace
->addConfReg(new pciExpSlotStatReg(0x0,0x0,0x0,reg_descr
),BRIDGE_PCIE_CAP_ADDR
+ PCI_EXP_SLOT_STAT_OFFSET
);
confSpace
->addConfReg(new pciExpSlotStatReg(0x0,0x1f,0x0,reg_descr
),BRIDGE_PCIE_CAP_ADDR
+ PCI_EXP_SLOT_STAT_OFFSET
);
snprintf(reg_descr
,100,"%s Device Serial Number Extended Capability ID",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,2,0x3,0x0),BRIDGE_DEV_SERNUM_XCAP_ADDR
);
snprintf(reg_descr
,100,"%s Device Serial Number Capability Version & Next Pointer",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,2,0xfb41,0x0),BRIDGE_DEV_SERNUM_XCAP_ADDR
+ SERNUM_VER_NXTPTR_OFFSET
);
snprintf(reg_descr
,100,"%s Device Serial Number Low",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,4,0xedf,0x0),BRIDGE_DEV_SERNUM_XCAP_ADDR
+ SERNUM_SN_LOW_OFFSET
);
snprintf(reg_descr
,100,"%s Device Serial Number High",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,4,0x1,0x0),BRIDGE_DEV_SERNUM_XCAP_ADDR
+ SERNUM_SN_HIGH_OFFSET
);
addAERCap(BRIDGE_ADV_ERR_CAP_ADDR
, BRIDGE_PWRBGT_HDR_ADDR
);
snprintf(reg_descr
,100,"%s Power Budgeting Enhanced Capability Header",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,4,0x14810004,0x0),BRIDGE_PWRBGT_HDR_ADDR
);
snprintf(reg_descr
,100,"%s Power Budgeting Data Select Register",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x0,0xff),BRIDGE_PWRBGT_HDR_ADDR
+ PWRBGT_DSEL_OFFSET
);
snprintf(reg_descr
,100,"%s Power Budgeting Data Register",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,4,0x0,0x0),BRIDGE_PWRBGT_HDR_ADDR
+ PWRBGT_DATA_OFFSET
);
snprintf(reg_descr
,100,"%s Power Budget Capability",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,4,0x1,0x0),BRIDGE_PWRBGT_HDR_ADDR
+ PWRBGT_DATA_CAP_OFFSET
);
dev_init_done(debug_level
);
mem32_base
= GET_MEM_BASE(confSpace
);
mem32_limit
= GET_MEM_LIMIT(confSpace
);
io_base
= GET_IO_BASE(confSpace
);
io_limit
= GET_IO_LIMIT(confSpace
);
mem64_base
= GET_PF_MEM_BASE(confSpace
);
mem64_limit
= GET_PF_MEM_LIMIT(confSpace
);
bCR
= (bridgeCommandReg
*)confSpace
->getConfReg(PCI_CONF_COMM
);
PcieBridge::module_added(mmi_instance_t target
, const char *target_name
){
if (secBusName
&& !strcmp(target_name
,secBusName
)){
secBusIf
= (pcieBusIf
*)mmi_get_interface(target
, PCIE_BUS_INTERFACE
);
secBusIf
->setBridgeIf((genericPcieDevIf
*)this);
if(busName
&& !strcmp(target_name
, busName
)){
busIf
= (pcieBusIf
*)mmi_get_interface(target
, PCIE_BUS_INTERFACE
);
dev_module_added(target_name
);
PcieBridge::module_deleted(mmi_instance_t target
, const char *target_name
){
dev_module_deleted(target_name
);
printf("%s: pcie-pcie virtual bridge device component of PLX 8532\n",getName());
printf("device id <0x%lx>, vendor id <0x%lx>\n",confSpace
->readConf(PCI_CONF_VENID
),\
confSpace
->readConf(PCI_CONF_DEVID
));
printf("The port type is %s\n",upstream_port
?"Upstream":"Downstream");
printf("Upstream pcie bus is <%s>, secondary pcie bus is <%s>\n",busName
,secBusName
);
printf("To display pcie config regs, type \'%s dump\'\n",getName());
PcieBridge::parse_arg(const char *arg
){
if (argval("secbus",arg
,&secBusName
)) {
debug_more("%s:secondary bus = %s\n",getName(),secBusName
);
}else if (!strcmp(arg
, "upstream")){
debug_more("%s: port type <Upstream>\n",getName());
return dev_parse_arg(arg
);
PcieBridge::check_args(){
debug_err("%s: ERROR: must specify a secondary PCIE bus\n", getName());
PcieBridge::get_interface(const char *name
){
if (!strcmp(name
, GENERIC_PCIE_DEV_INTERFACE
))
return (genericPcieDevIf
*)this;
else if(!strcmp(name
, PCI_BRIDGE_INTERFACE
))
return (pciBridgeIf
*)this;
PcieBridge::devif_confAccessCb(bool wr
, uint64_t offset
, uint8_t be
){
case PCI_BCNF_PF_BASE_HIGH
:
case PCI_BCNF_PF_BASE_LOW
:
case PCI_BCNF_PF_LIMIT_HIGH
:
case PCI_BCNF_PF_LIMIT_LOW
:
mem64_base
= GET_PF_MEM_BASE(confSpace
);
mem64_limit
= GET_PF_MEM_LIMIT(confSpace
);
if(mem64_base
< mem64_limit
){
debug_more("%s unmap MEM64[%llx %llx]\n",getName(), mem64_base
, mem64_limit
);
unmapSpace(PCIE_MEM
, mem64_base
);
mem64_base
= GET_PF_MEM_BASE(confSpace
);
mem64_limit
= GET_PF_MEM_LIMIT(confSpace
);
if (mem64_base
< mem64_limit
) {
debug_more("%s remap: MEM64 [%llx %llx]\n", getName(), mem64_base
, mem64_limit
);
mapSpace(PCIE_MEM
, mem64_base
, mem64_limit
- mem64_base
+ 1);
mem32_base
= GET_MEM_BASE(confSpace
);
mem32_limit
= GET_MEM_LIMIT(confSpace
);
if(mem32_base
< mem32_limit
){
debug_more("%s unmap: MEM[%lx %lx]\n",getName(), mem32_base
, mem32_limit
);
unmapSpace(PCIE_MEM
, mem32_base
);
mem32_base
= GET_MEM_BASE(confSpace
);
mem32_limit
= GET_MEM_LIMIT(confSpace
);
if (mem32_base
< mem32_limit
) {
debug_more("%s remap: MEM[%lx %lx]\n",getName(), mem32_base
, mem32_limit
);
mapSpace(PCIE_MEM
, mem32_base
, mem32_limit
- mem32_base
);
case PCI_BCNF_IO_BASE_LOW
:
case PCI_BCNF_IO_LIMIT_LOW
:
case PCI_BCNF_IO_BASE_HI
:
case PCI_BCNF_IO_LIMIT_HI
:
io_base
= GET_IO_BASE(confSpace
);
io_limit
= GET_IO_LIMIT(confSpace
);
debug_more("%s unmap: IO[%lx %lx]\n",getName(), io_base
, io_limit
);
unmapSpace(PCIE_IO
, io_base
);
io_base
= GET_IO_BASE(confSpace
);
io_limit
= GET_IO_LIMIT(confSpace
);
if (io_base
< io_limit
) {
debug_more("%s remap: IO[%lx %lx]\n",getName(), io_base
, io_limit
);
mapSpace(PCIE_IO
, io_base
, io_limit
- io_base
);
PcieBridge::devif_confAccess(bool wr
, uint32_t addr
, void * data
, uint8_t be
, uint16_t reqId
, addrMd_xactnType tType
, uint16_t length
, tlp_X args
, SAM_DeviceId
*id
) {
int size
= byteEnabletoSize(be
); // length is the number of words
if (tType
== conf_type1
) {
debug_more("%s:conf wr xactn type 1: addr <0x%x> size <%d> byte_en<0x%x> data<0x%llx>\n",
getName(), addr
, size
, be
,*(uint64_t*)data
);
// Change requester ID to bridge's ID for the handling in pcieBus::busif_access():
ret
= secBusIf
->busif_access(PCIE_CFG
, wr
, addr
, (uint64_t *)data
, length
, be
, getId(), tType
, id
, args
);
debug_more("%s:conf rd xactn type 1: addr <0x%x> size <%d> byte_en<0x%x> data<0x%llx>\n",
getName(), addr
, size
, be
, *(uint64_t*)data
);
if(debug_level
>= 2) printf("\n");
debug_err("Config address higher than 4K!\n");
return pcieCompleter(UR
,getId());
*(uint64_t*)data
&= 0xffffffff;
l_buf
= *(uint64_t*)data
;
*(uint64_t*)data
= swap_word(l_buf
);
*(uint64_t*)data
= swap_hword(l_buf
);
*(uint64_t*)data
= l_buf
;
debug_more("%s:conf xactn type 0: addr <0x%x> wr size <%d> byte_en<0x%x> data<0x%llx>\n",
getName(), addr
,size
, be
,*(uint64_t*)data
);
ret
= confSpace
->confAccessSize(addr
, wr
, (uint64_t *)data
, size
);
l_buf
= *(uint64_t*)data
;
*(uint64_t*)data
= swap_word(l_buf
& 0xFFFFFFFF);
*(uint64_t*)data
= swap_hword(l_buf
& 0xFFFF);
*(uint64_t*)data
= l_buf
& 0xFF;
debug_more("%s:conf xactn type 0: addr <0x%x> rd size <%d> byte_en<0x%x> data<0x%llx>\n",
getName(), addr
, size
, be
, *(uint64_t*)data
);
if(debug_level
>= 2) printf("\n");
devif_confAccessCb(wr
,addr
,be
);
return (ret
? pcieCompleter(SC
,getId()) : pcieCompleter(CA
,getId()));
PcieBridge::devif_memAccess(bool wr
, uint64_t addr
, addrMd_xactnType mode
, void * data
, uint16_t length
, uint8_t be
, uint16_t reqId
, tlp_X args
, SAM_DeviceId
*id
) {
direction_t direct
= direction(busIf
->busif_getBusno(), reqId
);
debug_more("%s: %s %s %s access at <0x%llx> of length <%4d> byte_en <0x%x> \n",
direct
== downstream
? "downstream":"upstream ",
mode
== mem_addr32
? "mem32" : "mem64",
if ((direct
== downstream
) && (addr
>= mem32_base
&& addr
< mem32_limit
|| addr
>= mem64_base
&& addr
< mem64_limit
)) {
return secBusIf
->busif_access(PCIE_MEM
, wr
, addr
, (uint64_t *)data
, length
, be
, reqId
, mode
, id
, args
);
} else if ((direct
== upstream
) && ((addr
< mem32_base
|| addr
>= mem32_limit
) && (addr
< mem64_base
|| addr
>= mem64_limit
))) {
return busIf
->busif_access(PCIE_MEM
, wr
, addr
, (uint64_t *)data
, length
, be
, reqId
, mode
, id
, args
);
return pcieCompleter(UR
,getId());
PcieBridge::devif_ioAccess(bool wr
, uint64_t addr
, void * data
, uint8_t be
, uint16_t reqId
, uint16_t length
, tlp_X args
, SAM_DeviceId
*id
) {
direction_t direct
= direction(busIf
->busif_getBusno(), reqId
);
debug_more("%s: %s %s %s access at <0x%llx> length <%d> be <0x%x> \n",
getName(), direct
== downstream
? "downstream":"upstream ",
"IO", wr
? "wr":"rd", addr
, length
, be
);
if ((direct
== downstream
) && addr
>= io_base
&& addr
< io_limit
) {
return secBusIf
->busif_access(PCIE_IO
, wr
, addr
, (uint64_t *)data
, length
, be
, reqId
, mem_addr32
, id
, args
);
} else if ((direct
== upstream
) && (addr
< io_base
|| addr
>= io_limit
)) {
return busIf
->busif_access(PCIE_IO
, wr
, addr
, (uint64_t *)data
, length
, be
, reqId
, mem_addr32
, id
, args
);
return pcieCompleter(UR
,getId());
PcieBridge::devif_msgAccess(uint8_t messageCode
, msgRouting route
, uint64_t tarIdOrAddr
, uint16_t reqId
, void * data
, uint16_t length
, uint16_t vendorId
, uint32_t vendor_data
, tlp_X args
, SAM_DeviceId
*id
){
case gathered_routed_to_RC
:
return busIf
->busif_msgAccess(messageCode
,route
,reqId
,id
,tarIdOrAddr
,data
,length
,vendorId
,
// intx message from downstream device or port.
if(messageCode
>= MSG_Assert_INTA
&& messageCode
<= MSG_Assert_INTD
)
return assertIntx((pciExpMsgCode
)messageCode
, reqId
, id
);
else if(messageCode
>= MSG_Deassert_INTA
&& messageCode
<= MSG_Deassert_INTD
)
return deassertIntx((pciExpMsgCode
)messageCode
, reqId
, id
);
debug_err("%s: don;t know how to handle message 0x%x\n", getName(), messageCode
);
return pcieCompleter(SIM_FAIL
);
return secBusIf
->busif_msgAccess(messageCode
,route
,reqId
,id
, tarIdOrAddr
,data
,length
,vendorId
,vendor_data
, args
);
debug_err("%s: address routing unsupported\n", getName());
debug_err("%s: ID routing unsupported\n", getName());
debug_err("%s: unknown message routing type %x\n",getName(),route
);
return pcieCompleter(SIM_FAIL
);
return pcieCompleter(SIM_OK
);
void PcieBridge::handle_ui(int argc
, char * argv
[]){
}else if(!strcmp(argv
[1],"dump")){
dumpDir
= getcwd(buf
,1024);
assert( errno
!= ERANGE
);
genericPcieDev::dump (dumpDir
, argv
[2]);
}else if(!strcmp(argv
[1],"restore")){
dumpDir
= getcwd(buf
,1024);
assert( errno
!= ERANGE
);
genericPcieDev::restore (dumpDir
, argv
[2]);
printf("%s restore: no restore filename specified\n",getName());
}else if(!strcmp(argv
[1],"debug")){
debug_level
= atoi(argv
[2]);
confSpace
->set_debug_level(debug_level
);
printf("%s: set debug level to %d\n",getName(),debug_level
);
printf("%s: current debug level %d\n",getName(),debug_level
);
debug_err("%s: unsupported UI command <%s>\n",getName(),argv
[1]);