Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / devices / pcie_bridge / include / pcie_bridge.h
/*
* ========== 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 ============================================
*/
#ifndef _PCIE_BRIDGE_
#define _PCIE_BRIDGE_
#include "pci.h"
#include "pcie.h"
#include "dr.h"
#include "pci_common.h"
#include "pci_bridge.h"
#include "arg.h"
#include <errno.h>
#include <unistd.h>
#include <list>
#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
const char * secBusName;
// 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;
bool upstream_port;
enum direction_t {downstream, upstream, peer};
direction_t direction(int BusNo, uint16_t reqId) {
uint16_t reqBus = reqId >> 8;
if (reqId == 0 || reqBus < BusNo)
return downstream;
else if (reqBus > BusNo)
return upstream;
else {
fprintf(stderr, "Peer request ID %x\n", reqId);
return peer;
}
}
bridgeCommandReg * bCR;
bool io_mapped() {return bCR->io_mapped();}
bool mem_mapped() {return bCR->mem_mapped();}
bool pendingIntr[4];
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
// the asserting port.
// 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);
intLine[line].sort();
intLine[line].unique();
if(pendingIntr[line]){
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;
public:
bool devif_isBridge(){return true;}
PcieBridge(const char* modname, const char * instance_name);
~PcieBridge();
void initPci();
void init_regs();
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);
// Module functions
const char *get_help();
bool parse_arg(const char *);
bool check_args();
void init_done();
void module_added(mmi_instance_t, const char*);
void module_deleted(mmi_instance_t, const char*);
void modinfo();
void *get_interface(const char*);
bool dump(FILE* fp);
bool restore(FILE* fp);
// 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**);
void ui_cmd_usage(){
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\
\'level\' = [0|1|2]\n");
printf(" dump [<filename>]\n \
dump the PCIE CSR contents to <filename>.pci in cwd\n \
default is stderr\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");
}
};
#endif