Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / devices / n2_piu / include / sam_piu.h
/*
* ========== Copyright Header Begin ==========================================
*
* OpenSPARC T2 Processor File: sam_piu.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 ============================================
*/
/*
* This is a port from Legions PIU library to SAM, with the intention
* of making as minimal changes as possible to the legion library sources,
* while making it mmi compliant as much as possible.
* Code that is not needed from SAM perspective is deleted.
*/
#include "module.h"
#include "arg.h"
#include "ncu.h"
#include "piu.h"
#include "dr.h"
#include <list>
using namespace std;
extern "C"{
static int access_piu(uint32_t cpuid, void* obj, uint64_t paddr, mmi_bool_t wr, uint32_t size, uint64_t* buf, uint8_t bytemask);
int n2piu_ui_cmd(void*, int argc, char * argv[]);
void samPiu_1ms_callback(void * piuobj, void * );
}
class samPiu:public Module, genericPcieDevIf{
private:
int primary_bus_no;
int secondary_bus_no;
int subordinate_bus_no;
int device;
int function;
const char *bus; // pcie bus name on the downstream
mmi_instance_t busMod; // pcie bus instance
const char * ncu;
mmi_instance_t ncuMod;
pcie_model_t piuModel;
const char * N2_PIU_VERSION;
public:
pcieBusIf *busIf; // pcie bus interface
n2Ncu * ncuIf;
static const uint64_t PIU_CSR_BASE = 0x8800000000;
static const uint64_t PIU_CSR_SIZE = 0x800000; // 8 MB
// this region maps the pcie conf/io/mem32/mem64 regions of
// downstream devices
static const uint64_t PIU_PCIE_BASE = 0xc000000000;
static const uint64_t PIU_PCIE_SIZE = 0x1000000000; // 64 GB
/*
* PIU CSR space allows only r/w's of 8 bytes.
* pcie config/io space allows r/w' s of 1,2,4 bytes.
* pcie mem32/mem64 allows r/w's of 1,2,4,8 bytes along with
* partial writes, which specify a bytemask.
*/
// some useful offsets into PIU_CSR_BASE
static const uint64_t PIU_DMU_PCIE_CONFREG_OFFSET = 0x653100;
public: // genericPcieDevIf
bool devif_isBridge(){ return false; }
bool devif_isRootCmplx(){return true; }
// piu does not support CONFIG access as a target
pcieCompleter devif_confAccess(bool wr, uint32_t offset, void * data, \
uint8_t be, uint16_t reqId, addrMd_xactnType, uint16_t, tlp_X,SAM_DeviceId *id){
return pcieCompleter(CA);
}
// piu does not support IO access as a target
pcieCompleter devif_ioAccess(bool wr, uint32_t addr, void * data,
uint8_t be, uint16_t reqId, uint16_t length , tlp_X args,SAM_DeviceId *id){
return pcieCompleter(CA);
}
int devif_getBusNo(){ return secondary_bus_no; }
int devif_getPriBusNo(){ return primary_bus_no; }
int devif_getSubBusNo() { return subordinate_bus_no; }
int devif_getDevice(){ return device; }
int devif_getFunction(){ return function; }
const char *devif_getName(){ return Module::getName(); }
const char *devif_getBusName(){ return "N2 PIU internal bus"; }
mmi_instance_t devif_getInstance(){ return Module::getInstance(); }
void devif_confAccessCb(bool wr, uint64_t offset, uint8_t be){}
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 *id);
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 *id);
// intr 0-19 are reserved, 20-23 intx, 24-59 ev q, 62 dmu, 63 peu
bool pendingIntr[64];
typedef list<int > intxStatus;
intxStatus intLine[4]; // 4 lists of pending interrupts, 1 for every device from a bus
pthread_mutex_t intxMutex;
pthread_mutex_t pendIntMutex;
pthread_mutex_t piuMutex;
pthread_mutex_t msiMutex[36]; // 36 event queues in total
static const int MONDO_INTA = 20;
pthread_mutex_t ncuMutex;
typedef list<VCPU_InterruptRequest* > irqList;
irqList irql;
uint64_t event_fire_time;
public: // Module interface
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*);
const char *get_version();
public: // others
samPiu(const char *modname, const char *instance_name);
n2Ncu * getNcu(){ return ncuIf; }
uint16_t getReqId(){ return PCIE_REQUESTER_ID(primary_bus_no,device,function); }
void sendMondo(pcie_mondo_t *);
int handlePio(uint32_t cpuid,uint64_t paddr, mmi_bool_t wr, \
uint32_t size, uint64_t* buf, uint8_t bytemask);
bool setPending(int ino, bool set){
pthread_mutex_lock(&pendIntMutex);
bool ret = pendingIntr[ino];
pendingIntr[ino] = set;
pthread_mutex_unlock(&pendIntMutex);
return ret;
}
bool getPending(int ino){
return pendingIntr[ino];
}
void setIntx(int devid,int line, bool set){
//printf("piu intx line %d set to %d\n",line,set);
if(line < 0 || line > 3)
assert(0);
pthread_mutex_lock(&intxMutex);
if(set){
intLine[line].push_back(devid);
intLine[line].sort();
intLine[line].unique();
setPending(line + MONDO_INTA, true);
}else{
intLine[line].remove(devid);
if(intLine[line].empty())
setPending(line + MONDO_INTA, false);
}
pthread_mutex_unlock(&intxMutex);
}
void handle_ui(int argc, char * argv[]);
void ui_cmd_usage(){
printf("ui format: %s <command> <command args> ... \n",getName());
printf("%s supports following UI commands\n",getName());
printf(" dump [<filename>]\n \
dump the CSR contents to \'filename\' \n \
default is stderr\n \
dump format is: <csr name> <csr physical offset> [<csr index> <csr value>,]+\n \
: pending interrupts (msi event q, intx)\n");
printf(" restore <filename>\n\
restore the CSR contents from \'filename\' \n\
restore file format is same as dump file format\n");
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");
}
void samPiu::timer_callback();
bool dump(FILE *fp);
bool restore(FILE *fp);
void dump_piu_csrs(FILE * fp);
void dump_intr(FILE * fp);
void dump_irq(FILE * fp);
void restore_piu_csrs(FILE * fp);
void restore_intr(FILE * fp);
void restore_irq(FILE * fp);
~samPiu(){}
};