Merge pull request #40 from joevt/master

Gazelle fixes, PCI changes and additions, MMIO changes, etc.
This commit is contained in:
Maxim Poliakovski 2023-01-11 23:05:15 +01:00 committed by GitHub
commit e510c11be2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 299 additions and 144 deletions

3
.gitignore vendored
View File

@ -29,3 +29,6 @@ build
build-*
*.dir
*.user
DerivedData
*.xcodeproj/project.xcworkspace
*.xcodeproj/xcuserdata

View File

@ -34,13 +34,13 @@ inline void _u32xu64(uint32_t a, uint64_t b, uint64_t &hi, uint32_t &lo)
{
uint64_t p0 = (b & 0xffffffff) * a;
uint64_t p1 = (b >> 32) * a;
lo = p0;
lo = (uint32_t)p0;
hi = (p0 >> 32) + p1;
}
inline void _u64xu64(uint64_t a, uint64_t b, uint64_t &hi, uint64_t &lo)
{
uint32_t p0h; uint64_t p0l; _u32xu64(b, a, p0h, p0l);
uint32_t p0h; uint64_t p0l; _u32xu64((uint32_t)b, a, p0h, p0l);
uint64_t p1h; uint32_t p1l; _u32xu64(b >> 32, a, p1h, p1l);
lo = p0l + ((uint64_t)p1l << 32);
hi = p0h + p1h + (lo < p0l);

View File

@ -32,7 +32,7 @@ TimerManager* TimerManager::timer_manager;
uint32_t TimerManager::add_oneshot_timer(uint64_t timeout, timer_cb cb)
{
if (!timeout || timeout <= MIN_TIMEOUT_NS) {
LOG_F(WARNING, "One-shot timer too short, timeout=%llu ns", timeout);
LOG_F(WARNING, "One-shot timer too short, timeout=%llu ns", (long long unsigned)timeout);
}
TimerInfo* ti = new TimerInfo;
@ -58,7 +58,7 @@ uint32_t TimerManager::add_oneshot_timer(uint64_t timeout, timer_cb cb)
uint32_t TimerManager::add_cyclic_timer(uint64_t interval, timer_cb cb)
{
if (!interval || interval <= MIN_TIMEOUT_NS) {
LOG_F(WARNING, "Cyclic timer interval too short, timeout=%llu ns", interval);
LOG_F(WARNING, "Cyclic timer interval too short, timeout=%llu ns", (long long unsigned)interval);
}
TimerInfo* ti = new TimerInfo;

View File

@ -45,7 +45,7 @@ inline void power_setsoov(uint32_t a, uint32_t b, uint32_t d) {
/** mask generator for rotate and shift instructions (§ 4.2.1.4 PowerpC PEM) */
static inline uint32_t power_rot_mask(unsigned rot_mb, unsigned rot_me) {
uint32_t m1 = 0xFFFFFFFFUL >> rot_mb;
uint32_t m2 = 0xFFFFFFFFUL << (31 - rot_me);
uint32_t m2 = (uint32_t)(0xFFFFFFFFUL << (31 - rot_me));
return ((rot_mb <= rot_me) ? m2 & m1 : m1 | m2);
}

View File

@ -100,7 +100,7 @@ void ppc_exception_handler(Except_Type exception_type, uint32_t srr1_bits) {
break;
default:
ABORT_F("Unknown exception occured: %X\n", exception_type);
ABORT_F("Unknown exception occured: %X\n", (unsigned)exception_type);
break;
}

View File

@ -849,38 +849,38 @@ uint64_t reg_op(string& reg_name, uint64_t val, bool is_write) {
try {
if (reg_name_u == "PC") {
if (is_write)
ppc_state.pc = val;
ppc_state.pc = (uint32_t)val;
return ppc_state.pc;
}
if (reg_name_u == "MSR") {
if (is_write)
ppc_state.msr = val;
ppc_state.msr = (uint32_t)val;
return ppc_state.msr;
}
if (reg_name_u == "CR") {
if (is_write)
ppc_state.cr = val;
ppc_state.cr = (uint32_t)val;
return ppc_state.cr;
}
if (reg_name_u == "FPSCR") {
if (is_write)
ppc_state.fpscr = val;
ppc_state.fpscr = (uint32_t)val;
return ppc_state.fpscr;
}
if (reg_name_u.substr(0, 1) == "R") {
reg_num_str = reg_name_u.substr(1);
reg_num = stoul(reg_num_str, NULL, 0);
reg_num = (unsigned)stoul(reg_num_str, NULL, 0);
if (reg_num < 32) {
if (is_write)
ppc_state.gpr[reg_num] = val;
ppc_state.gpr[reg_num] = (uint32_t)val;
return ppc_state.gpr[reg_num];
}
}
if (reg_name_u.substr(0, 1) == "FR") {
reg_num_str = reg_name_u.substr(2);
reg_num = stoul(reg_num_str, NULL, 0);
reg_num = (unsigned)stoul(reg_num_str, NULL, 0);
if (reg_num < 32) {
if (is_write)
ppc_state.fpr[reg_num].int64_r = val;
@ -890,20 +890,20 @@ uint64_t reg_op(string& reg_name, uint64_t val, bool is_write) {
if (reg_name_u.substr(0, 3) == "SPR") {
reg_num_str = reg_name_u.substr(3);
reg_num = stoul(reg_num_str, NULL, 0);
reg_num = (unsigned)stoul(reg_num_str, NULL, 0);
if (reg_num < 1024) {
if (is_write)
ppc_state.spr[reg_num] = val;
ppc_state.spr[reg_num] = (uint32_t)val;
return ppc_state.spr[reg_num];
}
}
if (reg_name_u.substr(0, 2) == "SR") {
reg_num_str = reg_name_u.substr(2);
reg_num = stoul(reg_num_str, NULL, 0);
reg_num = (unsigned)stoul(reg_num_str, NULL, 0);
if (reg_num < 16) {
if (is_write)
ppc_state.sr[reg_num] = val;
ppc_state.sr[reg_num] = (uint32_t)val;
return ppc_state.sr[reg_num];
}
}
@ -911,7 +911,7 @@ uint64_t reg_op(string& reg_name, uint64_t val, bool is_write) {
spr = SPRName2Num.find(reg_name_u);
if (spr != SPRName2Num.end()) {
if (is_write)
ppc_state.spr[spr->second] = val;
ppc_state.spr[spr->second] = (uint32_t)val;
return ppc_state.spr[spr->second];
}
} catch (...) {

View File

@ -125,11 +125,11 @@ static BATResult mpc601_block_address_translation(uint32_t la)
// logical to physical translation
pa = bat_entry->phys_hi | (la & ~bat_entry->hi_mask);
break;
return BATResult{bat_hit, prot, pa};
}
}
return BATResult{bat_hit, prot, pa};
return BATResult{bat_hit, 0, 0};
}
/** PowerPC-style block address translation. */
@ -742,6 +742,7 @@ void tlb_flush_entry(uint32_t ea)
tlb1 = &dtlb1_mode2[0];
tlb2 = &dtlb2_mode2[0];
break;
default:
case 5:
tlb1 = &dtlb1_mode3[0];
tlb2 = &dtlb2_mode3[0];
@ -967,7 +968,7 @@ void mmu_print_regs()
}
}
LOG_F(INFO, "");
LOG_F(INFO, "%s", "");
LOG_F(INFO, "SDR1 = 0x%X", ppc_state.spr[SPR::SDR1]);
LOG_F(INFO, "Segment registers:");
@ -1007,7 +1008,7 @@ inline T mmu_read_vmem(uint32_t guest_va)
// perform full address translation and refill the secondary TLB
tlb2_entry = dtlb2_refill(guest_va, 0);
if (tlb2_entry->flags & PAGE_NOPHYS) {
return UnmappedVal;
return (T)UnmappedVal;
}
}
#ifdef TLB_PROFILING
@ -1081,8 +1082,8 @@ inline void mmu_write_vmem(uint32_t guest_va, T value)
}
if (!(tlb1_entry->flags & TLBFlags::PTE_SET_C)) {
// perform full page address translation to update PTE.C bit
PATResult pat_res = page_address_translation(guest_va, false,
!!(ppc_state.msr & 0x4000), true);
page_address_translation(guest_va, false,
!!(ppc_state.msr & 0x4000), true);
tlb1_entry->flags |= TLBFlags::PTE_SET_C;
// don't forget to update the secondary TLB as well
@ -1120,8 +1121,8 @@ inline void mmu_write_vmem(uint32_t guest_va, T value)
if (!(tlb2_entry->flags & TLBFlags::PTE_SET_C)) {
// perform full page address translation to update PTE.C bit
PATResult pat_res = page_address_translation(guest_va, false,
!!(ppc_state.msr & 0x4000), true);
page_address_translation(guest_va, false,
!!(ppc_state.msr & 0x4000), true);
tlb2_entry->flags |= TLBFlags::PTE_SET_C;
}

View File

@ -729,7 +729,7 @@ void dppc_interpreter::ppc_srawi() {
/** mask generator for rotate and shift instructions (§ 4.2.1.4 PowerpC PEM) */
static inline uint32_t rot_mask(unsigned rot_mb, unsigned rot_me) {
uint32_t m1 = 0xFFFFFFFFUL >> rot_mb;
uint32_t m2 = 0xFFFFFFFFUL << (31 - rot_me);
uint32_t m2 = (uint32_t)(0xFFFFFFFFUL << (31 - rot_me));
return ((rot_mb <= rot_me) ? m2 & m1 : m1 | m2);
}
@ -861,11 +861,11 @@ static inline void calc_rtcl_value()
uint64_t new_ts = get_virt_time_ns();
uint64_t rtc_l = new_ts - rtc_timestamp + rtc_lo;
if (rtc_l >= ONE_BILLION_NS) { // check RTCL overflow
rtc_hi += rtc_l / ONE_BILLION_NS;
rtc_hi += (uint32_t)(rtc_l / ONE_BILLION_NS);
rtc_lo = rtc_l % ONE_BILLION_NS;
}
else {
rtc_lo = rtc_l;
rtc_lo = (uint32_t)rtc_l;
}
rtc_timestamp = new_ts;
}

View File

@ -52,7 +52,7 @@ using namespace std;
static uint32_t str2addr(string& addr_str) {
try {
return stoul(addr_str, NULL, 0);
return (uint32_t)stoul(addr_str, NULL, 0);
} catch (invalid_argument& exc) {
throw invalid_argument(string("Cannot convert ") + addr_str);
}
@ -60,7 +60,7 @@ static uint32_t str2addr(string& addr_str) {
static uint32_t str2num(string& num_str) {
try {
return stol(num_str, NULL, 0);
return (uint32_t)stol(num_str, NULL, 0);
} catch (invalid_argument& exc) {
throw invalid_argument(string("Cannot convert ") + num_str);
}
@ -512,7 +512,7 @@ void enter_debugger() {
}
} else if (cmd == "next" || cmd == "ni") {
addr_str = "PC";
addr = get_reg(addr_str) + 4;
addr = (uint32_t)get_reg(addr_str) + 4;
ppc_exec_until(addr);
} else if (cmd == "until") {
ss >> addr_str;
@ -588,7 +588,7 @@ void enter_debugger() {
#endif
} else {
addr_str = "PC";
addr = get_reg(addr_str);
addr = (uint32_t)get_reg(addr_str);
disasm(1, addr);
}
} catch (invalid_argument& exc) {

View File

@ -75,7 +75,8 @@ private:
class GossamerID : public MMIODevice {
public:
GossamerID(const uint16_t id) {
this->id = id, this->name = "Machine-id";
this->id = id;
this->name = "Machine-id";
supports_types(HWCompType::MMIO_DEV);
};
~GossamerID() = default;

View File

@ -39,7 +39,7 @@ using namespace std;
static uint32_t str2env(string& num_str) {
try {
return stoul(num_str, NULL, 0);
return (uint32_t)stoul(num_str, NULL, 0);
} catch (invalid_argument& exc) {
try {
string num_str2 = string("0x") + num_str;

View File

@ -298,6 +298,8 @@ void Bandit::verbose_address_space()
Chaos::Chaos(std::string name) : PCIHost()
{
this->name = name;
supports_types(HWCompType::PCI_HOST);
MemCtrlBase *mem_ctrl = dynamic_cast<MemCtrlBase *>
@ -308,8 +310,6 @@ Chaos::Chaos(std::string name) : PCIHost()
// base_addr + 0x800000 --> CONFIG_ADDR
// base_addr + 0xC00000 --> CONFIG_DATA
mem_ctrl->add_mmio_region(0xF0000000UL, 0x01000000, this);
this->name = name;
}
uint32_t Chaos::read(uint32_t rgn_start, uint32_t offset, int size)

View File

@ -102,7 +102,6 @@ public:
void write(uint32_t rgn_start, uint32_t offset, uint32_t value, int size);
private:
std::string name;
uint32_t config_addr;
};

View File

@ -27,10 +27,12 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <cinttypes>
#include <fstream>
#include <cstring>
#include <string>
PCIDevice::PCIDevice(std::string name)
{
this->name = name;
this->pci_name = name;
this->pci_rd_stat = [this]() { return this->status; };
@ -188,7 +190,10 @@ int PCIDevice::attach_exp_rom_image(const std::string img_path)
// determine image size
img_file.seekg(0, std::ios::end);
uint32_t exp_rom_image_size = img_file.tellg();
size_t exp_rom_image_size = img_file.tellg();
if (exp_rom_image_size > 4*1024*1024) {
throw std::runtime_error("expansion ROM file too large");
}
// verify PCI struct offset
uint16_t pci_struct_offset = 0;
@ -222,7 +227,7 @@ int PCIDevice::attach_exp_rom_image(const std::string img_path)
}
else {
LOG_F(WARNING, "%s: loaded expansion rom (%d bytes adjusted to %d bytes).",
this->pci_name.c_str(), exp_rom_image_size, this->exp_rom_size);
this->pci_name.c_str(), (int)exp_rom_image_size, this->exp_rom_size);
}
this->exp_bar_cfg = ~(this->exp_rom_size - 1);
@ -246,7 +251,7 @@ void PCIDevice::set_bar_value(int bar_num, uint32_t value)
{
uint32_t bar_cfg = this->bars_cfg[bar_num];
if (bar_cfg & 1) {
this->bars[bar_num] = (value & 0xFFFFFFFCUL) | 1;
this->bars[bar_num] = (value & 0xFFFFFFFCUL) | (bar_cfg & 3);
} else {
if (bar_cfg & 6) {
ABORT_F("Invalid or unsupported PCI space type: %d", (bar_cfg >> 1) & 3);

View File

@ -55,6 +55,7 @@ enum {
PCI_VENDOR_ATI = 0x1002,
PCI_VENDOR_MOTOROLA = 0x1057,
PCI_VENDOR_APPLE = 0x106B,
PCI_VENDOR_NVIDIA = 0x10DE,
};

View File

@ -53,6 +53,14 @@ bool PCIHost::pci_register_mmio_region(uint32_t start_addr, uint32_t size, PCIDe
return mem_ctrl->add_mmio_region(start_addr, size, obj);
}
bool PCIHost::pci_unregister_mmio_region(uint32_t start_addr, uint32_t size, PCIDevice* obj)
{
MemCtrlBase *mem_ctrl = dynamic_cast<MemCtrlBase *>
(gMachineObj->get_comp_by_type(HWCompType::MEM_CTRL));
// FIXME: add sanity checks!
return mem_ctrl->remove_mmio_region(start_addr, size, obj);
}
void PCIHost::attach_pci_device(std::string& dev_name, int slot_id)
{
if (!DeviceRegistry::device_registered(dev_name)) {

View File

@ -42,6 +42,7 @@ public:
virtual bool pci_register_device(int dev_num, PCIDevice* dev_instance);
virtual bool pci_register_mmio_region(uint32_t start_addr, uint32_t size, PCIDevice* obj);
virtual bool pci_unregister_mmio_region(uint32_t start_addr, uint32_t size, PCIDevice* obj);
virtual void attach_pci_device(std::string& dev_name, int slot_id);

View File

@ -104,8 +104,6 @@ protected:
void change_bus_phase(int initiator_id);
private:
std::string name;
// SCSI devices registered with this bus
std::array<ScsiDevice*, SCSI_MAX_DEVS> devices;

View File

@ -90,7 +90,12 @@ int RawFloppyImg::calc_phys_params()
// determine image size
img_file.seekg(0, img_file.end);
this->img_size = img_file.tellg();
size_t img_size = img_file.tellg();
if (img_size > 2*1024*1024) {
LOG_F(ERROR, "RawFloppyImg: image size is too large to determine disk format from image size!");
return -1;
}
this->img_size = (int)img_size;
img_file.seekg(0, img_file.beg);
img_file.close();
@ -212,7 +217,7 @@ int DiskCopy42Img::calc_phys_params() {
// determine image size
img_file.seekg(0, img_file.end);
this->img_size = img_file.tellg();
size_t img_size = img_file.tellg();
img_file.seekg(0, img_file.beg);
// get data size from image
@ -221,11 +226,12 @@ int DiskCopy42Img::calc_phys_params() {
img_file.read((char *)&buf, 4);
this->data_size = READ_DWORD_BE_U(buf);
if (this->data_size > this->img_size) {
if (this->data_size > img_size) {
img_file.close();
LOG_F(ERROR, "DiskCopy42Img: invalid data size %d", this->data_size);
return -1;
}
this->img_size = (int)img_size;
uint8_t disk_format = 0xFFU;

View File

@ -295,7 +295,7 @@ uint64_t MacSuperDrive::sync_to_disk()
track_time_ns -= this->index_delay;
// calculate current sector number from timestamp
int cur_sect_num = this->cur_sector = track_time_ns / this->sector_delay;
int cur_sect_num = this->cur_sector = (int)(track_time_ns / this->sector_delay);
this->sector_start_time = this->track_start_time + cur_sect_num * this->sector_delay +
this->index_delay;

View File

@ -128,7 +128,7 @@ uint8_t Swim3Ctrl::read(uint8_t reg_offset)
void Swim3Ctrl::write(uint8_t reg_offset, uint8_t value)
{
uint8_t old_mode_reg, status_addr;
uint8_t status_addr;
switch(reg_offset) {
case Swim3Reg::Timer:

View File

@ -25,6 +25,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <cstring>
#include <string>
#include <vector>
#include <loguru.hpp>
MemCtrlBase::~MemCtrlBase() {
@ -52,12 +53,74 @@ AddressMapEntry* MemCtrlBase::find_range(uint32_t addr) {
}
AddressMapEntry* MemCtrlBase::find_range_exact(uint32_t addr, uint32_t size, MMIODevice* dev_instance) {
if (size) {
uint32_t end = addr + size - 1;
for (auto& entry : address_map) {
if (addr == entry->start && end == entry->end && (!dev_instance || dev_instance == entry->devobj) )
return entry;
}
}
return nullptr;
}
AddressMapEntry* MemCtrlBase::find_range_contains(uint32_t addr, uint32_t size) {
if (size) {
uint32_t end = addr + size - 1;
for (auto& entry : address_map) {
if (addr >= entry->start && end <= entry->end)
return entry;
}
}
return nullptr;
}
AddressMapEntry* MemCtrlBase::find_range_overlaps(uint32_t addr, uint32_t size) {
if (size) {
uint32_t end = addr + size - 1;
for (auto& entry : address_map) {
if (end >= entry->start && addr <= entry->end)
return entry;
}
}
return nullptr;
}
bool MemCtrlBase::is_range_free(uint32_t addr, uint32_t size) {
bool result = true;
if (size) {
uint32_t end = addr + size - 1;
for (auto& entry : address_map) {
if (addr == entry->start && end == entry->end) {
LOG_F(WARNING, "memory region 0x%X..0x%X%s%s%s already exists", addr, end, entry->devobj ? " (" : "", entry->devobj ? entry->devobj->get_name().c_str() : "", entry->devobj ? ")" : "");
result = false;
}
else if (addr >= entry->start && end <= entry->end) {
LOG_F(WARNING, "0x%X..0x%X already exists in memory region 0x%X..0x%X%s%s%s", addr, end, entry->start, entry->end, entry->devobj ? " (" : "", entry->devobj ? entry->devobj->get_name().c_str() : "", entry->devobj ? ")" : "");
result = false;
}
else if (end >= entry->start && addr <= entry->end) {
LOG_F(ERROR, "0x%X..0x%X overlaps existing memory region 0x%X..0x%X%s%s%s", addr, end, entry->start, entry->end, entry->devobj ? " (" : "", entry->devobj ? entry->devobj->get_name().c_str() : "", entry->devobj ? ")" : "");
result = false;
}
}
}
return result;
}
bool MemCtrlBase::add_mem_region(
uint32_t start_addr, uint32_t size, uint32_t dest_addr, uint32_t type, uint8_t init_val = 0) {
AddressMapEntry *entry;
/* error if a memory region for the given range already exists */
if (find_range(start_addr) || find_range(start_addr + size))
if (!is_range_free(start_addr, size))
return false;
uint8_t* reg_content = new uint8_t[size];
@ -66,8 +129,9 @@ bool MemCtrlBase::add_mem_region(
entry = new AddressMapEntry;
uint32_t end = start_addr + size - 1;
entry->start = start_addr;
entry->end = start_addr + size - 1;
entry->end = end;
entry->mirror = dest_addr;
entry->type = type;
entry->devobj = 0;
@ -75,6 +139,14 @@ bool MemCtrlBase::add_mem_region(
this->address_map.push_back(entry);
LOG_F(INFO, "Added mem region 0x%X..0x%X (%s%s%s%s) -> 0x%X", start_addr, end,
entry->type & RT_ROM ? "ROM," : "",
entry->type & RT_RAM ? "RAM," : "",
entry->type & RT_MMIO ? "MMIO," : "",
entry->type & RT_MIRROR ? "MIRROR," : "",
dest_addr
);
return true;
}
@ -98,8 +170,9 @@ bool MemCtrlBase::add_mem_mirror(uint32_t start_addr, uint32_t dest_addr) {
entry = new AddressMapEntry;
uint32_t end = start_addr + (ref_entry->end - ref_entry->start);
entry->start = start_addr;
entry->end = start_addr + (ref_entry->end - ref_entry->start);
entry->end = end;
entry->mirror = dest_addr;
entry->type = ref_entry->type | RT_MIRROR;
entry->devobj = 0;
@ -107,6 +180,16 @@ bool MemCtrlBase::add_mem_mirror(uint32_t start_addr, uint32_t dest_addr) {
this->address_map.push_back(entry);
LOG_F(INFO, "Added mem region mirror 0x%X..0x%X (%s%s%s%s) -> 0x%X : 0x%X..0x%X%s%s%s", start_addr, end,
entry->type & RT_ROM ? "ROM," : "",
entry->type & RT_RAM ? "RAM," : "",
entry->type & RT_MMIO ? "MMIO," : "",
entry->type & RT_MIRROR ? "MIRROR," : "",
dest_addr,
ref_entry->start, ref_entry->end,
ref_entry->devobj ? " (" : "", ref_entry->devobj ? ref_entry->devobj->get_name().c_str() : "", ref_entry->devobj ? ")" : ""
);
return true;
}
@ -129,14 +212,15 @@ bool MemCtrlBase::set_data(uint32_t reg_addr, const uint8_t* data, uint32_t size
bool MemCtrlBase::add_mmio_region(uint32_t start_addr, uint32_t size, MMIODevice* dev_instance) {
AddressMapEntry *entry;
/* error if another region for the given range already exists */
if (find_range(start_addr) || find_range(start_addr + size - 1))
/* error if a memory region for the given range already exists */
if (!is_range_free(start_addr, size))
return false;
entry = new AddressMapEntry;
uint32_t end = start_addr + size - 1;
entry->start = start_addr;
entry->end = start_addr + size - 1;
entry->end = end;
entry->mirror = 0;
entry->type = RT_MMIO;
entry->devobj = dev_instance;
@ -144,9 +228,33 @@ bool MemCtrlBase::add_mmio_region(uint32_t start_addr, uint32_t size, MMIODevice
this->address_map.push_back(entry);
LOG_F(INFO, "Added mmio region 0x%X..0x%X%s%s%s", start_addr, end, dev_instance ? " (" : "", dev_instance ? dev_instance->get_name().c_str() : "", dev_instance ? ")" : "");
return true;
}
bool MemCtrlBase::remove_mmio_region(uint32_t start_addr, uint32_t size, MMIODevice* dev_instance) {
int found = 0;
uint32_t end = start_addr + size - 1;
address_map.erase(std::remove_if(address_map.begin(), address_map.end(),
[start_addr, end, dev_instance, &found](const AddressMapEntry *entry) {
bool result = (start_addr == entry->start && end == entry->end && (!dev_instance || dev_instance == entry->devobj));
found += result;
return result;
}
), address_map.end());
if (found == 0)
LOG_F(ERROR, "Cannot find mmio region 0x%X..0x%X%s%s%s to remove", start_addr, end, dev_instance ? " (" : "", dev_instance ? dev_instance->get_name().c_str() : "", dev_instance ? ")" : "");
else if (found > 1)
LOG_F(ERROR, "Removed %d occurrences of mmio region 0x%X..0x%X%s%s%s", found, start_addr, end, dev_instance ? " (" : "", dev_instance ? dev_instance->get_name().c_str() : "", dev_instance ? ")" : "");
else
LOG_F(INFO, "Removed mmio region 0x%X..0x%X%s%s%s", start_addr, end, dev_instance ? " (" : "", dev_instance ? dev_instance->get_name().c_str() : "", dev_instance ? ")" : "");
return (found > 0);
}
AddressMapEntry* MemCtrlBase::find_rom_region()
{
for (auto& entry : address_map) {

View File

@ -68,10 +68,16 @@ public:
virtual bool add_mem_mirror(uint32_t start_addr, uint32_t dest_addr);
virtual bool add_mmio_region(uint32_t start_addr, uint32_t size, MMIODevice* dev_instance);
virtual bool remove_mmio_region(uint32_t start_addr, uint32_t size, MMIODevice* dev_instance);
virtual bool set_data(uint32_t reg_addr, const uint8_t* data, uint32_t size);
AddressMapEntry* find_range(uint32_t addr);
AddressMapEntry* find_range_exact(uint32_t addr, uint32_t size, MMIODevice* dev_instance);
AddressMapEntry* find_range_contains(uint32_t addr, uint32_t size);
AddressMapEntry* find_range_overlaps(uint32_t addr, uint32_t size);
bool is_range_free(uint32_t addr, uint32_t size);
AddressMapEntry* find_rom_region();
protected:

View File

@ -37,8 +37,6 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
MPC106::MPC106() : MemCtrlBase(), PCIDevice("Grackle"), PCIHost()
{
this->name = "Grackle";
supports_types(HWCompType::MEM_CTRL | HWCompType::MMIO_DEV |
HWCompType::PCI_HOST | HWCompType::PCI_DEV);
@ -255,7 +253,7 @@ void MPC106::setup_ram() {
}
if (!this->add_ram_region(0, ram_size)) {
LOG_F(ERROR, "MPC106 RAM allocation failed!");
LOG_F(WARNING, "MPC106 RAM allocation 0x%X..0x%X failed (maybe already exists?)", 0, ram_size - 1);
}
}

View File

@ -35,7 +35,7 @@ PsxCtrl::PsxCtrl(int bridge_num, std::string name)
// add MMIO region for the PSX control registers
add_mmio_region(0xF8000000, 0x70, this);
this->sys_id = 0x30040000; // TODO: use correct value here!
this->sys_id = 0x10000000;
this->chip_rev = 0; // old PSX, what's about PSX+?
this->sys_config = PSX_BUS_SPEED_50;
}

View File

@ -336,7 +336,6 @@ void CharIoSocket::rcv_disable()
bool CharIoSocket::rcv_char_available()
{
static int consecutivechars = 0;
static int count = 0;
if (consecutivechars >= 15) {
consecutivechars++;
@ -377,7 +376,7 @@ bool CharIoSocket::rcv_char_available()
if (sockfd != -1) {
if (FD_ISSET(sockfd, &readfds)) {
uint8_t c;
int received = recv(sockfd, &c, 1, 0);
int received = (int)recv(sockfd, &c, 1, 0);
if (received == -1) {
if (acceptfd == -1) {
//LOG_F(INFO, "socket sock read (not accepted yet) err: %s", strerror(errno)); // this happens once before accept
@ -443,7 +442,7 @@ int CharIoSocket::xmit_char(uint8_t c)
CharIoSocket::rcv_char_available();
if (acceptfd != -1) {
int sent = send(acceptfd, &c, 1, 0);
int sent = (int)send(acceptfd, &c, 1, 0);
if (sent == -1) {
LOG_F(INFO, "socket accept write err: %s", strerror(errno));
}
@ -463,7 +462,7 @@ int CharIoSocket::rcv_char(uint8_t *c)
CharIoSocket::rcv_char_available();
if (acceptfd != -1) {
int received = recv(acceptfd, c, 1, 0);
int received = (int)recv(acceptfd, c, 1, 0);
if (received == -1) {
LOG_F(INFO, "socket accept read err: %s", strerror(errno));
}

View File

@ -92,7 +92,6 @@ uint8_t EsccController::read(uint8_t reg_offset)
} else {
return this->ch_a->read_reg(this->reg_ptr);
}
this->reg_ptr = 0;
break;
case EsccReg::Port_B_Data:
return this->ch_b->receive_byte();

View File

@ -147,12 +147,12 @@ long sound_out_callback(cubeb_stream *stream, void *user_data,
out_frames = 0;
while (req_frames > 0) {
if (!dma_ch->pull_data(req_frames << 2, &got_len, &p_in)) {
if (!dma_ch->pull_data((uint32_t)req_frames << 2, &got_len, &p_in)) {
frames = got_len >> 2;
in_buf = (int16_t*)p_in;
for (int i = frames; i > 0; i--) {
for (int i = (int)frames; i > 0; i--) {
out_buf[0] = BYTESWAP_16(in_buf[0]);
out_buf[1] = BYTESWAP_16(in_buf[1]);
in_buf += 2;

View File

@ -557,7 +557,7 @@ void ATIRage::crtc_enable() {
void ATIRage::draw_hw_cursor(uint8_t *dst_buf, int dst_pitch) {
uint8_t *src_buf, *src_row, *dst_row, px4;
int horz_offset = READ_DWORD_LE_A(&this->mm_regs[ATI_CUR_HORZ_VERT_OFF]) & 0x3F;
// int horz_offset = READ_DWORD_LE_A(&this->mm_regs[ATI_CUR_HORZ_VERT_OFF]) & 0x3F;
int vert_offset = (READ_DWORD_LE_A(&this->mm_regs[ATI_CUR_HORZ_VERT_OFF]) >> 16) & 0x3F;
src_buf = &this->vram_ptr[(READ_DWORD_LE_A(&this->mm_regs[ATI_CUR_OFFSET]) * 8)];

View File

@ -59,6 +59,7 @@ ControlVideo::ControlVideo()
this->vendor_id = PCI_VENDOR_APPLE;
this->device_id = 3;
this->class_rev = 0;
this->bars_cfg[0] = 0xFFFFFFFFUL; // I/O region (4 bytes but it's weird because bit 1 is set)
this->bars_cfg[1] = 0xFFFFF000UL; // base address for the HW registers (4KB)
this->bars_cfg[2] = 0xFC000000UL; // base address for the VRAM (64MB)
@ -84,6 +85,10 @@ ControlVideo::ControlVideo()
void ControlVideo::notify_bar_change(int bar_num)
{
switch (bar_num) {
case 0:
this->io_base = this->bars[bar_num] & ~3;
LOG_F(INFO, "Control: I/O space address set to 0x%08X", this->io_base);
break;
case 1:
if (this->regs_base != (this->bars[bar_num] & 0xFFFFFFF0UL)) {
this->regs_base = this->bars[bar_num] & 0xFFFFFFF0UL;
@ -116,18 +121,22 @@ uint32_t ControlVideo::read(uint32_t rgn_start, uint32_t offset, int size)
}
}
switch (offset >> 4) {
case ControlRegs::TEST:
result = this->test;
break;
case ControlRegs::MON_SENSE:
result = this->cur_mon_id << 6;
break;
default:
LOG_F(INFO, "read from 0x%08X:0x%08X", rgn_start, offset);
if (rgn_start == this->regs_base) {
switch (offset >> 4) {
case ControlRegs::TEST:
result = this->test;
break;
case ControlRegs::MON_SENSE:
result = this->cur_mon_id << 6;
break;
default:
LOG_F(INFO, "read from 0x%08X:0x%08X", rgn_start, offset);
}
return BYTESWAP_32(result);
}
return BYTESWAP_32(result);
return 0;
}
void ControlVideo::write(uint32_t rgn_start, uint32_t offset, uint32_t value, int size)
@ -141,75 +150,77 @@ void ControlVideo::write(uint32_t rgn_start, uint32_t offset, uint32_t value, in
return;
}
value = BYTESWAP_32(value);
if (rgn_start == this->regs_base) {
value = BYTESWAP_32(value);
switch (offset >> 4) {
case ControlRegs::VFPEQ:
case ControlRegs::VFP:
case ControlRegs::VAL:
case ControlRegs::VBP:
case ControlRegs::VBPEQ:
case ControlRegs::VSYNC:
case ControlRegs::VHLINE:
case ControlRegs::PIPED:
case ControlRegs::HPIX:
case ControlRegs::HFP:
case ControlRegs::HAL:
case ControlRegs::HBWAY:
case ControlRegs::HSP:
case ControlRegs::HEQ:
case ControlRegs::HLFLN:
case ControlRegs::HSERR:
this->swatch_params[(offset >> 4) - 1] = value;
break;
case ControlRegs::TEST:
if (this->test != value) {
if ((this->test & ~TEST_STROBE) != (value & ~TEST_STROBE)) {
this->test = value;
this->test_shift = 0;
LOG_F(9, "New TEST value: 0x%08X", this->test);
} else {
LOG_F(9, "TEST strobe bit flipped, new value: 0x%08X", value);
this->test = value;
if (++this->test_shift >= 3) {
LOG_F(9, "Received TEST reg value: 0x%08X", this->test & ~TEST_STROBE);
if ((this->test ^ this->prev_test) & 0x400) {
if (this->test & 0x400) {
this->disable_display();
} else {
this->enable_display();
switch (offset >> 4) {
case ControlRegs::VFPEQ:
case ControlRegs::VFP:
case ControlRegs::VAL:
case ControlRegs::VBP:
case ControlRegs::VBPEQ:
case ControlRegs::VSYNC:
case ControlRegs::VHLINE:
case ControlRegs::PIPED:
case ControlRegs::HPIX:
case ControlRegs::HFP:
case ControlRegs::HAL:
case ControlRegs::HBWAY:
case ControlRegs::HSP:
case ControlRegs::HEQ:
case ControlRegs::HLFLN:
case ControlRegs::HSERR:
this->swatch_params[(offset >> 4) - 1] = value;
break;
case ControlRegs::TEST:
if (this->test != value) {
if ((this->test & ~TEST_STROBE) != (value & ~TEST_STROBE)) {
this->test = value;
this->test_shift = 0;
LOG_F(9, "New TEST value: 0x%08X", this->test);
} else {
LOG_F(9, "TEST strobe bit flipped, new value: 0x%08X", value);
this->test = value;
if (++this->test_shift >= 3) {
LOG_F(9, "Received TEST reg value: 0x%08X", this->test & ~TEST_STROBE);
if ((this->test ^ this->prev_test) & 0x400) {
if (this->test & 0x400) {
this->disable_display();
} else {
this->enable_display();
}
this->prev_test = this->test;
}
this->prev_test = this->test;
}
}
}
break;
case ControlRegs::GBASE:
this->fb_base = value;
break;
case ControlRegs::ROW_WORDS:
this->row_words = value;
break;
case ControlRegs::MON_SENSE:
LOG_F(9, "Control: monitor sense written with 0x%X", value);
value = (value >> 3) & 7;
this->cur_mon_id = this->display_id->read_monitor_sense(value & 7, value ^ 7);
break;
case ControlRegs::ENABLE:
this->flags = value;
break;
case ControlRegs::GSC_DIVIDE:
this->clock_divider = value;
break;
case ControlRegs::REFRESH_COUNT:
LOG_F(INFO, "Control: refresh count set to 0x%08X", value);
break;
case ControlRegs::INT_ENABLE:
this->int_enable = value;
break;
default:
LOG_F(INFO, "write 0x%08X to 0x%08X:0x%08X", value, rgn_start, offset);
}
break;
case ControlRegs::GBASE:
this->fb_base = value;
break;
case ControlRegs::ROW_WORDS:
this->row_words = value;
break;
case ControlRegs::MON_SENSE:
LOG_F(9, "Control: monitor sense written with 0x%X", value);
value = (value >> 3) & 7;
this->cur_mon_id = this->display_id->read_monitor_sense(value & 7, value ^ 7);
break;
case ControlRegs::ENABLE:
this->flags = value;
break;
case ControlRegs::GSC_DIVIDE:
this->clock_divider = value;
break;
case ControlRegs::REFRESH_COUNT:
LOG_F(INFO, "Control: refresh count set to 0x%08X", value);
break;
case ControlRegs::INT_ENABLE:
this->int_enable = value;
break;
default:
LOG_F(INFO, "write 0x%08X to 0x%08X:0x%08X", value, rgn_start, offset);
}
}

View File

@ -117,6 +117,7 @@ private:
std::unique_ptr<uint8_t[]> vram_ptr;
uint32_t vram_size;
uint32_t io_base = 0;
uint32_t vram_base = 0;
uint32_t regs_base = 0;
uint32_t prev_test = 0x433;

View File

@ -88,7 +88,6 @@ DisplayID::DisplayID(uint8_t std_code, uint8_t ext_code)
uint8_t DisplayID::read_monitor_sense(uint8_t levels, uint8_t dirs)
{
uint8_t scl, sda;
uint16_t result;
switch(this->id_kind) {
case Disp_Id_Kind::DDC2B:

View File

@ -36,6 +36,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
int initialize_catalyst(std::string& id)
{
LOG_F(INFO, "Building machine catalyst");
PlatinumCtrl* platinum_obj;
PCIHost *pci_host = dynamic_cast<PCIHost*>(gMachineObj->get_comp_by_name("Bandit1"));

View File

@ -269,7 +269,8 @@ void MachineFactory::set_machine_settings(map<string, string> &settings) {
string MachineFactory::machine_name_from_rom(string& rom_filepath) {
ifstream rom_file;
uint32_t file_size, config_info_offset, rom_id;
size_t file_size;
uint32_t config_info_offset, rom_id;
char rom_id_str[17];
string machine_name = "";
@ -354,7 +355,7 @@ int MachineFactory::load_boot_rom(string& rom_filepath) {
gMachineObj->get_comp_by_type(HWCompType::MEM_CTRL));
if ((rom_reg = mem_ctrl->find_rom_region())) {
mem_ctrl->set_data(rom_reg->start, sysrom_mem, file_size);
mem_ctrl->set_data(rom_reg->start, sysrom_mem, (uint32_t)file_size);
} else {
ABORT_F("Could not locate physical ROM region!");
}

View File

@ -47,6 +47,8 @@ int get_cpu_pll_value(const uint64_t cpu_freq_hz) {
int initialize_gazelle(std::string& id)
{
LOG_F(INFO, "Building machine gazelle");
PCIHost *pci_host = dynamic_cast<PCIHost*>(gMachineObj->get_comp_by_name("PsxPci1"));
// register O'Hare I/O controller with the main PCI bus

View File

@ -94,6 +94,8 @@ static void setup_ram_slot(std::string name, int i2c_addr, int capacity_megs) {
int initialize_gossamer(std::string& id)
{
LOG_F(INFO, "Building machine gossamer");
// get pointer to the memory controller/PCI host bridge object
MPC106* grackle_obj = dynamic_cast<MPC106*>(gMachineObj->get_comp_by_name("Grackle"));
@ -107,7 +109,7 @@ int initialize_gossamer(std::string& id)
gMachineObj->add_device("MachineID", std::unique_ptr<GossamerID>(new GossamerID(sys_reg)));
grackle_obj->add_mmio_region(
0xFF000004, 4096, dynamic_cast<MMIODevice*>(gMachineObj->get_comp_by_name("MachineID")));
0xFF000000 + 4, 4096 - 4, dynamic_cast<MMIODevice*>(gMachineObj->get_comp_by_name("MachineID")));
// allocate ROM region
if (!grackle_obj->add_rom_region(0xFFC00000, 0x400000)) {

View File

@ -38,6 +38,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
int initialize_pdm(std::string& id)
{
LOG_F(INFO, "Building machine pdm");
uint16_t machine_id;
// get raw pointer to HMC object

View File

@ -73,7 +73,7 @@ bool StrProperty::check_val(std::string str)
uint32_t IntProperty::get_int()
{
try {
uint32_t result = strtoul(this->get_string().c_str(), 0, 0);
uint32_t result = (uint32_t)strtoul(this->get_string().c_str(), 0, 0);
/* perform value check */
if (!this->check_val(result)) {

View File

@ -36,6 +36,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
int initialize_tnt(std::string& id)
{
LOG_F(INFO, "Building machine tnt");
HammerheadCtrl* memctrl_obj;
PCIHost *pci_host = dynamic_cast<PCIHost*>(gMachineObj->get_comp_by_name("Bandit1"));