Stubbed SuperIO and CMOS devices

Properly clean up devices when Xbox is deleted
This commit is contained in:
StrikerX3 2018-03-11 13:32:13 -03:00
parent 131b7f9c80
commit bc09528869
10 changed files with 175 additions and 11 deletions

View file

@ -0,0 +1,24 @@
#include "cmos.h"
#include "openxbox/log.h"
#include "openxbox/io.h"
namespace openxbox {
CMOS::CMOS() {
}
void CMOS::Reset() {
}
bool CMOS::IORead(uint32_t port, uint32_t *value, uint8_t size) {
log_warning("CMOS::IORead: Unhandled read! port = 0x%x, size = %d\n", port, size);
return false;
}
bool CMOS::IOWrite(uint32_t port, uint32_t value, uint8_t size) {
log_warning("CMOS::IOWrite: Unhandled write! port = 0x%x, size = %d, value = 0x%x\n", port, size, value);
return false;
}
}

View file

@ -0,0 +1,26 @@
#pragma once
#include <cstdint>
#include "openxbox/cpu.h"
namespace openxbox {
#define PORT_CMOS_CONTROL 0x70
#define PORT_CMOS_DATA 0x71
#define PORT_CMOS_EXT_CONTROL 0x72
#define PORT_CMOS_BASE PORT_CMOS_CONTROL
#define PORT_CMOS_COUNT (PORT_CMOS_EXT_CONTROL - PORT_CMOS_CONTROL + 1)
class CMOS : public IODevice {
public:
CMOS();
void Reset();
bool IORead(uint32_t port, uint32_t *value, uint8_t size) override;
bool IOWrite(uint32_t port, uint32_t value, uint8_t size) override;
private:
};
}

View file

@ -12,6 +12,9 @@ namespace openxbox {
#define PORT_PIT_DATA_2 0x42
#define PORT_PIT_COMMAND 0x43
#define PORT_PIT_BASE PORT_PIT_DATA_0
#define PORT_PIT_COUNT (PORT_PIT_COMMAND - PORT_PIT_DATA_0 + 1)
class i8254 : public IODevice {
public:
i8254(i8259 *pic, float tickRate = 1000.0f);

View file

@ -13,6 +13,11 @@ namespace openxbox {
#define PORT_PIC_MASTER_ELCR 0x4D0
#define PORT_PIC_SLAVE_ELCR 0x4D1
#define PORT_PIC_MASTER_BASE PORT_PIC_MASTER_COMMAND
#define PORT_PIC_SLAVE_BASE PORT_PIC_SLAVE_COMMAND
#define PORT_PIC_ELCR_BASE PORT_PIC_MASTER_ELCR
#define PORT_PIC_COUNT 2
#define PIC_MASTER 0
#define PIC_SLAVE 1

View file

@ -0,0 +1,24 @@
#include "superio.h"
#include "openxbox/log.h"
#include "openxbox/io.h"
namespace openxbox {
SuperIO::SuperIO() {
}
void SuperIO::Reset() {
}
bool SuperIO::IORead(uint32_t port, uint32_t *value, uint8_t size) {
log_warning("SuperIO::IORead: Unhandled read! port = 0x%x, size = %d\n", port, size);
return false;
}
bool SuperIO::IOWrite(uint32_t port, uint32_t value, uint8_t size) {
log_warning("SuperIO::IOWrite: Unhandled write! port = 0x%x, size = %d, value = 0x%x\n", port, size, value);
return false;
}
}

View file

@ -0,0 +1,28 @@
#pragma once
#include <cstdint>
#include "openxbox/cpu.h"
namespace openxbox {
#define PORT_SUPERIO_CONFIG 0x2E
#define PORT_SUPERIO_DATA 0x2F
#define PORT_SUPERIO_BASE PORT_SUPERIO_CONFIG
#define PORT_SUPERIO_COUNT 2
#define PORT_SUPERIO_UART_BASE 0x3F8
#define PORT_SUPERIO_UART_COUNT 8
class SuperIO : public IODevice {
public:
SuperIO();
void Reset();
bool IORead(uint32_t port, uint32_t *value, uint8_t size) override;
bool IOWrite(uint32_t port, uint32_t value, uint8_t size) override;
private:
};
}

View file

@ -50,6 +50,15 @@ NV2ADevice::NV2ADevice(uint16_t vendorID, uint16_t deviceID, uint8_t revisionID,
{
}
NV2ADevice::~NV2ADevice() {
m_running = false;
m_PFIFO.cache1.cache_cond.notify_all();
m_PFIFO.puller_thread.join();
m_VblankThread.join();
}
// PCI Device functions
void NV2ADevice::Init() {
@ -67,6 +76,7 @@ void NV2ADevice::Init() {
Reset();
m_running = true;
m_PFIFO.puller_thread = std::thread(PFIFO_Puller_Thread, this);
m_VblankThread = std::thread(VBlankThread, this);
}
@ -2287,15 +2297,18 @@ void NV2ADevice::pfifo_run_pusher() {
}
}
void* NV2ADevice::PFIFO_Puller_Thread(NV2ADevice *nv2a) {
void NV2ADevice::PFIFO_Puller_Thread(NV2ADevice *nv2a) {
Cache1State *state = &nv2a->m_PFIFO.cache1;
while (true) {
while (nv2a->m_running) {
// Scope the lock so that it automatically unlocks at tne end of this block
{
std::unique_lock<std::mutex> lk(state->mutex);
while (state->cache.empty() || !state->pull_enabled) {
state->cache_cond.wait(lk);
if (!nv2a->m_running) {
break;
}
}
// Copy cache to working_cache
@ -2409,7 +2422,7 @@ void NV2ADevice::VBlankThread(NV2ADevice *nv2a) {
auto nextStop = high_resolution_clock::now();
auto interval = duration<long long, std::ratio<1, 1000000>>((long long)(1000000.0f / 60.0f));
while (true) {
while (nv2a->m_running) {
nv2a->m_PCRTC.pendingInterrupts |= NV_PCRTC_INTR_0_VBLANK;
nv2a->UpdateIRQ();

View file

@ -12,10 +12,11 @@ namespace openxbox {
class NV2ADevice : public PCIDevice {
public:
// constructor
NV2ADevice(uint16_t vendorID, uint16_t deviceID, uint8_t revisionID,
uint8_t *pSystemRAM, uint32_t systemRAMSize,
i8259 *pic);
~NV2ADevice();
// PCI Device functions
void Init();
@ -114,7 +115,7 @@ private:
void pfifo_run_pusher();
static void* PFIFO_Puller_Thread(NV2ADevice* pNV2a);
static void PFIFO_Puller_Thread(NV2ADevice* pNV2a);
static void VBlankThread(NV2ADevice* pNV2A);
void UpdateIRQ();
@ -138,6 +139,7 @@ private:
VGACommonState m_VGAState;
bool m_running;
std::vector<NV2ABlockInfo> m_MemoryRegions;
std::thread m_VblankThread;
};

View file

@ -29,12 +29,38 @@ Xbox::Xbox(IOpenXBOXCPUModule *cpuModule)
/*!
* Destructor
*/
Xbox::~Xbox()
{
Xbox::~Xbox() {
if (m_cpu) m_cpuModule->FreeCPU(m_cpu);
if (m_ram) vfree(m_ram);
if (m_rom) vfree(m_rom);
if (m_memRegion) delete m_memRegion;
if (m_SMC != nullptr) delete m_SMC;
if (m_EEPROM != nullptr) delete m_EEPROM;
if (m_TVEncoder != nullptr) delete m_TVEncoder;
if (m_SMBus != nullptr) delete m_SMBus;
if (m_MCPXRAM != nullptr) delete m_MCPXRAM;
if (m_LPC != nullptr) delete m_LPC;
if (m_USB1 != nullptr) delete m_USB1;
if (m_USB2 != nullptr) delete m_USB2;
if (m_NVNet != nullptr) delete m_NVNet;
if (m_NVAPU != nullptr) delete m_NVAPU;
if (m_AC97 != nullptr) delete m_AC97;
if (m_IDE != nullptr) delete m_IDE;
if (m_NV2A != nullptr) delete m_NV2A;
if (m_PCIBus != nullptr) delete m_PCIBus;
if (m_HostBridge != nullptr) delete m_HostBridge;
if (m_PCIBridge != nullptr) delete m_PCIBridge;
if (m_AGPBridge != nullptr) delete m_AGPBridge;
if (m_CMOS != nullptr) delete m_CMOS;
if (m_SuperIO != nullptr) delete m_SuperIO;
if (m_i8254 != nullptr) delete m_i8254;
if (m_i8259 != nullptr) delete m_i8259;
}
/*!
@ -161,9 +187,13 @@ int Xbox::Initialize(OpenXBOXSettings *settings)
// Create PIT and PIC
m_i8259 = new i8259(m_cpu);
m_i8254 = new i8254(m_i8259, settings->hw_sysclock_tickRate);
m_SuperIO = new SuperIO();
m_CMOS = new CMOS();
m_i8259->Reset();
m_i8254->Reset();
m_SuperIO->Reset();
m_CMOS->Reset();
// Create busses
m_PCIBus = new PCIBus();
@ -224,15 +254,20 @@ int Xbox::Initialize(OpenXBOXSettings *settings)
m_PCIBus->ConnectDevice(PCI_DEVID(1, PCI_DEVFN(0, 0)), m_NV2A);
// Map I/O ports and MMIO addresses
m_ioMapper.MapIODevice(PORT_PIC_MASTER_COMMAND, 2, m_i8259);
m_ioMapper.MapIODevice(PORT_PIC_SLAVE_COMMAND, 2, m_i8259);
m_ioMapper.MapIODevice(PORT_PIC_MASTER_ELCR, 2, m_i8259);
m_ioMapper.MapIODevice(PORT_PIC_MASTER_BASE, PORT_PIC_COUNT, m_i8259);
m_ioMapper.MapIODevice(PORT_PIC_SLAVE_BASE, PORT_PIC_COUNT, m_i8259);
m_ioMapper.MapIODevice(PORT_PIC_ELCR_BASE, PORT_PIC_COUNT, m_i8259);
m_ioMapper.MapIODevice(PORT_PIT_DATA_0, 4, m_i8254);
m_ioMapper.MapIODevice(PORT_PIT_BASE, PORT_PIT_COUNT, m_i8254);
m_ioMapper.MapIODevice(PORT_PCI_CONFIG_ADDRESS, 1, m_PCIBus);
m_ioMapper.MapIODevice(PORT_PCI_CONFIG_DATA, 4, m_PCIBus);
m_ioMapper.MapIODevice(PORT_SUPERIO_BASE, PORT_SUPERIO_COUNT, m_SuperIO);
m_ioMapper.MapIODevice(PORT_SUPERIO_UART_BASE, PORT_SUPERIO_UART_COUNT, m_SuperIO);
m_ioMapper.MapIODevice(PORT_CMOS_BASE, PORT_CMOS_COUNT, m_CMOS);
// Add the PCI bus as a dynamic I/O mapper
m_ioMapper.AddDevice(m_PCIBus);

View file

@ -22,6 +22,8 @@
#include "openxbox/hw/basic/i8254.h"
#include "openxbox/hw/basic/i8259.h"
#include "openxbox/hw/basic/superio.h"
#include "openxbox/hw/basic/cmos.h"
#include "openxbox/hw/bus/smbus.h"
#include "openxbox/hw/bus/pcibus.h"
@ -66,6 +68,8 @@ protected:
i8254 *m_i8254;
i8259 *m_i8259;
SuperIO *m_SuperIO;
CMOS *m_CMOS;
SMBus *m_SMBus;
SMCDevice *m_SMC;