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) {
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) {
return pci_cfg_rev_read(this->addr_mask, offset, size);
switch (reg_offs) {
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;
}
@ -112,27 +100,15 @@ void Bandit::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size)
return;
}
uint32_t offset = reg_offs & 3;
reg_offs &= ~3;
if (~-size & offset) {
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);
switch (reg_offs) {
case BANDIT_ADDR_MASK:
this->addr_mask = BYTESWAP_32(value);
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)
@ -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
result = this->pci_cfg_read(reg_offs + (offset & 3), size);
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 + (offset & 3), size);
result = this->dev_map[idsel]->pci_cfg_read(reg_offs, size);
} else {
dev_num = WHAT_BIT_SET(idsel) + 11;
LOG_F(
@ -220,7 +196,7 @@ void Bandit::write(uint32_t rgn_start, uint32_t offset, uint32_t value, int size
LOG_F(
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),
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;
}
@ -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",
this->name.c_str(), idsel, this->config_addr,
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;
}
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;
}
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 {
dev_num = WHAT_BIT_SET(idsel) + 11;
LOG_F(
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),
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 {
@ -344,7 +320,7 @@ uint32_t Chaos::read(uint32_t rgn_start, uint32_t offset, int size)
}
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 {
dev_num = WHAT_BIT_SET(idsel) + 11;
LOG_F(
@ -382,7 +358,7 @@ void Chaos::write(uint32_t rgn_start, uint32_t offset, uint32_t value, int size)
LOG_F(
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),
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;
}
@ -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",
this->name.c_str(), idsel, this->config_addr,
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;
}
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 {
dev_num = WHAT_BIT_SET(idsel) + 11;
LOG_F(
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),
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 {

View File

@ -52,16 +52,6 @@ uint32_t PCIDevice::pci_cfg_read(uint32_t reg_offs, uint32_t size)
{
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) {
case PCI_CFG_DEV_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:
LOG_F(
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
);
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)
{
uint32_t data;
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)
);
if (size == 4) {
data = BYTESWAP_32(value);
} else {
// get current register content as DWORD and update it partially
data = BYTESWAP_32(this->pci_cfg_read(reg_offs, 4));
write_mem_rev(((uint8_t *)&data) + (reg_offs & 3), 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) {
case PCI_CFG_STAT_CMD:
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;
case PCI_CFG_ROM_BAR:
if ((data & this->exp_bar_cfg) == this->exp_bar_cfg) {
this->exp_rom_bar = (data & (this->exp_bar_cfg | 1));
if (data == 0xFFFFF800UL) {
this->exp_rom_bar = this->exp_bar_cfg;
} else {
this->exp_rom_bar = (data & (this->exp_bar_cfg | 1));
this->exp_rom_bar = (data & 0xFFFFF801UL);
if (this->exp_rom_bar & 1) {
this->map_exp_rom_mem();
} else {
@ -167,7 +156,7 @@ void PCIDevice::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size)
LOG_F(
WARNING, "%s: attempt to write to reserved/unimplemented register @%02x.%c = %0*x",
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];
if (bar_cfg & 1) {
this->bars[bar_num] = (value & 0xFFFFFFFCUL) | (bar_cfg & 3);
this->bars[bar_num] = (value & 0xFFFFFFFCUL) | 1;
} else {
if (bar_cfg & 6) {
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;
rom_addr = this->exp_rom_bar & this->exp_bar_cfg;
rom_addr = this->exp_rom_bar & 0xFFFFF800UL;
rom_size = ~this->exp_bar_cfg + 1;
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)
@ -133,16 +133,17 @@ int RawFloppyImg::calc_phys_params()
} else if (buf[0] == 0xD2 && buf[1] == 0xD7) {
// check MFS volume size
} 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, "Volume size: %llu, Image size: %d", vol_size, this->img_size);
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;
// 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 {
if (offset >= 0x200000) {
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;
} else {
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;
bus_num = (this->config_addr >> 8) & 0xFF;
bus_num = (this->config_addr >> 8) & 0xFF;
dev_num = (this->config_addr >> 19) & 0x1F;
fun_num = (this->config_addr >> 16) & 0x07;
reg_offs = (this->config_addr >> 24) & 0xFC;
if (bus_num) {
LOG_F(
ERROR,
"%s err: read attempt from non-local PCI bus, config_addr = %x, offset = %x %02x:%02x.%x @%02x.%c",
this->name.c_str(), this->config_addr, offset, bus_num, dev_num, fun_num, reg_offs,
size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size
);
LOG_F(
ERROR,
"%s err: read attempt from non-local PCI bus, config_addr = %x %02x:%02x.%x @%02x.%c",
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
);
return 0xFFFFFFFFUL; // PCI spec §6.1
}
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 {
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 {
LOG_F(
ERROR,
"%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
);
return 0xFFFFFFFFUL; // PCI spec §6.1
@ -155,10 +155,10 @@ uint32_t MPC106::pci_read(uint32_t offset, uint32_t size) {
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;
bus_num = (this->config_addr >> 8) & 0xFF;
bus_num = (this->config_addr >> 8) & 0xFF;
dev_num = (this->config_addr >> 19) & 0x1F;
fun_num = (this->config_addr >> 16) & 0x07;
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) {
LOG_F(
ERROR,
"%s err: write attempt to non-local PCI bus, config_addr = %x, offset = %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,
size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size,
size * 2, flip_sized(value, size)
);
"%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, bus_num, dev_num, fun_num, reg_offs,
size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size,
size * 2, value
);
return;
}
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 {
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 {
LOG_F(
ERROR,
"%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 * 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);
}
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
);
}
return pci_cfg_rev_read(READ_DWORD_LE_A(&this->my_pci_cfg_hdr[reg_offs]), offset, size);
return read_mem(&this->my_pci_cfg_hdr[reg_offs], 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;
}
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
uint32_t *addr = (uint32_t *)&this->my_pci_cfg_hdr[reg_offs];
WRITE_DWORD_LE_A(addr, pci_cfg_rev_write(READ_DWORD_LE_A(addr), offset, size, value));
write_mem(&this->my_pci_cfg_hdr[reg_offs], value, size);
if (this->my_pci_cfg_hdr[0xF2] & 8) {
#ifdef MPC106_DEBUG

View File

@ -59,8 +59,8 @@ public:
protected:
/* PCI access */
uint32_t pci_read(uint32_t offset, uint32_t size);
void pci_write(uint32_t offset, uint32_t value, uint32_t size);
uint32_t pci_read(uint32_t size);
void pci_write(uint32_t value, uint32_t size);
/* my own PCI configuration registers access */
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);
}
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) {
case 0x40:
return pci_cfg_rev_read(this->user_cfg, offset, size);
return this->user_cfg;
default:
LOG_F(
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
);
LOG_F(WARNING, "ATIRage: reading from unimplemented config register at 0x%X", reg_offs);
}
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) {
PCIDevice::pci_cfg_write(reg_offs, value, size);
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)
);
}
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)
);
} else {
switch (reg_offs) {
case 0x40:
this->user_cfg = value;
break;
default:
LOG_F(WARNING, "ATIRage: writing to unimplemented config register at 0x%X", reg_offs);
}
}
}

View File

@ -59,7 +59,6 @@ ControlVideo::ControlVideo()
this->vendor_id = PCI_VENDOR_APPLE;
this->device_id = 3;
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[2] = 0xFC000000UL; // base address for the VRAM (64MB)
@ -85,10 +84,6 @@ ControlVideo::ControlVideo()
void ControlVideo::notify_bar_change(int 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:
if (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) {
case ControlRegs::TEST:
result = this->test;
break;
case ControlRegs::MON_SENSE:
result = this->cur_mon_id << 6;
break;
default:
LOG_F(INFO, "read from 0x%08X:0x%08X", rgn_start, offset);
}
return BYTESWAP_32(result);
switch (offset >> 4) {
case ControlRegs::TEST:
result = this->test;
break;
case ControlRegs::MON_SENSE:
result = this->cur_mon_id << 6;
break;
default:
LOG_F(INFO, "read from 0x%08X:0x%08X", rgn_start, offset);
}
return 0;
return BYTESWAP_32(result);
}
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;
}
if (rgn_start == this->regs_base) {
value = BYTESWAP_32(value);
value = BYTESWAP_32(value);
switch (offset >> 4) {
case ControlRegs::VFPEQ:
case ControlRegs::VFP:
case ControlRegs::VAL:
case ControlRegs::VBP:
case ControlRegs::VBPEQ:
case ControlRegs::VSYNC:
case ControlRegs::VHLINE:
case ControlRegs::PIPED:
case ControlRegs::HPIX:
case ControlRegs::HFP:
case ControlRegs::HAL:
case ControlRegs::HBWAY:
case ControlRegs::HSP:
case ControlRegs::HEQ:
case ControlRegs::HLFLN:
case ControlRegs::HSERR:
this->swatch_params[(offset >> 4) - 1] = value;
break;
case ControlRegs::TEST:
if (this->test != value) {
if ((this->test & ~TEST_STROBE) != (value & ~TEST_STROBE)) {
this->test = value;
this->test_shift = 0;
LOG_F(9, "New TEST value: 0x%08X", this->test);
} else {
LOG_F(9, "TEST strobe bit flipped, new value: 0x%08X", value);
this->test = value;
if (++this->test_shift >= 3) {
LOG_F(9, "Received TEST reg value: 0x%08X", this->test & ~TEST_STROBE);
if ((this->test ^ this->prev_test) & 0x400) {
if (this->test & 0x400) {
this->disable_display();
} else {
this->enable_display();
}
this->prev_test = this->test;
switch (offset >> 4) {
case ControlRegs::VFPEQ:
case ControlRegs::VFP:
case ControlRegs::VAL:
case ControlRegs::VBP:
case ControlRegs::VBPEQ:
case ControlRegs::VSYNC:
case ControlRegs::VHLINE:
case ControlRegs::PIPED:
case ControlRegs::HPIX:
case ControlRegs::HFP:
case ControlRegs::HAL:
case ControlRegs::HBWAY:
case ControlRegs::HSP:
case ControlRegs::HEQ:
case ControlRegs::HLFLN:
case ControlRegs::HSERR:
this->swatch_params[(offset >> 4) - 1] = value;
break;
case ControlRegs::TEST:
if (this->test != value) {
if ((this->test & ~TEST_STROBE) != (value & ~TEST_STROBE)) {
this->test = value;
this->test_shift = 0;
LOG_F(9, "New TEST value: 0x%08X", this->test);
} else {
LOG_F(9, "TEST strobe bit flipped, new value: 0x%08X", value);
this->test = value;
if (++this->test_shift >= 3) {
LOG_F(9, "Received TEST reg value: 0x%08X", this->test & ~TEST_STROBE);
if ((this->test ^ this->prev_test) & 0x400) {
if (this->test & 0x400) {
this->disable_display();
} else {
this->enable_display();
}
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;
uint32_t vram_size;
uint32_t io_base = 0;
uint32_t vram_base = 0;
uint32_t regs_base = 0;
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
to by addr, perform necessary byte swapping so that the byte order
of the destination remains unchanged. */