mirror of
https://github.com/StrikerX3/StrikeBox.git
synced 2024-06-21 13:52:36 -04:00
Flesh out SuperIO and make devices map themselves
Only enable SuperIO on Debug Kits
This commit is contained in:
parent
bc09528869
commit
550a870680
|
@ -11,6 +11,12 @@ CMOS::CMOS() {
|
|||
void CMOS::Reset() {
|
||||
}
|
||||
|
||||
bool CMOS::MapIO(IOMapper *mapper) {
|
||||
if (!mapper->MapIODevice(PORT_CMOS_BASE, PORT_CMOS_COUNT, this)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
|
@ -18,6 +18,8 @@ public:
|
|||
CMOS();
|
||||
void Reset();
|
||||
|
||||
bool MapIO(IOMapper *mapper);
|
||||
|
||||
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:
|
||||
|
|
|
@ -27,6 +27,12 @@ void i8254::Reset() {
|
|||
m_running = false;
|
||||
}
|
||||
|
||||
bool i8254::MapIO(IOMapper *mapper) {
|
||||
if (!mapper->MapIODevice(PORT_PIT_BASE, PORT_PIT_COUNT, this)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool i8254::IORead(uint32_t port, uint32_t *value, uint8_t size) {
|
||||
*value = 0;
|
||||
return true;
|
||||
|
|
|
@ -20,10 +20,12 @@ public:
|
|||
i8254(i8259 *pic, float tickRate = 1000.0f);
|
||||
void Reset();
|
||||
|
||||
void Run();
|
||||
bool MapIO(IOMapper *mapper);
|
||||
|
||||
bool IORead(uint32_t port, uint32_t *value, uint8_t size) override;
|
||||
bool IOWrite(uint32_t port, uint32_t value, uint8_t size) override;
|
||||
|
||||
void Run();
|
||||
private:
|
||||
i8259 *m_pic;
|
||||
float m_tickRate;
|
||||
|
|
|
@ -71,6 +71,14 @@ void i8259::Reset(int pic) {
|
|||
UpdateIRQ(pic);
|
||||
}
|
||||
|
||||
bool i8259::MapIO(IOMapper *mapper) {
|
||||
if (!mapper->MapIODevice(PORT_PIC_MASTER_BASE, PORT_PIC_COUNT, this)) return false;
|
||||
if (!mapper->MapIODevice(PORT_PIC_SLAVE_BASE, PORT_PIC_COUNT, this)) return false;
|
||||
if (!mapper->MapIODevice(PORT_PIC_ELCR_BASE, PORT_PIC_COUNT, this)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void i8259::RaiseIRQ(int index) {
|
||||
if (index <= 7) {
|
||||
SetIRQ(PIC_MASTER, index, true);
|
||||
|
|
|
@ -26,6 +26,8 @@ public:
|
|||
i8259(Cpu *cpu);
|
||||
void Reset();
|
||||
|
||||
bool MapIO(IOMapper *mapper);
|
||||
|
||||
bool IORead(uint32_t port, uint32_t *value, uint8_t size) override;
|
||||
bool IOWrite(uint32_t port, uint32_t value, uint8_t size) override;
|
||||
|
||||
|
|
|
@ -6,17 +6,119 @@
|
|||
namespace openxbox {
|
||||
|
||||
SuperIO::SuperIO() {
|
||||
memset(m_configRegs, 0, sizeof(m_configRegs));
|
||||
memset(m_deviceRegs, 0, sizeof(m_deviceRegs));
|
||||
|
||||
m_configRegs[CONFIG_PORT_LOW] = (uint8_t)(PORT_SUPERIO_BASE & 0xFF);
|
||||
m_configRegs[CONFIG_PORT_HIGH] = (uint8_t)(PORT_SUPERIO_BASE >> 8);
|
||||
|
||||
m_inConfigMode = false;
|
||||
m_selectedReg = 0;
|
||||
|
||||
// TODO: init serial cores
|
||||
}
|
||||
|
||||
void SuperIO::Reset() {
|
||||
}
|
||||
|
||||
bool SuperIO::MapIO(IOMapper *mapper) {
|
||||
if (!mapper->MapIODevice(PORT_SUPERIO_BASE, PORT_SUPERIO_COUNT, this)) return false;
|
||||
if (!mapper->MapIODevice(PORT_SUPERIO_UART_BASE_1, PORT_SUPERIO_UART_COUNT_1, this)) return false;
|
||||
if (!mapper->MapIODevice(PORT_SUPERIO_UART_BASE_2, PORT_SUPERIO_UART_COUNT_2, this)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SuperIO::UpdateDevices() {
|
||||
// TODO: update serial cores
|
||||
}
|
||||
|
||||
bool SuperIO::IORead(uint32_t port, uint32_t *value, uint8_t size) {
|
||||
log_spew("SuperIO::IORead: port = 0x%x, size = %d\n", port, size);
|
||||
|
||||
switch (port) {
|
||||
case PORT_SUPERIO_CONFIG:
|
||||
*value = 0;
|
||||
return true;
|
||||
case PORT_SUPERIO_DATA:
|
||||
if (m_selectedReg < MAX_CONFIG_REG) {
|
||||
*value = m_configRegs[m_selectedReg];
|
||||
}
|
||||
else {
|
||||
if (m_configRegs[CONFIG_DEVICE_NUMBER] >= MAX_DEVICE) {
|
||||
log_warning("SuperIO::IORead: Device number out of range! %d >= %d\n", m_configRegs[CONFIG_DEVICE_NUMBER], MAX_DEVICE);
|
||||
*value = 0;
|
||||
}
|
||||
else {
|
||||
uint8_t* dev = m_deviceRegs[m_configRegs[CONFIG_DEVICE_NUMBER]];
|
||||
*value = dev[m_selectedReg];
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (port >= PORT_SUPERIO_UART_BASE_1 && port <= PORT_SUPERIO_UART_END_1) {
|
||||
// TODO: redirect to serial device 1
|
||||
}
|
||||
|
||||
if (port >= PORT_SUPERIO_UART_BASE_2 && port <= PORT_SUPERIO_UART_END_2) {
|
||||
// TODO: redirect to serial device 2
|
||||
}
|
||||
|
||||
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_spew("SuperIO::IOWrite: port = 0x%x, size = %d, value = 0x%x\n", port, size, value);
|
||||
|
||||
switch (port) {
|
||||
case PORT_SUPERIO_CONFIG:
|
||||
if (value == ENTER_CONFIG_KEY) {
|
||||
#ifdef _DEBUG
|
||||
if (m_inConfigMode) {
|
||||
log_warning("SuperIO::IOWrite: Attempted to reenter configuration mode\n");
|
||||
}
|
||||
log_debug("SuperIO::IOWrite: Entering configuration mode\n");
|
||||
#endif
|
||||
m_inConfigMode = true;
|
||||
}
|
||||
else if (value == EXIT_CONFIG_KEY) {
|
||||
#ifdef _DEBUG
|
||||
if (!m_inConfigMode) {
|
||||
log_warning("SuperIO::IOWrite: Attempted to reexit configuration mode\n");
|
||||
}
|
||||
log_debug("SuperIO::IOWrite: Exiting configuration mode\n");
|
||||
#endif
|
||||
m_inConfigMode = false;
|
||||
|
||||
UpdateDevices();
|
||||
}
|
||||
else {
|
||||
m_selectedReg = value;
|
||||
}
|
||||
return true;
|
||||
case PORT_SUPERIO_DATA:
|
||||
if (m_selectedReg < MAX_CONFIG_REG) {
|
||||
// Global configuration register
|
||||
m_configRegs[m_selectedReg] = value;
|
||||
}
|
||||
else {
|
||||
// Device register
|
||||
#ifdef _DEBUG
|
||||
if (m_configRegs[CONFIG_DEVICE_NUMBER] >= MAX_DEVICE) {
|
||||
log_warning("SuperIO::IOWrite: Device number out of range! %d >= %d\n", m_configRegs[CONFIG_DEVICE_NUMBER], MAX_DEVICE);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
uint8_t* dev = m_deviceRegs[m_configRegs[CONFIG_DEVICE_NUMBER]];
|
||||
dev[m_selectedReg] = value;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
log_warning("SuperIO::IOWrite: Unhandled write! port = 0x%x, size = %d, value = 0x%x\n", port, size, value);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -6,23 +6,65 @@
|
|||
|
||||
namespace openxbox {
|
||||
|
||||
#define PORT_SUPERIO_CONFIG 0x2E
|
||||
#define PORT_SUPERIO_DATA 0x2F
|
||||
#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_BASE PORT_SUPERIO_CONFIG
|
||||
#define PORT_SUPERIO_COUNT 2
|
||||
|
||||
#define PORT_SUPERIO_UART_BASE_1 0x3F8
|
||||
#define PORT_SUPERIO_UART_END_1 0x3FF
|
||||
#define PORT_SUPERIO_UART_COUNT_1 (PORT_SUPERIO_UART_END_1 - PORT_SUPERIO_UART_BASE_1 + 1)
|
||||
|
||||
#define PORT_SUPERIO_UART_BASE_2 0x2F8
|
||||
#define PORT_SUPERIO_UART_END_2 0x2FF
|
||||
#define PORT_SUPERIO_UART_COUNT_2 (PORT_SUPERIO_UART_END_2 - PORT_SUPERIO_UART_BASE_2 + 1)
|
||||
|
||||
|
||||
#define DEVICE_FDD 0x0
|
||||
#define DEVICE_PARALLEL_PORT 0x3
|
||||
#define DEVICE_SERIAL_PORT_1 0x4
|
||||
#define DEVICE_SERIAL_PORT_2 0x5
|
||||
#define DEVICE_KEYBOARD 0x7
|
||||
#define DEVICE_GAME_PORT 0x9
|
||||
#define DEVICE_PME 0xA
|
||||
#define DEVICE_MPU_401 0xB
|
||||
#define MAX_DEVICE 0xC
|
||||
|
||||
#define ENTER_CONFIG_KEY 0x55
|
||||
#define EXIT_CONFIG_KEY 0xAA
|
||||
|
||||
#define MAX_CONFIG_REG 0x30
|
||||
#define MAX_DEVICE_REGS 0xFF
|
||||
|
||||
#define CONFIG_DEVICE_NUMBER 0x07
|
||||
#define CONFIG_PORT_LOW 0x26
|
||||
#define CONFIG_PORT_HIGH 0x27
|
||||
|
||||
#define CONFIG_DEVICE_ACTIVATE 0x30
|
||||
#define CONFIG_DEVICE_BASE_ADDRESS_HIGH 0x60
|
||||
#define CONFIG_DEVICE_BASE_ADDRESS_LOW 0x61
|
||||
#define CONFIG_DEVICE_INETRRUPT 0x70
|
||||
|
||||
#define PORT_SUPERIO_UART_BASE 0x3F8
|
||||
#define PORT_SUPERIO_UART_COUNT 8
|
||||
|
||||
class SuperIO : public IODevice {
|
||||
public:
|
||||
SuperIO();
|
||||
void Reset();
|
||||
|
||||
bool MapIO(IOMapper *mapper);
|
||||
|
||||
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:
|
||||
void UpdateDevices();
|
||||
|
||||
bool m_inConfigMode;
|
||||
uint32_t m_selectedReg;
|
||||
|
||||
uint8_t m_configRegs[MAX_CONFIG_REG];
|
||||
uint8_t m_deviceRegs[MAX_DEVICE][MAX_DEVICE_REGS];
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -5,6 +5,14 @@
|
|||
|
||||
namespace openxbox {
|
||||
|
||||
bool PCIBus::MapIO(IOMapper *mapper) {
|
||||
if (!mapper->MapIODevice(PORT_PCI_CONFIG_ADDRESS, 1, this)) return false;
|
||||
if (!mapper->MapIODevice(PORT_PCI_CONFIG_DATA, 4, this)) return false;
|
||||
if (!mapper->AddDevice(this)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PCIBus::ConnectDevice(uint32_t deviceId, PCIDevice *pDevice) {
|
||||
if (m_Devices.find(deviceId) != m_Devices.end()) {
|
||||
log_warning("PCIBus: Attempting to connect two devices to the same device address\n");
|
||||
|
|
|
@ -31,6 +31,8 @@ typedef struct {
|
|||
|
||||
class PCIBus : public IODevice {
|
||||
public:
|
||||
bool MapIO(IOMapper *mapper);
|
||||
|
||||
void ConnectDevice(uint32_t deviceId, PCIDevice *pDevice);
|
||||
|
||||
bool IORead(uint32_t port, uint32_t *value, uint8_t size) override;
|
||||
|
|
|
@ -187,13 +187,17 @@ 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();
|
||||
if (settings->hw_model == DebugKit) {
|
||||
m_SuperIO = new SuperIO();
|
||||
}
|
||||
|
||||
m_i8259->Reset();
|
||||
m_i8254->Reset();
|
||||
m_SuperIO->Reset();
|
||||
m_CMOS->Reset();
|
||||
if (settings->hw_model == DebugKit) {
|
||||
m_SuperIO->Reset();
|
||||
}
|
||||
|
||||
// Create busses
|
||||
m_PCIBus = new PCIBus();
|
||||
|
@ -254,22 +258,13 @@ 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_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_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);
|
||||
m_i8259->MapIO(&m_ioMapper);
|
||||
m_i8254->MapIO(&m_ioMapper);
|
||||
m_CMOS->MapIO(&m_ioMapper);
|
||||
m_PCIBus->MapIO(&m_ioMapper);
|
||||
if (settings->hw_model == DebugKit) {
|
||||
m_SuperIO->MapIO(&m_ioMapper);
|
||||
}
|
||||
|
||||
// TODO: Handle other SMBUS Addresses, like PIC_ADDRESS, XCALIBUR_ADDRESS
|
||||
// Resources:
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
namespace openxbox {
|
||||
|
||||
class IOMapper;
|
||||
|
||||
/*!
|
||||
* Abstract base class that represents devices that respond to port-mapped
|
||||
* and/or memory-mapped I/O.
|
||||
|
@ -16,6 +18,8 @@ namespace openxbox {
|
|||
*/
|
||||
class IODevice {
|
||||
public:
|
||||
virtual bool MapIO(IOMapper *mapper) = 0;
|
||||
|
||||
virtual bool IORead(uint32_t port, uint32_t *value, uint8_t size);
|
||||
virtual bool IOWrite(uint32_t port, uint32_t value, uint8_t size);
|
||||
|
||||
|
|
Loading…
Reference in a new issue