* ========== Copyright Header Begin ==========================================
* OpenSPARC T2 Processor File: pcie_bridge.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 ============================================
#define BRIDGE_POWER_CAP_ADDR 0x40
#define BRIDGE_MSI_CAP_ADDR 0x48
#define BRIDGE_PCIE_CAP_ADDR 0x68
#define BRIDGE_DEV_SERNUM_XCAP_ADDR 0x100
#define SERNUM_VER_NXTPTR_OFFSET 2
#define SERNUM_SN_LOW_OFFSET 4
#define SERNUM_SN_HIGH_OFFSET 8
#define BRIDGE_ADV_ERR_CAP_ADDR 0xfb4
#define BRIDGE_PWRBGT_HDR_ADDR 0x138
#define PWRBGT_DSEL_OFFSET 4
#define PWRBGT_DATA_OFFSET 8
#define PWRBGT_DATA_CAP_OFFSET 0xc
class PcieBridge
: public genericPcieDev
, public Module
{
// pcieBridgeIf is exported to the downstream pcie Bus.
pcieBusIf
*secBusIf
; // pcie bus intf on the secondary interface
// pcie bus intf on the primary side is member of genericPcieDev
uint64_t mem64_base
, mem64_limit
;
uint32_t mem32_base
, mem32_limit
, io_base
, io_limit
;
enum direction_t
{downstream
, upstream
, peer
};
direction_t
direction(int BusNo
, uint16_t reqId
) {
uint16_t reqBus
= reqId
>> 8;
if (reqId
== 0 || reqBus
< BusNo
)
fprintf(stderr
, "Peer request ID %x\n", reqId
);
bool io_mapped() {return bCR
->io_mapped();}
bool mem_mapped() {return bCR
->mem_mapped();}
typedef std::list
<int > intxStatus
;
intxStatus intLine
[4]; // 4 lists of pending Intx interrupts,
// indexed with INT[A|B|C|D] type.
// For an upstream port -
// it holds the downstream port number of
// For a downstream port it holds the dev #
// An assert Intx message adds the port/dev
// # entry to this list, a deassert removes
// it. As long as there is an entry, an Intx
// message is pended to upstream bridge,
// otherwise a deassertIntx is send.
pthread_mutex_t intMutex
;
// route the received Intx message to upstream bridge.
pcieCompleter
assertIntx(pciExpMsgCode messageCode
, uint16_t reqId
,SAM_DeviceId
*id
){
uint16_t port_dev
= reqId
& 0xff;
// include both the dev and fun values
assert(messageCode
>= MSG_Assert_INTA
&& messageCode
<= MSG_Assert_INTD
);
int line
= upstream_port
? ( (port_dev
>> 3 & 0x1f ) %4 + (messageCode
- MSG_Assert_INTA
)) % 4 : \
messageCode
- MSG_Assert_INTA
;
pthread_mutex_lock(&intMutex
);
intLine
[line
].push_back(port_dev
);
debug_more("%s: asserting Intr%c from dev <%d> fun <%d> - Line already asserted\n",getName(),'A' + line
, reqId
>> 3 & 0x1f, reqId
& 0x7 );
pthread_mutex_unlock(&intMutex
);
return pcieCompleter(SC
,getId());
pendingIntr
[line
] = true;
pthread_mutex_unlock(&intMutex
);
debug_more("%s: asserting Intr%c from dev <%d> fun <%d>\n",getName(),'A' + line
, reqId
>> 3 & 0x1f, reqId
& 0x7 );
uint8_t code
= line
+ MSG_Assert_INTA
;
msgRouting r
= msgDB
->msgCode2Routing((pciExpMsgCode
)code
);
return busIf
->busif_msgAccess(code
, r
, getId(),id
);
pcieCompleter
deassertIntx(pciExpMsgCode messageCode
, uint16_t reqId
, SAM_DeviceId
*id
){
uint16_t port_dev
= reqId
& 0xff;
// include both the dev and fun values
assert(messageCode
>= MSG_Deassert_INTA
&& messageCode
<= MSG_Deassert_INTD
);
int line
= upstream_port
? ( (port_dev
>> 3 & 0x1f ) %4 + (messageCode
- MSG_Deassert_INTA
)) % 4 : \
messageCode
- MSG_Deassert_INTA
;
pthread_mutex_lock(&intMutex
);
intLine
[line
].remove(port_dev
);
if(!intLine
[line
].empty()){
debug_more("%s: Deasserting Intr%c from dev <%d> fun <%d> - Line still asserted\n",getName(),'A' + line
, reqId
>> 3 & 0x1f, reqId
& 0x7 );
pthread_mutex_unlock(&intMutex
);
return pcieCompleter(SC
,getId());
pendingIntr
[line
] = false;
pthread_mutex_unlock(&intMutex
);
debug_more("%s: Deasserting Intr%c from dev <%d> fun <%d>\n",getName(),'A' + line
, reqId
>> 3 & 0x1f, reqId
& 0x7 );
uint8_t code
= line
+ MSG_Deassert_INTA
;
msgRouting r
= msgDB
->msgCode2Routing((pciExpMsgCode
)code
);
return busIf
->busif_msgAccess(code
, r
, getId(),id
);
const char * dump_version1_0
;
const char * current_dump_version
;
bool devif_isBridge(){return true;}
PcieBridge(const char* modname
, const char * instance_name
);
bool downstream_request(uint16_t reqId
);
mmi_instance_t
devif_getInstance() {return Module::instance
;}
const char *devif_getName() {return Module::getName();}
void devif_confAccessCb(bool wr
, uint64_t offset
, uint8_t be
=0xf);
bool parse_arg(const char *);
void module_added(mmi_instance_t
, const char*);
void module_deleted(mmi_instance_t
, const char*);
void *get_interface(const char*);
// genericPcieDev virtual/unimplemented functions
// or functions that need to be overridden eg
// devif_memAccess, devif_ioAccess, etc.
pcieCompleter
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
*samId
);
pcieCompleter
devif_confAccess(bool wr
, uint32_t offset
, void * data
, \
uint8_t be
,uint16_t reqId
, addrMd_xactnType tType
, uint16_t length
, tlp_X args
,SAM_DeviceId
*samId
);
pcieCompleter
devif_ioAccess(bool wr
, uint64_t addr
, void * data
, uint8_t be
, \
uint16_t reqId
, uint16_t length
, tlp_X args
,SAM_DeviceId
*samId
);
pcieCompleter
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
*samId
);
int devif_getPriBusNo() {return (confSpace
->readConf(PCI_BCNF_PRIBUS
) & 0xff);}
int devif_getBusNo() {return (confSpace
->readConf(PCI_BCNF_SECBUS
) & 0xff);}
int devif_getSubBusNo() {return (confSpace
->readConf(PCI_BCNF_SUBBUS
) & 0xff);}
void handle_ui(int, char**);
printf("ui format: %s <command> <command args> ... \n",getName());
printf("%s supports following UI commands\n",getName());
printf(" debug [<level>]\n\
set the debug level for debug prints to \'level\'\n\
if \'level\' not provided, print current debug level\n\
printf(" dump [<filename>]\n \
dump the PCIE CSR contents to <filename>.pci in cwd\n \
dump format is: <csr pciconf offset> <csr value> <csr r/w mask> <csr size> <csr name>\n");
printf(" restore <filename>\n\
restore the PCIE CSR contents from <filename>.pci in cwd \n\
restore file format is same as dump file format\n");