diff --git a/devices/common/pci/bandit.cpp b/devices/common/pci/bandit.cpp index 133568e..32813e9 100644 --- a/devices/common/pci/bandit.cpp +++ b/devices/common/pci/bandit.cpp @@ -60,28 +60,38 @@ Bandit::Bandit(int bridge_num, std::string name) : MMIODevice(), PCIHost() uint32_t Bandit::read(uint32_t reg_start, uint32_t offset, int size) { - int dev_num, dev_fn; - uint8_t reg_offs; - uint32_t result; + int fun_num; + uint8_t reg_offs; + uint32_t result, idsel; if (offset & BANDIT_CONFIG_SPACE) { if (offset & 0x00400000) { // access to the CONFIG_DATA pseudo-register causes a Config Cycle - if (this->config_addr & BANDIT_DEV_NUM) { // access to myself - result = this->pci_cfg_read(this->config_addr & 0xFFU, size); - } else { - dev_num = this->config_addr >> 12; - dev_fn = this->config_addr >> 8; - reg_offs = this->config_addr & 0xFFU; + if (this->config_addr & BANDIT_CAR_TYPE) { + LOG_F(WARNING, "%s: config cycle type 1 not supported yet", this->name.c_str()); + return 0; + } - if (this->dev_map.count(dev_num)) { - result = this->dev_map[dev_num]->pci_cfg_read(reg_offs, size); + idsel = (this->config_addr >> 11) & 0x1FFFFFU; + fun_num = (this->config_addr >> 8) & 7; + reg_offs = this->config_addr & 0xFCU; + + if (!SINGLE_BIT_SET(idsel)) { + LOG_F(ERROR, "%s: invalid IDSEL=0x%X passed", this->name.c_str(), idsel); + return 0; + } + + if (idsel == BANDIT_ID_SEL) { // access to myself + result = this->pci_cfg_read(reg_offs, size); + } else { + if (this->dev_map.count(idsel)) { + result = this->dev_map[idsel]->pci_cfg_read(reg_offs, size); } else { LOG_F( ERROR, "%s err: read attempt from non-existing PCI device %d \n", this->name.c_str(), - dev_num); + idsel); result = 0; } } @@ -96,32 +106,43 @@ uint32_t Bandit::read(uint32_t reg_start, uint32_t offset, int size) void Bandit::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size) { - int dev_num, dev_fn; - uint8_t reg_offs; + int fun_num; + uint8_t reg_offs; + uint32_t idsel; if (offset & BANDIT_CONFIG_SPACE) { if (offset & 0x00400000) { // access to the CONFIG_DATA pseudo-register causes a Config Cycle - if (this->config_addr & BANDIT_DEV_NUM) { // access to myself - this->pci_cfg_write(this->config_addr & 0xFFU, value, size); + if (this->config_addr & BANDIT_CAR_TYPE) { + LOG_F(WARNING, "%s: config cycle type 1 not supported yet", this->name.c_str()); return; } - dev_num = this->config_addr >> 12; - dev_fn = this->config_addr >> 8; - reg_offs = this->config_addr & 0xFFU; + idsel = (this->config_addr >> 11) & 0x1FFFFFU; + fun_num = (this->config_addr >> 8) & 7; + reg_offs = this->config_addr & 0xFCU; - if (this->dev_map.count(dev_num)) { - this->dev_map[dev_num]->pci_cfg_write(reg_offs, value, size); + if (!SINGLE_BIT_SET(idsel)) { + LOG_F(ERROR, "%s: invalid IDSEL=0x%X passed", this->name.c_str(), idsel); + return; + } + + if (idsel == BANDIT_ID_SEL) { // access to myself + this->pci_cfg_write(reg_offs, value, size); + return; + } + + if (this->dev_map.count(idsel)) { + this->dev_map[idsel]->pci_cfg_write(reg_offs, value, size); } else { LOG_F( ERROR, "%s err: write attempt to non-existing PCI device %d \n", this->name.c_str(), - dev_num); + idsel); } } else { - this->config_addr = BYTESWAP_32(value) & 0x3FFFFF; + this->config_addr = BYTESWAP_32(value); } } else { // I/O space access LOG_F(WARNING, "%s: I/O space write not implemented yet", this->name.c_str()); diff --git a/devices/common/pci/bandit.h b/devices/common/pci/bandit.h index 6ceaae8..cd0f597 100644 --- a/devices/common/pci/bandit.h +++ b/devices/common/pci/bandit.h @@ -36,8 +36,12 @@ along with this program. If not, see . #include #include -#define BANDIT_DEV_NUM (1 << 11) -#define BANDIT_CONFIG_SPACE 0x00800000 +#define BANDIT_ID_SEL (1 << 0) // Bandit's own IDSEL +#define BANDIT_CAR_TYPE (1 << 0) // Bandit config address type bit +#define BANDIT_CONFIG_SPACE 0x00800000 // Bandit Config Space bit + +/** checks if one bit is set at time, return 0 if not */ +#define SINGLE_BIT_SET(val) ((val) && !((val) & ((val)-1))) class Bandit : public MMIODevice, public PCIHost {//}, public PCIDevice { public: