Revert "PCI fixes"

This commit is contained in:
Maxim Poliakovski 2022-09-02 23:24:06 +00:00 committed by GitHub
parent 467e4df7dc
commit 3a5c61797c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 159 additions and 309 deletions

View File

@ -81,27 +81,15 @@ uint32_t Bandit::pci_cfg_read(uint32_t reg_offs, uint32_t size)
if (reg_offs < 64) { if (reg_offs < 64) {
return PCIDevice::pci_cfg_read(reg_offs, size); return PCIDevice::pci_cfg_read(reg_offs, size);
} }
uint32_t offset = reg_offs & 3;
reg_offs &= ~3;
if (~-size & offset) {
LOG_F(
WARNING, "%s: unaligned read @%02x.%c",
this->name.c_str(), reg_offs + offset,
size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size
);
}
if (reg_offs == BANDIT_ADDR_MASK) { switch (reg_offs) {
return pci_cfg_rev_read(this->addr_mask, offset, size); case BANDIT_ADDR_MASK:
return BYTESWAP_32(this->addr_mask);
default:
LOG_F(WARNING, "%s: reading from unimplemented config register at 0x%X",
this->pci_name.c_str(), reg_offs);
} }
LOG_F(
WARNING, "%s: reading from unimplemented config register @%02x.%c",
this->name.c_str(), reg_offs + offset,
size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size
);
return 0; return 0;
} }
@ -112,27 +100,15 @@ void Bandit::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size)
return; return;
} }
uint32_t offset = reg_offs & 3; switch (reg_offs) {
reg_offs &= ~3; case BANDIT_ADDR_MASK:
if (~-size & offset) { this->addr_mask = BYTESWAP_32(value);
LOG_F(
WARNING, "%s: unaligned write @%02x.%c = %0*x",
this->name.c_str(), reg_offs + offset,
size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size, size * 2, flip_sized(value, size)
);
}
if (reg_offs == BANDIT_ADDR_MASK) {
this->addr_mask = pci_cfg_rev_write(this->addr_mask, offset, size, value);
this->verbose_address_space(); this->verbose_address_space();
return; break;
default:
LOG_F(WARNING, "%s: writing to unimplemented config register at 0x%X",
this->pci_name.c_str(), reg_offs);
} }
LOG_F(
WARNING, "%s: writing to unimplemented config register @%02x.%c = %0*x",
this->name.c_str(), reg_offs + offset,
size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size, size * 2, flip_sized(value, size)
);
} }
uint32_t Bandit::read(uint32_t rgn_start, uint32_t offset, int size) uint32_t Bandit::read(uint32_t rgn_start, uint32_t offset, int size)
@ -171,10 +147,10 @@ uint32_t Bandit::read(uint32_t rgn_start, uint32_t offset, int size)
} }
if (idsel == BANDIT_ID_SEL) { // access to myself if (idsel == BANDIT_ID_SEL) { // access to myself
result = this->pci_cfg_read(reg_offs + (offset & 3), size); result = this->pci_cfg_read(reg_offs, size);
} else { } else {
if (this->dev_map.count(idsel)) { if (this->dev_map.count(idsel)) {
result = this->dev_map[idsel]->pci_cfg_read(reg_offs + (offset & 3), size); result = this->dev_map[idsel]->pci_cfg_read(reg_offs, size);
} else { } else {
dev_num = WHAT_BIT_SET(idsel) + 11; dev_num = WHAT_BIT_SET(idsel) + 11;
LOG_F( LOG_F(
@ -220,7 +196,7 @@ void Bandit::write(uint32_t rgn_start, uint32_t offset, uint32_t value, int size
LOG_F( LOG_F(
WARNING, "%s: write config cycle type 1 not supported yet %02x:%02x.%x @%02x.%c = %0*x", WARNING, "%s: write config cycle type 1 not supported yet %02x:%02x.%x @%02x.%c = %0*x",
this->name.c_str(), bus_num, dev_num, fun_num, reg_offs + (offset & 3), this->name.c_str(), bus_num, dev_num, fun_num, reg_offs + (offset & 3),
size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size, size * 2, flip_sized(value, size) size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size, size * 2, value
); );
return; return;
} }
@ -232,24 +208,24 @@ void Bandit::write(uint32_t rgn_start, uint32_t offset, uint32_t value, int size
ERROR, "%s: write invalid IDSEL=0x%X config:0x%X ??:??.%x? @%02x?.%c = %0*x", ERROR, "%s: write invalid IDSEL=0x%X config:0x%X ??:??.%x? @%02x?.%c = %0*x",
this->name.c_str(), idsel, this->config_addr, this->name.c_str(), idsel, this->config_addr,
fun_num, reg_offs + (offset & 3), fun_num, reg_offs + (offset & 3),
size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size, size * 2, flip_sized(value, size) size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size, size * 2, value
); );
return; return;
} }
if (idsel == BANDIT_ID_SEL) { // access to myself if (idsel == BANDIT_ID_SEL) { // access to myself
this->pci_cfg_write(reg_offs + (offset & 3), value, size); this->pci_cfg_write(reg_offs, value, size);
return; return;
} }
if (this->dev_map.count(idsel)) { if (this->dev_map.count(idsel)) {
this->dev_map[idsel]->pci_cfg_write(reg_offs + (offset & 3), value, size); this->dev_map[idsel]->pci_cfg_write(reg_offs, value, size);
} else { } else {
dev_num = WHAT_BIT_SET(idsel) + 11; dev_num = WHAT_BIT_SET(idsel) + 11;
LOG_F( LOG_F(
ERROR, "%s err: write attempt to non-existing PCI device ??:%02x.%x @%02x.%c = %0*x", ERROR, "%s err: write attempt to non-existing PCI device ??:%02x.%x @%02x.%c = %0*x",
this->name.c_str(), dev_num, fun_num, reg_offs + (offset & 3), this->name.c_str(), dev_num, fun_num, reg_offs + (offset & 3),
size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size, size * 2, flip_sized(value, size) size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size, size * 2, value
); );
} }
} else { } else {
@ -344,7 +320,7 @@ uint32_t Chaos::read(uint32_t rgn_start, uint32_t offset, int size)
} }
if (this->dev_map.count(idsel)) { if (this->dev_map.count(idsel)) {
result = this->dev_map[idsel]->pci_cfg_read(reg_offs + (offset & 3), size); result = this->dev_map[idsel]->pci_cfg_read(reg_offs, size);
} else { } else {
dev_num = WHAT_BIT_SET(idsel) + 11; dev_num = WHAT_BIT_SET(idsel) + 11;
LOG_F( LOG_F(
@ -382,7 +358,7 @@ void Chaos::write(uint32_t rgn_start, uint32_t offset, uint32_t value, int size)
LOG_F( LOG_F(
WARNING, "%s: write config cycle type 1 not supported yet %02x:%02x.%x @%02x.%c = %0*x", WARNING, "%s: write config cycle type 1 not supported yet %02x:%02x.%x @%02x.%c = %0*x",
this->name.c_str(), bus_num, dev_num, fun_num, reg_offs + (offset & 3), this->name.c_str(), bus_num, dev_num, fun_num, reg_offs + (offset & 3),
size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size, size * 2, flip_sized(value, size) size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size, size * 2, value
); );
return; return;
} }
@ -394,19 +370,19 @@ void Chaos::write(uint32_t rgn_start, uint32_t offset, uint32_t value, int size)
ERROR, "%s: write invalid IDSEL=0x%X config:0x%X ??:??.%x? @%02x?.%c = %0*x", ERROR, "%s: write invalid IDSEL=0x%X config:0x%X ??:??.%x? @%02x?.%c = %0*x",
this->name.c_str(), idsel, this->config_addr, this->name.c_str(), idsel, this->config_addr,
fun_num, reg_offs + (offset & 3), fun_num, reg_offs + (offset & 3),
size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size, size * 2, flip_sized(value, size) size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size, size * 2, value
); );
return; return;
} }
if (this->dev_map.count(idsel)) { if (this->dev_map.count(idsel)) {
this->dev_map[idsel]->pci_cfg_write(reg_offs + (offset & 3), value, size); this->dev_map[idsel]->pci_cfg_write(reg_offs, value, size);
} else { } else {
dev_num = WHAT_BIT_SET(idsel) + 11; dev_num = WHAT_BIT_SET(idsel) + 11;
LOG_F( LOG_F(
ERROR, "%s err: write attempt to non-existing VCI device ??:%02x.%x @%02x.%c = %0*x", ERROR, "%s err: write attempt to non-existing VCI device ??:%02x.%x @%02x.%c = %0*x",
this->name.c_str(), dev_num, fun_num, reg_offs + (offset & 3), this->name.c_str(), dev_num, fun_num, reg_offs + (offset & 3),
size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size, size * 2, flip_sized(value, size) size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size, size * 2, value
); );
} }
} else { } else {

View File

@ -52,16 +52,6 @@ uint32_t PCIDevice::pci_cfg_read(uint32_t reg_offs, uint32_t size)
{ {
uint32_t result; uint32_t result;
uint32_t offset = reg_offs & 3;
reg_offs &= ~3;
if (~-size & offset) {
LOG_F(
WARNING, "%s: unaligned read @%02x.%c",
this->pci_name.c_str(), reg_offs + offset,
size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size
);
}
switch (reg_offs) { switch (reg_offs) {
case PCI_CFG_DEV_ID: case PCI_CFG_DEV_ID:
result = (this->device_id << 16) | (this->vendor_id); result = (this->device_id << 16) | (this->vendor_id);
@ -99,32 +89,31 @@ uint32_t PCIDevice::pci_cfg_read(uint32_t reg_offs, uint32_t size)
default: default:
LOG_F( LOG_F(
WARNING, "%s: attempt to read from reserved/unimplemented register @%02x.%c", WARNING, "%s: attempt to read from reserved/unimplemented register @%02x.%c",
this->pci_name.c_str(), reg_offs + offset, this->pci_name.c_str(), reg_offs,
size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size
); );
return 0; return 0;
} }
return pci_cfg_rev_read(result, offset, size); if (size == 4) {
return BYTESWAP_32(result);
} else {
return read_mem_rev(((uint8_t *)&result) + (reg_offs & 3), size);
}
} }
void PCIDevice::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size) void PCIDevice::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size)
{ {
uint32_t data; uint32_t data;
uint32_t offset = reg_offs & 3; if (size == 4) {
reg_offs &= ~3; data = BYTESWAP_32(value);
if (~-size & offset) { } else {
LOG_F( // get current register content as DWORD and update it partially
WARNING, "%s: unaligned write @%02x.%c = %0*x", data = BYTESWAP_32(this->pci_cfg_read(reg_offs, 4));
this->pci_name.c_str(), reg_offs + offset, write_mem_rev(((uint8_t *)&data) + (reg_offs & 3), value, size);
size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size, size * 2, flip_sized(value, size)
);
} }
// get current register content as DWORD and update it partially
data = pci_cfg_rev_write(size == 4 ? 0 : BYTESWAP_32(this->pci_cfg_read(reg_offs, 4)), offset, size, value);
switch (reg_offs) { switch (reg_offs) {
case PCI_CFG_STAT_CMD: case PCI_CFG_STAT_CMD:
this->pci_wr_stat(data >> 16); this->pci_wr_stat(data >> 16);
@ -148,10 +137,10 @@ void PCIDevice::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size)
} }
break; break;
case PCI_CFG_ROM_BAR: case PCI_CFG_ROM_BAR:
if ((data & this->exp_bar_cfg) == this->exp_bar_cfg) { if (data == 0xFFFFF800UL) {
this->exp_rom_bar = (data & (this->exp_bar_cfg | 1)); this->exp_rom_bar = this->exp_bar_cfg;
} else { } else {
this->exp_rom_bar = (data & (this->exp_bar_cfg | 1)); this->exp_rom_bar = (data & 0xFFFFF801UL);
if (this->exp_rom_bar & 1) { if (this->exp_rom_bar & 1) {
this->map_exp_rom_mem(); this->map_exp_rom_mem();
} else { } else {
@ -167,7 +156,7 @@ void PCIDevice::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size)
LOG_F( LOG_F(
WARNING, "%s: attempt to write to reserved/unimplemented register @%02x.%c = %0*x", WARNING, "%s: attempt to write to reserved/unimplemented register @%02x.%c = %0*x",
this->pci_name.c_str(), reg_offs, this->pci_name.c_str(), reg_offs,
size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size, size * 2, flip_sized(value, size) size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size, size * 2, value
); );
} }
} }
@ -254,7 +243,7 @@ void PCIDevice::set_bar_value(int bar_num, uint32_t value)
{ {
uint32_t bar_cfg = this->bars_cfg[bar_num]; uint32_t bar_cfg = this->bars_cfg[bar_num];
if (bar_cfg & 1) { if (bar_cfg & 1) {
this->bars[bar_num] = (value & 0xFFFFFFFCUL) | (bar_cfg & 3); this->bars[bar_num] = (value & 0xFFFFFFFCUL) | 1;
} else { } else {
if (bar_cfg & 6) { if (bar_cfg & 6) {
ABORT_F("Invalid or unsupported PCI space type: %d", (bar_cfg >> 1) & 3); ABORT_F("Invalid or unsupported PCI space type: %d", (bar_cfg >> 1) & 3);
@ -268,7 +257,7 @@ void PCIDevice::map_exp_rom_mem()
{ {
uint32_t rom_addr, rom_size; uint32_t rom_addr, rom_size;
rom_addr = this->exp_rom_bar & this->exp_bar_cfg; rom_addr = this->exp_rom_bar & 0xFFFFF800UL;
rom_size = ~this->exp_bar_cfg + 1; rom_size = ~this->exp_bar_cfg + 1;
if (!this->exp_rom_addr || this->exp_rom_addr != rom_addr) { if (!this->exp_rom_addr || this->exp_rom_addr != rom_addr) {

View File

@ -64,7 +64,7 @@ static FlopImgType identify_image(std::ifstream& img_file)
} }
} }
return FlopImgType::RAW; return FlopImgType::UNKNOWN;
} }
static int64_t get_hfs_vol_size(const uint8_t *mdb_data) static int64_t get_hfs_vol_size(const uint8_t *mdb_data)
@ -133,16 +133,17 @@ int RawFloppyImg::calc_phys_params()
} else if (buf[0] == 0xD2 && buf[1] == 0xD7) { } else if (buf[0] == 0xD2 && buf[1] == 0xD7) {
// check MFS volume size // check MFS volume size
} else { } else {
LOG_F(WARNING, "RawFloppyImg: unknown volume type!"); LOG_F(ERROR, "RawFloppyImg: unknown volume type!");
return -1;
} }
if (vol_size && (vol_size > this->img_size)) { if (vol_size > this->img_size) {
LOG_F(INFO, "RawFloppyImg: volume size > image size!"); LOG_F(INFO, "RawFloppyImg: volume size > image size!");
LOG_F(INFO, "Volume size: %llu, Image size: %d", vol_size, this->img_size); LOG_F(INFO, "Volume size: %llu, Image size: %d", vol_size, this->img_size);
return -1; return -1;
} }
// raw images don't include anything other than raw disk data // raw images don't include anything than raw disk data
this->data_size = this->img_size; this->data_size = this->img_size;
// guess disk format from image file size // guess disk format from image file size

View File

@ -89,7 +89,7 @@ uint32_t MPC106::read(uint32_t rgn_start, uint32_t offset, int size) {
} else { } else {
if (offset >= 0x200000) { if (offset >= 0x200000) {
if (this->config_addr & 0x80) // process only if bit E (enable) is set if (this->config_addr & 0x80) // process only if bit E (enable) is set
return pci_read(offset & 3, size); return pci_read(size);
} }
} }
@ -113,39 +113,39 @@ void MPC106::write(uint32_t rgn_start, uint32_t offset, uint32_t value, int size
this->config_addr = value; this->config_addr = value;
} else { } else {
if (this->config_addr & 0x80) // process only if bit E (enable) is set if (this->config_addr & 0x80) // process only if bit E (enable) is set
return pci_write(offset & 3, value, size); return pci_write(value, size);
} }
} }
} }
uint32_t MPC106::pci_read(uint32_t offset, uint32_t size) { uint32_t MPC106::pci_read(uint32_t size) {
int bus_num, dev_num, fun_num, reg_offs; int bus_num, dev_num, fun_num, reg_offs;
bus_num = (this->config_addr >> 8) & 0xFF; bus_num = (this->config_addr >> 8) & 0xFF;
dev_num = (this->config_addr >> 19) & 0x1F; dev_num = (this->config_addr >> 19) & 0x1F;
fun_num = (this->config_addr >> 16) & 0x07; fun_num = (this->config_addr >> 16) & 0x07;
reg_offs = (this->config_addr >> 24) & 0xFC; reg_offs = (this->config_addr >> 24) & 0xFC;
if (bus_num) { if (bus_num) {
LOG_F( LOG_F(
ERROR, ERROR,
"%s err: read attempt from non-local PCI bus, config_addr = %x, offset = %x %02x:%02x.%x @%02x.%c", "%s err: read attempt from non-local PCI bus, config_addr = %x %02x:%02x.%x @%02x.%c",
this->name.c_str(), this->config_addr, offset, bus_num, dev_num, fun_num, reg_offs, this->name.c_str(), this->config_addr, bus_num, dev_num, fun_num, reg_offs,
size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size
); );
return 0xFFFFFFFFUL; // PCI spec §6.1 return 0xFFFFFFFFUL; // PCI spec §6.1
} }
if (dev_num == 0 && fun_num == 0) { // dev_num 0 is assigned to myself if (dev_num == 0 && fun_num == 0) { // dev_num 0 is assigned to myself
return this->pci_cfg_read(reg_offs + offset, size); return this->pci_cfg_read(reg_offs, size);
} else { } else {
if (this->dev_map.count(dev_num)) { if (this->dev_map.count(dev_num)) {
return this->dev_map[dev_num]->pci_cfg_read(reg_offs + offset, size); return this->dev_map[dev_num]->pci_cfg_read(reg_offs, size);
} else { } else {
LOG_F( LOG_F(
ERROR, ERROR,
"%s err: read attempt from non-existing PCI device %02x:%02x.%x @%02x.%c", "%s err: read attempt from non-existing PCI device %02x:%02x.%x @%02x.%c",
this->name.c_str(), bus_num, dev_num, fun_num, reg_offs + offset, this->name.c_str(), bus_num, dev_num, fun_num, reg_offs,
size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size
); );
return 0xFFFFFFFFUL; // PCI spec §6.1 return 0xFFFFFFFFUL; // PCI spec §6.1
@ -155,10 +155,10 @@ uint32_t MPC106::pci_read(uint32_t offset, uint32_t size) {
return 0; return 0;
} }
void MPC106::pci_write(uint32_t offset, uint32_t value, uint32_t size) { void MPC106::pci_write(uint32_t value, uint32_t size) {
int bus_num, dev_num, fun_num, reg_offs; int bus_num, dev_num, fun_num, reg_offs;
bus_num = (this->config_addr >> 8) & 0xFF; bus_num = (this->config_addr >> 8) & 0xFF;
dev_num = (this->config_addr >> 19) & 0x1F; dev_num = (this->config_addr >> 19) & 0x1F;
fun_num = (this->config_addr >> 16) & 0x07; fun_num = (this->config_addr >> 16) & 0x07;
reg_offs = (this->config_addr >> 24) & 0xFC; reg_offs = (this->config_addr >> 24) & 0xFC;
@ -166,26 +166,26 @@ void MPC106::pci_write(uint32_t offset, uint32_t value, uint32_t size) {
if (bus_num) { if (bus_num) {
LOG_F( LOG_F(
ERROR, ERROR,
"%s err: write attempt to non-local PCI bus, config_addr = %x, offset = %x %02x:%02x.%x @%02x.%c = %0*x", "%s err: write attempt to non-local PCI bus, config_addr = %x %02x:%02x.%x @%02x.%c = %0*x",
this->name.c_str(), this->config_addr, offset, bus_num, dev_num, fun_num, reg_offs + offset, this->name.c_str(), this->config_addr, bus_num, dev_num, fun_num, reg_offs,
size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size, size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size,
size * 2, flip_sized(value, size) size * 2, value
); );
return; return;
} }
if (dev_num == 0 && fun_num == 0) { // dev_num 0 is assigned to myself if (dev_num == 0 && fun_num == 0) { // dev_num 0 is assigned to myself
this->pci_cfg_write(reg_offs + offset, value, size); this->pci_cfg_write(reg_offs, value, size);
} else { } else {
if (this->dev_map.count(dev_num)) { if (this->dev_map.count(dev_num)) {
this->dev_map[dev_num]->pci_cfg_write(reg_offs + offset, value, size); this->dev_map[dev_num]->pci_cfg_write(reg_offs, value, size);
} else { } else {
LOG_F( LOG_F(
ERROR, ERROR,
"%s err: write attempt to non-existing PCI device %02x:%02x.%x @%02x.%c = %0*x", "%s err: write attempt to non-existing PCI device %02x:%02x.%x @%02x.%c = %0*x",
this->name.c_str(), bus_num, dev_num, fun_num, reg_offs + offset, this->name.c_str(), bus_num, dev_num, fun_num, reg_offs,
size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size, size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size,
size * 2, flip_sized(value, size) size * 2, value
); );
} }
} }
@ -200,17 +200,7 @@ uint32_t MPC106::pci_cfg_read(uint32_t reg_offs, uint32_t size) {
return PCIDevice::pci_cfg_read(reg_offs, size); return PCIDevice::pci_cfg_read(reg_offs, size);
} }
uint32_t offset = reg_offs & 3; return read_mem(&this->my_pci_cfg_hdr[reg_offs], size);
reg_offs &= ~3;
if (~-size & offset) {
LOG_F(
WARNING, "%s: unaligned read @%02x.%c",
this->pci_name.c_str(), reg_offs + offset,
size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size
);
}
return pci_cfg_rev_read(READ_DWORD_LE_A(&this->my_pci_cfg_hdr[reg_offs]), offset, size);
} }
void MPC106::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size) { void MPC106::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size) {
@ -223,20 +213,9 @@ void MPC106::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size) {
return; return;
} }
uint32_t offset = reg_offs & 3;
reg_offs &= ~3;
if (~-size & offset) {
LOG_F(
WARNING, "%s: unaligned write @%02x.%c = %0*x",
this->pci_name.c_str(), reg_offs + offset,
size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size, size * 2, flip_sized(value, size)
);
}
// FIXME: implement write-protection for read-only registers // FIXME: implement write-protection for read-only registers
uint32_t *addr = (uint32_t *)&this->my_pci_cfg_hdr[reg_offs]; write_mem(&this->my_pci_cfg_hdr[reg_offs], value, size);
WRITE_DWORD_LE_A(addr, pci_cfg_rev_write(READ_DWORD_LE_A(addr), offset, size, value));
if (this->my_pci_cfg_hdr[0xF2] & 8) { if (this->my_pci_cfg_hdr[0xF2] & 8) {
#ifdef MPC106_DEBUG #ifdef MPC106_DEBUG

View File

@ -59,8 +59,8 @@ public:
protected: protected:
/* PCI access */ /* PCI access */
uint32_t pci_read(uint32_t offset, uint32_t size); uint32_t pci_read(uint32_t size);
void pci_write(uint32_t offset, uint32_t value, uint32_t size); void pci_write(uint32_t value, uint32_t size);
/* my own PCI configuration registers access */ /* my own PCI configuration registers access */
uint32_t pci_cfg_read(uint32_t reg_offs, uint32_t size); uint32_t pci_cfg_read(uint32_t reg_offs, uint32_t size);

View File

@ -167,25 +167,11 @@ uint32_t ATIRage::pci_cfg_read(uint32_t reg_offs, uint32_t size)
return PCIDevice::pci_cfg_read(reg_offs, size); return PCIDevice::pci_cfg_read(reg_offs, size);
} }
uint32_t offset = reg_offs & 3;
reg_offs &= ~3;
if (~-size & offset) {
LOG_F(
WARNING, "%s: unaligned read @%02x.%c",
this->pci_name.c_str(), reg_offs + offset,
size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size
);
}
switch (reg_offs) { switch (reg_offs) {
case 0x40: case 0x40:
return pci_cfg_rev_read(this->user_cfg, offset, size); return this->user_cfg;
default: default:
LOG_F( LOG_F(WARNING, "ATIRage: reading from unimplemented config register at 0x%X", reg_offs);
WARNING, "%s: reading from unimplemented config register @%02x.%c",
this->pci_name.c_str(), reg_offs + offset,
size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size
);
} }
return 0; return 0;
@ -195,29 +181,14 @@ void ATIRage::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size)
{ {
if (reg_offs < 64) { if (reg_offs < 64) {
PCIDevice::pci_cfg_write(reg_offs, value, size); PCIDevice::pci_cfg_write(reg_offs, value, size);
return; } else {
} switch (reg_offs) {
case 0x40:
uint32_t offset = reg_offs & 3; this->user_cfg = value;
reg_offs &= ~3; break;
if (~-size & offset) { default:
LOG_F( LOG_F(WARNING, "ATIRage: writing to unimplemented config register at 0x%X", reg_offs);
WARNING, "%s: unaligned write @%02x.%c = %0*x", }
this->pci_name.c_str(), reg_offs + offset,
size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size, size * 2, flip_sized(value, size)
);
}
switch (reg_offs) {
case 0x40:
this->user_cfg = pci_cfg_rev_write(this->user_cfg, offset, size, value);
break;
default:
LOG_F(
WARNING, "%s: writing to unimplemented config register @%02x.%c = %0*x",
this->pci_name.c_str(), reg_offs + offset,
size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size, size * 2, flip_sized(value, size)
);
} }
} }

View File

@ -59,7 +59,6 @@ ControlVideo::ControlVideo()
this->vendor_id = PCI_VENDOR_APPLE; this->vendor_id = PCI_VENDOR_APPLE;
this->device_id = 3; this->device_id = 3;
this->class_rev = 0; this->class_rev = 0;
this->bars_cfg[0] = 0xFFFFFFFFUL; // I/O region (4 bytes but it's weird because bit 1 is set)
this->bars_cfg[1] = 0xFFFFF000UL; // base address for the HW registers (4KB) this->bars_cfg[1] = 0xFFFFF000UL; // base address for the HW registers (4KB)
this->bars_cfg[2] = 0xFC000000UL; // base address for the VRAM (64MB) this->bars_cfg[2] = 0xFC000000UL; // base address for the VRAM (64MB)
@ -85,10 +84,6 @@ ControlVideo::ControlVideo()
void ControlVideo::notify_bar_change(int bar_num) void ControlVideo::notify_bar_change(int bar_num)
{ {
switch (bar_num) { switch (bar_num) {
case 0:
this->io_base = this->bars[bar_num] & ~3;
LOG_F(INFO, "Control: I/O space address set to 0x%08X", this->io_base);
break;
case 1: case 1:
if (this->regs_base != (this->bars[bar_num] & 0xFFFFFFF0UL)) { if (this->regs_base != (this->bars[bar_num] & 0xFFFFFFF0UL)) {
this->regs_base = this->bars[bar_num] & 0xFFFFFFF0UL; this->regs_base = this->bars[bar_num] & 0xFFFFFFF0UL;
@ -121,22 +116,18 @@ uint32_t ControlVideo::read(uint32_t rgn_start, uint32_t offset, int size)
} }
} }
if (rgn_start == this->regs_base) { switch (offset >> 4) {
switch (offset >> 4) { case ControlRegs::TEST:
case ControlRegs::TEST: result = this->test;
result = this->test; break;
break; case ControlRegs::MON_SENSE:
case ControlRegs::MON_SENSE: result = this->cur_mon_id << 6;
result = this->cur_mon_id << 6; break;
break; default:
default: LOG_F(INFO, "read from 0x%08X:0x%08X", rgn_start, offset);
LOG_F(INFO, "read from 0x%08X:0x%08X", rgn_start, offset);
}
return BYTESWAP_32(result);
} }
return 0; return BYTESWAP_32(result);
} }
void ControlVideo::write(uint32_t rgn_start, uint32_t offset, uint32_t value, int size) void ControlVideo::write(uint32_t rgn_start, uint32_t offset, uint32_t value, int size)
@ -150,77 +141,75 @@ void ControlVideo::write(uint32_t rgn_start, uint32_t offset, uint32_t value, in
return; return;
} }
if (rgn_start == this->regs_base) { value = BYTESWAP_32(value);
value = BYTESWAP_32(value);
switch (offset >> 4) { switch (offset >> 4) {
case ControlRegs::VFPEQ: case ControlRegs::VFPEQ:
case ControlRegs::VFP: case ControlRegs::VFP:
case ControlRegs::VAL: case ControlRegs::VAL:
case ControlRegs::VBP: case ControlRegs::VBP:
case ControlRegs::VBPEQ: case ControlRegs::VBPEQ:
case ControlRegs::VSYNC: case ControlRegs::VSYNC:
case ControlRegs::VHLINE: case ControlRegs::VHLINE:
case ControlRegs::PIPED: case ControlRegs::PIPED:
case ControlRegs::HPIX: case ControlRegs::HPIX:
case ControlRegs::HFP: case ControlRegs::HFP:
case ControlRegs::HAL: case ControlRegs::HAL:
case ControlRegs::HBWAY: case ControlRegs::HBWAY:
case ControlRegs::HSP: case ControlRegs::HSP:
case ControlRegs::HEQ: case ControlRegs::HEQ:
case ControlRegs::HLFLN: case ControlRegs::HLFLN:
case ControlRegs::HSERR: case ControlRegs::HSERR:
this->swatch_params[(offset >> 4) - 1] = value; this->swatch_params[(offset >> 4) - 1] = value;
break; break;
case ControlRegs::TEST: case ControlRegs::TEST:
if (this->test != value) { if (this->test != value) {
if ((this->test & ~TEST_STROBE) != (value & ~TEST_STROBE)) { if ((this->test & ~TEST_STROBE) != (value & ~TEST_STROBE)) {
this->test = value; this->test = value;
this->test_shift = 0; this->test_shift = 0;
LOG_F(9, "New TEST value: 0x%08X", this->test); LOG_F(9, "New TEST value: 0x%08X", this->test);
} else { } else {
LOG_F(9, "TEST strobe bit flipped, new value: 0x%08X", value); LOG_F(9, "TEST strobe bit flipped, new value: 0x%08X", value);
this->test = value; this->test = value;
if (++this->test_shift >= 3) { if (++this->test_shift >= 3) {
LOG_F(9, "Received TEST reg value: 0x%08X", this->test & ~TEST_STROBE); LOG_F(9, "Received TEST reg value: 0x%08X", this->test & ~TEST_STROBE);
if ((this->test ^ this->prev_test) & 0x400) { if ((this->test ^ this->prev_test) & 0x400) {
if (this->test & 0x400) { if (this->test & 0x400) {
this->disable_display(); this->disable_display();
} else { } else {
this->enable_display(); this->enable_display();
}
this->prev_test = this->test;
} }
this->prev_test = this->test;
} }
} }
} }
break;
case ControlRegs::GBASE:
this->fb_base = value;
break;
case ControlRegs::ROW_WORDS:
this->row_words = value;
break;
case ControlRegs::MON_SENSE:
LOG_F(9, "Control: monitor sense written with 0x%X", value);
value = (value >> 3) & 7;
this->cur_mon_id = this->display_id->read_monitor_sense(value & 7, value ^ 7);
break;
case ControlRegs::ENABLE:
this->flags = value;
break;
case ControlRegs::GSC_DIVIDE:
this->clock_divider = value;
break;
case ControlRegs::REFRESH_COUNT:
LOG_F(INFO, "Control: refresh count set to 0x%08X", value);
break;
case ControlRegs::INT_ENABLE:
this->int_enable = value;
break;
default:
LOG_F(INFO, "write 0x%08X to 0x%08X:0x%08X", value, rgn_start, offset);
} }
break;
case ControlRegs::GBASE:
this->fb_base = value;
break;
case ControlRegs::ROW_WORDS:
this->row_words = value;
break;
case ControlRegs::MON_SENSE:
LOG_F(9, "Control: monitor sense written with 0x%X", value);
value = (value >> 3) & 7;
this->cur_mon_id = this->display_id->read_monitor_sense(value & 7, value ^ 7);
break;
case ControlRegs::ENABLE:
this->flags = value;
break;
case ControlRegs::GSC_DIVIDE:
this->clock_divider = value;
break;
case ControlRegs::REFRESH_COUNT:
LOG_F(INFO, "Control: refresh count set to 0x%08X", value);
break;
case ControlRegs::INT_ENABLE:
this->int_enable = value;
break;
default:
LOG_F(INFO, "write 0x%08X to 0x%08X:0x%08X", value, rgn_start, offset);
} }
} }

View File

@ -117,7 +117,6 @@ private:
std::unique_ptr<uint8_t[]> vram_ptr; std::unique_ptr<uint8_t[]> vram_ptr;
uint32_t vram_size; uint32_t vram_size;
uint32_t io_base = 0;
uint32_t vram_base = 0; uint32_t vram_base = 0;
uint32_t regs_base = 0; uint32_t regs_base = 0;
uint32_t prev_test = 0x433; uint32_t prev_test = 0x433;

View File

@ -177,60 +177,6 @@ inline uint32_t read_mem_rev(const uint8_t* buf, uint32_t size) {
} }
} }
/* value is dword from PCI config. MSB..LSB of value is stored in PCI config as 0:LSB..3:MSB.
result is part of value at byte offset from LSB and size bytes (with wrap around) and flipped as required for pci_cfg_read result. */
inline uint32_t pci_cfg_rev_read(uint32_t value, uint32_t offset, uint32_t size) {
switch (size << 2 | offset) {
case 0x04: return value & 0xff; // 0
case 0x05: return (value >> 8) & 0xff; // 1
case 0x06: return (value >> 16) & 0xff; // 2
case 0x07: return (value >> 24) & 0xff; // 3
case 0x08: return ((value & 0xff) << 8) | ((value >> 8) & 0xff); // 0 1
case 0x09: return ( value & 0xff00) | ((value >> 16) & 0xff); // 1 2
case 0x0a: return ((value >> 8) & 0xff00) | ((value >> 24) & 0xff); // 2 3
case 0x0b: return ((value >> 16) & 0xff00) | ( value & 0xff); // 3 0
case 0x10: return ((value & 0xff) << 24) | ((value & 0xff00) << 8) | ((value >> 8) & 0xff00) | ((value >> 24) & 0xff); // 0 1 2 3
case 0x11: return ((value & 0xff00) << 16) | ( value & 0xff0000) | ((value >> 16) & 0xff00) | ( value & 0xff); // 1 2 3 0
case 0x12: return ((value & 0xff0000) << 8) | ((value >> 8) & 0xff0000) | ((value & 0xff) << 8) | ((value >> 8) & 0xff); // 2 3 0 1
case 0x13: return ( value & 0xff000000) | ((value & 0xff) << 16) | ( value & 0xff00) | ((value >> 16) & 0xff); // 3 0 1 2
default: LOG_F(ERROR, "pci_cfg_rev: invalid offset %d for size %d!", offset, size); return 0xffffffff;
}
}
/* value is dword from PCI config. MSB..LSB of value (3.2.1.0) is stored in PCI config as 0:LSB..3:MSB.
data is flipped bytes (d0.d1.d2.d3, as passed to pci_cfg_write) to be merged into value.
result is part of value at byte offset from LSB and size bytes (with wrap around) modified by data. */
inline uint32_t pci_cfg_rev_write(uint32_t value, uint32_t offset, uint32_t size, uint32_t data) {
switch (size << 2 | offset) {
case 0x04: return (value & 0xffffff00) | (data & 0xff); // 3 2 1 d0
case 0x05: return (value & 0xffff00ff) | ((data & 0xff) << 8); // 3 2 d0 0
case 0x06: return (value & 0xff00ffff) | ((data & 0xff) << 16); // 3 d0 1 0
case 0x07: return (value & 0x00ffffff) | ((data & 0xff) << 24); // d0 2 1 0
case 0x08: return (value & 0xffff0000) | ((data >> 8) & 0xff) | ((data & 0xff) << 8); // 3 2 d1 d0
case 0x09: return (value & 0xff0000ff) | (data & 0xff00) | ((data & 0xff) << 16); // 3 d1 d0 0
case 0x0a: return (value & 0x0000ffff) | ((data & 0xff00) << 8) | ((data & 0xff) << 24); // d1 d0 1 0
case 0x0b: return (value & 0x00ffff00) | ((data & 0xff00) << 16) | (data & 0xff); // d0 2 1 d1
case 0x10: return ((data & 0xff) << 24) | ((data & 0xff00) << 8) | ((data >> 8) & 0xff00) | ((data >> 24) & 0xff); // d3 d2 d1 d0
case 0x11: return ((data & 0xff00) << 16) | ( data & 0xff0000) | ((data >> 16) & 0xff00) | ( data & 0xff); // d2 d1 d0 d3
case 0x12: return ((data & 0xff0000) << 8) | ((data >> 8) & 0xff0000) | ((data & 0xff) << 8) | ((data >> 8) & 0xff); // d1 d0 d3 d2
case 0x13: return ( data & 0xff000000) | ((data & 0xff) << 16) | ( data & 0xff00) | ((data >> 16) & 0xff); // d0 d3 d2 d1
default: LOG_F(ERROR, "pci_cfg_rev: invalid offset %d for size %d!", offset, size); return 0xffffffff;
}
}
inline uint32_t flip_sized(uint32_t value, uint32_t size) {
switch (size) {
case 1: return value;
case 2: return BYTESWAP_16(value);
case 4: return BYTESWAP_32(value);
default: LOG_F(ERROR, "flip_sized: invalid size %d!", size); return 0xffffffff;
}
}
/* write the specified value of the specified size to memory pointed /* write the specified value of the specified size to memory pointed
to by addr, perform necessary byte swapping so that the byte order to by addr, perform necessary byte swapping so that the byte order
of the destination remains unchanged. */ of the destination remains unchanged. */