From a8c62985456b6e477cd89a65b64aa40bbc709fe6 Mon Sep 17 00:00:00 2001 From: Maxim Poliakovski Date: Tue, 31 Mar 2020 18:25:58 +0200 Subject: [PATCH] devices: skeleton for ATI Rage emulation. --- devices/atirage.cpp | 86 ++++++++++++++++++++++++++++++++---- devices/atirage.h | 41 ++++++++++------- devices/heathrow.cpp | 9 ---- devices/macio.h | 2 - machines/machinefactory.cpp | 1 - machines/machinegossamer.cpp | 6 +++ 6 files changed, 108 insertions(+), 37 deletions(-) diff --git a/devices/atirage.cpp b/devices/atirage.cpp index 7ec93aa..8f79e8c 100644 --- a/devices/atirage.cpp +++ b/devices/atirage.cpp @@ -22,21 +22,89 @@ along with this program. If not, see . #include #include #include "endianswap.h" +#include "memreadwrite.h" +#include "pcidevice.h" #include -ATIRage::ATIRage() { - +ATIRage::ATIRage(uint16_t dev_id) : PCIDevice("ati-rage") +{ + WRITE_DWORD_BE_A(&this->pci_cfg[0], (dev_id << 16) | ATI_PCI_VENDOR_ID); + WRITE_DWORD_BE_A(&this->pci_cfg[8], 0x0300005C); + WRITE_DWORD_BE_A(&this->pci_cfg[0x3C], 0x00080100); } -uint32_t ATIRage::read(int reg, int size) { - LOG_F(INFO, "Reading reg=%X, size %d", reg, (size * 8)); - return reg; +uint32_t ATIRage::pci_cfg_read(uint32_t reg_offs, uint32_t size) +{ + uint32_t res = 0; + + 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); + } + + LOG_F(INFO, "Return value: 0x%X", res); + return res; } -void ATIRage::write(int reg, uint32_t value, int size) { - LOG_F(INFO, "Writing reg=%X, value=%X, size %d", reg, value, (size * 8)); +void ATIRage::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size) +{ + LOG_F(INFO, "Writing into ATI Rage PCI config space, offset = 0x%X, val=0x%X size=%d", + reg_offs, BYTESWAP_32(value), size); + + switch (reg_offs) { + case 0x10: /* BAR 0 */ + if (value == 0xFFFFFFFFUL) { + WRITE_DWORD_LE_A(&this->pci_cfg[0x10], 0xFF000008); + } + else { + WRITE_DWORD_LE_A(&this->pci_cfg[0x10], 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); + } + else { + WRITE_DWORD_LE_A(&this->pci_cfg[0x14], value); + } + case 0x18: /* BAR 2 */ + if (value == 0xFFFFFFFFUL) { + WRITE_DWORD_LE_A(&this->pci_cfg[0x18], 0xFFFFF000); + } + else { + WRITE_DWORD_LE_A(&this->pci_cfg[0x18], 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); + break; + default: + WRITE_DWORD_LE_A(&this->pci_cfg[reg_offs], value); + } } -void ATIRage::atirage_init() { -} \ No newline at end of file +uint32_t ATIRage::read(uint32_t reg_start, uint32_t offset, int size) +{ + LOG_F(INFO, "Reading reg=%X, size %d", offset, size); + return 0; +} + +void ATIRage::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size) +{ + LOG_F(INFO, "Writing reg=%X, value=%X, size %d", offset, value, size); +} diff --git a/devices/atirage.h b/devices/atirage.h index 0ef44e4..1db21b1 100644 --- a/devices/atirage.h +++ b/devices/atirage.h @@ -1,9 +1,18 @@ -#ifndef ATIRAGE_H -#define ATIRAGE_H +#ifndef ATI_RAGE_H +#define ATI_RAGE_H + #include +#include "pcidevice.h" using namespace std; +/* PCI related definitions. */ +enum { + ATI_PCI_VENDOR_ID = 0x1002, + ATI_RAGE_PRO_DEV_ID = 0x4750, + ATI_RAGE_GT_DEV_ID = 0x4754, +}; + /** Mach registers offsets. */ enum { ATI_CTRC_H_TOTAL_DISP = 0x0000, @@ -34,14 +43,22 @@ enum { ATI_CONTEXT_MASK = 0x0320, }; -class ATIRage +class ATIRage : public PCIDevice { public: - ATIRage(); + ATIRage(uint16_t dev_id); ~ATIRage() = default; - uint32_t read(int reg, int size); - void write(int reg, uint32_t value, int size); + 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 */ + 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); private: uint32_t atirage_membuf_regs[9]; /* ATI Rage Memory Buffer Registers */ @@ -49,14 +66,6 @@ private: uint32_t atirage_cmdfifo_regs[3]; /* ATI Rage Command FIFO Registers */ uint32_t atirage_datapath_regs[12]; /* ATI Rage Data Path Registers*/ - uint8_t atirage_vid_mem[8242880]; - - uint8_t atirage_cfg[256] = { - 0x02, 0x10, //Vendor: ATI Technologies - 0x50, 0x47, //Device: 3D Rage Pro PCI - - }; - - void atirage_init(); + uint8_t pci_cfg[256] = { 0 }; /* PCI configuration space */ }; -#endif /* ATIRAGE_H */ \ No newline at end of file +#endif /* ATI_RAGE_H */ diff --git a/devices/heathrow.cpp b/devices/heathrow.cpp index 0f0e91b..fa33839 100644 --- a/devices/heathrow.cpp +++ b/devices/heathrow.cpp @@ -26,7 +26,6 @@ along with this program. If not, see . #include "viacuda.h" #include "awacs.h" #include "dbdma.h" -#include "atirage.h" #include "machines/machinebase.h" /** Heathrow Mac I/O device emulation. @@ -43,8 +42,6 @@ HeathrowIC::HeathrowIC() : PCIDevice("mac-io/heathrow") this->viacuda = new ViaCuda(); gMachineObj->add_subdevice("ViaCuda", this->viacuda); - this->atirage = new ATIRage(); - this->screamer = new AWACDevice(); this->snd_out_dma = new DMAChannel(this->screamer); this->screamer->set_dma_out(this->snd_out_dma); @@ -131,9 +128,6 @@ uint32_t HeathrowIC::read(uint32_t reg_start, uint32_t offset, int size) case 8: res = dma_read(offset - 0x8000, size); break; - case 0x12: - res = this->atirage->read(offset - 0x12000, size); - break; case 0x14: res = this->screamer->snd_ctrl_read(offset - 0x14000, size); break; @@ -166,9 +160,6 @@ void HeathrowIC::write(uint32_t reg_start, uint32_t offset, uint32_t value, int case 8: dma_write(offset - 0x8000, value, size); break; - case 0x12: - this->atirage->write(offset - 0x12000, value, size); - break; case 0x14: this->screamer->snd_ctrl_write(offset - 0x14000, value, size); break; diff --git a/devices/macio.h b/devices/macio.h index fef0130..0b77dab 100644 --- a/devices/macio.h +++ b/devices/macio.h @@ -61,7 +61,6 @@ along with this program. If not, see . #include "nvram.h" #include "awacs.h" #include "dbdma.h" -#include "atirage.h" /** Heathrow ASIC emulation @@ -135,7 +134,6 @@ private: ViaCuda *viacuda; /* VIA cell with Cuda MCU attached to it */ NVram *nvram; /* NVRAM cell */ AWACDevice *screamer; /* Screamer audio codec instance */ - ATIRage *atirage; /* Screamer audio codec instance */ DMAChannel *snd_out_dma; }; diff --git a/machines/machinefactory.cpp b/machines/machinefactory.cpp index 6e844d5..19b9b56 100644 --- a/machines/machinefactory.cpp +++ b/machines/machinefactory.cpp @@ -94,7 +94,6 @@ void load_rom(ifstream& rom_file, uint32_t file_size) int create_machine_for_rom(const char* rom_filepath) { ifstream rom_file; - int result; uint32_t file_size, config_info_offset, rom_id; char rom_id_str[17]; diff --git a/machines/machinegossamer.cpp b/machines/machinegossamer.cpp index b065461..6065e18 100644 --- a/machines/machinegossamer.cpp +++ b/machines/machinegossamer.cpp @@ -32,6 +32,7 @@ along with this program. If not, see . #include "devices/macio.h" #include "devices/viacuda.h" #include "devices/spdram.h" +#include "devices/atirage.h" static void setup_ram_slot(std::string name, int i2c_addr, int capacity_megs) { @@ -88,6 +89,11 @@ int create_gossamer() setup_ram_slot("RAM_DIMM_2", 0x56, 0); /* RAM slot 2 -> empty by default */ setup_ram_slot("RAM_DIMM_3", 0x55, 0); /* RAM slot 3 -> empty by default */ + /* register ATI 3D Rage Pro video card with the PCI host bridge */ + gMachineObj->add_component("ATIRage", new ATIRage(ATI_RAGE_PRO_DEV_ID)); + grackle_obj->pci_register_device(18, + dynamic_cast(gMachineObj->get_comp_by_name("ATIRage"))); + /* Init virtual CPU and request MPC750 CPU aka G3 */ ppc_cpu_init(grackle_obj, PPC_VER::MPC750);