mirror of
https://github.com/dingusdev/dingusppc.git
synced 2025-01-11 05:29:43 +00:00
ATI Rage: basic register access via PCI I/O space.
This commit is contained in:
parent
a243c79d0f
commit
b6fcd289a3
@ -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);
|
||||
|
@ -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 */
|
||||
|
Loading…
x
Reference in New Issue
Block a user