* ========== Copyright Header Begin ==========================================
* OpenSPARC T2 Processor File: pci_common.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 ============================================
uint16_t size
; //size of the register
void * data
; //pointer to device. to be
//used by devices providing
//custom read/write for nonstandard conf regs,
//unimplemented, reserved reg etc
bool isHole
; //true for unimplemented registers
pciConfReg(uint16_t sz
= 0x100){
// args (reg name, reg size, por value, write mask, impl. specific data)
pciConfReg(const char * n
,uint16_t sz
, uint32_t v
, uint32_t m
,void * d
= 0){
name
= new char[strlen(n
)+1];
void setDebug(int level
){ debug_level
= level
; }
// devices with different read/write accesses (eg rw1c) should override
// these functions to provide custom behaviour and to implement device
// read 'bytes_to_read/write' bytes starting from 'byte_offset'.
// if the 'size' of register is less than bytes_to_read/write then
// read/write the whole register. return the number
// of bytes read/written.
virtual uint8_t read(uint32_t *buf
, uint8_t bytes_to_read
, uint8_t byte_offset
= 0,uint8_t buf_offset
= 0){
// return the bytes in buf. 'bytes_to_read' bytes are filled in from (char*)buf + buf_offset
// w/0 affecting the other bytes in *buf.
uint8_t bytes_read
= (size
- byte_offset
) >= bytes_to_read
? bytes_to_read
: size
- byte_offset
;
uint64_t byte_mask
= (~ ((uint64_t) -1 << bytes_read
* 8));//eg for bytes_read=1, mask = 0xff
*buf
= (*buf
& ~(byte_mask
<< buf_offset
* 8)) | (val
>> byte_offset
* 8 & byte_mask
) << buf_offset
* 8;
virtual uint8_t write(uint32_t buf
, uint8_t byte_offset
, uint8_t bytes_to_write
){
uint8_t bytes_written
= (size
- byte_offset
) >= bytes_to_write
? bytes_to_write
:size
- byte_offset
;
uint64_t byte_mask
= ~((uint64_t) -1 << bytes_written
* 8);
//reset the writable bits in 'val' to 0, in the range
//val |= val & ~mask & (byte_mask << byte_offset);
val
= val
& ~(mask
& (byte_mask
<< byte_offset
));
val
|= ((buf
& byte_mask
) << byte_offset
* 8) & mask
;
printf("Name<%s>,size<0x%x>mask<0x%lx>value<0x%lx -> 0x%lx>\n",name
,size
,mask
,oldval
,val
);
printf("Hole: size<0x%x>\n",size
);
virtual void setMask(uint32_t m
){mask
= m
;}
virtual uint32_t getMask(){ return mask
;}
virtual void setVal(uint32_t v
){val
= v
;}
printf("Name<%s>,size<0x%x>value<0x%lx>,mask<0x%lx>\n",name
,size
,val
,mask
);
printf("Hole: size<0x%x>\n",size
);
return (mask
== 0) ? true: false;
inline uint32_t getVal(){
uint32_t mask
; //mask for s/w access
// set bit to either 0 or 1, taking into account the s/w mask
virtual bool setBit(uint8_t bit_pos
, uint8_t buf
){
val
|= val
& ~mask
& 1 << bit_pos
;
val
|= mask
& buf
<< bit_pos
;
// set the bit to 1 irrespective of s/w mask.
// to be used by device models when acting from the h/w side
virtual void setBit(uint8_t bit_pos
){
val
|= (uint32_t)1 << bit_pos
;
// reset a bit to 0, overriding the mask
virtual void resetBit(uint8_t bit_pos
){
val
&= ~((uint32_t)1 << bit_pos
);
virtual bool getBit(uint8_t bit_pos
, uint8_t *buf
){
*buf
= val
>> bit_pos
& 0x1;
virtual uint8_t getBit(uint8_t bit_pos
){
return val
>> bit_pos
& 0x1;
// set some bit range, overriding the s/w mask
virtual bool setRange(uint8_t left_bit_pos
, uint8_t right_bit_pos
,uint32_t buf
){
//bits counted from left to right
uint32_t bit_mask
= ((uint32_t)-1 << left_bit_pos
+ 1) ^ ((uint32_t)-1 << right_bit_pos
);
val
|= val
& bit_mask
; //reset the bits to 0
val
|= ((buf
) << right_bit_pos
) & bit_mask
;//fill in the bit field
virtual bool getRange(uint8_t left_bit_pos
, uint8_t right_bit_pos
,uint32_t *buf
){
uint32_t bit_mask
= (uint32_t)-1 << left_bit_pos
^ (uint32_t)-1 << right_bit_pos
;
*buf
= val
>> left_bit_pos
& bit_mask
;
//comparison function (reverse than normal default case)
bool operator()(int key1
, int key2
)const{
map
<int,pciConfReg
*,compare
> pciConfRegMap
; //key is the offset of the register into the conf space
map
<int,pciConfReg
*,compare
>::iterator pciConfIter
;
typedef map
<int,pciConfReg
*,compare
>::iterator iter_t
;
void initConf(confHeaderType
);
bool addConfReg(pciConfReg
* cr
, int offset
);
bool deleteConfReg(int offset
);
bool confAccessSize(int offset
,bool wr
, uint64_t * buf
,uint8_t size
);
bool pciConfSpace::confAccessByteE(int offset
,bool wr
, uint64_t * in_buf
,uint8_t be
);
inline bool setMask(int offset
, uint32_t mask
);
inline bool setVal(int offset
, uint32_t value
);
// return pointer to the configuration register. useful for direct access
// functions like setBit() etc
pciConfReg
*getConfReg(int offset
){
iter_t iter
= pciConfRegMap
.find(offset
);
if(iter
== pciConfRegMap
.end())
else if(iter
->second
->isHole
)
uint32_t readConf(int offset
){
pciConfReg
* reg
= getConfReg(offset
);
pciConfSpace(confHeaderType htype
= pciHeader0
){
pciConfRegMap
[0] = new pciConfReg();
// pcie conf reg map = 0x1000
pciConfSpace(int size
= 0x100){
pciConfRegMap
[0] = new pciConfReg(size
);
for(pciConfIter
= pciConfRegMap
.begin(); pciConfIter
!= pciConfRegMap
.end(); pciConfIter
++){
printf("offset:%x:",pciConfIter
->first
);pciConfIter
->second
->print();
void set_debug_level(int level
){
for(pciConfIter
= pciConfRegMap
.begin(); pciConfIter
!= pciConfRegMap
.end(); pciConfIter
++)
pciConfIter
->second
->setDebug(level
);
#define Here _Here(__FILE__, __LINE__)
void set_debug_level(int n
){debug_l
= n
;}
void Debug_err(const char *fmt
, ...){
vfprintf(stderr
, fmt
, ap
);
void Debug_info(const char *fmt
, ...){
vfprintf(stderr
, fmt
, ap
);
void Debug_more(const char *fmt
, ...){
vfprintf(stderr
, fmt
, ap
);
_Here(const char *f
, int n
){
const char *p
= strrchr(f
, '/');
snprintf(herebuf
, sizeof herebuf
, "%s(L%d)",p
?(p
+1):f
, n
);
#endif // __PCI_COMMON_H__