// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: 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 * pcieToPciBridge_help
= "\n\
SAM model for Intel 41210 Serial to Parallel PCIE-PCI bridge\n\
sysconf bridge <instance name> bus=<primary bus> dev=<device> fun=<function> secbus=<secondary bus>\n\
<instance name> is any user specified name for the module\n\
<primary bus> is the instance name of the upstream pcie bus module\n\
<device> is the device number of bridge on upstream pcie bus\n\
<function> is the function number of bridge on upstream pcie bus\n\
<secondary bus> is the instance name of the downstream pci bus module\n\
For UI help type <instance name>\n\
For module specific info type \'modinfo <instance name>\'";
pcieToPciBridge_ui_cmd (void * obj
, int argc
, char * argv
[]){
pcieToPciBridge
* i
= dynamic_cast<pcieToPciBridge
*>((Module
*)obj
);
i
->handle_ui(argc
, argv
);
#define BRIDGE_CAP_STRUCT_ADDR 0x44
#define BRIDGE_MSI_CAP_ADDR 0x5c
#define BRIDGE_POWER_CAP_ADDR 0x6c
#define BRIDGE_PCIX_CAP_ADDR 0xd8
#define BRIDGE_AER_CAP_OFFSET 0x100
#define BRIDGE_POWER_BUDGET_CAP_OFFSET 0x300
Module::get_help_string(){
return pcieToPciBridge_help
;
Module::create(const char *_modname
, const char *_instance_name
){
return new pcieToPciBridge(_modname
, _instance_name
);
pcieToPciBridge::pcieToPciBridge(const char* modname
, const char * instance_name
)
: Module(modname
, instance_name
){
debug_info("Pcie bridge: creating instance %s\n", instance_name
);
mem32_base
= mem32_limit
= 0;
mem64_base
= mem64_limit
= 0;
mmi_register_instance_cmd(getInstance(),pcieToPciBridge_help
,pcieToPciBridge_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
pcieToPciBridge::~pcieToPciBridge(){
debug_info("%s: destructor\n", HERE
);
pcieToPciBridge::get_help(){
return Module::get_help_string();
pcieToPciBridge::initPci(){
snprintf(reg_descr
, 100, "%s-%s Vender ID", devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
, 2,0x8086,0x0,0x0),PCI_CONF_VENID
);
snprintf(reg_descr
, 100, "%s-%s Device ID", devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
, 2,function
?0x0341:0x0340,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,0x10,0xf900),PCI_CONF_STAT
);//write mask = 0xf900
// 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,0x0,0x0,0x0),PCI_CONF_REVID
);// rev id = 0x00, 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,0x81,0x00),PCI_CONF_HEADER
);
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 Master Latency Timer",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x40,0xf8),PCI_BCNF_LATENCY_TIMER
);//0x40, rw
snprintf(reg_descr
,100,"%s-%s I/O Base",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x00,0xf0),PCI_BCNF_IO_BASE_LOW
);//0x00, rw
snprintf(reg_descr
,100,"%s-%s I/O Limit",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x00,0xf0),PCI_BCNF_IO_LIMIT_LOW
);//0x00, rw
snprintf(reg_descr
,100,"%s-%s Secondary Status",devif_getName(),busName
);
confSpace
->addConfReg(new pciSecondaryStatusReg(0x2a,0xf900,0,reg_descr
),PCI_BCNF_SEC_STATUS
);//0x2a, rw
snprintf(reg_descr
,100,"%s-%s Memory Base",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,2,0x00,0xfff0),PCI_BCNF_MEM_BASE
);//0x00, 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,0x01,0xfff0),PCI_BCNF_PF_BASE_LOW
);//0x01, 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,0x0,0x0),PCI_BCNF_IO_BASE_HI
); //0x0, RO
snprintf(reg_descr
,100,"%s-%s I/O Limit High",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,2,0x0,0x0),PCI_BCNF_IO_LIMIT_HI
); //0x0, RO
snprintf(reg_descr
,100,"%s-%s Capabilities List Pointer",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x44,0x0),PCI_BCNF_CAP_PTR
); //0x44, 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,0x0,0x0),PCI_BCNF_IPIN
); //0x0, RO
snprintf(reg_descr
,100,"%s-%s Bridge control",devif_getName(),busName
);
confSpace
->addConfReg(new pciBridgeControlReg(0x0,0xf7f,0x0,reg_descr
),PCI_BCNF_BCNTRL
); //0x0, RW
snprintf(reg_descr
,100,"%s-%s Bridge configuration",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,2,0x2880,0x4683),PCI_BCNF_BCNF
); //0x2880, RW
snprintf(reg_descr
,100,"%s-%s Multi-Transaction Timer",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x0,0xf8),PCI_BCNF_MTT
); //0x0, RW
snprintf(reg_descr
,100,"%s-%s PCI Clock Control",devif_getName(),busName
);
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0xdf,0x7f),PCI_BCNF_PCLKC
); //0xdf, RW
snprintf(reg_descr
,100,"%s PCI Express Capability Identifier",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x10,0x00),BRIDGE_CAP_STRUCT_ADDR
+ PCI_EXP_CAP_ID_OFFSET
);//ro
snprintf(reg_descr
,100,"%s Next Item Pointer",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,BRIDGE_MSI_CAP_ADDR
,0x0),BRIDGE_CAP_STRUCT_ADDR
+ PCI_EXP_NXT_CAP_PTR_OFFSET
);//, ro
snprintf(reg_descr
,100,"%s PCI Express Capability",getName());
confSpace
->addConfReg(new pciExpCapReg(0x71,0x0,0,reg_descr
),BRIDGE_CAP_STRUCT_ADDR
+ PCI_EXP_CAP_REG_OFFSET
);//0x1
snprintf(reg_descr
,100,"%s PCI Express Device Capabilities Register",getName());
confSpace
->addConfReg(new pciExpDevCapReg(0x1,0x0,0,reg_descr
),BRIDGE_CAP_STRUCT_ADDR
+ PCI_EXP_DEV_CAP_OFFSET
);//
snprintf(reg_descr
,100,"%s PCI Express Device Control Register",getName());
confSpace
->addConfReg(new pciExpDevCntrlReg(0x2000,0xf0ef,0,reg_descr
),BRIDGE_CAP_STRUCT_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_CAP_STRUCT_ADDR
+ PCI_EXP_DEV_STAT_OFFSET
);//
snprintf(reg_descr
,100,"%s PCI Express Link Capabilities Register",getName());
confSpace
->addConfReg(new pciExpLnkCapReg(0x3e481,0x0,0x0,reg_descr
),BRIDGE_CAP_STRUCT_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_CAP_STRUCT_ADDR
+ PCI_EXP_LINK_CONT_OFFSET
);//
snprintf(reg_descr
,100,"%s PCI Express Link Status Register",getName());
confSpace
->addConfReg(new pciExpLnkStatReg(0x1081,0x0,0x0,reg_descr
),BRIDGE_CAP_STRUCT_ADDR
+ PCI_EXP_LINK_STAT_OFFSET
);//
addMsiCap(BRIDGE_POWER_CAP_ADDR
, BRIDGE_MSI_CAP_ADDR
, 0x80);
addAERCap(BRIDGE_AER_CAP_OFFSET
,BRIDGE_POWER_BUDGET_CAP_OFFSET
);
// pcix power management registers
snprintf(reg_descr
,100,"%s PM_CAPID",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x1,0x0),0x6c);
snprintf(reg_descr
,100,"%s PM_NXTP",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0xd8,0x0),0x6d);
snprintf(reg_descr
,100,"%s PM_PMC",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,2,0xc802,0x0),0x6e);
snprintf(reg_descr
,100,"%s PM_PMCSR",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,2,0x0,0x3),0x70);
snprintf(reg_descr
,100,"%s PM_BSE",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x0,0x0),0x72);
snprintf(reg_descr
,100,"%s PM_DATA",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x0,0x0),0x73);
snprintf(reg_descr
,100,"%s PM_CAPID",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x7,0x0),0xd8);
snprintf(reg_descr
,100,"%s PM_NXTP",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x0,0x0),0xd9);
snprintf(reg_descr
,100,"%s PX_SSTS",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,2,0x3,0x0),0xda);
snprintf(reg_descr
,100,"%s PX_BSTS",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,4,0x0,0x0),0xdc);
snprintf(reg_descr
,100,"%s PX_USTC",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,4,0xffffffff,0xffff0000),0xe0);
snprintf(reg_descr
,100,"%s PX_DSTC",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,4,0xffffffff,0xffff0000),0xe4);
snprintf(reg_descr
,100,"%s BINIT",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,4,0x3,0x1f),0xfc);
snprintf(reg_descr
,100,"%s PCIXERRUNC_PTR",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,2,0x0,0x0),0x138);
snprintf(reg_descr
,100,"%s PCIEXERRUNC_SEV",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,2,0x0,0xffff),0x134);
snprintf(reg_descr
,100,"%s PCIEXRRUNC_MSK",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,2,0x20,0xffff),0x130);
snprintf(reg_descr
,100,"%s PCIXERRUNC_STS",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,2,0x0,0xffff),0x12c);
snprintf(reg_descr
,100,"%s PCIXHDR_LOG0",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,4,0x0,0x0),0x13c);
snprintf(reg_descr
,100,"%s PCIXHDR_LOG1",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,4,0x0,0x0),0x140);
snprintf(reg_descr
,100,"%s PCIXHDR_LOG2",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,4,0x0,0x0),0x144);
snprintf(reg_descr
,100,"%s PCIXHDR_LOG3",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,4,0x0,0x0),0x148);
snprintf(reg_descr
,100,"%s ARB_CNTRL",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,2,0xff,0xffff),0x16a);
snprintf(reg_descr
,100,"%s SSR",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,2,0x0,0x0),0x170);
snprintf(reg_descr
,100,"%s PREFCTRL-Lower",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,4,0x5060,0x3f0770),0x178);
snprintf(reg_descr
,100,"%s PREFCTRL-Upper",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,4,0x4000,0xc00),0x17c);
// power budgeting registers.
snprintf(reg_descr
,100,"%s power budgeting enhanced cap hdr",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,4,0x10004,0x0),0x300);
snprintf(reg_descr
,100,"%s power budgeting data select",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x0,0xff),0x304);
snprintf(reg_descr
,100,"%s power budgeting data register",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,4,0x0,0x0),0x308);
pcieToPciBridge::init_done(){
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
);
pcieToPciBridge::module_added(mmi_instance_t target
, const char *target_name
){
if (secBusName
&& !strcmp(target_name
,secBusName
)){
secBusIf
= (pciBusIf
*)mmi_get_interface(target
, PCI_BUS_INTERFACE
);
if(busName
&& !strcmp(target_name
, busName
)){
busIf
= (pcieBusIf
*)mmi_get_interface(target
, PCIE_BUS_INTERFACE
);
dev_module_added(target_name
);
pcieToPciBridge::module_deleted(mmi_instance_t target
, const char *target_name
){
dev_module_deleted(target_name
);
pcieToPciBridge::modinfo(){
printf("%s is a Intel pcie-pci bridge device\n",getName());
printf("device id <0x%lx>, vendor id <0x%lx>\n",confSpace
->readConf(PCI_CONF_VENID
),\
confSpace
->readConf(PCI_CONF_DEVID
));
printf("it's primary pcie bus is <%s>, secondary pci bus is <%s>\n",busName
,secBusName
);
printf("to display pcie config regs, type \'%s dump\'\n",getName());
pcieToPciBridge::parse_arg(const char *arg
){
if(argval("secbus",arg
,&secBusName
)){
debug_more("%s:secondary bus = %s\n",getName(),secBusName
);
return dev_parse_arg(arg
);
pcieToPciBridge::check_args(){
debug_err("%s: ERROR: must specify a secondary PCI bus\n", getName());
pcieToPciBridge::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;
pcieToPciBridge::map_pin_vpin(int device
, int line
, bool ast
) {
int vpin
= (device
% 4 + line
) % 4;
case 0: return MSG_Assert_INTA
;
case 1: return MSG_Assert_INTB
;
case 2: return MSG_Assert_INTC
;
case 3: return MSG_Assert_INTD
;
case 0: return MSG_Deassert_INTA
;
case 1: return MSG_Deassert_INTB
;
case 2: return MSG_Deassert_INTC
;
case 3: return MSG_Deassert_INTD
;
pcieToPciBridge::busif_interrupt_in(bool set
, mmi_instance_t busMod
, int device
, int line
, SAM_DeviceId
*id
) {
pciExpMsgCode vpin
= map_pin_vpin(device
, line
, set
);
ret
= handleCompletion(assertIntx(vpin
,device
,id
));
ret
= handleCompletion(deassertIntx(vpin
, device
,id
));
debug_err("ERROR: PCI/X device %d, pin %d INT assertion failed!\n", device
, line
);
pcieToPciBridge::busif_free_interrupt(mmi_instance_t busMod
, int dev_number
) {
debug_more("%s: free interrupt\n",getName());
pcieToPciBridge::busif_dma_out(uint64_t vaddr
, void *data
, long count
, mmi_instance_t caller
,uint16_t requesterId
,SAM_DeviceId
*id
) {
int length
= (count
- 1)/4 + 1;
// assume contiguous byte access.
be
= pcie_countToBe(count
);
be
= pcie_countToBe(count
);
if((count
% 4) == 0 ) be
= 0xff;
be
= pcie_countToBe(count
% 4) << 4;
debug_more("%s: busif_dma_out:byte count 0x%llx,pcie tlp length 0x%lx,pcie tlp be 0x%x\n",getName(),count
,length
,be
);
busIf
->busif_access(PCIE_MEM
, true, vaddr
, data
, length
, be
, PCIE_REQUESTER_ID(busIf
->busif_getBusno(),0,0), mem_addr32
,id
);
pcieToPciBridge::busif_dma_in(uint64_t vaddr
, void *data
, long count
, mmi_instance_t caller
,uint16_t requesterId
, SAM_DeviceId
*id
) {
int length
= (count
- 1)/4 + 1;
// assume contiguous byte access.
be
= pcie_countToBe(count
);
be
= pcie_countToBe(count
);
if((count
% 4) == 0 ) be
= 0xff;
be
= pcie_countToBe(count
% 4) << 4;
debug_more("%s: busif_dma_in:bytecount 0x%llx,pcie tlp length 0x%lx,pcie tlp be 0x%x\n",getName(),count
,length
,be
);
busIf
->busif_access(PCIE_MEM
, false, vaddr
, data
, length
, be
, PCIE_REQUESTER_ID(busIf
->busif_getBusno(),0,0) , mem_addr32
,id
);
pcieToPciBridge::busif_add_interrupt(mmi_instance_t busMod
,int device
,int dev_type
, int slot_irl
[],bool isMulti
= false) {
debug_more("%s:ADD INT\n",getName());
/* PCI Express Enhanced Configuration address to conventional PCI
Configuration address translation (type 1 to type 0) */
pcieToPciBridge::pcie_eh1_pci0_translation(uint32_t addr
) {
uint16_t dev_fun
, reg
; uint32_t bus
, ret
;
bus
= addr
>> busShift
& 0xff;
dev_fun
= addr
>> funShift
& 0xff;
ret
= bus
<< 16 | dev_fun
<< 8 | reg
;
pcieToPciBridge::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
+ 1);
case PCI_BCNF_IO_BASE_LOW
:
case PCI_BCNF_IO_LIMIT_LOW
:
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("Bridge remap: IO [%lx %lx]\n", io_base
, io_limit
);
mapSpace(PCIE_IO
, io_base
, io_limit
- io_base
+ 1);
pcieToPciBridge::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
) {
addr
= pcie_eh1_pci0_translation(addr
);
*(uint64_t*)data
&= 0xffffffff;
uint32_t 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 wr xactn type 1: addr <0x%x> size<%d> be<0x%x> data<0x%llx>\n",
getName(), addr
, size
, be
,*(uint64_t*)data
);
status
= secBusIf
->busif_access_w_size(PCI_CFG
, addr
, addr
, wr
, (uint64_t *)data
, size
,id
);
uint32_t 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 rd xactn type 1: addr <0x%x> size<%d> be<0x%x> data<0x%llx>\n",
getName(), addr
, size
, be
, *(uint64_t*)data
);
if(debug_level
>= 2) printf("\n");
return pcieCompleter(SC
,getId());
else if( status
== MASTER_ABORT
)
return pcieCompleter(CA
,getId());
return pcieCompleter(UR
,getId());
*(uint64_t*)data
&= 0xffffffff;
uint32_t 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> be<0x%x> data<0x%llx>\n",
getName(), addr
, size
, be
,*(uint64_t*)data
);
ret
= confSpace
->confAccessSize(addr
, wr
, (uint64_t *)data
, size
);
if(wr
&& debug_level
>= 2) printf("\n");
uint32_t 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> be<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()));
pcieToPciBridge::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
) {
int size
= byteEnabletoSize(be
);
if (addr
>= mem32_base
&& addr
< mem32_limit
|| addr
>= mem64_base
&& addr
< mem64_limit
) {
debug_more("%s downstream wr mem access: addr <0x%x> size<%d> be<0x%x> data<0x%llx>\n",
getName(), addr
, size
, be
, *(uint64_t*)data
);
secBusIf
->busif_access_w_size(mode
== mem_addr64
? PCI_MEM64
: PCI_MEM32
, addr
, addr
, wr
, (uint64_t *)data
, size
,id
);
debug_more("%s downstream rd mem access: addr <0x%x> size<%d> be<0x%x> data<0x%llx>\n",
getName(), addr
, size
, be
, *(uint64_t*)data
);
return pcieCompleter(SC
, getId());
return pcieCompleter(UR
, getId());
pcieToPciBridge::devif_ioAccess(bool wr
, uint64_t addr
, void * data
, uint8_t be
, uint16_t reqId
, \
uint16_t length
, tlp_X args
, SAM_DeviceId
*id
) {
return pcieCompleter(UR
, getId());
pcieToPciBridge::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
){
return pcieCompleter(UR
,getId());
bool pcieToPciBridge::dump (FILE * fp
){
const int bufsize
= 64 * 1024;
char *dumpDir
= DR_get_dir();
bool ret
= genericPcieDev::dump (dumpDir
, getName());
// dump the device numbers of downstream devices
fprintf(fp
,"%s\n",current_dump_version
);
fprintf(fp
,"downstream 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");
bool pcieToPciBridge::restore (FILE * fp
){
const int bufsize
= 64 * 1024;
char *dumpDir
= DR_get_dir();
bool ret
= genericPcieDev::restore (dumpDir
, getName());
// 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
void pcieToPciBridge::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]);