ATI Rage: basic register access via PCI I/O space.

This commit is contained in:
Maxim Poliakovski 2020-03-31 21:19:10 +02:00
parent a243c79d0f
commit b6fcd289a3
2 changed files with 123 additions and 39 deletions

View File

@ -33,6 +33,53 @@ 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)
{
/* size-dependent endian convertsion */
/* FIXME: make it reusable */
switch (size) {
case 4:
value = BYTESWAP_32(value);
break;
case 2:
value = BYTESWAP_16(value);
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);
break;
default:
LOG_F(ERROR, "ATI Rage: unknown register at 0x%X", offset);
}
}
uint32_t ATIRage::pci_cfg_read(uint32_t reg_offs, uint32_t size)
{
uint32_t res = 0;
@ -65,32 +112,32 @@ 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[0x10], 0xFF000008);
WRITE_DWORD_LE_A(&this->pci_cfg[CFG_REG_BAR0], 0xFF000008);
}
else {
WRITE_DWORD_LE_A(&this->pci_cfg[0x10], value);
WRITE_DWORD_LE_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[0x14], 0x0000FFF1);
WRITE_DWORD_LE_A(&this->pci_cfg[CFG_REG_BAR1], 0x0000FFF1);
}
else {
WRITE_DWORD_LE_A(&this->pci_cfg[0x14], value);
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[0x18], 0xFFFFF000);
WRITE_DWORD_LE_A(&this->pci_cfg[CFG_REG_BAR2], 0xFFFFF000);
}
else {
WRITE_DWORD_LE_A(&this->pci_cfg[0x18], value);
WRITE_DWORD_LE_A(&this->pci_cfg[CFG_REG_BAR2], value);
}
break;
case 0x1C: /* BAR 3: unimplemented */
case 0x20: /* BAR 4: unimplemented */
case 0x24: /* BAR 5: unimplemented */
case 0x30: /* Expansion ROM Base Addr: unimplemented */
WRITE_DWORD_LE_A(&this->pci_cfg[reg_offs], 0);
case CFG_REG_BAR3: /* unimplemented */
case CFG_REG_BAR4: /* unimplemented */
case CFG_REG_BAR5: /* unimplemented */
case CFG_EXP_BASE: /* no expansion ROM */
WRITE_DWORD_BE_A(&this->pci_cfg[reg_offs], 0);
break;
default:
WRITE_DWORD_LE_A(&this->pci_cfg[reg_offs], value);
@ -98,6 +145,31 @@ void ATIRage::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size)
}
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;
}
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;
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);
return false;
}
this->write_reg(offset - io_base, value, size);
return true;
}
uint32_t ATIRage::read(uint32_t reg_start, uint32_t offset, int size)
{
LOG_F(INFO, "Reading reg=%X, size %d", offset, size);

View File

@ -15,32 +15,36 @@ enum {
/** Mach registers offsets. */
enum {
ATI_CTRC_H_TOTAL_DISP = 0x0000,
ATI_CRTC_H_SYNC_STRT_WID = 0x0004,
ATI_CTRC_V_TOTAL_DISP = 0x0008,
ATI_CRTC_V_SYNC_STRT_WID = 0x000C,
ATI_CTRC_INT_CNTL = 0x0018,
ATI_CTRC_GEN_CNTL = 0x001C,
ATI_DSP_CONFIG = 0x0020,
ATI_DSP_TOGGLE = 0x0024,
ATI_TIMER_CFG = 0x0028,
ATI_MEM_BUF_CNTL = 0x002C,
ATI_MEM_ADDR_CFG = 0x0034,
ATI_VGA_DSP_CFG = 0x004C,
ATI_VGA_DSP_TGL = 0x0050,
ATI_DSP2_CONFIG = 0x0054,
ATI_DSP2_TOGGLE = 0x0058,
ATI_EXT_MEM_CNTL = 0x00AC,
ATI_MEM_CNTL = 0x00B0,
ATI_VGA_WP_SEL = 0x00B4,
ATI_VGA_RP_SEL = 0x00B8,
ATI_I2C_CNTL_1 = 0x00BC,
ATI_DST_OFF_PITCH = 0x0100,
ATI_SRC_OFF_PITCH = 0x0180,
ATI_DP_PIX_WIDTH = 0x02D0,
ATI_DST_X_Y = 0x02E8,
ATI_DST_WIDTH_HEIGHT = 0x02EC,
ATI_CONTEXT_MASK = 0x0320,
ATI_CRTC_H_TOTAL_DISP = 0x0000,
ATI_CRTC_H_SYNC_STRT_WID = 0x0004,
ATI_CRTC_V_TOTAL_DISP = 0x0008,
ATI_CRTC_V_SYNC_STRT_WID = 0x000C,
ATI_CRTC_INT_CNTL = 0x0018,
ATI_CRTC_GEN_CNTL = 0x001C,
ATI_DSP_CONFIG = 0x0020,
ATI_DSP_TOGGLE = 0x0024,
ATI_TIMER_CFG = 0x0028,
ATI_MEM_BUF_CNTL = 0x002C,
ATI_MEM_ADDR_CFG = 0x0034,
ATI_VGA_DSP_CFG = 0x004C,
ATI_VGA_DSP_TGL = 0x0050,
ATI_DSP2_CONFIG = 0x0054,
ATI_DSP2_TOGGLE = 0x0058,
ATI_BUS_CNTL = 0x00A0,
ATI_EXT_MEM_CNTL = 0x00AC,
ATI_MEM_CNTL = 0x00B0,
ATI_VGA_WP_SEL = 0x00B4,
ATI_VGA_RP_SEL = 0x00B8,
ATI_I2C_CNTL_1 = 0x00BC,
ATI_DAC_CNTL = 0x00C4,
ATI_GEN_TEST_CNTL = 0x00D0,
ATI_CFG_STAT0 = 0x00E4,
ATI_DST_OFF_PITCH = 0x0100,
ATI_SRC_OFF_PITCH = 0x0180,
ATI_DP_PIX_WIDTH = 0x02D0,
ATI_DST_X_Y = 0x02E8,
ATI_DST_WIDTH_HEIGHT = 0x02EC,
ATI_CONTEXT_MASK = 0x0320,
};
class ATIRage : public PCIDevice
@ -49,17 +53,25 @@ public:
ATIRage(uint16_t dev_id);
~ATIRage() = default;
/* MMIODevice methods */
uint32_t read(uint32_t reg_start, uint32_t offset, int size);
void write(uint32_t reg_start, uint32_t offset, uint32_t value, int size);
bool supports_type(HWCompType type) { return type == HWCompType::MMIO_DEV; };
void set_host(PCIHost* host_instance) { this->host_instance = host_instance; };
/* PCI device methods */
bool supports_io_space(void) { return true; };
uint32_t pci_cfg_read(uint32_t reg_offs, uint32_t size);
void pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size);
/* I/O space access methods */
bool pci_io_read(uint32_t offset, uint32_t size, uint32_t *res);
bool pci_io_write(uint32_t offset, uint32_t value, uint32_t size) ;
protected:
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 */