* ========== Copyright Header Begin ==========================================
* OpenSPARC T2 Processor File: pci_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 ============================================
// this file contains register definitions of some
// registers found in type 1 header of pci/pcie bridge.
#define swap_hword(value) \
((uint32_t)(((value) & 0xff) << 8 | (value) >> 8))
#define swap_word(value) \
((uint32_t)((Word)swap_hword((HWord)((value) & 0xffff)) << 16 | \
(Word)swap_hword((HWord)((value) >> 16))))
#define swap_lword(value) \
((uint64_t)((((LWord)swap_word(LO_W(value))) << 32) | \
((LWord)swap_word(HI_W(value)))))
// some macros originally defined in pcie-pci bridge code
#define GET_IO_BASE(cfg_space) ( (cfg_space->readConf(PCI_BCNF_IO_BASE_HI) << 16) | \
(cfg_space->readConf(PCI_BCNF_IO_BASE_LOW) >> 4 << 12))
#define GET_IO_LIMIT(cfg_space) ( (cfg_space->readConf(PCI_BCNF_IO_LIMIT_HI) << 16) | \
((cfg_space->readConf(PCI_BCNF_IO_LIMIT_LOW) >> 4 << 12) | 0xfff))
#define GET_PF_MEM_BASE(cfg_space) ((uint64_t)cfg_space->readConf(PCI_BCNF_PF_BASE_HIGH) << 32) | \
(cfg_space->readConf(PCI_BCNF_PF_BASE_LOW) >> 4 << 20)
#define GET_PF_MEM_LIMIT(cfg_space) ((( (uint64_t)cfg_space->readConf(PCI_BCNF_PF_LIMIT_HIGH) << 32) | \
(cfg_space->readConf(PCI_BCNF_PF_LIMIT_LOW) >> 4 << 20)) | 0xfffff)
#define GET_MEM_BASE(cfg_space) cfg_space->readConf(PCI_BCNF_MEM_BASE) >> 4 << 20
#define GET_MEM_LIMIT(cfg_space) ((cfg_space->readConf(PCI_BCNF_MEM_LIMIT) >> 4 << 20) | 0xfffff)
class bridgeCommandReg
:public pciConfReg
{
enum commandRegBits
{IO_SPACE
= 0, MEM_SPACE
= 1, BUS_MASTER
= 2};
enum space_type
{IO
= 0, MEM
= 1, PREFETCH_MEM
= 2};
bool io_enabled
, mem_enabled
;
void enable_io() {io_enabled
= true;}
void enable_mem() {mem_enabled
= true;}
void disable_io() {io_enabled
= false;}
void disable_mem() {mem_enabled
= false;}
void check_map(space_type spt
, uint64_t base
, uint64_t limit
, bool isMap
) {
fprintf(stderr
, "%s: %s %llx %llx\n", isMap
? "Map" : "Unmap",
(spt
== MEM
? "PCIE MEM" : "PCIE PREFETCHABLE MEM"), base
, limit
);
assert(((genericPcieDev
*)data
)->mapSpace(PCIE_IO
, base
, limit
- base
+ 1));
assert(((genericPcieDev
*)data
)->unmapSpace(PCIE_IO
, base
));
assert(((genericPcieDev
*)data
)->mapSpace(PCIE_MEM
, base
, limit
- base
+ 1));
assert(((genericPcieDev
*)data
)->unmapSpace(PCIE_MEM
, base
));
void mapSpace(pcie_space spc
, bool isMap
){
uint64_t base
, limit
, up_base
, up_limit
;
base
= GET_IO_BASE(((genericPcieDev
*)data
)->confSpace
);
limit
= GET_IO_LIMIT(((genericPcieDev
*)data
)->confSpace
);
check_map(IO
, base
, limit
, isMap
);
base
= GET_PF_MEM_BASE(((genericPcieDev
*)data
)->confSpace
);
limit
= GET_PF_MEM_LIMIT(((genericPcieDev
*)data
)->confSpace
);
check_map(PREFETCH_MEM
, base
, limit
, isMap
);
base
= GET_MEM_BASE(((genericPcieDev
*)data
)->confSpace
);
limit
= GET_MEM_LIMIT(((genericPcieDev
*)data
)->confSpace
);
check_map(MEM
, base
, limit
, isMap
);
bridgeCommandReg(const char * name
, genericPcieDev
* d
, uint16_t write_mask
,uint16_t val
=0):pciConfReg(name
,2,val
,write_mask
& 0x547, (void *)d
)
printf("Bridge command reg constructor error: must provide genericPcieDev device pointer\n");
io_enabled
= mem_enabled
= false;
bool io_mapped() {return io_enabled
;}
bool mem_mapped() {return mem_enabled
;}
uint8_t write(uint32_t buf
, uint8_t byte_offset
, uint8_t bytes_to_write
) {
buf
&= ~((int32_t)-1 << (ret
<< 3));
uint32_t new_val
= val
| (mask
& buf
);
uint32_t changed_bits
= new_val
^ val
;
printf("Name<%s>,size<0x%x>mask<0x%lx>value<0x%lx -> 0x%lx>\n",name
,size
,mask
,val
,new_val
);
if(changed_bits
& 1 << IO_SPACE
){ //I/O space map bit has changed
if(val
& 1 << IO_SPACE
) { //bit set to 1
} else if (io_mapped()) { //bit set to 0
mapSpace(PCIE_IO
, false);
if(changed_bits
& 1 << MEM_SPACE
){
if(val
& 1 << MEM_SPACE
){ //bit set to 1
mapSpace(PCIE_MEM
, true);
}else if (mem_mapped()) {
mapSpace(PCIE_MEM
, false);
class pciSecondaryStatusReg
:public pciConfReg
{
MASTER_DATA_PARITY_ERR
= 8,
SIGNALED_TARGET_ABORT
= 11,
MEDIUM_DEVSEL_TIMING
= 1,
pciSecondaryStatusReg(uint16_t por_val
= 0x0, uint16_t mask
= 0xf900, \
void * d
= 0, const char * name
= "pciSecStatReg")
:pciConfReg(name
, 2, por_val
, mask
, d
){}
uint8_t write(uint32_t buf
, uint8_t byte_offset
, uint8_t bytes_to_write
){
assert(bytes_to_write
== 2);
// if fails, write a more generic function in here.
buf
&= mask
; // 0 out the ro bits if any in buf
buf
= ~buf
; // flip the 0's to 1's and vice versa
val
&= buf
; // and with val so that bits set to 1 are turned off
// bits written to with 0 are unaffected.
printf("Name<%s>,size<0x%x>mask<0x%lx>value<0x%lx -> 0x%lx>\n",name
,size
,mask
,oldval
,val
);
class pciBridgeControlReg
:public pciConfReg
{
PARITY_ERROR_RESPONSE_EN
= 0,
FAST_BACK_TO_BACK_EN
= 7,
PRIMARY_DISCARD_TIMER
= 8,
SECONDARY_DISCARD_TIMER
= 9,
DISCARD_TIMER_STATUS
= 10, // RW1C bit
DISCARD_TIMER_ERR_EN
= 11
pciBridgeControlReg(uint16_t por_val
= 0x0, uint16_t mask
= 0xeff, \
void * d
= 0, const char * name
= "pciBridgeCtrlReg")
:pciConfReg(name
, 2, por_val
, mask
, d
){}
uint8_t write(uint32_t buf
, uint8_t byte_offset
, uint8_t bytes_to_write
){
uint32_t bit10_in_buf
= buf
& 1 << DISCARD_TIMER_STATUS
;
uint32_t bit10_in_val
= val
& 1 << DISCARD_TIMER_STATUS
;
pciConfReg::write(buf
,byte_offset
,bytes_to_write
);
if((bytes_to_write
> 1) && bit10_in_buf
&& bit10_in_val
)
val
&= ~((uint32_t)1 << DISCARD_TIMER_STATUS
);
printf("Name<%s>,size<0x%x>mask<0x%lx>value<0x%lx -> 0x%lx>\n",name
,size
,mask
,oldval
,val
);
#endif// __PCI_BRIDGE_H__