* ========== 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.
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 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
{
uint64_t base
, size
, mask
;
//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
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
{
pci_info_t pci_info
[NLEAF
][PCI_NSPACES
];
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
pciDevIntrInfo pciIntrInfo
[V4_MAX_SCHIZO_DEVICES
];
addr_val_pair av_pairs
[NUM_PAIRS
];
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
);
uint64_t a_iommu_va2pa(int isRead
, uint64_t vaddr
);
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
);
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
);
uint64_t b_iommu_va2pa(int isRead
, uint64_t vaddr
);
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
);
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
);
Schizo(const char *modname
, const char *instance_name
);
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);
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*);
static void swapBuf(int size
, uint64_t *buf
);
int getStartInterruptIndex(mmi_instance_t busMod
, int devNum
);
//schizo appears as device 0 function 0 on the
class schizoPciDev
:public genericPciDevIf
{
pciConfSpace
* confSpace
;
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
;
pciXactnStatus
devif_special_cycle(uint16_t mssg
, uint16_t data
){
pciXactnStatus
devif_intr_ack(uint64_t * data
){
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
);
schizoPciDev(Schizo
* ptr
,const char * bus_name
, bool bus
){
busName
= strdup(bus_name
);
confSpace
= new pciConfSpace(pciHeaderNull
);
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 */