Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / devices / schizo / include / schizo_module.h
/*
* ========== Copyright Header Begin ==========================================
*
* OpenSPARC T2 Processor File: schizo_module.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 ============================================
*/
/*
* Copyright 2004 by Sun Microsystems, Inc.
* All rights reserved.
*
* W% 04/08/04
*/
#ifndef _SCHIZO_MODULE_H
#define _SCHIZO_MODULE_H
#include <assert.h>
#include <strings.h>
#include "pci.h"
#include "pci_dev.h"
#include "mmi.h"
#include "module.h"
#include "schizo_impl.h"
extern devRegistry * samDevs;
#define MAX_SCHIZO_DEVICES 10 // 8 devices, pciA, pciB
#define V4_MAX_SCHIZO_DEVICES 64
#define LO_U32(x) ((uint32_t)((uint32_t *)&(x))[1])
#define HI_U32(x) ((uint32_t)((uint32_t *)&(x))[0])
#define swap_hword(value) \
(((value) & 0xff) << 8 | (value) >> 8)
#define swap_word(value) \
((uint32_t)swap_hword((uint16_t)((value) & 0xffff)) << 16 | \
(uint32_t)swap_hword((uint16_t)((value) >> 16)))
#define swap_lword(value) \
((uint64_t)swap_word(LO_U32(value)) << 32 | \
(uint64_t)swap_word(HI_U32(value)))
#define NUM_PAIRS 8
#define NID(X) ((X & 0x3e0) >> 5)
typedef struct {uint64_t addr, value;} addr_val_pair;
typedef enum {LEAFA, LEAFB, NLEAF} leaf_t;
typedef struct pci_info {
const char *name;
mmi_instance_t bus;
pciBusIf *busif;
uint64_t base, size, mask;
pci_space_t space;
leaf_t leaf;
} pci_info_t;
class schizoPciDev;
//structure to map pci devices to interrupt number.
//each PCI device is allocated 4 interrupts, based
//upon the slot from 0-31. The other interrupts are
//reserved for Schizo internal interrupts, OBIO and
//new link.
struct pciDevIntrInfo{
mmi_instance_t busMod; //module pointer of bus on which device is attached
uint8_t devNum; //sysconf device argument of device
uint8_t devType; //type of device eg network etc
};
extern "C" int schizo_access (uint32_t cpu_id, void* obj, uint64_t paddr, mmi_bool_t wr, uint32_t size, uint64_t* buf,uint8_t bytemask=PHYSIO_BYTEMASK_ALL);
extern "C" int pci_access (uint32_t cpu_id, void* obj, uint64_t paddr, mmi_bool_t wr, uint32_t size, uint64_t* buf, uint8_t bytemask=PHYSIO_BYTEMASK_ALL);
class Schizo : public Module, pciBridgeIf {
private:
const char *pciA, *pciB;
pci_info_t pci_info[NLEAF][PCI_NSPACES];
uint64_t cpuPaddr;
int aid;
static const uint64_t IO_SPACE_ADDR = 0x40000000000ULL;
static const uint64_t PCI_CONF_IO_ADDR =0x40200000000ULL;
static const uint64_t PCI_IO_ADDR_OFFSET = 0x1000000ULL;
static const uint64_t PCI_MEM_ADDR = 0x40400000000ULL;
static const int NUM_ENTRIES = 16; // number of TLB/TSB entries in Schizo
int boot_flag;
schizo_structT* msp;
bool retDevIntfA;
schizoPciDev * pciDevA;
schizoPciDev * pciDevB;
pciDevIntrInfo pciIntrInfo[V4_MAX_SCHIZO_DEVICES];
char fkPromBus_A_Str[7];
char fkPromBus_B_Str[7];
addr_val_pair av_pairs[NUM_PAIRS];
private:
bool dump(FILE *);
bool restore(FILE *);
bool restore_v4(FILE *);
bool restore_v5(FILE *);
void init_msp();
void init_mdu_regs();
void init_regs();
void init_pci();
void destroy_pci();
int rd_wr_mdu_reg(uint32_t paddr, uint64_t* buf, bool_t wr);
Register_set regs_range(uint64_t phy_addr);
Address_space calc_range(uint64_t *pyaddr);
Safari_space get_range(uint64_t *pyaddr);
int access_schizo_internals(uint32_t cpu_id, uint64_t paddr, bool_t wr, uint32_t, uint64_t *buf,SAM_DeviceId * samId);
int range_scsrbase(uint64_t paddr, bool_t wr, uint64_t *buf);
int range_pci_a_csrbase(uint32_t cpu_id, uint64_t paddr, bool_t wr, uint64_t *buf);
int range_pci_b_csrbase(uint32_t cpu_id, uint64_t paddr, bool_t wr, uint64_t *buf);
int rd_wr_stc_b_diags(uint32_t paddr, uint64_t* buf, bool_t wr);
int rd_wr_stc_a_diags(uint32_t paddr, uint64_t* buf, bool_t wr);
// mmu a
public:
uint64_t a_iommu_va2pa(int isRead, uint64_t vaddr);
private:
bool_t a_flush_entry(uint32_t vaddr);
void a_flush_entries(uint32_t context);
bool_t a_iommu_match(Tlb_entry_t* entry, uint32_t vaddr);
int a_get_lru_entry();
uint64_t a_calc_tsb_ptr( uint32_t vaddr);
bool_t a_schizo_iommu_lookup(uint32_t vaddr);
bool_t a_schizo_iommu_load_tte_tlb(uint32_t vaddr, uint64_t tte_entry);
uint64_t a_translate_to_paddr(uint32_t vaddr);
uint64_t a_vaddr2paddr(uint32_t vaddr, Tlb_entry_t* line);
void a_update_lru_status(int num);
int a_rd_wr_iommu_diags(uint32_t paddr, uint64_t* buf, bool_t wr);
bool_t a_check_all_used();
uint64_t a_compare_entry(uint32_t vpn);
bool_t a_any_match(Tlb_entry_t* entry, uint32_t vpn);
// mmu b
public:
uint64_t b_iommu_va2pa(int isRead, uint64_t vaddr);
private:
bool_t b_flush_entry(uint32_t vaddr);
void b_flush_entries(uint32_t context);
bool_t b_iommu_match(Tlb_entry_t* entry, uint32_t vaddr);
int b_get_lru_entry();
uint64_t b_calc_tsb_ptr( uint32_t vaddr);
bool_t b_schizo_iommu_lookup(uint32_t vaddr);
bool_t b_schizo_iommu_load_tte_tlb(uint32_t vaddr, uint64_t tte_entry);
uint64_t b_translate_to_paddr(uint32_t vaddr);
uint64_t b_vaddr2paddr(uint32_t vaddr, Tlb_entry_t* line);
void b_update_lru_status(int num);
int b_rd_wr_iommu_diags(uint32_t paddr, uint64_t* buf, bool_t wr);
bool_t b_check_all_used();
uint64_t b_compare_entry(uint32_t vpn);
bool_t b_any_match(Tlb_entry_t* entry, uint32_t vpn);
static const uint64_t ULL(int n) { return (uint64_t)(n); };
static const uint64_t KB(int n) { return 1024ULL * ULL(n); };
static const uint64_t MB(int n) { return (1024ULL * KB(n)); };
static const uint64_t GB(int n) { return (1024ULL * MB(n)); };
static const uint64_t BIT(int n) { return 1ULL << (n); };
static const int LO(uint64_t n) { return (int)n; };
static const int HI(uint64_t n) { return (int)(n >> 32); };
static const int FFS(uint64_t n) { return n ? (LO(n) ? ffs(LO(n)) : (32 + ffs(HI(n)))) : 0; };
friend int schizo_access(uint32_t cpu_id, void* obj, uint64_t paddr, mmi_bool_t wr, uint32_t size, uint64_t* buf,uint8_t bytemask);
friend int pci_access(uint32_t cpu_id, void* obj, uint64_t paddr, mmi_bool_t wr, uint32_t size, uint64_t* buf, uint8_t bytemask);
int access_memory_controllers(uint32_t cpu_id, uint64_t paddr, bool_t wr, uint32_t, uint64_t *buf);
void map_pci(leaf_t leaf, pci_space_t, uint64_t , uint64_t ,uint64_t);
void unmap_pci(leaf_t leaf, pci_space_t);
void send_mondo_intr(uint64_t mondo, uint32_t dev_type, uint32_t dev_id);
int Schizo::interrupt_deassert(int indx);
public:
Schizo(const char *modname, const char *instance_name);
~Schizo();
public:
int busif_add_interrupt(mmi_instance_t busMod,int device,int dev_type, int slot_irl[], bool isMulti);
int busif_free_interrupt(mmi_instance_t busMod, int dev_number);
int busif_interrupt_in(bool set,mmi_instance_t busMod, int device, int line, SAM_DeviceId *id);
int busif_dma_out(uint64_t vaddr, void *data, long count, mmi_instance_t caller,uint16_t requesterId,SAM_DeviceId *id);
int busif_dma_in(uint64_t vaddr, void *data, long count, mmi_instance_t caller,uint16_t requesterId, SAM_DeviceId *id);
// override the pciTargetIf functions. they do nothing in schizo impl. and should be never called
pciXactnStatus pciTarget_mem32access(uint64_t offset, bool wr,uint64_t * buf, uint8_t size){return SIM_INTERNAL_ERROR;}
pciXactnStatus pciTarget_mem64access(uint64_t offset, bool wr,uint64_t * buf, uint8_t size){return SIM_INTERNAL_ERROR;}
pciXactnStatus pciTarget_ioaccess(uint64_t offset, bool wr,uint64_t * buf, uint8_t size){return SIM_INTERNAL_ERROR;}
pciXactnStatus pciTarget_special_cycle(uint16_t mssg, uint16_t data){return SIM_INTERNAL_ERROR;}
pciXactnStatus pciTarget_intr_ack(uint64_t *data){return SIM_INTERNAL_ERROR;}
// the bus number is hardwired in schizo to 0
int busif_get_secondary_busno(){return 0;}
public: // Module interface
void record_mapping(uint64_t, uint64_t);
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*);
void get_dev_props();
static void swapBuf(int size, uint64_t *buf);
#ifndef V5_FAKEPROM
int getStartInterruptIndex(mmi_instance_t busMod, int devNum);
#endif
};
//schizo appears as device 0 function 0 on the
//pci buses it controls.
class schizoPciDev:public genericPciDevIf{
uint8_t deviceNumber;
uint8_t functionNumber;
const char *busName;
bool isBusA;
Schizo* schizo;
pciConfSpace * confSpace;
public:
const char *devif_getBusName(){return busName;}
int devif_getDevice(){return deviceNumber;}
int devif_getFunction(){return functionNumber;}
mmi_instance_t devif_getInstance(){return schizo->getInstance();}
const char *devif_getName(){return schizo->getName();}
pciXactnStatus devif_access_w_byte_enable(pci_space_t, uint64_t paddr, uint64_t offset, bool_t wr, uint64_t* buf, uint8_t byte_enable,SAM_DeviceId * id){
if(id) *id = schizo->samId;
return MASTER_ABORT;
}
pciXactnStatus devif_special_cycle(uint16_t mssg, uint16_t data){
return MASTER_ABORT;
}
pciXactnStatus devif_intr_ack(uint64_t * data){
return MASTER_ABORT;
}
pciXactnStatus devif_access_w_size(pci_space_t space, uint64_t paddr, uint64_t offset, bool_t wr, uint64_t* buf, uint8_t size,SAM_DeviceId * id){
if(id) *id = schizo->samId;
confSpace->confAccessSize(offset,wr,buf,size);
if(space == PCI_CFG)
return SUCCESS;
else
return MASTER_ABORT;
}
schizoPciDev(Schizo * ptr,const char * bus_name, bool bus){
schizo = ptr;
deviceNumber = 0;
functionNumber = 0;
busName = strdup(bus_name);
isBusA = bus;
confSpace = new pciConfSpace(pciHeaderNull);
initPci(isBusA);
};
private:
void initPci(bool bus){
char reg_descr[100];
snprintf(reg_descr,100,"%s-%s Vendor ID", devif_getName(),busName);
confSpace->addConfReg(new pciConfReg(reg_descr, 2,0x108e,0x0,0x0),PCI_CONF_VENID);//0x108e, ro
snprintf(reg_descr,100,"%s-%s Device ID", devif_getName(),busName);
confSpace->addConfReg(new pciConfReg(reg_descr, 2,0x8001,0x0,0x0),PCI_CONF_DEVID); //0x8001, ro
snprintf(reg_descr,100,"%s-%s command reg", devif_getName(),busName);
confSpace->addConfReg(new pciCommandReg(reg_descr,(genericPciDev*)this,0x140,0x6),PCI_CONF_COMM);// write mask = 0x140
snprintf(reg_descr,100,"%s-%s status reg", devif_getName(),busName);
confSpace->addConfReg(new pciStatusReg(reg_descr,(genericPciDev*)this,bus?0x280:0x2a0,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 class",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,0x0,0x0),PCI_CONF_SUBCLASS);//0x00, 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 latency timer",devif_getName(),busName);
confSpace->addConfReg(new pciConfReg(reg_descr,1,0x0,0xf8),PCI_CONF_LATENCY_TIMER);//0x00,
snprintf(reg_descr,100,"%s-%s Header type",devif_getName(),busName);
confSpace->addConfReg(new pciConfReg(reg_descr,1,0x00,0x00),PCI_CONF_HEADER); //0x00,ro
snprintf(reg_descr,100,"%s-%s Bus number",devif_getName(),busName);
confSpace->addConfReg(new pciConfReg(reg_descr,1,0x00,0xff),0x40); //0x00, rw
snprintf(reg_descr,100,"%s-%s Subordinate bus number",devif_getName(),busName);
confSpace->addConfReg(new pciConfReg(reg_descr,1,0x00,0xff),0x41); //0x00, rw
}
};
#endif /* _SCHIZO_MODULE_H */