mirror of
https://github.com/dingusdev/dingusppc.git
synced 2025-01-11 05:29:43 +00:00
ATI Rage: partial register access implemented.
This commit is contained in:
parent
b6fcd289a3
commit
9f95fde279
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user