ATI Rage: partial register access implemented.

This commit is contained in:
Maxim Poliakovski 2020-04-01 03:24:39 +02:00
parent b6fcd289a3
commit 9f95fde279
2 changed files with 117 additions and 68 deletions

View File

@ -33,52 +33,84 @@ ATIRage::ATIRage(uint16_t dev_id) : PCIDevice("ati-rage")
WRITE_DWORD_BE_A(&this->pci_cfg[0x3C], 0x00080100);
}
void ATIRage::write_reg(uint32_t offset, uint32_t value, uint32_t size)
uint32_t ATIRage::size_dep_read(uint8_t *buf, uint32_t size)
{
/* size-dependent endian convertsion */
/* FIXME: make it reusable */
switch (size) {
switch(size) {
case 4:
value = BYTESWAP_32(value);
return READ_DWORD_LE_A(buf);
break;
case 2:
value = BYTESWAP_16(value);
return READ_WORD_LE_A(buf);
break;
}
switch (offset) {
case ATI_CRTC_INT_CNTL:
LOG_F(INFO, "ATI Rage: CRTC_INT_CNTL set to 0x%X", value);
break;
case ATI_CRTC_GEN_CNTL:
LOG_F(INFO, "ATI Rage: CRTC_GEN_CNTL set to 0x%X", value);
break;
case ATI_MEM_ADDR_CFG:
LOG_F(INFO, "ATI Rage: MEM_ADDR_CFG set to 0x%X", value);
break;
case ATI_BUS_CNTL:
LOG_F(INFO, "ATI Rage: BUS_CNTL set to 0x%X", value);
break;
case ATI_EXT_MEM_CNTL:
LOG_F(INFO, "ATI Rage: EXT_MEM_CNTL set to 0x%X", value);
break;
case ATI_MEM_CNTL:
LOG_F(INFO, "ATI Rage: MEM_CNTL set to 0x%X", value);
break;
case ATI_DAC_CNTL:
LOG_F(INFO, "ATI Rage: DAC_CNTL set to 0x%X", value);
break;
case ATI_GEN_TEST_CNTL:
LOG_F(INFO, "ATI Rage: GEN_TEST_CNTL set to 0x%X", value);
break;
case ATI_CFG_STAT0:
LOG_F(INFO, "ATI Rage: CONFIG_STAT0 set to 0x%X", value);
case 1:
return *buf;
break;
default:
LOG_F(ERROR, "ATI Rage: unknown register at 0x%X", offset);
LOG_F(WARNING, "ATI Rage read: invalid size %d", size);
return 0;
}
}
void ATIRage::size_dep_write(uint8_t *buf, uint32_t value, uint32_t size)
{
switch (size) {
case 4:
WRITE_DWORD_BE_A(buf, value);
break;
case 2:
WRITE_WORD_BE_A(buf, value & 0xFFFFU);
break;
case 1:
*buf = value & 0xFF;
}
}
void ATIRage::write_reg(uint32_t offset, uint32_t value, uint32_t size)
{
const char* reg_name;
/* size-dependent endian conversion */
size_dep_write(&this->block_io_regs[offset], value, size);
switch (offset & ~3) {
case ATI_CRTC_INT_CNTL:
reg_name = "CRTC_INT_CNTL";
break;
case ATI_CRTC_GEN_CNTL:
reg_name = "CRTC_GEN_CNTL";
break;
case ATI_MEM_ADDR_CFG:
reg_name = "MEM_ADDR_CFG";
break;
case ATI_CLOCK_CNTL:
reg_name = "CLOCK_CNTL";
break;
case ATI_BUS_CNTL:
reg_name = "BUS_CNTL";
break;
case ATI_EXT_MEM_CNTL:
reg_name = "EXT_MEM_CNTL";
break;
case ATI_MEM_CNTL:
reg_name = "MEM_CNTL";
break;
case ATI_DAC_CNTL:
reg_name = "DAC_CNTL";
break;
case ATI_GEN_TEST_CNTL:
reg_name = "GEN_TEST_CNTL";
break;
case ATI_CFG_STAT0:
reg_name = "CONFIG_STAT0";
break;
default:
reg_name = "unknown";
}
LOG_F(INFO, "ATI Rage: %s register at 0x%X set to 0x%X", reg_name,
offset & ~3, READ_DWORD_LE_A(&this->block_io_regs[offset & ~3]));
}
uint32_t ATIRage::pci_cfg_read(uint32_t reg_offs, uint32_t size)
{
@ -86,19 +118,7 @@ uint32_t ATIRage::pci_cfg_read(uint32_t reg_offs, uint32_t size)
LOG_F(INFO, "Reading ATI Rage config space, offset = 0x%X, size=%d", reg_offs, size);
switch (size) {
case 4:
res = READ_DWORD_LE_U(&this->pci_cfg[reg_offs]);
break;
case 2:
res = READ_WORD_LE_U(&this->pci_cfg[reg_offs]);
break;
case 1:
res = this->pci_cfg[reg_offs];
break;
default:
LOG_F(WARNING, "ATI Rage pci_cfg_read(): invalid size %d", size);
}
res = size_dep_read(&this->pci_cfg[reg_offs], size);
LOG_F(INFO, "Return value: 0x%X", res);
return res;
@ -112,25 +132,25 @@ void ATIRage::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size)
switch (reg_offs) {
case 0x10: /* BAR 0 */
if (value == 0xFFFFFFFFUL) {
WRITE_DWORD_LE_A(&this->pci_cfg[CFG_REG_BAR0], 0xFF000008);
WRITE_DWORD_BE_A(&this->pci_cfg[CFG_REG_BAR0], 0xFF000008);
}
else {
WRITE_DWORD_LE_A(&this->pci_cfg[CFG_REG_BAR0], value);
WRITE_DWORD_BE_A(&this->pci_cfg[CFG_REG_BAR0], value);
}
break;
case 0x14: /* BAR 1: I/O space base, 256 bytes wide */
if (value == 0xFFFFFFFFUL) {
WRITE_DWORD_LE_A(&this->pci_cfg[CFG_REG_BAR1], 0x0000FFF1);
WRITE_DWORD_BE_A(&this->pci_cfg[CFG_REG_BAR1], 0x0000FFF1);
}
else {
WRITE_DWORD_BE_A(&this->pci_cfg[CFG_REG_BAR1], value);
}
case 0x18: /* BAR 2 */
if (value == 0xFFFFFFFFUL) {
WRITE_DWORD_LE_A(&this->pci_cfg[CFG_REG_BAR2], 0xFFFFF000);
WRITE_DWORD_BE_A(&this->pci_cfg[CFG_REG_BAR2], 0xFFFFF000);
}
else {
WRITE_DWORD_LE_A(&this->pci_cfg[CFG_REG_BAR2], value);
WRITE_DWORD_BE_A(&this->pci_cfg[CFG_REG_BAR2], value);
}
break;
case CFG_REG_BAR3: /* unimplemented */
@ -140,28 +160,51 @@ void ATIRage::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size)
WRITE_DWORD_BE_A(&this->pci_cfg[reg_offs], 0);
break;
default:
WRITE_DWORD_LE_A(&this->pci_cfg[reg_offs], value);
size_dep_write(&this->pci_cfg[reg_offs], value, size);
}
}
bool ATIRage::io_access_allowed(uint32_t offset, uint32_t *p_io_base)
{
if (!(this->pci_cfg[CFG_REG_CMD] & 1)) {
LOG_F(WARNING, "ATI I/O space disabled in the command reg");
return false;
}
uint32_t io_base = READ_DWORD_LE_A(&this->pci_cfg[CFG_REG_BAR1]) & ~3;
if (offset < io_base || offset >(io_base + 0x100)) {
LOG_F(WARNING, "Rage: I/O out of range, base=0x%X, offset=0x%X", io_base, offset);
return false;
}
*p_io_base = io_base;
return true;
}
bool ATIRage::pci_io_read(uint32_t offset, uint32_t size, uint32_t *res)
{
LOG_F(INFO, "ATI Rage I/O space read, offset=0x%X, size=%d", offset, size);
return false;
uint32_t io_base;
if (!this->io_access_allowed(offset, &io_base)) {
return false;
}
*res = size_dep_read(&this->block_io_regs[offset - io_base], size);
LOG_F(INFO, "ATI Rage I/O space read, offset=0x%X, size=%d, val=0x%X", offset, size, *res);
return true;
}
bool ATIRage::pci_io_write(uint32_t offset, uint32_t value, uint32_t size)
{
uint32_t io_base = READ_DWORD_LE_A(&this->pci_cfg[CFG_REG_BAR1]) & ~3;
uint32_t io_base;
if (!(this->pci_cfg[CFG_REG_CMD] & 1)) {
LOG_F(WARNING, "ATI I/O space disabled in the command reg");
return false;
}
if (offset < io_base || offset >(io_base + 0x100)) {
LOG_F(WARNING, "Rage: I/O out of range, base=0x%X, offset=0x%X", io_base, offset);
if (!this->io_access_allowed(offset, &io_base)) {
return false;
}

View File

@ -30,6 +30,7 @@ enum {
ATI_VGA_DSP_TGL = 0x0050,
ATI_DSP2_CONFIG = 0x0054,
ATI_DSP2_TOGGLE = 0x0058,
ATI_CLOCK_CNTL = 0x0090,
ATI_BUS_CNTL = 0x00A0,
ATI_EXT_MEM_CNTL = 0x00AC,
ATI_MEM_CNTL = 0x00B0,
@ -70,13 +71,18 @@ public:
bool pci_io_write(uint32_t offset, uint32_t value, uint32_t size) ;
protected:
uint32_t size_dep_read(uint8_t* buf, uint32_t size);
void size_dep_write(uint8_t* buf, uint32_t val, uint32_t size);
bool io_access_allowed(uint32_t offset, uint32_t* p_io_base);
void write_reg(uint32_t offset, uint32_t value, uint32_t size);
private:
uint32_t atirage_membuf_regs[9]; /* ATI Rage Memory Buffer Registers */
uint32_t atirage_scratch_regs[4]; /* ATI Rage Scratch Registers */
uint32_t atirage_cmdfifo_regs[3]; /* ATI Rage Command FIFO Registers */
uint32_t atirage_datapath_regs[12]; /* ATI Rage Data Path Registers*/
//uint32_t atirage_membuf_regs[9]; /* ATI Rage Memory Buffer Registers */
//uint32_t atirage_scratch_regs[4]; /* ATI Rage Scratch Registers */
//uint32_t atirage_cmdfifo_regs[3]; /* ATI Rage Command FIFO Registers */
//uint32_t atirage_datapath_regs[12]; /* ATI Rage Data Path Registers*/
uint8_t block_io_regs[256] = { 0 };
uint8_t pci_cfg[256] = { 0 }; /* PCI configuration space */
};