mirror of
https://github.com/holub/mame
synced 2025-04-16 05:24:54 +03:00
Initial work towards a sis630 based chipset driver (#9635)
- Add more or less complete implementations of sis630_host, sis950_lpc, sis630_gui, sis5513_ide, sis7001_usb, sis7018_audio, sis900_eth devices; - Removed gamecstl.cpp in favour to the new sis630.cpp driver; - i386.cpp: enable CMOV feature for Pentium III and 4; - i386.cpp: add PSN stub feature for Pentium III; New machines marked as NOT_WORKING ---------------------------------- Shuttle MS-11 [Angelo Salese, archive.org]
This commit is contained in:
parent
09062b24a3
commit
e6180e3510
@ -2737,6 +2737,22 @@ if (MACHINES["PCI"]~=null) then
|
||||
MAME_DIR .. "src/devices/machine/vrc5074.h",
|
||||
MAME_DIR .. "src/devices/machine/gt64xxx.cpp",
|
||||
MAME_DIR .. "src/devices/machine/gt64xxx.h",
|
||||
MAME_DIR .. "src/devices/machine/sis5513_ide.cpp",
|
||||
MAME_DIR .. "src/devices/machine/sis5513_ide.h",
|
||||
MAME_DIR .. "src/devices/machine/sis630_host.cpp",
|
||||
MAME_DIR .. "src/devices/machine/sis630_host.h",
|
||||
MAME_DIR .. "src/devices/machine/sis630_gui.cpp",
|
||||
MAME_DIR .. "src/devices/machine/sis630_gui.h",
|
||||
MAME_DIR .. "src/devices/machine/sis7001_usb.cpp",
|
||||
MAME_DIR .. "src/devices/machine/sis7001_usb.h",
|
||||
MAME_DIR .. "src/devices/machine/sis7018_audio.cpp",
|
||||
MAME_DIR .. "src/devices/machine/sis7018_audio.h",
|
||||
MAME_DIR .. "src/devices/machine/sis900_eth.cpp",
|
||||
MAME_DIR .. "src/devices/machine/sis900_eth.h",
|
||||
MAME_DIR .. "src/devices/machine/sis950_lpc.cpp",
|
||||
MAME_DIR .. "src/devices/machine/sis950_lpc.h",
|
||||
MAME_DIR .. "src/devices/machine/sis950_smbus.cpp",
|
||||
MAME_DIR .. "src/devices/machine/sis950_smbus.h",
|
||||
MAME_DIR .. "src/devices/machine/sis85c496.cpp",
|
||||
MAME_DIR .. "src/devices/machine/sis85c496.h",
|
||||
}
|
||||
|
@ -2116,6 +2116,7 @@ files {
|
||||
MAME_DIR .. "src/mame/drivers/pcxt.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/quakeat.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/queen.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/sis630.cpp",
|
||||
}
|
||||
|
||||
createMAMEProjects(_target, _subtarget, "igs")
|
||||
@ -4844,7 +4845,6 @@ files {
|
||||
MAME_DIR .. "src/mame/drivers/gambl186.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/galaxi.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/galgame.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/gamecstl.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/gamemasters.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/gammagic.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/gamtor.cpp",
|
||||
|
@ -3390,6 +3390,7 @@ files {
|
||||
MAME_DIR .. "src/mame/drivers/nforcepc.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/pc.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/pcipc.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/sis630.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/tandy1t.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/tosh1000.cpp",
|
||||
MAME_DIR .. "src/mame/machine/tosh1000_bram.cpp",
|
||||
|
@ -3333,12 +3333,38 @@ void pentium3_device::device_reset()
|
||||
|
||||
// [ 0:0] FPU on chip
|
||||
// [ 4:4] Time Stamp Counter
|
||||
// [ 8:8] CMPXCHG8B instruction
|
||||
// [ D:D] PTE Global Bit
|
||||
m_feature_flags = 0x00002011; // TODO: enable relevant flags here
|
||||
// [15:15] CMOV and FCMOV
|
||||
// [18:18] PSN (Processor Serial Number, P3 only)
|
||||
m_feature_flags = 0x0004a111; // TODO: enable relevant flags here
|
||||
|
||||
CHANGE_PC(m_eip);
|
||||
}
|
||||
|
||||
void pentium3_device::opcode_cpuid()
|
||||
{
|
||||
switch (REG32(EAX))
|
||||
{
|
||||
case 0x00000003:
|
||||
{
|
||||
// TODO: lower part of 96 bits s/n for Pentium III processors only (ditched in 4)
|
||||
// (upper 32-bits part is in EAX=1 EAX return)
|
||||
// NB: if this is triggered from an Arcade system then there's a very good chance
|
||||
// that is trying to tie the serial as a form of copy protection cfr. gamecstl
|
||||
logerror("CPUID with EAX=00000003 (Pentium III PSN?) at %08x!\n", m_eip);
|
||||
REG32(EAX) = 0x00000000;
|
||||
REG32(EBX) = 0x00000000;
|
||||
REG32(ECX) = 0x01234567;
|
||||
REG32(EDX) = 0x89abcdef;
|
||||
CYCLES(CYCLES_CPUID);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
pentium_pro_device::opcode_cpuid();
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Intel Pentium 4 */
|
||||
|
||||
@ -3402,7 +3428,9 @@ void pentium4_device::device_reset()
|
||||
m_cpu_version = REG32(EDX);
|
||||
|
||||
// [ 0:0] FPU on chip
|
||||
m_feature_flags = 0x00000001; // TODO: enable relevant flags here
|
||||
// [ 8:8] CMPXCHG8B instruction
|
||||
// [15:15] CMOV and FCMOV
|
||||
m_feature_flags = 0x00008101; // TODO: enable relevant flags here
|
||||
|
||||
CHANGE_PC(m_eip);
|
||||
}
|
||||
|
@ -1650,6 +1650,8 @@ public:
|
||||
protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
virtual void opcode_cpuid() override;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,5 +1,10 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Olivier Galibert
|
||||
/*
|
||||
* References:
|
||||
* - PCI local bus (rev 2.x)
|
||||
* - https://wiki.osdev.org/PCI
|
||||
*/
|
||||
#include "emu.h"
|
||||
#include "pci.h"
|
||||
|
||||
@ -87,6 +92,12 @@ pci_device::pci_device(const machine_config &mconfig, device_type type, const ch
|
||||
}
|
||||
}
|
||||
|
||||
// main_id << 16 = vendor ID ($00-$01)
|
||||
// main_id & 0xffff = device ID ($02-$03)
|
||||
// revision = board versioning ($08)
|
||||
// pclass = programming interface/sub class code/base class code ($09-$0b)
|
||||
// subsystem_id << 16 = sub vendor ID ($2c-$2d) - NB: not all cards have these
|
||||
// subsystem_id & 0xffff = sub device ID ($2e-$2f) /
|
||||
void pci_device::set_ids(uint32_t _main_id, uint8_t _revision, uint32_t _pclass, uint32_t _subsystem_id)
|
||||
{
|
||||
main_id = _main_id;
|
||||
@ -257,6 +268,17 @@ void pci_device::expansion_base_w(offs_t offset, uint32_t data, uint32_t mem_mas
|
||||
remap_cb();
|
||||
}
|
||||
|
||||
// if non-zero a CAPability PoinTeR marks an offset in PCI config space where a standard extension is located
|
||||
// For example if capptr_r is 0xc0 then [offset+0xc0] has a capability identifier that is set with:
|
||||
// bits 31-16 <capability dependant, usually revision and supported sub-features>
|
||||
// bits 15-8 next capptr offset, 0x00 to determine the given item as last
|
||||
// bits 7-0 capability ID:
|
||||
// - 0x01 PMI Power Management Interface
|
||||
// - 0x02 AGP Accelerated Graphics Port
|
||||
// - 0x03 VPD Vital Product Data
|
||||
// - 0x04 Slot Identification
|
||||
// - 0x05 MSI Message Signaled Interrupts
|
||||
// - 0x06 CompactPCI Hot Swap
|
||||
uint8_t pci_device::capptr_r()
|
||||
{
|
||||
return 0x00;
|
||||
|
@ -193,7 +193,7 @@ public:
|
||||
uint16_t iolimitu_r();
|
||||
void iolimitu_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
uint16_t bridge_control_r();
|
||||
void bridge_control_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
virtual void bridge_control_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
|
||||
protected:
|
||||
enum
|
||||
|
363
src/devices/machine/sis5513_ide.cpp
Normal file
363
src/devices/machine/sis5513_ide.cpp
Normal file
@ -0,0 +1,363 @@
|
||||
// license: BSD-3-Clause
|
||||
// copyright-holders: Angelo Salese
|
||||
/**************************************************************************************************
|
||||
|
||||
SiS 5513 IDE controller
|
||||
|
||||
TODO:
|
||||
- Derive from common pci-ide.cpp interface
|
||||
(what flavour that emulates tho? PCI regs 0x40-0x52 don't match)
|
||||
|
||||
**************************************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "sis5513_ide.h"
|
||||
|
||||
#define LOG_IO (1U << 1) // log PCI register accesses
|
||||
#define LOG_TODO (1U << 2) // log unimplemented registers
|
||||
#define LOG_MAP (1U << 3) // log full remaps
|
||||
|
||||
#define VERBOSE (LOG_GENERAL | LOG_IO | LOG_TODO | LOG_MAP)
|
||||
//#define LOG_OUTPUT_FUNC osd_printf_warning
|
||||
|
||||
#include "logmacro.h"
|
||||
|
||||
#define LOGIO(...) LOGMASKED(LOG_IO, __VA_ARGS__)
|
||||
#define LOGMAP(...) LOGMASKED(LOG_MAP, __VA_ARGS__)
|
||||
#define LOGTODO(...) LOGMASKED(LOG_TODO, __VA_ARGS__)
|
||||
|
||||
DEFINE_DEVICE_TYPE(SIS5513_IDE, sis5513_ide_device, "sis5513_ide", "SiS 5513 IDE Controller")
|
||||
|
||||
sis5513_ide_device::sis5513_ide_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: pci_device(mconfig, SIS5513_IDE, tag, owner, clock)
|
||||
, m_ide1(*this, "ide1")
|
||||
, m_ide2(*this, "ide2")
|
||||
, m_irq_pri_callback(*this)
|
||||
, m_irq_sec_callback(*this)
|
||||
, m_bus_master_space(*this, finder_base::DUMMY_TAG, AS_PROGRAM)
|
||||
{
|
||||
}
|
||||
|
||||
void sis5513_ide_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
BUS_MASTER_IDE_CONTROLLER(config, m_ide1).options(ata_devices, "hdd", nullptr, false);
|
||||
m_ide1->irq_handler().set([this](int state) { m_irq_pri_callback(state); });
|
||||
m_ide1->set_bus_master_space(m_bus_master_space);
|
||||
|
||||
BUS_MASTER_IDE_CONTROLLER(config, m_ide2).options(ata_devices, "cdrom", nullptr, false);
|
||||
m_ide2->irq_handler().set([this](int state) { m_irq_sec_callback(state); });
|
||||
m_ide2->set_bus_master_space(m_bus_master_space);
|
||||
}
|
||||
|
||||
void sis5513_ide_device::config_map(address_map &map)
|
||||
{
|
||||
pci_device::config_map(map);
|
||||
// map(0x10, 0x4f).unmaprw();
|
||||
map(0x09, 0x09).w(FUNC(sis5513_ide_device::prog_if_w));
|
||||
// base I/O relocation (effective only when native mode is on)
|
||||
// map(0x10, 0x13) Primary channel command base
|
||||
// map(0x14, 0x17) Primary channel control base
|
||||
// map(0x18, 0x1b) Secondary channel command base
|
||||
// map(0x1c, 0x1f) Secondary channel control base
|
||||
|
||||
// map(0x20, 0x23) Bus master IDE control register base (0x10 I/O regs)
|
||||
map(0x10, 0x23).rw(FUNC(sis5513_ide_device::bar_r), FUNC(sis5513_ide_device::bar_w));
|
||||
map(0x24, 0x27).unmaprw();
|
||||
map(0x40, 0x52).rw(FUNC(sis5513_ide_device::unmap_log_r), FUNC(sis5513_ide_device::unmap_log_w));
|
||||
map(0x4a, 0x4a).rw(FUNC(sis5513_ide_device::ide_ctrl_0_r), FUNC(sis5513_ide_device::ide_ctrl_0_w));
|
||||
map(0x52, 0x52).rw(FUNC(sis5513_ide_device::ide_misc_ctrl_r), FUNC(sis5513_ide_device::ide_misc_ctrl_w));
|
||||
|
||||
|
||||
// map(0x2c, 0x2f) subsystem ID (written once)
|
||||
|
||||
// map(0x3c, 0x3d) interrupt line/pin
|
||||
|
||||
// map(0x40, 0x40) IDE Primary channel master data recovery time
|
||||
// map(0x41, 0x41) IDE Primary channel master data active time (Ultra DMA)
|
||||
// map(0x42, 0x42) IDE Primary channel slave data recovery time
|
||||
// map(0x43, 0x43) IDE Primary channel slave data active time (Ultra DMA)
|
||||
// map(0x44, 0x47) ^ Same for IDE Secondary
|
||||
|
||||
// map(0x48, 0x48) IDE status
|
||||
// map(0x4a, 0x4b) IDE general control regs
|
||||
|
||||
// map(0x4c, 0x4d) prefetch count of primary channel
|
||||
// map(0x4e, 0x4f) prefetch count of secondary channel
|
||||
|
||||
// map(0x52, 0x52) IDE misc control regs
|
||||
}
|
||||
|
||||
#if 0
|
||||
void sis5513_ide_device::compatible_io_map(address_map &map)
|
||||
{
|
||||
map(0x0170, 0x0177).rw(FUNC(sis5513_ide_device::ide2_read32_cs0_r), FUNC(sis5513_ide_device::ide2_write32_cs0_w));
|
||||
map(0x01f0, 0x01f7).rw(FUNC(sis5513_ide_device::ide1_read32_cs0_r), FUNC(sis5513_ide_device::ide1_write32_cs0_w));
|
||||
map(0x0376, 0x0376).rw(FUNC(sis5513_ide_device::ide2_read_cs1_r), FUNC(sis5513_ide_device::ide2_write_cs1_w));
|
||||
map(0x03f6, 0x03f6).rw(FUNC(sis5513_ide_device::ide1_read_cs1_r), FUNC(sis5513_ide_device::ide1_write_cs1_w));
|
||||
}
|
||||
#endif
|
||||
|
||||
// $1f0
|
||||
void sis5513_ide_device::ide1_command_map(address_map &map)
|
||||
{
|
||||
map(0, 7).rw(FUNC(sis5513_ide_device::ide1_read32_cs0_r), FUNC(sis5513_ide_device::ide1_write32_cs0_w));
|
||||
}
|
||||
|
||||
// $3f4
|
||||
void sis5513_ide_device::ide1_control_map(address_map &map)
|
||||
{
|
||||
map(2, 2).rw(FUNC(sis5513_ide_device::ide1_read_cs1_r), FUNC(sis5513_ide_device::ide1_write_cs1_w));
|
||||
}
|
||||
|
||||
// $170
|
||||
void sis5513_ide_device::ide2_command_map(address_map &map)
|
||||
{
|
||||
map(0, 7).rw(FUNC(sis5513_ide_device::ide2_read32_cs0_r), FUNC(sis5513_ide_device::ide2_write32_cs0_w));
|
||||
}
|
||||
|
||||
// $374
|
||||
void sis5513_ide_device::ide2_control_map(address_map &map)
|
||||
{
|
||||
map(2, 2).rw(FUNC(sis5513_ide_device::ide2_read_cs1_r), FUNC(sis5513_ide_device::ide2_write_cs1_w));
|
||||
}
|
||||
|
||||
void sis5513_ide_device::bus_master_ide_control_map(address_map &map)
|
||||
{
|
||||
map(0x0, 0x7).rw(m_ide1, FUNC(bus_master_ide_controller_device::bmdma_r), FUNC(bus_master_ide_controller_device::bmdma_w));
|
||||
map(0x8, 0xf).rw(m_ide2, FUNC(bus_master_ide_controller_device::bmdma_r), FUNC(bus_master_ide_controller_device::bmdma_w));
|
||||
}
|
||||
|
||||
void sis5513_ide_device::device_start()
|
||||
{
|
||||
pci_device::device_start();
|
||||
|
||||
m_irq_pri_callback.resolve();
|
||||
m_irq_sec_callback.resolve();
|
||||
|
||||
add_map(8, M_IO, FUNC(sis5513_ide_device::ide1_command_map));
|
||||
add_map(4, M_IO, FUNC(sis5513_ide_device::ide1_control_map));
|
||||
add_map(8, M_IO, FUNC(sis5513_ide_device::ide2_command_map));
|
||||
add_map(4, M_IO, FUNC(sis5513_ide_device::ide2_control_map));
|
||||
add_map(16, M_IO, FUNC(sis5513_ide_device::bus_master_ide_control_map));
|
||||
}
|
||||
|
||||
|
||||
void sis5513_ide_device::device_reset()
|
||||
{
|
||||
pci_device::device_reset();
|
||||
|
||||
command = 0x0000;
|
||||
status = 0x0000;
|
||||
pclass = 0x01018a;
|
||||
m_ide_ctrl0 = 0;
|
||||
m_ide_misc = 0;
|
||||
m_bar[0] = 0x1f0;
|
||||
m_bar[1] = 0x3f4;
|
||||
m_bar[2] = 0x170;
|
||||
m_bar[3] = 0x374;
|
||||
m_bar[4] = 0xf00;
|
||||
for (int i = 0; i < 5; i++)
|
||||
bank_infos[i].adr = m_bar[i];
|
||||
remap_cb();
|
||||
}
|
||||
|
||||
inline bool sis5513_ide_device::ide1_mode()
|
||||
{
|
||||
return (pclass & 0x3) == 3;
|
||||
}
|
||||
|
||||
inline bool sis5513_ide_device::ide2_mode()
|
||||
{
|
||||
return (pclass & 0xc) == 0xc;
|
||||
}
|
||||
|
||||
// In compatible mode BARs with legacy addresses but can values written can still be readout.
|
||||
// In practice we need to override writes and make sure we flush remapping accordingly
|
||||
inline void sis5513_ide_device::flush_ide_mode()
|
||||
{
|
||||
// Map Primary IDE Channel
|
||||
if (ide1_mode())
|
||||
{
|
||||
// PCI Mode
|
||||
pci_device::address_base_w(0, m_bar[0]);
|
||||
pci_device::address_base_w(1, m_bar[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Legacy Mode
|
||||
pci_device::address_base_w(0, 0x1f0);
|
||||
pci_device::address_base_w(1, 0x3f4);
|
||||
}
|
||||
|
||||
// Map Secondary IDE Channel
|
||||
if (ide2_mode())
|
||||
{
|
||||
// PCI Mode
|
||||
pci_device::address_base_w(2, m_bar[2]);
|
||||
pci_device::address_base_w(3, m_bar[3]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Legacy Mode
|
||||
pci_device::address_base_w(2, 0x170);
|
||||
pci_device::address_base_w(3, 0x374);
|
||||
}
|
||||
}
|
||||
|
||||
void sis5513_ide_device::prog_if_w(u8 data)
|
||||
{
|
||||
uint32_t oldVal = pclass;
|
||||
pclass = (pclass & ~(0xff)) | (data & 0xff);
|
||||
// Check for switch to/from compatibility (legacy) mode from/to pci mode
|
||||
if ((oldVal ^ pclass) & 0xf)
|
||||
flush_ide_mode();
|
||||
}
|
||||
|
||||
u32 sis5513_ide_device::bar_r(offs_t offset)
|
||||
{
|
||||
if (bank_reg_infos[offset].bank == -1)
|
||||
return 0;
|
||||
int bid = bank_reg_infos[offset].bank;
|
||||
if (bank_reg_infos[offset].hi)
|
||||
return bank_infos[bid].adr >> 32;
|
||||
int flags = bank_infos[bid].flags;
|
||||
return (m_bar[offset] & ~(bank_infos[bid].size - 1)) | (flags & M_IO ? 1 : 0) | (flags & M_64A ? 4 : 0) | (flags & M_PREF ? 8 : 0);
|
||||
}
|
||||
|
||||
void sis5513_ide_device::bar_w(offs_t offset, u32 data)
|
||||
{
|
||||
m_bar[offset] = data;
|
||||
// Bits 0 (primary) and 2 (secondary) control if the mapping is legacy or BAR
|
||||
switch (offset) {
|
||||
case 0 ... 1:
|
||||
if (ide1_mode())
|
||||
pci_device::address_base_w(offset, data);
|
||||
break;
|
||||
case 2 ... 3:
|
||||
if (ide2_mode())
|
||||
pci_device::address_base_w(offset, data);
|
||||
break;
|
||||
default:
|
||||
// Only the first 4 bars are controlled by pif
|
||||
pci_device::address_base_w(offset, data);
|
||||
}
|
||||
logerror("Mapping bar[%i] = %08x\n", offset, data);
|
||||
}
|
||||
|
||||
u8 sis5513_ide_device::ide_ctrl_0_r()
|
||||
{
|
||||
LOGIO("IDE ctrl 0 read [$4a] %02x\n", m_ide_ctrl0);
|
||||
return m_ide_ctrl0;
|
||||
}
|
||||
|
||||
void sis5513_ide_device::ide_ctrl_0_w(u8 data)
|
||||
{
|
||||
LOGIO("IDE ctrl 0 write [$4a] %02x\n", data);
|
||||
m_ide_ctrl0 = data;
|
||||
// TODO: bit 1 disables IDE ch. 0, bit 2 ch. 1
|
||||
// remap_cb();
|
||||
}
|
||||
|
||||
u8 sis5513_ide_device::ide_misc_ctrl_r()
|
||||
{
|
||||
LOGIO("IDE misc ctrl read [$52] %02x\n", m_ide_misc);
|
||||
return m_ide_misc;
|
||||
}
|
||||
|
||||
void sis5513_ide_device::ide_misc_ctrl_w(u8 data)
|
||||
{
|
||||
LOGIO("IDE misc ctrl write [$52] %02x\n", data);
|
||||
m_ide_misc = data;
|
||||
|
||||
const bool compatible_mode = BIT(m_ide_misc, 2);
|
||||
pclass &= 0xffff85;
|
||||
|
||||
if (compatible_mode)
|
||||
{
|
||||
//LOGMAP("- Compatible Mode\n");
|
||||
intr_pin = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Native Mode
|
||||
pclass |= 0xa;
|
||||
intr_pin = 1;
|
||||
}
|
||||
|
||||
flush_ide_mode();
|
||||
}
|
||||
|
||||
/*
|
||||
* Debugging
|
||||
*/
|
||||
|
||||
u8 sis5513_ide_device::unmap_log_r(offs_t offset)
|
||||
{
|
||||
LOGTODO("IDE Unemulated [%02x] R\n", offset + 0x40);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sis5513_ide_device::unmap_log_w(offs_t offset, u8 data)
|
||||
{
|
||||
LOGTODO("IDE Unemulated [%02x] %02x W\n", offset + 0x40, data);
|
||||
}
|
||||
|
||||
/*
|
||||
* Start of legacy handling, to be moved out
|
||||
*/
|
||||
|
||||
uint32_t sis5513_ide_device::ide1_read32_cs0_r(offs_t offset, uint32_t mem_mask)
|
||||
{
|
||||
if (!(command & 1))
|
||||
return 0xffffffff;
|
||||
return m_ide1->read_cs0(offset, mem_mask);
|
||||
}
|
||||
|
||||
void sis5513_ide_device::ide1_write32_cs0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
|
||||
{
|
||||
if (!(command & 1))
|
||||
return;
|
||||
m_ide1->write_cs0(offset, data, mem_mask);
|
||||
}
|
||||
|
||||
uint32_t sis5513_ide_device::ide2_read32_cs0_r(offs_t offset, uint32_t mem_mask)
|
||||
{
|
||||
if (!(command & 1))
|
||||
return 0xffffffff;
|
||||
return m_ide2->read_cs0(offset, mem_mask);
|
||||
}
|
||||
|
||||
void sis5513_ide_device::ide2_write32_cs0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
|
||||
{
|
||||
if (!(command & 1))
|
||||
return;
|
||||
m_ide2->write_cs0(offset, data, mem_mask);
|
||||
}
|
||||
|
||||
uint8_t sis5513_ide_device::ide1_read_cs1_r()
|
||||
{
|
||||
if (!(command & 1))
|
||||
return 0xff;
|
||||
return m_ide1->read_cs1(1, 0xff0000) >> 16;
|
||||
}
|
||||
|
||||
void sis5513_ide_device::ide1_write_cs1_w(uint8_t data)
|
||||
{
|
||||
if (!(command & 1))
|
||||
return;
|
||||
m_ide1->write_cs1(1, data << 16, 0xff0000);
|
||||
}
|
||||
|
||||
uint8_t sis5513_ide_device::ide2_read_cs1_r()
|
||||
{
|
||||
if (!(command & 1))
|
||||
return 0xff;
|
||||
return m_ide2->read_cs1(1, 0xff0000) >> 16;
|
||||
}
|
||||
|
||||
void sis5513_ide_device::ide2_write_cs1_w(uint8_t data)
|
||||
{
|
||||
if (!(command & 1))
|
||||
return;
|
||||
m_ide2->write_cs1(1, data << 16, 0xff0000);
|
||||
}
|
89
src/devices/machine/sis5513_ide.h
Normal file
89
src/devices/machine/sis5513_ide.h
Normal file
@ -0,0 +1,89 @@
|
||||
// license: BSD-3-Clause
|
||||
// copyright-holders: Angelo Salese
|
||||
|
||||
#ifndef MAME_MACHINE_SIS5513_IDE_H
|
||||
#define MAME_MACHINE_SIS5513_IDE_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pci.h"
|
||||
#include "machine/pci-ide.h"
|
||||
|
||||
class sis5513_ide_device : public pci_device
|
||||
{
|
||||
public:
|
||||
template <typename T> sis5513_ide_device(
|
||||
const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock,
|
||||
T &&host_tag, uint32_t bmspace = AS_PROGRAM
|
||||
) : sis5513_ide_device(mconfig, tag, owner, clock)
|
||||
{
|
||||
// IDE controller with 0xd0 as programming i/f "ATA Host Adapters standard"
|
||||
// pclass bits 1-3 are actually 1 when controller is in native mode
|
||||
// pclass bits 0-2 can be r/w from $09
|
||||
set_ids(0x10395513, 0xd0, 0x010180, 0x00);
|
||||
m_bus_master_space.set_tag(host_tag, bmspace);
|
||||
}
|
||||
sis5513_ide_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
auto irq_pri() { return m_irq_pri_callback.bind(); }
|
||||
auto irq_sec() { return m_irq_sec_callback.bind(); }
|
||||
|
||||
protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
|
||||
// virtual void reset_all_mappings() override;
|
||||
|
||||
// virtual void map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
|
||||
// uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) override;
|
||||
|
||||
virtual void config_map(address_map &map) override;
|
||||
|
||||
void ide1_command_map(address_map &map);
|
||||
void ide1_control_map(address_map &map);
|
||||
void ide2_command_map(address_map &map);
|
||||
void ide2_control_map(address_map &map);
|
||||
void bus_master_ide_control_map(address_map &map);
|
||||
private:
|
||||
required_device<bus_master_ide_controller_device> m_ide1;
|
||||
required_device<bus_master_ide_controller_device> m_ide2;
|
||||
devcb_write_line m_irq_pri_callback;
|
||||
devcb_write_line m_irq_sec_callback;
|
||||
required_address_space m_bus_master_space;
|
||||
|
||||
bool ide1_mode();
|
||||
bool ide2_mode();
|
||||
|
||||
u32 bar_r(offs_t offset);
|
||||
void bar_w(offs_t offset, u32 data);
|
||||
u32 m_bar[5]{};
|
||||
|
||||
void prog_if_w(u8 data);
|
||||
u8 ide_ctrl_0_r();
|
||||
void ide_ctrl_0_w(u8 data);
|
||||
u8 ide_misc_ctrl_r();
|
||||
void ide_misc_ctrl_w(u8 data);
|
||||
|
||||
u8 m_ide_ctrl0 = 0;
|
||||
u8 m_ide_misc = 0;
|
||||
|
||||
uint32_t ide1_read32_cs0_r(offs_t offset, uint32_t mem_mask = ~0);
|
||||
void ide1_write32_cs0_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
|
||||
uint32_t ide2_read32_cs0_r(offs_t offset, uint32_t mem_mask = ~0);
|
||||
void ide2_write32_cs0_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
|
||||
uint8_t ide1_read_cs1_r();
|
||||
void ide1_write_cs1_w(uint8_t data);
|
||||
uint8_t ide2_read_cs1_r();
|
||||
void ide2_write_cs1_w(uint8_t data);
|
||||
|
||||
// void compatible_io_map(address_map &map);
|
||||
void flush_ide_mode();
|
||||
|
||||
u8 unmap_log_r(offs_t offset);
|
||||
void unmap_log_w(offs_t offset, u8 data);
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(SIS5513_IDE, sis5513_ide_device)
|
||||
|
||||
#endif
|
709
src/devices/machine/sis630_gui.cpp
Normal file
709
src/devices/machine/sis630_gui.cpp
Normal file
@ -0,0 +1,709 @@
|
||||
// license: BSD-3-Clause
|
||||
// copyright-holders: Angelo Salese
|
||||
/**************************************************************************************************
|
||||
|
||||
SiS 630 Video GUI portion (SVGA-based) & 301 video bridge
|
||||
|
||||
- 630 core is SVGA based:
|
||||
\- has two sets of extended CRTC ($3c4) regs;
|
||||
\- a dedicated MPEG-2 video playback interface;
|
||||
\- a digital video interface to 301;
|
||||
- 301 draws to a separate monitor, and it was originally tied to a SiS300 AGP card,
|
||||
(which we don't have a dump of at the time of this writing):
|
||||
\- can select VGA, NTSC, PAL or LCD sources;
|
||||
\- Has separate set of VGA and RAMDAC regs;
|
||||
\- Has TV encoder;
|
||||
\- Has macrovision regs;
|
||||
- GUI is the 630 PCI/AGP i/f
|
||||
\- it's actually internal to the rest of 630;
|
||||
\- 301 is external but closely tied to it: the digital i/f ports (RIO+$4) selects where it
|
||||
should start drawing/sync etc. while the "VGA2 regs" (RIO+$14) seems to be a custom set
|
||||
rather than be related at all (i.e. it most likely be just capable to have VGA-like
|
||||
resolutions).
|
||||
- sis_main.c portions refers to the correlated Linux driver at
|
||||
https://github.com/torvalds/linux/blob/master/drivers/video/fbdev/sis/sis_main.c
|
||||
|
||||
TODO:
|
||||
- Backward port '630 GUI/PCI implementation to '300 and other flavours
|
||||
(needs VGA mods to do this properly);
|
||||
- 2d acceleration;
|
||||
- Turbo queue stuff;
|
||||
- AGP;
|
||||
- interlace (cfr. xubuntu 6.10 splash screen on 1024x768x32);
|
||||
- xubuntu 6.10 splash screen is decentered (zooming?)
|
||||
- xubuntu 6.10 splash screen text is unreadable or not visible depending on res selected;
|
||||
- Interface with '301 bridge (a lovely can of worms);
|
||||
|
||||
**************************************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "sis630_gui.h"
|
||||
|
||||
#define LOG_IO (1U << 1) // log PCI register accesses
|
||||
#define LOG_TODO (1U << 2) // log unimplemented registers
|
||||
#define LOG_MAP (1U << 3) // log full remaps
|
||||
#define LOG_AGP (1U << 4) // log AGP
|
||||
#define LOG_SVGA (1U << 5) // log SVGA
|
||||
|
||||
#define VERBOSE (LOG_GENERAL | LOG_IO | LOG_TODO | LOG_MAP | LOG_AGP | LOG_SVGA)
|
||||
//#define LOG_OUTPUT_FUNC osd_printf_warning
|
||||
|
||||
#include "logmacro.h"
|
||||
|
||||
#define LOGIO(...) LOGMASKED(LOG_IO, __VA_ARGS__)
|
||||
#define LOGMAP(...) LOGMASKED(LOG_MAP, __VA_ARGS__)
|
||||
#define LOGTODO(...) LOGMASKED(LOG_TODO, __VA_ARGS__)
|
||||
#define LOGAGP(...) LOGMASKED(LOG_AGP, __VA_ARGS__)
|
||||
#define LOGSVGA(...) LOGMASKED(LOG_SVGA, __VA_ARGS__)
|
||||
|
||||
/**************************
|
||||
*
|
||||
* SVGA implementation
|
||||
*
|
||||
*************************/
|
||||
|
||||
// TODO: later variant of 5598
|
||||
// (definitely doesn't have dual segment mode for instance)
|
||||
DEFINE_DEVICE_TYPE(SIS630_SVGA, sis630_svga_device, "sis630_svga", "SiS 630 SVGA")
|
||||
|
||||
sis630_svga_device::sis630_svga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: svga_device(mconfig, SIS630_SVGA, tag, owner, clock)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void sis630_svga_device::device_start()
|
||||
{
|
||||
svga_device::device_start();
|
||||
zero();
|
||||
|
||||
// Avoid an infinite loop when displaying. 0 is not possible anyway.
|
||||
vga.crtc.maximum_scan_line = 1;
|
||||
|
||||
// copy over interfaces
|
||||
vga.read_dipswitch.set(nullptr); //read_dipswitch;
|
||||
vga.svga_intf.seq_regcount = 0x05;
|
||||
vga.svga_intf.crtc_regcount = 0x27;
|
||||
vga.svga_intf.vram_size = 64*1024*1024;
|
||||
//vga.memory = std::make_unique<uint8_t []>(vga.svga_intf.vram_size);
|
||||
}
|
||||
|
||||
void sis630_svga_device::device_reset()
|
||||
{
|
||||
svga_device::device_reset();
|
||||
|
||||
m_svga_bank_reg_w = m_svga_bank_reg_r = 0;
|
||||
m_unlock_reg = false;
|
||||
//m_dual_seg_mode = false;
|
||||
}
|
||||
|
||||
// Page 144
|
||||
uint8_t sis630_svga_device::crtc_reg_read(uint8_t index)
|
||||
{
|
||||
if (index < 0x19)
|
||||
return svga_device::crtc_reg_read(index);
|
||||
|
||||
// make sure '301 CRT2 is not enabled
|
||||
if (index == 0x30)
|
||||
return 0;
|
||||
|
||||
if (index == 0x31)
|
||||
return 0x60;
|
||||
|
||||
if (index == 0x32)
|
||||
return 0x20;
|
||||
|
||||
// TODO: if one of these is 0xff then it enables a single port transfer to $b8000
|
||||
return m_crtc_ext_regs[index];
|
||||
}
|
||||
|
||||
void sis630_svga_device::crtc_reg_write(uint8_t index, uint8_t data)
|
||||
{
|
||||
if (index < 0x19)
|
||||
svga_device::crtc_reg_write(index, data);
|
||||
else
|
||||
{
|
||||
m_crtc_ext_regs[index] = data;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t sis630_svga_device::seq_reg_read(uint8_t index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
// extended id register
|
||||
case 0x05:
|
||||
return m_unlock_reg ? 0xa1 : 0x21;
|
||||
case 0x06:
|
||||
return m_ramdac_mode;
|
||||
case 0x07:
|
||||
return m_ext_misc_ctrl_0;
|
||||
case 0x0a:
|
||||
return m_ext_vert_overflow;
|
||||
case 0x0b ... 0x0c:
|
||||
return m_ext_horz_overflow[index - 0xb];
|
||||
case 0x0d:
|
||||
return vga.crtc.start_addr_latch >> 16;
|
||||
case 0x14:
|
||||
// sis_main.c calculates VRAM size in two ways:
|
||||
// 1. the legacy way ('300), by probing this register
|
||||
// 2. by reading '630 PCI host register $63 (as shared DRAM?)
|
||||
// Method 1 seems enough to enforce "64MB" message at POST,
|
||||
// 2 is probably more correct but unsure about how to change the shared area in BIOS
|
||||
// (shutms11 will always write a "0x41" on fresh CMOS then a "0x47"
|
||||
// on successive boots no matter what)
|
||||
const u8 bus_width = m_seq_ext_regs[index] & 0xc0;
|
||||
return (bus_width) | ((vga.svga_intf.vram_size / (1024 * 1024) - 1) & 0x3f);
|
||||
}
|
||||
|
||||
//LOGSVGA("Unemulated index R [%02x]\n", index);
|
||||
return m_seq_ext_regs[index];
|
||||
}
|
||||
|
||||
std::tuple<u8, u8> sis630_svga_device::flush_true_color_mode()
|
||||
{
|
||||
// punt if extended or true color is off
|
||||
if ((m_ramdac_mode & 0x12) != 0x12)
|
||||
return std::make_tuple(0, 0);
|
||||
|
||||
const u8 res = (m_ext_misc_ctrl_0 & 4) >> 2;
|
||||
|
||||
return std::make_tuple(res, res ^ 1);
|
||||
}
|
||||
|
||||
void sis630_svga_device::recompute_params()
|
||||
{
|
||||
// TODO: ext clock
|
||||
recompute_params_clock(1, XTAL(25'174'800).value());
|
||||
}
|
||||
|
||||
|
||||
void sis630_svga_device::seq_reg_write(uint8_t index, uint8_t data)
|
||||
{
|
||||
if (index < vga.svga_intf.seq_regcount)
|
||||
svga_device::seq_reg_write(index, data);
|
||||
else
|
||||
{
|
||||
if (index == 0x05)
|
||||
{
|
||||
m_unlock_reg = (data == 0x86);
|
||||
LOGSVGA("Unlock register write %02x (%s)\n", data, m_unlock_reg ? "unlocked" : "locked");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!m_unlock_reg)
|
||||
{
|
||||
LOGSVGA("Attempt to write to extended SVGA while locked [$%02x] -> %02x\n", index, data);
|
||||
return;
|
||||
}
|
||||
|
||||
m_seq_ext_regs[index] = data;
|
||||
|
||||
switch(index)
|
||||
{
|
||||
/*
|
||||
* x--- ---- GFX mode linear addressing enable
|
||||
* -x-- ---- GFX hardware cursor display
|
||||
* --x- ---- GFX mode interlace
|
||||
* ---x ---- True Color enable (ties with index 0x07 bit 2)
|
||||
* ---- x--- RGB16 enable
|
||||
* ---- -x-- RGB15 enable
|
||||
* ---- --x- enhanced GFX mode enable
|
||||
* ---- ---x enhanced text mode enable
|
||||
*/
|
||||
case 0x06:
|
||||
m_ramdac_mode = data;
|
||||
LOGSVGA("RAMDAC mode %02x\n", data);
|
||||
|
||||
if (!BIT(data, 1))
|
||||
{
|
||||
svga.rgb8_en = svga.rgb15_en = svga.rgb16_en = svga.rgb24_en = svga.rgb32_en = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (BIT(data, 2))
|
||||
svga.rgb15_en = 1;
|
||||
if (BIT(data, 3))
|
||||
svga.rgb16_en = 1;
|
||||
std::tie(svga.rgb24_en, svga.rgb32_en) = flush_true_color_mode();
|
||||
}
|
||||
break;
|
||||
case 0x07:
|
||||
LOGSVGA("Extended Misc. Control register 0 (%02x) %02x\n", index, data);
|
||||
m_ext_misc_ctrl_0 = data;
|
||||
std::tie(svga.rgb24_en, svga.rgb32_en) = flush_true_color_mode();
|
||||
break;
|
||||
case 0x0a:
|
||||
LOGSVGA("Extended vertical Overflow register (%02x) %02x\n", index, data);
|
||||
m_ext_vert_overflow = data;
|
||||
vga.crtc.vert_retrace_end = (vga.crtc.vert_retrace_end & 0xf) | ((data & 0x20) >> 1);
|
||||
vga.crtc.vert_blank_end = (vga.crtc.vert_blank_end & 0x00ff) | ((data & 0x10) << 4);
|
||||
vga.crtc.vert_retrace_start = (vga.crtc.vert_retrace_start & 0x03ff) | ((data & 0x08) << 7);
|
||||
vga.crtc.vert_blank_start = (vga.crtc.vert_blank_start & 0x03ff) | ((data & 0x04) << 8);
|
||||
vga.crtc.vert_disp_end = (vga.crtc.vert_disp_end & 0x03ff) | ((data & 0x02) << 9);
|
||||
vga.crtc.vert_total = (vga.crtc.vert_total & 0x03ff) | ((data & 0x01) << 10);
|
||||
recompute_params();
|
||||
break;
|
||||
case 0x0b:
|
||||
//m_dual_seg_mode = bool(BIT(data, 3));
|
||||
LOGSVGA("Extended horizontal Overflow 1 (%02x) %02x\n", index, data);
|
||||
m_ext_horz_overflow[0] = data;
|
||||
|
||||
vga.crtc.horz_retrace_start = (vga.crtc.horz_retrace_start & 0x00ff) | ((data & 0xc0) << 2);
|
||||
vga.crtc.horz_blank_start = (vga.crtc.horz_blank_start & 0x00ff) | ((data & 0x30) << 4);
|
||||
vga.crtc.horz_disp_end = (vga.crtc.horz_disp_end & 0x00ff) | ((data & 0x0c) << 6);
|
||||
vga.crtc.horz_total = (vga.crtc.horz_total & 0x00ff) | ((data & 0x03) << 8);
|
||||
|
||||
recompute_params();
|
||||
break;
|
||||
case 0x0c:
|
||||
LOGSVGA("Extended horizontal Overflow 2 (%02x) %02x\n", index, data);
|
||||
m_ext_horz_overflow[1] = data;
|
||||
|
||||
vga.crtc.horz_retrace_end = (vga.crtc.horz_retrace_end & 0x001f) | ((data & 0x04) << 3);
|
||||
vga.crtc.horz_blank_end = (vga.crtc.horz_blank_end & 0x003f) | ((data & 0x03) << 6);
|
||||
recompute_params();
|
||||
break;
|
||||
case 0x0d:
|
||||
LOGSVGA("Extended starting address register (%02x) %02x\n", index, data);
|
||||
vga.crtc.start_addr_latch &= ~0xff0000;
|
||||
vga.crtc.start_addr_latch |= data << 16;
|
||||
break;
|
||||
case 0x0e:
|
||||
LOGSVGA("Extended pitch register (%02x) %02x\n", index, data);
|
||||
// sis_main.c implicitly sets this with bits 0-3 granularity, assume being right
|
||||
vga.crtc.offset = (vga.crtc.offset & 0x00ff) | ((data & 0x0f) << 8);
|
||||
break;
|
||||
case 0x1e:
|
||||
if (data & 0x40)
|
||||
popmessage("Warning: enable 2d engine");
|
||||
break;
|
||||
case 0x20:
|
||||
if (data & 0x81)
|
||||
popmessage("Warning: %s %s", BIT(data, 7) ? "PCI address enabled" : "", BIT(data, 0) ? "memory map I/O enable" : "");
|
||||
break;
|
||||
default:
|
||||
LOGSVGA("Extended write %02x %02x\n", index, data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t sis630_svga_device::offset()
|
||||
{
|
||||
if (svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb24_en || svga.rgb32_en)
|
||||
return vga.crtc.offset << 3;
|
||||
return svga_device::offset();
|
||||
}
|
||||
|
||||
// read by gamecstl Kontron BIOS
|
||||
u8 sis630_svga_device::port_03c0_r(offs_t offset)
|
||||
{
|
||||
if (offset == 0xd)
|
||||
return m_svga_bank_reg_w;
|
||||
if (offset == 0xb)
|
||||
return m_svga_bank_reg_r;
|
||||
|
||||
return svga_device::port_03c0_r(offset);
|
||||
}
|
||||
|
||||
void sis630_svga_device::port_03c0_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
// TODO: for '630 it's always with dual segment enabled?
|
||||
|
||||
if (offset == 0xd)
|
||||
{
|
||||
//if (m_dual_seg_mode)
|
||||
m_svga_bank_reg_w = (data & 0x3f) * 0x10000;
|
||||
//else
|
||||
{
|
||||
// m_svga_bank_reg_w = (data >> 4) * 0x10000;
|
||||
// m_svga_bank_reg_r = (data & 0xf) * 0x10000;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (offset == 0xb)
|
||||
{
|
||||
//if (m_dual_seg_mode)
|
||||
m_svga_bank_reg_r = (data & 0x3f) * 0x10000;
|
||||
// otherwise ignored if dual segment mode disabled
|
||||
return;
|
||||
}
|
||||
|
||||
svga_device::port_03c0_w(offset, data);
|
||||
}
|
||||
|
||||
uint8_t sis630_svga_device::mem_r(offs_t offset)
|
||||
{
|
||||
if (svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb24_en || svga.rgb32_en)
|
||||
return svga_device::mem_linear_r(offset + m_svga_bank_reg_r);
|
||||
return svga_device::mem_r(offset);
|
||||
}
|
||||
|
||||
void sis630_svga_device::mem_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
if (svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb24_en || svga.rgb32_en)
|
||||
{
|
||||
svga_device::mem_linear_w(offset + m_svga_bank_reg_w, data);
|
||||
return;
|
||||
}
|
||||
svga_device::mem_w(offset, data);
|
||||
}
|
||||
|
||||
/*****************************
|
||||
*
|
||||
* 630 GUI PCI implementation
|
||||
*
|
||||
****************************/
|
||||
|
||||
DEFINE_DEVICE_TYPE(SIS630_GUI, sis630_gui_device, "sis630_gui", "SiS 630 GUI")
|
||||
|
||||
sis630_gui_device::sis630_gui_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: pci_device(mconfig, SIS630_GUI, tag, owner, clock)
|
||||
, m_svga(*this, "svga")
|
||||
, m_gui_rom(*this, "gui_rom")
|
||||
{
|
||||
set_ids(0x10396300, 0x00, 0x030000, 0x00);
|
||||
}
|
||||
|
||||
ROM_START( sis630gui )
|
||||
ROM_REGION32_LE( 0xc000, "gui_rom", ROMREGION_ERASEFF )
|
||||
// TODO: why the OEM ROM is 0xc000 in size?
|
||||
// 0x8000-0xbfff mostly contains a charset, may be either programmable via a dedicated interface
|
||||
// or the dump above is half size.
|
||||
// gamecstl dump ver. 2.06.50
|
||||
// (which actually writes to VRAM with the actual expansion ROM enabled, uh?)
|
||||
ROM_SYSTEM_BIOS( 0, "2.06.50", "Ver. 2.06.50 OEM" )
|
||||
ROMX_LOAD( "oemrom.bin", 0x0000, 0xc000, BAD_DUMP CRC(03d8df9d) SHA1(8fb80a2bf4067d9bebc90fb498448869ae795b2b), ROM_BIOS(0) )
|
||||
|
||||
// "SiS 630 (Ver. 2.02.1c) [AGP VGA] (Silicon Integrated Systems Corp.).bin"
|
||||
ROM_SYSTEM_BIOS( 1, "2.02.1c", "Ver. 2.02.1c" )
|
||||
ROMX_LOAD( "sis630.bin", 0x0000, 0x8000, BAD_DUMP CRC(f04ef9b0) SHA1(2396a79cd4045362bfc511090b146daa85902b4d), ROM_BIOS(1) )
|
||||
ROM_END
|
||||
|
||||
const tiny_rom_entry *sis630_gui_device::device_rom_region() const
|
||||
{
|
||||
return ROM_NAME(sis630gui);
|
||||
}
|
||||
|
||||
void sis630_gui_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
|
||||
screen.set_raw(XTAL(25'174'800), 900, 0, 640, 526, 0, 480);
|
||||
screen.set_screen_update(m_svga, FUNC(sis630_svga_device::screen_update));
|
||||
|
||||
SIS630_SVGA(config, m_svga, 0);
|
||||
m_svga->set_screen("screen");
|
||||
// 64MB according to POST
|
||||
// documentation claims 128MB, assume being wrong
|
||||
m_svga->set_vram_size(64*1024*1024);
|
||||
}
|
||||
|
||||
void sis630_gui_device::config_map(address_map &map)
|
||||
{
|
||||
pci_device::config_map(map);
|
||||
map(0x2c, 0x2d).r(FUNC(sis630_gui_device::subvendor_r));
|
||||
map(0x2e, 0x2f).r(FUNC(sis630_gui_device::subsystem_r));
|
||||
map(0x2c, 0x2f).w(FUNC(sis630_gui_device::subvendor_w));
|
||||
|
||||
// map(0x3c, 0x3d) irq line/pin
|
||||
|
||||
map(0x34, 0x34).r(FUNC(sis630_gui_device::capptr_r));
|
||||
|
||||
map(0x50, 0x53).r(FUNC(sis630_gui_device::agp_id_r));
|
||||
map(0x54, 0x57).r(FUNC(sis630_gui_device::agp_status_r));
|
||||
map(0x58, 0x5b).rw(FUNC(sis630_gui_device::agp_command_r), FUNC(sis630_gui_device::agp_command_w));
|
||||
map(0x5c, 0x5c).lr8(NAME([] () { return 0; })); // NULL terminator
|
||||
}
|
||||
|
||||
u8 sis630_gui_device::capptr_r()
|
||||
{
|
||||
return 0x50;
|
||||
}
|
||||
|
||||
// TODO: move to specific interface
|
||||
u32 sis630_gui_device::agp_id_r()
|
||||
{
|
||||
LOGAGP("Read AGP ID [$50]\n");
|
||||
// bits 23-16 AGP v1.0
|
||||
// bits 15-8 0x5c NEXT_PTR (which goes to NULL terminator, heh)
|
||||
// bits 7-0 CAP_ID (0x02 for AGP)
|
||||
return 0x00105c02;
|
||||
}
|
||||
|
||||
u32 sis630_gui_device::agp_status_r()
|
||||
{
|
||||
LOGAGP("Read AGP status [$54]\n");
|
||||
// RQ (1 + 1), 2X and 1X capable
|
||||
return 0x01000003;
|
||||
}
|
||||
|
||||
u32 sis630_gui_device::agp_command_r(offs_t offset, uint32_t mem_mask)
|
||||
{
|
||||
LOGAGP("Read AGP command [$58] %d %d %08x\n", m_agp.enable, m_agp.data_rate, mem_mask);
|
||||
// TODO: enable gets cleared by AGP_RESET, or even from PCI RST#
|
||||
return m_agp.enable << 8 | (m_agp.data_rate & 7);
|
||||
}
|
||||
|
||||
void sis630_gui_device::agp_command_w(offs_t offset, uint32_t data, uint32_t mem_mask)
|
||||
{
|
||||
LOGAGP("Write AGP command [$c8] %08x & %08x\n", data, mem_mask);
|
||||
|
||||
if (ACCESSING_BITS_8_15)
|
||||
{
|
||||
m_agp.enable = bool(BIT(m_agp.enable, 8));
|
||||
LOGAGP("- AGP_ENABLE = %d\n", m_agp.enable);
|
||||
}
|
||||
|
||||
if (ACCESSING_BITS_0_7)
|
||||
{
|
||||
// quick checker, to be translated into an AGP interface
|
||||
std::map<u8, std::string> agp_transfer_rates = {
|
||||
{ 0, "(illegal 0)" },
|
||||
{ 1, "1X" },
|
||||
{ 2, "2X" },
|
||||
{ 3, "(illegal 3)" }
|
||||
};
|
||||
|
||||
// make sure the AGP DATA_RATE specs are honored
|
||||
const u8 data_rate = data & 3;
|
||||
LOGAGP("- DATA_RATE = %s enabled=%d\n", agp_transfer_rates.at(data_rate), m_agp.enable);
|
||||
m_agp.data_rate = data_rate;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: may be common to PCI base interface, verify
|
||||
void sis630_gui_device::subvendor_w(offs_t offset, u32 data, u32 mem_mask)
|
||||
{
|
||||
// write once
|
||||
if (m_subsystem_logger_mask & mem_mask)
|
||||
{
|
||||
LOG("Warning: subvendor ID possible rewrite! old=%08x & %08x data=%08x & %08x\n"
|
||||
, subsystem_id
|
||||
, m_subsystem_logger_mask
|
||||
, data
|
||||
, mem_mask
|
||||
);
|
||||
}
|
||||
m_subsystem_logger_mask |= mem_mask;
|
||||
|
||||
COMBINE_DATA(&subsystem_id);
|
||||
LOGIO("subsystem ID write [$2c] %08x & %08x (%08x)\n", data, mem_mask, subsystem_id);
|
||||
}
|
||||
|
||||
void sis630_gui_device::memory_map(address_map &map)
|
||||
{
|
||||
map(0x0000000, 0x3ffffff).rw(m_svga, FUNC(sis630_svga_device::mem_linear_r), FUNC(sis630_svga_device::mem_linear_w)).umask32(0xffffffff);
|
||||
}
|
||||
|
||||
void sis630_gui_device::io_map(address_map &map)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// "Relocate I/O" -> RIO
|
||||
void sis630_gui_device::space_io_map(address_map &map)
|
||||
{
|
||||
// RIO + 0x00: video capture regs on '300, omitted or missing on '630
|
||||
// RIO + 0x02: MPEG-2 video playback
|
||||
// RIO + 0x04: digital video interface (to '301 only?)
|
||||
// RIO + 0x10: 301 TV encoder
|
||||
// RIO + 0x12: 301 macrovision regs
|
||||
// RIO + 0x14: 301 VGA2 regs
|
||||
// RIO + 0x16: 301 RAMDAC
|
||||
// RIO + 0x30/+0x40/+0x50: omitted, legacy '300/'630 VGA regs?
|
||||
// (gamecstl definitely tries to access 0x44 index 5 for readback extension ID)
|
||||
map(0x30, 0x3f).rw(FUNC(sis630_gui_device::vga_3b0_r), FUNC(sis630_gui_device::vga_3b0_w));
|
||||
map(0x40, 0x4f).rw(FUNC(sis630_gui_device::vga_3c0_r), FUNC(sis630_gui_device::vga_3c0_w));
|
||||
map(0x50, 0x5f).rw(FUNC(sis630_gui_device::vga_3d0_r), FUNC(sis630_gui_device::vga_3d0_w));
|
||||
}
|
||||
|
||||
void sis630_gui_device::legacy_memory_map(address_map &map)
|
||||
{
|
||||
map(0xa0000, 0xbffff).rw(FUNC(sis630_gui_device::vram_r), FUNC(sis630_gui_device::vram_w));
|
||||
}
|
||||
|
||||
void sis630_gui_device::legacy_io_map(address_map &map)
|
||||
{
|
||||
map(0x03b0, 0x03bf).rw(FUNC(sis630_gui_device::vga_3b0_r), FUNC(sis630_gui_device::vga_3b0_w));
|
||||
map(0x03c0, 0x03cf).rw(FUNC(sis630_gui_device::vga_3c0_r), FUNC(sis630_gui_device::vga_3c0_w));
|
||||
map(0x03d0, 0x03df).rw(FUNC(sis630_gui_device::vga_3d0_r), FUNC(sis630_gui_device::vga_3d0_w));
|
||||
}
|
||||
|
||||
void sis630_gui_device::map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
|
||||
uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void sis630_gui_device::device_start()
|
||||
{
|
||||
pci_device::device_start();
|
||||
|
||||
add_map(64*1024*1024, M_MEM, FUNC(sis630_gui_device::memory_map));
|
||||
// claims 128KB, which goes outside the pentium range.
|
||||
// Assume memory mapped, given the size should be yet another VGA memory compatible window.
|
||||
add_map(128*1024, M_MEM, FUNC(sis630_gui_device::io_map));
|
||||
add_map(128, M_IO, FUNC(sis630_gui_device::space_io_map));
|
||||
|
||||
add_rom((u8 *)m_gui_rom->base(), m_gui_rom->bytes());
|
||||
|
||||
// INTA#
|
||||
intr_pin = 1;
|
||||
}
|
||||
|
||||
void sis630_gui_device::device_reset()
|
||||
{
|
||||
pci_device::device_reset();
|
||||
|
||||
command = 0x0004;
|
||||
status = 0x0220;
|
||||
|
||||
m_subsystem_logger_mask = 0;
|
||||
}
|
||||
|
||||
// TODO: remove these trampolines
|
||||
uint8_t sis630_gui_device::vram_r(offs_t offset)
|
||||
{
|
||||
return downcast<sis630_svga_device *>(m_svga.target())->mem_r(offset);
|
||||
}
|
||||
|
||||
void sis630_gui_device::vram_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
downcast<sis630_svga_device *>(m_svga.target())->mem_w(offset, data);
|
||||
}
|
||||
|
||||
u32 sis630_gui_device::vga_3b0_r(offs_t offset, uint32_t mem_mask)
|
||||
{
|
||||
uint32_t result = 0;
|
||||
if (ACCESSING_BITS_0_7)
|
||||
result |= downcast<sis630_svga_device *>(m_svga.target())->port_03b0_r(offset * 4 + 0) << 0;
|
||||
if (ACCESSING_BITS_8_15)
|
||||
result |= downcast<sis630_svga_device *>(m_svga.target())->port_03b0_r(offset * 4 + 1) << 8;
|
||||
if (ACCESSING_BITS_16_23)
|
||||
result |= downcast<sis630_svga_device *>(m_svga.target())->port_03b0_r(offset * 4 + 2) << 16;
|
||||
if (ACCESSING_BITS_24_31)
|
||||
result |= downcast<sis630_svga_device *>(m_svga.target())->port_03b0_r(offset * 4 + 3) << 24;
|
||||
return result;
|
||||
}
|
||||
|
||||
void sis630_gui_device::vga_3b0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
|
||||
{
|
||||
if (ACCESSING_BITS_0_7)
|
||||
downcast<sis630_svga_device *>(m_svga.target())->port_03b0_w(offset * 4 + 0, data >> 0);
|
||||
if (ACCESSING_BITS_8_15)
|
||||
downcast<sis630_svga_device *>(m_svga.target())->port_03b0_w(offset * 4 + 1, data >> 8);
|
||||
if (ACCESSING_BITS_16_23)
|
||||
downcast<sis630_svga_device *>(m_svga.target())->port_03b0_w(offset * 4 + 2, data >> 16);
|
||||
if (ACCESSING_BITS_24_31)
|
||||
downcast<sis630_svga_device *>(m_svga.target())->port_03b0_w(offset * 4 + 3, data >> 24);
|
||||
}
|
||||
|
||||
|
||||
u32 sis630_gui_device::vga_3c0_r(offs_t offset, uint32_t mem_mask)
|
||||
{
|
||||
uint32_t result = 0;
|
||||
if (ACCESSING_BITS_0_7)
|
||||
result |= downcast<sis630_svga_device *>(m_svga.target())->port_03c0_r(offset * 4 + 0) << 0;
|
||||
if (ACCESSING_BITS_8_15)
|
||||
result |= downcast<sis630_svga_device *>(m_svga.target())->port_03c0_r(offset * 4 + 1) << 8;
|
||||
if (ACCESSING_BITS_16_23)
|
||||
result |= downcast<sis630_svga_device *>(m_svga.target())->port_03c0_r(offset * 4 + 2) << 16;
|
||||
if (ACCESSING_BITS_24_31)
|
||||
result |= downcast<sis630_svga_device *>(m_svga.target())->port_03c0_r(offset * 4 + 3) << 24;
|
||||
return result;
|
||||
}
|
||||
|
||||
void sis630_gui_device::vga_3c0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
|
||||
{
|
||||
if (ACCESSING_BITS_0_7)
|
||||
downcast<sis630_svga_device *>(m_svga.target())->port_03c0_w(offset * 4 + 0, data >> 0);
|
||||
if (ACCESSING_BITS_8_15)
|
||||
downcast<sis630_svga_device *>(m_svga.target())->port_03c0_w(offset * 4 + 1, data >> 8);
|
||||
if (ACCESSING_BITS_16_23)
|
||||
downcast<sis630_svga_device *>(m_svga.target())->port_03c0_w(offset * 4 + 2, data >> 16);
|
||||
if (ACCESSING_BITS_24_31)
|
||||
downcast<sis630_svga_device *>(m_svga.target())->port_03c0_w(offset * 4 + 3, data >> 24);
|
||||
}
|
||||
|
||||
u32 sis630_gui_device::vga_3d0_r(offs_t offset, uint32_t mem_mask)
|
||||
{
|
||||
uint32_t result = 0;
|
||||
if (ACCESSING_BITS_0_7)
|
||||
result |= downcast<sis630_svga_device *>(m_svga.target())->port_03d0_r(offset * 4 + 0) << 0;
|
||||
if (ACCESSING_BITS_8_15)
|
||||
result |= downcast<sis630_svga_device *>(m_svga.target())->port_03d0_r(offset * 4 + 1) << 8;
|
||||
if (ACCESSING_BITS_16_23)
|
||||
result |= downcast<sis630_svga_device *>(m_svga.target())->port_03d0_r(offset * 4 + 2) << 16;
|
||||
if (ACCESSING_BITS_24_31)
|
||||
result |= downcast<sis630_svga_device *>(m_svga.target())->port_03d0_r(offset * 4 + 3) << 24;
|
||||
return result;
|
||||
}
|
||||
|
||||
void sis630_gui_device::vga_3d0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
|
||||
{
|
||||
if (ACCESSING_BITS_0_7)
|
||||
downcast<sis630_svga_device *>(m_svga.target())->port_03d0_w(offset * 4 + 0, data >> 0);
|
||||
if (ACCESSING_BITS_8_15)
|
||||
downcast<sis630_svga_device *>(m_svga.target())->port_03d0_w(offset * 4 + 1, data >> 8);
|
||||
if (ACCESSING_BITS_16_23)
|
||||
downcast<sis630_svga_device *>(m_svga.target())->port_03d0_w(offset * 4 + 2, data >> 16);
|
||||
if (ACCESSING_BITS_24_31)
|
||||
downcast<sis630_svga_device *>(m_svga.target())->port_03d0_w(offset * 4 + 3, data >> 24);
|
||||
}
|
||||
|
||||
/*****************************
|
||||
*
|
||||
* 630 bridge PCI implementation
|
||||
*
|
||||
****************************/
|
||||
|
||||
DEFINE_DEVICE_TYPE(SIS630_BRIDGE, sis630_bridge_device, "sis630_bridge", "SiS 630 Virtual PCI-to-PCI bridge")
|
||||
|
||||
sis630_bridge_device::sis630_bridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: pci_bridge_device(mconfig, SIS630_BRIDGE, tag, owner, clock)
|
||||
, m_vga(*this, finder_base::DUMMY_TAG)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void sis630_bridge_device::map_extra(
|
||||
uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
|
||||
uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space
|
||||
)
|
||||
{
|
||||
// command extensions
|
||||
// VGA control - forward legacy VGA addresses to AGP
|
||||
// TODO: doc implies that is unaffected by base and limit?
|
||||
if (BIT(bridge_control, 3))
|
||||
{
|
||||
memory_space->install_device(0, 0xfffff, *m_vga, &sis630_gui_device::legacy_memory_map);
|
||||
io_space->install_device(0, 0x0fff, *m_vga, &sis630_gui_device::legacy_io_map);
|
||||
}
|
||||
|
||||
// TODO: ISA control
|
||||
// forward to "primary PCI" (host & LPC?) for A8 or A9 blocks for each 1KB blocks in I/O spaces,
|
||||
// (i.e. $100-$3ff, $500-$7ff, $900-$bff etc.)
|
||||
// even if I/O range is inside base and limits
|
||||
// if (BIT(bridge_control, 2))
|
||||
// ...
|
||||
}
|
||||
|
||||
void sis630_bridge_device::bridge_control_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
pci_bridge_device::bridge_control_w(offset, data, mem_mask);
|
||||
LOGMAP("- %s VGA control\n", bridge_control & 8 ? "Enable" : "Disable");
|
||||
remap_cb();
|
||||
}
|
||||
|
||||
void sis630_bridge_device::device_start()
|
||||
{
|
||||
pci_bridge_device::device_start();
|
||||
}
|
||||
|
||||
void sis630_bridge_device::device_reset()
|
||||
{
|
||||
pci_bridge_device::device_reset();
|
||||
}
|
144
src/devices/machine/sis630_gui.h
Normal file
144
src/devices/machine/sis630_gui.h
Normal file
@ -0,0 +1,144 @@
|
||||
// license: BSD-3-Clause
|
||||
// copyright-holders: Angelo Salese
|
||||
|
||||
#ifndef MAME_MACHINE_SIS630_VGA_H
|
||||
#define MAME_MACHINE_SIS630_VGA_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pci.h"
|
||||
#include "video/pc_vga.h"
|
||||
|
||||
class sis630_svga_device : public svga_device
|
||||
{
|
||||
public:
|
||||
sis630_svga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
virtual uint8_t mem_r(offs_t offset) override;
|
||||
virtual void mem_w(offs_t offset, uint8_t data) override;
|
||||
|
||||
virtual u8 port_03c0_r(offs_t offset) override;
|
||||
virtual void port_03c0_w(offs_t offset, uint8_t data) override;
|
||||
|
||||
protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual uint8_t crtc_reg_read(uint8_t index) override;
|
||||
virtual void crtc_reg_write(uint8_t index, uint8_t data) override;
|
||||
virtual uint8_t seq_reg_read(uint8_t index) override;
|
||||
virtual void seq_reg_write(uint8_t index, uint8_t data) override;
|
||||
virtual uint16_t offset() override;
|
||||
virtual void recompute_params() override;
|
||||
|
||||
u8 m_crtc_ext_regs[0x100]{};
|
||||
u8 m_seq_ext_regs[0x100]{};
|
||||
u8 m_ramdac_mode = 0;
|
||||
u8 m_ext_misc_ctrl_0 = 0;
|
||||
u8 m_ext_vert_overflow = 0;
|
||||
u8 m_ext_horz_overflow[2]{};
|
||||
u32 m_svga_bank_reg_w = 0;
|
||||
u32 m_svga_bank_reg_r = 0;
|
||||
bool m_unlock_reg = false;
|
||||
|
||||
std::tuple<u8, u8> flush_true_color_mode();
|
||||
// bool m_dual_seg_mode = false;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(SIS630_SVGA, sis630_svga_device)
|
||||
|
||||
|
||||
class sis630_gui_device : public pci_device
|
||||
{
|
||||
public:
|
||||
sis630_gui_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
void legacy_memory_map(address_map &map);
|
||||
void legacy_io_map(address_map &map);
|
||||
|
||||
protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
|
||||
virtual const tiny_rom_entry *device_rom_region() const override;
|
||||
|
||||
// virtual void reset_all_mappings() override;
|
||||
|
||||
virtual void map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
|
||||
uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) override;
|
||||
|
||||
virtual void config_map(address_map &map) override;
|
||||
|
||||
void memory_map(address_map &map);
|
||||
void io_map(address_map &map);
|
||||
void space_io_map(address_map &map);
|
||||
|
||||
private:
|
||||
required_device<sis630_svga_device> m_svga;
|
||||
required_memory_region m_gui_rom;
|
||||
|
||||
u8 vram_r(offs_t offset);
|
||||
void vram_w(offs_t offset, uint8_t data);
|
||||
u32 vga_3b0_r(offs_t offset, uint32_t mem_mask = ~0);
|
||||
void vga_3b0_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
|
||||
u32 vga_3c0_r(offs_t offset, uint32_t mem_mask = ~0);
|
||||
void vga_3c0_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
|
||||
u32 vga_3d0_r(offs_t offset, uint32_t mem_mask = ~0);
|
||||
void vga_3d0_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
|
||||
|
||||
void subvendor_w(offs_t offset, u32 data, u32 mem_mask = ~0);
|
||||
|
||||
virtual u8 capptr_r() override;
|
||||
u32 agp_id_r();
|
||||
u32 agp_status_r();
|
||||
u32 agp_command_r(offs_t offset, uint32_t mem_mask);
|
||||
void agp_command_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
|
||||
|
||||
struct {
|
||||
bool enable = false;
|
||||
u8 data_rate = 0;
|
||||
} m_agp;
|
||||
|
||||
u32 m_subsystem_logger_mask = 0;
|
||||
|
||||
u8 unmap_log_r(offs_t offset);
|
||||
void unmap_log_w(offs_t offset, u8 data);
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(SIS630_GUI, sis630_gui_device)
|
||||
|
||||
class sis630_bridge_device : public pci_bridge_device
|
||||
{
|
||||
public:
|
||||
template <typename T> sis630_bridge_device(
|
||||
const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock,
|
||||
T &&gui_tag
|
||||
) : sis630_bridge_device(mconfig, tag, owner, clock)
|
||||
{
|
||||
// either 0001 or 6001 as device ID
|
||||
set_ids_bridge(0x10396001, 0x00);
|
||||
//set_multifunction_device(true);
|
||||
m_vga.set_tag(std::forward<T>(gui_tag));
|
||||
}
|
||||
|
||||
sis630_bridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
virtual void map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
|
||||
uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) override;
|
||||
|
||||
private:
|
||||
required_device<sis630_gui_device> m_vga;
|
||||
|
||||
virtual void bridge_control_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
|
||||
|
||||
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(SIS630_BRIDGE, sis630_bridge_device)
|
||||
|
||||
|
||||
#endif
|
441
src/devices/machine/sis630_host.cpp
Normal file
441
src/devices/machine/sis630_host.cpp
Normal file
@ -0,0 +1,441 @@
|
||||
// license: BSD-3-Clause
|
||||
// copyright-holders: Angelo Salese
|
||||
/**************************************************************************************************
|
||||
|
||||
SiS630 host implementation (northbridge)
|
||||
|
||||
TODO:
|
||||
- AGP and VGA interfaces;
|
||||
- Is ACPI declared here shared with LPC or a different one?
|
||||
\- shutms11 maps it to the exact same place (I/O $5000), may be interleaved?
|
||||
- HW trap control;
|
||||
- PCI-Hole;
|
||||
- Convert RAM to device;
|
||||
- Integrated VGA control;
|
||||
|
||||
**************************************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "sis630_host.h"
|
||||
|
||||
|
||||
#define LOG_IO (1U << 1) // log PCI register accesses
|
||||
#define LOG_TODO (1U << 2) // log unimplemented registers
|
||||
#define LOG_MAP (1U << 3) // log full remaps
|
||||
#define LOG_AGP (1U << 4) // log AGP
|
||||
|
||||
#define VERBOSE (LOG_GENERAL | LOG_IO | LOG_TODO | LOG_AGP)
|
||||
//#define LOG_OUTPUT_FUNC osd_printf_warning
|
||||
|
||||
#include "logmacro.h"
|
||||
|
||||
#define LOGIO(...) LOGMASKED(LOG_IO, __VA_ARGS__)
|
||||
#define LOGMAP(...) LOGMASKED(LOG_MAP, __VA_ARGS__)
|
||||
#define LOGTODO(...) LOGMASKED(LOG_TODO, __VA_ARGS__)
|
||||
#define LOGAGP(...) LOGMASKED(LOG_AGP, __VA_ARGS__)
|
||||
|
||||
DEFINE_DEVICE_TYPE(SIS630_HOST, sis630_host_device, "sis630_host", "SiS 630 Host-to-PCI Bridge")
|
||||
|
||||
sis630_host_device::sis630_host_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: pci_host_device(mconfig, SIS630_HOST, tag, owner, clock)
|
||||
, m_host_cpu(*this, finder_base::DUMMY_TAG)
|
||||
{
|
||||
}
|
||||
|
||||
void sis630_host_device::device_start()
|
||||
{
|
||||
pci_host_device::device_start();
|
||||
|
||||
memory_window_start = 0;
|
||||
memory_window_end = 0xffffffff;
|
||||
memory_offset = 0;
|
||||
io_window_start = 0;
|
||||
io_window_end = 0xffff;
|
||||
io_offset = 0;
|
||||
|
||||
memory_space = &m_host_cpu->space(AS_PROGRAM);
|
||||
io_space = &m_host_cpu->space(AS_IO);
|
||||
add_map(8*1024*1024, M_MEM, FUNC(sis630_host_device::memory_map));
|
||||
|
||||
m_ram.resize(m_ram_size/4);
|
||||
}
|
||||
|
||||
void sis630_host_device::device_reset()
|
||||
{
|
||||
pci_host_device::device_reset();
|
||||
|
||||
command = 0x0005;
|
||||
status = 0x0210;
|
||||
|
||||
m_shadow_ram_ctrl = 0;
|
||||
m_vga_control = 0;
|
||||
std::fill(std::begin(m_agp_mailbox), std::end(m_agp_mailbox), 0);
|
||||
|
||||
remap_cb();
|
||||
}
|
||||
|
||||
void sis630_host_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void sis630_host_device::config_map(address_map &map)
|
||||
{
|
||||
pci_host_device::config_map(map);
|
||||
// override header type, needed for actual IDE detection
|
||||
map(0x0e, 0x0e).lr8(NAME([] () { return 0x80; }));
|
||||
|
||||
// override first BAR slot for gfx window base address
|
||||
map(0x10, 0x13).rw(FUNC(pci_device::address_base_r), FUNC(pci_device::address_base_w));
|
||||
|
||||
map(0x34, 0x34).r(FUNC(sis630_host_device::capptr_r));
|
||||
|
||||
// host & DRAM regs
|
||||
// map(0x50, 0x51) host interface control
|
||||
// map(0x52, 0x53) DRAM misc control 1 & 2
|
||||
// map(0x54, 0x55) DRAM timing control 1 & 2
|
||||
// map(0x56, 0x56) DRAM misc control 3
|
||||
// map(0x57, 0x57) SDRAM/VCM init control
|
||||
// map(0x58, 0x58) DRAM buffer slew rating
|
||||
// map(0x59, 0x5a) DRAM buffer strength and current rating
|
||||
// map(0x5b, 0x5b) PCI buffer strength and current rating
|
||||
// map(0x60, 0x62) DRAMx type register (x = 0, 1 or 2)
|
||||
map(0x63, 0x63).rw(FUNC(sis630_host_device::dram_status_r), FUNC(sis630_host_device::dram_status_w));
|
||||
// map(0x64, 0x64) FBC control register
|
||||
// map(0x65, 0x65) DIMM switch control
|
||||
// map(0x68, 0x69) ACPI I/O base
|
||||
map(0x6a, 0x6a).rw(FUNC(sis630_host_device::smram_r), FUNC(sis630_host_device::smram_w));
|
||||
// map(0x6b, 0x6b) self refresh command output timing control
|
||||
// map(0x6c, 0x6c) power management DRAM self refresh control
|
||||
|
||||
// Shadow RAM & PCI-Hole area
|
||||
map(0x70, 0x73).rw(FUNC(sis630_host_device::shadow_ram_ctrl_r), FUNC(sis630_host_device::shadow_ram_ctrl_w));
|
||||
map(0x77, 0x77).rw(FUNC(sis630_host_device::pci_hole_r), FUNC(sis630_host_device::pci_hole_w));
|
||||
// map(0x78, 0x79) PCI-Hole #1 allocation
|
||||
// map(0x7a, 0x7b) PCI-Hole #2 allocation
|
||||
|
||||
// HW Trap control
|
||||
// map(0x7c, 0x7c) VGA
|
||||
// map(0x7d, 0x7d) Southbridge
|
||||
// map(0x7e, 0x7f) Northbridge
|
||||
|
||||
// Host Bridge & PCI arbiter characteristics
|
||||
// map(0x80, 0x80) Target bridge DRAM characteristics
|
||||
// map(0x81, 0x81) PCI discard timer for delay transaction
|
||||
// map(0x82, 0x82) PCI target bridge bus characteristics
|
||||
// map(0x83, 0x83) CPU to PCI characteristics
|
||||
// map(0x84, 0x85) PCI grant timer
|
||||
// map(0x86, 0x86) CPU idle timer for PCI
|
||||
// map(0x87, 0x87) Host bridge & PCI master priority timer
|
||||
// map(0x88, 0x89) PCI discard timer for PCI hold
|
||||
|
||||
// Clock Control
|
||||
// map(0x8c, 0x8c) SDRCLK/SDWCLK
|
||||
// map(0x8d, 0x8d) SDWCLK
|
||||
// map(0x8e, 0x8e) CPU & SDRAM clock relationship
|
||||
// map(0x8f, 0x8f) FBCRCLK/FBCWCLK control
|
||||
|
||||
// GART and page table regs
|
||||
// map(0x90, 0x93) GART base address
|
||||
// map(0x94, 0x94) Graphic window control
|
||||
// map(0x97, 0x97) Page table cache control
|
||||
// map(0x98, 0x98) Page table cache invalidation control
|
||||
|
||||
// Integrated VGA control
|
||||
map(0x9c, 0x9c).rw(FUNC(sis630_host_device::vga_control_r), FUNC(sis630_host_device::vga_control_w));
|
||||
|
||||
// AGP
|
||||
// map(0xa0, 0xa3) DRAM priority timer control
|
||||
map(0xa0, 0xa3).rw(FUNC(sis630_host_device::agp_priority_timer_r), FUNC(sis630_host_device::agp_priority_timer_w));
|
||||
// map(0xa4, 0xaf) General purpose register (generic mailboxes?)
|
||||
map(0xa4, 0xaf).rw(FUNC(sis630_host_device::agp_mailbox_r), FUNC(sis630_host_device::agp_mailbox_w));
|
||||
// map(0xc0, 0xc3) AGP capability identifier
|
||||
map(0xc0, 0xc3).r(FUNC(sis630_host_device::agp_id_r));
|
||||
map(0xc4, 0xc7).r(FUNC(sis630_host_device::agp_status_r));
|
||||
map(0xc8, 0xcb).rw(FUNC(sis630_host_device::agp_command_r), FUNC(sis630_host_device::agp_command_w));
|
||||
}
|
||||
|
||||
// TODO: verify if we need these trampolines
|
||||
void sis630_host_device::memory_map(address_map &map)
|
||||
{
|
||||
}
|
||||
|
||||
void sis630_host_device::map_shadowram(address_space *memory_space, uint32_t start_offs, uint32_t end_offs, bool read_enable, bool write_enable)
|
||||
{
|
||||
LOGMAP("- 0x%08x-0x%08x ", start_offs, end_offs);
|
||||
|
||||
switch(write_enable << 1 | read_enable)
|
||||
{
|
||||
case 0:
|
||||
LOGMAP("shadow RAM off\n");
|
||||
//memory_space->unmap_write(start_offs, end_offs);
|
||||
break;
|
||||
case 1:
|
||||
LOGMAP("shadow RAM r/o\n");
|
||||
memory_space->install_rom(start_offs, end_offs, &m_ram[start_offs/4]);
|
||||
break;
|
||||
case 2:
|
||||
LOGMAP("shadow RAM w/o\n");
|
||||
//memory_space->install_rom(start_offs, end_offs, m_region->base() + bios_rom_offset);
|
||||
memory_space->install_writeonly(start_offs, end_offs, &m_ram[start_offs/4]);
|
||||
break;
|
||||
case 3:
|
||||
LOGMAP("shadow RAM r/w\n");
|
||||
memory_space->install_ram(start_offs, end_offs, &m_ram[start_offs/4]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void sis630_host_device::map_extra(
|
||||
uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
|
||||
uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space
|
||||
) {
|
||||
io_space->install_device(0, 0xffff, *static_cast<pci_host_device *>(this), &pci_host_device::io_configuration_access_map);
|
||||
|
||||
regenerate_config_mapping();
|
||||
|
||||
memory_space->install_ram(0x00000000, 0x0009ffff, &m_ram[0x00000000/4]);
|
||||
// memory_space->install_ram(0x000a0000, 0x000bffff, &m_ram[0x000a0000/4]);
|
||||
|
||||
LOGMAP("Host Remapping table (shadow: %08x smram: %02x):\n", m_shadow_ram_ctrl, m_smram);
|
||||
|
||||
for (int i = 0; i < 12; i ++)
|
||||
{
|
||||
u32 start_offs = 0x000c0000 + i * 0x4000;
|
||||
u32 end_offs = start_offs + 0x3fff;
|
||||
|
||||
map_shadowram(
|
||||
memory_space,
|
||||
start_offs, end_offs,
|
||||
bool(BIT(m_shadow_ram_ctrl, i)), bool(BIT(m_shadow_ram_ctrl, i + 16))
|
||||
);
|
||||
}
|
||||
|
||||
map_shadowram(
|
||||
memory_space,
|
||||
0xf0000, 0xfffff,
|
||||
bool(BIT(m_shadow_ram_ctrl, 12)), bool(BIT(m_shadow_ram_ctrl, 28))
|
||||
);
|
||||
|
||||
// System Management Memory Region handling
|
||||
// Potentially overrides VGA VRAM if on
|
||||
if (BIT(m_smram, 4))
|
||||
{
|
||||
u8 smram_config = m_smram >> 5;
|
||||
|
||||
// POST checks for config 6 only, other settings aren't tested
|
||||
// TODO: setting 3 and 5 are undocumented, verify if mirror logic is correct
|
||||
if (smram_config == 3 || smram_config == 5)
|
||||
throw emu_fatalerror("SMRAM config = %d!", smram_config);
|
||||
|
||||
const u32 host_addresses[8] = {
|
||||
0xe0000, 0xb0000, 0xe0000, 0xb0000,
|
||||
0xe0000, 0xe0000, 0xa0000, 0xa0000
|
||||
};
|
||||
const u32 smram_sizes[8] = {
|
||||
0x07fff, 0xffff, 0x7fff, 0xffff,
|
||||
0x07fff, 0x7fff, 0xffff, 0x1ffff
|
||||
};
|
||||
const u32 system_memory_addresses[8] = {
|
||||
0xe0000, 0xb0000, 0xa0000, 0xb0000,
|
||||
0xb0000, 0xb0000, 0xa0000, 0xa0000
|
||||
};
|
||||
const u32 host_address_start = host_addresses[smram_config];
|
||||
const u32 host_address_end = host_address_start + smram_sizes[smram_config];
|
||||
const u32 system_memory_address = system_memory_addresses[smram_config];
|
||||
LOGMAP("- SMRAM %02x relocation %08x-%08x to %08x\n"
|
||||
, m_smram
|
||||
, host_address_start
|
||||
, host_address_end
|
||||
, system_memory_address
|
||||
);
|
||||
memory_space->install_ram(host_address_start, host_address_end, &m_ram[system_memory_address/4]);
|
||||
}
|
||||
|
||||
// TODO: shadow RAM bit 15?
|
||||
// Always on after POST, should give shared access to PCI cards on the bus,
|
||||
// BIOS mentions 8M of "shared memory", unknown how this works out.
|
||||
// TODO: undocumented shadow RAM configs bits 7 and 23 after POST IDE check on shutms11 (programmer errors?)
|
||||
|
||||
memory_space->install_ram(0x00100000, m_ram_size - 1, &m_ram[0x00100000/4]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* I/O implemtation
|
||||
*
|
||||
*/
|
||||
|
||||
u8 sis630_host_device::capptr_r()
|
||||
{
|
||||
LOGIO("Read capptr_r [$34]\n");
|
||||
return 0xc0;
|
||||
}
|
||||
|
||||
u8 sis630_host_device::dram_status_r()
|
||||
{
|
||||
LOGIO("Read DRAM status [$63] (%02x)\n", m_dram_status);
|
||||
return m_dram_status;
|
||||
}
|
||||
|
||||
void sis630_host_device::dram_status_w(u8 data)
|
||||
{
|
||||
LOGIO("Write DRAM status [$63] %02x\n", data);
|
||||
|
||||
m_dram_status = data;
|
||||
// TODO: bit 7 is shared memory control
|
||||
}
|
||||
|
||||
|
||||
u8 sis630_host_device::smram_r()
|
||||
{
|
||||
LOGIO("Read SMRAM [$6a] (%02x)\n", m_smram);
|
||||
return m_smram;
|
||||
}
|
||||
|
||||
void sis630_host_device::smram_w(u8 data)
|
||||
{
|
||||
LOGIO("Write SMRAM [$6a] %02x\n", data);
|
||||
m_smram = data;
|
||||
remap_cb();
|
||||
}
|
||||
|
||||
u32 sis630_host_device::shadow_ram_ctrl_r(offs_t offset, uint32_t mem_mask)
|
||||
{
|
||||
LOGIO("Read shadow RAM setting [$70] %08x (%08x)\n", mem_mask, m_shadow_ram_ctrl);
|
||||
return m_shadow_ram_ctrl;
|
||||
}
|
||||
|
||||
void sis630_host_device::shadow_ram_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_shadow_ram_ctrl);
|
||||
LOGMAP("Write shadow RAM setting [$70] %08x & %08x (%08x)\n", data, mem_mask, m_shadow_ram_ctrl);
|
||||
remap_cb();
|
||||
}
|
||||
|
||||
u8 sis630_host_device::pci_hole_r()
|
||||
{
|
||||
LOGIO("Read PCI hole [$77]\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sis630_host_device::pci_hole_w(u8 data)
|
||||
{
|
||||
LOGIO("Write PCI hole [$77] %02x\n", data);
|
||||
if (data)
|
||||
LOG("Warning: PCI hole area enabled! %02x\n", data);
|
||||
}
|
||||
|
||||
u8 sis630_host_device::vga_control_r()
|
||||
{
|
||||
LOGIO("Read integrated VGA control data [$9c] %02x\n", m_vga_control);
|
||||
return m_vga_control;
|
||||
}
|
||||
|
||||
void sis630_host_device::vga_control_w(u8 data)
|
||||
{
|
||||
LOGIO("Write integrated VGA control data [$9c] %02x\n", data);
|
||||
// TODO: "integrated VGA control" (?)
|
||||
m_vga_control = data;
|
||||
// remap_cb();
|
||||
}
|
||||
|
||||
u32 sis630_host_device::agp_priority_timer_r(offs_t offset, uint32_t mem_mask)
|
||||
{
|
||||
LOGIO("Read AGP priority timer [$a0] %08x (%08x)\n", mem_mask, m_agp_priority_timer);
|
||||
return m_agp_priority_timer;
|
||||
}
|
||||
|
||||
void sis630_host_device::agp_priority_timer_w(offs_t offset, uint32_t data, uint32_t mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_agp_priority_timer);
|
||||
LOGIO("Write AGP priority timer [$a0] %08x & %08x (%08x)\n", data, mem_mask, m_agp_priority_timer);
|
||||
}
|
||||
|
||||
u8 sis630_host_device::agp_mailbox_r(offs_t offset)
|
||||
{
|
||||
LOGIO("Read AGP mailbox [$%02x] (%02x)\n", offset + 0xa4, m_agp_mailbox[offset]);
|
||||
return m_agp_mailbox[offset];
|
||||
}
|
||||
|
||||
void sis630_host_device::agp_mailbox_w(offs_t offset, u8 data)
|
||||
{
|
||||
LOGIO("Write AGP mailbox [$%02x] %02x\n", offset + 0xa4, data);
|
||||
m_agp_mailbox[offset] = data;
|
||||
}
|
||||
|
||||
// TODO: move to generic interface
|
||||
u32 sis630_host_device::agp_id_r()
|
||||
{
|
||||
LOGAGP("Read AGP ID [$c0]\n");
|
||||
// bits 23-16 AGP v2.0
|
||||
// bits 15-8 0x00 no NEXT_PTR (NULL terminates here)
|
||||
// bits 7-0 CAP_ID (0x02 for AGP)
|
||||
return 0x00200002;
|
||||
}
|
||||
|
||||
u32 sis630_host_device::agp_status_r()
|
||||
{
|
||||
LOGAGP("Read AGP status [$c4]\n");
|
||||
// bits 31-24 RQ max number of AGP command requests (0x1f + 1 = 32)
|
||||
// bit 9: SBA, side band addressing enabled
|
||||
// ---- -xxx RATE
|
||||
// ---- -1-- 4X transfer capable
|
||||
// ---- --1- 2X transfer capable
|
||||
// ---- ---1 1X transfer capable
|
||||
// NB: documentation claims a RATE of 0x03 then contradicts with "111b" value, do the math
|
||||
// It gets setup with a 4X at POST, assume 0x07 is right
|
||||
|
||||
// Stuff that isn't enabled here:
|
||||
// bit 5: 4G support address greater than 4 GB
|
||||
// bit 4: FW transfer support
|
||||
|
||||
return 0x1f000207;
|
||||
}
|
||||
|
||||
u32 sis630_host_device::agp_command_r(offs_t offset, uint32_t mem_mask)
|
||||
{
|
||||
LOGAGP("Read AGP command [$c8] %d %d %02x\n", m_agp.sba_enable, m_agp.enable, m_agp.data_rate);
|
||||
// TODO: enable gets cleared by AGP_RESET, or even from PCI RST#
|
||||
return m_agp.sba_enable << 9 | m_agp.enable << 8 | (m_agp.data_rate & 7);
|
||||
}
|
||||
|
||||
void sis630_host_device::agp_command_w(offs_t offset, uint32_t data, uint32_t mem_mask)
|
||||
{
|
||||
LOGAGP("Write AGP command [$c8] %08x & %08x\n", data, mem_mask);
|
||||
if (ACCESSING_BITS_8_15)
|
||||
{
|
||||
m_agp.sba_enable = bool(BIT(m_agp.sba_enable, 9));
|
||||
m_agp.enable = bool(BIT(m_agp.enable, 8));
|
||||
LOGAGP("- SBA_ENABLE = %d AGP_ENABLE = %d\n", m_agp.sba_enable, m_agp.enable);
|
||||
}
|
||||
|
||||
if (ACCESSING_BITS_0_7)
|
||||
{
|
||||
// quick checker, to be translated into an AGP interface
|
||||
std::map<u8, std::string> agp_transfer_rates = {
|
||||
{ 0, "(illegal 0)" },
|
||||
{ 1, "1X" },
|
||||
{ 2, "2X" },
|
||||
{ 3, "(illegal 3)" },
|
||||
{ 4, "4X" },
|
||||
{ 5, "(illegal 5)" },
|
||||
{ 6, "(illegal 6)" },
|
||||
{ 7, "(illegal 7)" }
|
||||
};
|
||||
|
||||
// make sure the AGP DATA_RATE specs are honored
|
||||
const u8 data_rate = data & 7;
|
||||
LOGAGP("- DATA_RATE = %s enabled=%d\n", agp_transfer_rates.at(data_rate), m_agp.enable);
|
||||
m_agp.data_rate = data_rate;
|
||||
|
||||
// should probably never be enabled since it reads out from the ID
|
||||
if (data & 0x30)
|
||||
LOG("Warning: AGP unsupported i/f set 4G=%d FW_Enable=%d\n", bool(BIT(data, 5)), bool(BIT(data, 4)));
|
||||
}
|
||||
}
|
98
src/devices/machine/sis630_host.h
Normal file
98
src/devices/machine/sis630_host.h
Normal file
@ -0,0 +1,98 @@
|
||||
// license: BSD-3-Clause
|
||||
// copyright-holders: Angelo Salese
|
||||
|
||||
#ifndef MAME_MACHINE_SIS630_HOST_H
|
||||
#define MAME_MACHINE_SIS630_HOST_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pci.h"
|
||||
#include "sis630_gui.h"
|
||||
|
||||
class sis630_host_device : public pci_host_device
|
||||
{
|
||||
public:
|
||||
template <typename T> sis630_host_device(
|
||||
const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock,
|
||||
T &&cpu_tag, int ram_size
|
||||
) : sis630_host_device(mconfig, tag, owner, clock)
|
||||
{
|
||||
// Revision 1 -> A1
|
||||
set_ids(0x10390630, 0x01, 0x060000, 0x00);
|
||||
set_multifunction_device(true);
|
||||
m_host_cpu.set_tag(std::forward<T>(cpu_tag));
|
||||
set_ram_size(ram_size);
|
||||
}
|
||||
|
||||
sis630_host_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
void set_ram_size(int ram_size) { m_ram_size = ram_size; }
|
||||
|
||||
|
||||
protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
|
||||
virtual bool map_first() const override { return true; }
|
||||
|
||||
// virtual void reset_all_mappings() override;
|
||||
|
||||
virtual void map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
|
||||
uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) override;
|
||||
|
||||
virtual void config_map(address_map &map) override;
|
||||
|
||||
void memory_map(address_map &map);
|
||||
|
||||
private:
|
||||
required_device<cpu_device> m_host_cpu;
|
||||
std::vector<uint32_t> m_ram;
|
||||
|
||||
void map_shadowram(address_space *memory_space, offs_t start_offs, offs_t end_offs, bool read_enable, bool write_enable);
|
||||
|
||||
int m_ram_size = 0;
|
||||
u8 m_dram_status = 0;
|
||||
u32 m_shadow_ram_ctrl = 0;
|
||||
u8 m_vga_control = 0;
|
||||
u8 m_agp_mailbox[12]{};
|
||||
u8 m_smram = 0;
|
||||
u32 m_agp_priority_timer = 0;
|
||||
|
||||
u8 dram_status_r();
|
||||
void dram_status_w(u8 data);
|
||||
|
||||
u8 pci_hole_r();
|
||||
void pci_hole_w(u8 data);
|
||||
|
||||
u8 vga_control_r();
|
||||
void vga_control_w(u8 data);
|
||||
|
||||
u32 shadow_ram_ctrl_r(offs_t offset, uint32_t mem_mask = ~0);
|
||||
void shadow_ram_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
|
||||
|
||||
u8 smram_r();
|
||||
void smram_w(u8 data);
|
||||
|
||||
u32 agp_priority_timer_r(offs_t offset, uint32_t mem_mask = ~0);
|
||||
void agp_priority_timer_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
|
||||
|
||||
u8 agp_mailbox_r(offs_t offset);
|
||||
void agp_mailbox_w(offs_t offset, u8 data);
|
||||
|
||||
virtual uint8_t capptr_r() override;
|
||||
u32 agp_id_r();
|
||||
u32 agp_status_r();
|
||||
u32 agp_command_r(offs_t offset, uint32_t mem_mask);
|
||||
void agp_command_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
|
||||
|
||||
struct {
|
||||
bool sba_enable = false;
|
||||
bool enable = false;
|
||||
u8 data_rate = 0;
|
||||
} m_agp;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(SIS630_HOST, sis630_host_device)
|
||||
|
||||
|
||||
#endif
|
93
src/devices/machine/sis7001_usb.cpp
Normal file
93
src/devices/machine/sis7001_usb.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
// license: BSD-3-Clause
|
||||
// copyright-holders: Angelo Salese
|
||||
/**************************************************************************************************
|
||||
|
||||
SiS 7001 USB Host controller
|
||||
|
||||
TODO:
|
||||
- Stub interface, to be improved;
|
||||
- PCI values omitted from docs, assumes same as OpenHCI;
|
||||
|
||||
**************************************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "sis7001_usb.h"
|
||||
|
||||
#define LOG_IO (1U << 1) // log PCI register accesses
|
||||
#define LOG_MAP (1U << 2) // log full remaps
|
||||
|
||||
#define VERBOSE (LOG_GENERAL | LOG_IO | LOG_MAP)
|
||||
//#define LOG_OUTPUT_FUNC osd_printf_warning
|
||||
|
||||
#include "logmacro.h"
|
||||
|
||||
#define LOGIO(...) LOGMASKED(LOG_IO, __VA_ARGS__)
|
||||
#define LOGMAP(...) LOGMASKED(LOG_MAP, __VA_ARGS__)
|
||||
|
||||
DEFINE_DEVICE_TYPE(SIS7001_USB, sis7001_usb_device, "sis7001_usb", "SiS 7001 USB Host Controller")
|
||||
|
||||
sis7001_usb_device::sis7001_usb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: pci_device(mconfig, SIS7001_USB, tag, owner, clock)
|
||||
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void sis7001_usb_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void sis7001_usb_device::config_map(address_map &map)
|
||||
{
|
||||
pci_device::config_map(map);
|
||||
}
|
||||
|
||||
void sis7001_usb_device::io_map(address_map &map)
|
||||
{
|
||||
// operational mode
|
||||
map(0x000, 0x003).lr32(NAME([]() { return 0x00000110; }));
|
||||
// ...
|
||||
// HcFmInterval (Windows OSes fails if this isn't r/w)
|
||||
map(0x034, 0x037).lrw32(
|
||||
NAME([this]() { return m_HcFmInterval; } ),
|
||||
NAME([this](offs_t offset, u32 data, u32 mem_mask) { COMBINE_DATA(&m_HcFmInterval); LOG("Write HcFmInterval %08x & %08x\n", data, mem_mask); })
|
||||
);
|
||||
// ...
|
||||
// HcRhDescriptorA, writeable except for 0x4ff
|
||||
map(0x048, 0x04b).lr32(NAME([this]() { return 0x01000000 | m_downstream_ports; }));
|
||||
// ...
|
||||
// map(0x05c, 0x05c) last item for function 2, missing on function 3
|
||||
|
||||
// legacy support mode (8-bit each)
|
||||
// map(0x100, 0x100) control, bit 0 enables emulation mode
|
||||
// map(0x104, 0x104) input
|
||||
// map(0x108, 0x108) output
|
||||
// map(0x10c, 0x10f) status
|
||||
}
|
||||
|
||||
void sis7001_usb_device::map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
|
||||
uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space)
|
||||
{
|
||||
// TODO: overrides I/O ports $0060-$0064 (emulation mode)
|
||||
}
|
||||
|
||||
void sis7001_usb_device::device_start()
|
||||
{
|
||||
pci_device::device_start();
|
||||
|
||||
add_map(512, M_MEM, FUNC(sis7001_usb_device::io_map));
|
||||
|
||||
// INTD#
|
||||
intr_pin = 4;
|
||||
}
|
||||
|
||||
|
||||
void sis7001_usb_device::device_reset()
|
||||
{
|
||||
pci_device::device_reset();
|
||||
|
||||
command = 0x0000;
|
||||
status = 0x0000;
|
||||
m_HcFmInterval = 0;
|
||||
}
|
53
src/devices/machine/sis7001_usb.h
Normal file
53
src/devices/machine/sis7001_usb.h
Normal file
@ -0,0 +1,53 @@
|
||||
// license: BSD-3-Clause
|
||||
// copyright-holders: Angelo Salese
|
||||
|
||||
#ifndef MAME_MACHINE_SIS7001_USB_H
|
||||
#define MAME_MACHINE_SIS7001_USB_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pci.h"
|
||||
|
||||
class sis7001_usb_device : public pci_device
|
||||
{
|
||||
public:
|
||||
sis7001_usb_device(
|
||||
const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock,
|
||||
int num_ports
|
||||
) : sis7001_usb_device(mconfig, tag, owner, clock)
|
||||
{
|
||||
// 0x0c0310 - Serial Bus Controller, USB, OpenHCI Host
|
||||
// Assume no rev.
|
||||
set_ids(0x10397001, 0x00, 0x0c0310, 0x00);
|
||||
// TODO: should really read from a std::list interface
|
||||
m_downstream_ports = num_ports;
|
||||
}
|
||||
sis7001_usb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
static constexpr feature_type unemulated_features() { return feature::MEDIA; }
|
||||
|
||||
protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
|
||||
// virtual void reset_all_mappings() override;
|
||||
|
||||
virtual void map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
|
||||
uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) override;
|
||||
|
||||
virtual void config_map(address_map &map) override;
|
||||
|
||||
void io_map(address_map &map);
|
||||
|
||||
private:
|
||||
u8 m_downstream_ports;
|
||||
u32 m_HcFmInterval = 0;
|
||||
|
||||
u8 unmap_log_r(offs_t offset);
|
||||
void unmap_log_w(offs_t offset, u8 data);
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(SIS7001_USB, sis7001_usb_device)
|
||||
|
||||
#endif
|
126
src/devices/machine/sis7018_audio.cpp
Normal file
126
src/devices/machine/sis7018_audio.cpp
Normal file
@ -0,0 +1,126 @@
|
||||
// license: BSD-3-Clause
|
||||
// copyright-holders: Angelo Salese
|
||||
/**************************************************************************************************
|
||||
|
||||
SiS 7018 Audio device (AC97 complaint)
|
||||
|
||||
TODO:
|
||||
- Stub interface, to be improved;
|
||||
- Should be easy to at least inherit SB16/MIDI/game port devices;
|
||||
|
||||
**************************************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "sis7018_audio.h"
|
||||
|
||||
#define LOG_IO (1U << 1) // log PCI register accesses
|
||||
#define LOG_TODO (1U << 2) // log unimplemented registers
|
||||
#define LOG_MAP (1U << 3) // log full remaps
|
||||
#define LOG_PMC (1U << 4) // log PMC access
|
||||
|
||||
#define VERBOSE (LOG_GENERAL | LOG_IO | LOG_TODO | LOG_MAP | LOG_PMC)
|
||||
//#define LOG_OUTPUT_FUNC osd_printf_warning
|
||||
|
||||
#include "logmacro.h"
|
||||
|
||||
#define LOGIO(...) LOGMASKED(LOG_IO, __VA_ARGS__)
|
||||
#define LOGMAP(...) LOGMASKED(LOG_MAP, __VA_ARGS__)
|
||||
#define LOGTODO(...) LOGMASKED(LOG_TODO, __VA_ARGS__)
|
||||
#define LOGPMC(...) LOGMASKED(LOG_PMC, __VA_ARGS__)
|
||||
|
||||
DEFINE_DEVICE_TYPE(SIS7018_AUDIO, sis7018_audio_device, "sis7018_audio", "SiS 7018 Audio AC97")
|
||||
|
||||
sis7018_audio_device::sis7018_audio_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: pci_device(mconfig, SIS7018_AUDIO, tag, owner, clock)
|
||||
|
||||
{
|
||||
// 0x040100 - Multimedia device, audio device (vendor specific i/f)
|
||||
// 0x01 - Rev 1
|
||||
set_ids(0x10397018, 0x01, 0x040100, 0x00);
|
||||
}
|
||||
|
||||
void sis7018_audio_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void sis7018_audio_device::config_map(address_map &map)
|
||||
{
|
||||
pci_device::config_map(map);
|
||||
// map(0x003e, 0x003f) max latency min=0x02, max=0x18
|
||||
|
||||
map(0x40, 0xe3).rw(FUNC(sis7018_audio_device::unmap_log_r), FUNC(sis7018_audio_device::unmap_log_w));
|
||||
|
||||
// PMC capability identifier
|
||||
map(0xdc, 0xdf).r(FUNC(sis7018_audio_device::pmc_id_r));
|
||||
// map(0xe0, 0xe3).r(FUNC(sis7018_audio_device::pmc_status_r), FUNC(sis7018_audio_device::pmc_control_w));
|
||||
}
|
||||
|
||||
u8 sis7018_audio_device::capptr_r()
|
||||
{
|
||||
LOGIO("AUDIO Read capptr_r [$34]\n");
|
||||
return 0xdc;
|
||||
}
|
||||
|
||||
// TODO: move to specific interface
|
||||
u32 sis7018_audio_device::pmc_id_r()
|
||||
{
|
||||
LOGPMC("Read PMC ID [$dc]\n");
|
||||
// bits 31-16 PPMI v1.0, D1 / D2 supported, no PCI clock for PME#
|
||||
// bits 15-8 0x00 no NEXT_PTR (NULL terminates here)
|
||||
// bits 7-0 PM_CAP_ID (0x01 for PMC)
|
||||
return 0xe6110001;
|
||||
}
|
||||
|
||||
void sis7018_audio_device::memory_map(address_map &map)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void sis7018_audio_device::io_map(address_map &map)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void sis7018_audio_device::map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
|
||||
uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space)
|
||||
{
|
||||
// io_space->install_device(0, 0x03ff, *this, &sis7018_audio_device::io_map);
|
||||
// TODO: legacy handling, including game port
|
||||
}
|
||||
|
||||
void sis7018_audio_device::device_start()
|
||||
{
|
||||
pci_device::device_start();
|
||||
add_map(256, M_IO, FUNC(sis7018_audio_device::io_map));
|
||||
// not explicitly stated, assume 4096 size from the MEM decoding
|
||||
add_map(4096, M_MEM, FUNC(sis7018_audio_device::memory_map));
|
||||
}
|
||||
|
||||
|
||||
void sis7018_audio_device::device_reset()
|
||||
{
|
||||
pci_device::device_reset();
|
||||
|
||||
command = 0x0000;
|
||||
status = 0x0000;
|
||||
// INTB#
|
||||
intr_pin = 2;
|
||||
// TODO: can be written to with $46=1
|
||||
subsystem_id = 0x10397018;
|
||||
}
|
||||
|
||||
/*
|
||||
* Debugging
|
||||
*/
|
||||
|
||||
u8 sis7018_audio_device::unmap_log_r(offs_t offset)
|
||||
{
|
||||
LOGTODO("AUDIO Unemulated [%02x] R\n", offset + 0x40);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sis7018_audio_device::unmap_log_w(offs_t offset, u8 data)
|
||||
{
|
||||
LOGTODO("AUDIO Unemulated [%02x] %02x W\n", offset + 0x40, data);
|
||||
}
|
46
src/devices/machine/sis7018_audio.h
Normal file
46
src/devices/machine/sis7018_audio.h
Normal file
@ -0,0 +1,46 @@
|
||||
// license: BSD-3-Clause
|
||||
// copyright-holders: Angelo Salese
|
||||
|
||||
#ifndef MAME_MACHINE_SIS7018_AUDIO_H
|
||||
#define MAME_MACHINE_SIS7018_AUDIO_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pci.h"
|
||||
|
||||
class sis7018_audio_device : public pci_device
|
||||
{
|
||||
public:
|
||||
sis7018_audio_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
static constexpr feature_type unemulated_features() { return feature::SOUND; }
|
||||
|
||||
protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
|
||||
// virtual void reset_all_mappings() override;
|
||||
|
||||
virtual void map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
|
||||
uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) override;
|
||||
|
||||
virtual void config_map(address_map &map) override;
|
||||
|
||||
void memory_map(address_map &map);
|
||||
void io_map(address_map &map);
|
||||
|
||||
private:
|
||||
virtual u8 capptr_r() override;
|
||||
|
||||
u32 pmc_id_r();
|
||||
// void pmc_status_r();
|
||||
// u32 pmc_control(offs_t offset, u32 data, u32 mem_mask = ~0);
|
||||
|
||||
u8 unmap_log_r(offs_t offset);
|
||||
void unmap_log_w(offs_t offset, u8 data);
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(SIS7018_AUDIO, sis7018_audio_device)
|
||||
|
||||
#endif
|
161
src/devices/machine/sis900_eth.cpp
Normal file
161
src/devices/machine/sis900_eth.cpp
Normal file
@ -0,0 +1,161 @@
|
||||
// license: BSD-3-Clause
|
||||
// copyright-holders: Angelo Salese
|
||||
/**************************************************************************************************
|
||||
|
||||
SiS 900 Fast Ethernet Controller / Adapter
|
||||
|
||||
TODO:
|
||||
- Stub interface, to be improved;
|
||||
- Sensible defaults for EEPROM;
|
||||
|
||||
**************************************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "sis900_eth.h"
|
||||
|
||||
#define LOG_IO (1U << 1) // log PCI register accesses
|
||||
#define LOG_TODO (1U << 2) // log unimplemented registers
|
||||
#define LOG_MAP (1U << 3) // log full remaps
|
||||
#define LOG_PMC (1U << 4) // log PMC access
|
||||
|
||||
#define VERBOSE (LOG_GENERAL | LOG_IO | LOG_TODO | LOG_MAP | LOG_PMC)
|
||||
//#define LOG_OUTPUT_FUNC osd_printf_warning
|
||||
|
||||
#include "logmacro.h"
|
||||
|
||||
#define LOGIO(...) LOGMASKED(LOG_IO, __VA_ARGS__)
|
||||
#define LOGMAP(...) LOGMASKED(LOG_MAP, __VA_ARGS__)
|
||||
#define LOGTODO(...) LOGMASKED(LOG_TODO, __VA_ARGS__)
|
||||
#define LOGPMC(...) LOGMASKED(LOG_PMC, __VA_ARGS__)
|
||||
|
||||
DEFINE_DEVICE_TYPE(SIS900_ETH, sis900_eth_device, "sis900_eth", "SiS 900 Fast Ethernet Adapter")
|
||||
|
||||
sis900_eth_device::sis900_eth_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: pci_device(mconfig, SIS900_ETH, tag, owner, clock)
|
||||
, m_eeprom(*this, "eeprom")
|
||||
, m_eth_rom(*this, "eth_rom")
|
||||
{
|
||||
// 0x020000 - Network Ethernet controller
|
||||
// 0x80 - "Silicon revision" (sic)
|
||||
set_ids(0x10390900, 0x80, 0x020000, 0x00);
|
||||
}
|
||||
|
||||
void sis900_eth_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
EEPROM_93C66_16BIT(config, m_eeprom); // NM93Cxx
|
||||
}
|
||||
|
||||
void sis900_eth_device::config_map(address_map &map)
|
||||
{
|
||||
pci_device::config_map(map);
|
||||
map(0x40, 0x43).r(FUNC(sis900_eth_device::pmc_id_r));
|
||||
// map(0x44, 0x47).r(FUNC(sis900_eth_device::pmc_status_r), FUNC(sis900_eth_device::pmc_control_w));
|
||||
}
|
||||
|
||||
void sis900_eth_device::memory_map(address_map &map)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void sis900_eth_device::io_map(address_map &map)
|
||||
{
|
||||
map(0x08, 0x08).rw(FUNC(sis900_eth_device::eromar_r), FUNC(sis900_eth_device::eromar_w));
|
||||
}
|
||||
|
||||
void sis900_eth_device::map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
|
||||
uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space)
|
||||
{
|
||||
// io_space->install_device(0, 0x03ff, *this, &sis900_eth_device::io_map);
|
||||
}
|
||||
|
||||
ROM_START( sis900eth )
|
||||
ROM_REGION32_LE( 0x10000, "eth_rom", ROMREGION_ERASEFF )
|
||||
ROM_LOAD( "pxe_m.19", 0x0000, 0xa000, BAD_DUMP CRC(c8da34a6) SHA1(f11b4f5398176b7d924c63c77a1951cb83020e48) )
|
||||
// structure:
|
||||
// [0x00] signature -> 0x55aa
|
||||
// [0x08] MAC address
|
||||
// [0x0b] checksum
|
||||
// PCIR signature+[0x00] vendor ID -> 0x1039
|
||||
// PCIR signature+[0x02] device ID -> 0x0900
|
||||
ROM_END
|
||||
|
||||
const tiny_rom_entry *sis900_eth_device::device_rom_region() const
|
||||
{
|
||||
return ROM_NAME(sis900eth);
|
||||
}
|
||||
|
||||
void sis900_eth_device::device_start()
|
||||
{
|
||||
pci_device::device_start();
|
||||
|
||||
add_map(256, M_IO, FUNC(sis900_eth_device::io_map));
|
||||
add_map(4096, M_MEM, FUNC(sis900_eth_device::memory_map));
|
||||
add_rom((u8 *)m_eth_rom->base(), m_eth_rom->bytes());
|
||||
|
||||
// INTC#
|
||||
intr_pin = 3;
|
||||
// TODO: "if auto load is enabled it is set by subvendor ID stored in EEPROM" (?)
|
||||
subsystem_id = 0x10390900;
|
||||
}
|
||||
|
||||
void sis900_eth_device::device_reset()
|
||||
{
|
||||
pci_device::device_reset();
|
||||
|
||||
command = 0x0000;
|
||||
status = 0x0290;
|
||||
|
||||
m_eromar_mode = false;
|
||||
}
|
||||
|
||||
uint8_t sis900_eth_device::capptr_r()
|
||||
{
|
||||
return 0x40;
|
||||
}
|
||||
|
||||
// TODO: move to specific interface
|
||||
u32 sis900_eth_device::pmc_id_r()
|
||||
{
|
||||
LOGPMC("Read PMC ID [$40]\n");
|
||||
// bits 31-16 PPMI v1.0 / v1.0a, D1 / D2 supported, PME# D0/D1/D2/D3hot & optional D3cold
|
||||
// bits 15-8 0x00 no NEXT_PTR (NULL terminates here)
|
||||
// bits 7-0 PM_CAP_ID (0x01 for PMC)
|
||||
// TODO: versioning may depend on ROM installed
|
||||
return 0xfe010001;
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O space
|
||||
*/
|
||||
|
||||
u8 sis900_eth_device::eromar_r()
|
||||
{
|
||||
// TODO: doc claims all bits are readable, looks unlikely?
|
||||
u8 res = m_eromar_mode << 7;
|
||||
if (m_eromar_mode)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
else
|
||||
res |= m_eeprom->do_read() << 1;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void sis900_eth_device::eromar_w(u8 data)
|
||||
{
|
||||
m_eromar_mode = bool(BIT(data, 7));
|
||||
|
||||
LOGIO("eromar_w %s selected %02x\n", m_eromar_mode ? "HomePHY" : "eeprom", data);
|
||||
|
||||
if (m_eromar_mode)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
else
|
||||
{
|
||||
m_eeprom->cs_write(BIT(data, 3));
|
||||
m_eeprom->clk_write(BIT(data, 2));
|
||||
m_eeprom->di_write(BIT(data, 0));
|
||||
}
|
||||
}
|
53
src/devices/machine/sis900_eth.h
Normal file
53
src/devices/machine/sis900_eth.h
Normal file
@ -0,0 +1,53 @@
|
||||
// license: BSD-3-Clause
|
||||
// copyright-holders: Angelo Salese
|
||||
|
||||
#ifndef MAME_MACHINE_SIS900_ETH_H
|
||||
#define MAME_MACHINE_SIS900_ETH_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pci.h"
|
||||
#include "machine/eepromser.h"
|
||||
|
||||
class sis900_eth_device : public pci_device
|
||||
{
|
||||
public:
|
||||
sis900_eth_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
static constexpr feature_type unemulated_features() { return feature::LAN; }
|
||||
|
||||
protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
|
||||
virtual const tiny_rom_entry *device_rom_region() const override;
|
||||
|
||||
// virtual void reset_all_mappings() override;
|
||||
|
||||
virtual void map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
|
||||
uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) override;
|
||||
|
||||
virtual void config_map(address_map &map) override;
|
||||
|
||||
void memory_map(address_map &map);
|
||||
void io_map(address_map &map);
|
||||
|
||||
private:
|
||||
required_device<eeprom_serial_93cxx_device> m_eeprom;
|
||||
required_memory_region m_eth_rom;
|
||||
|
||||
bool m_eromar_mode;
|
||||
|
||||
virtual uint8_t capptr_r() override;
|
||||
u32 pmc_id_r();
|
||||
// void pmc_status_r();
|
||||
// u32 pmc_control(offs_t offset, u32 data, u32 mem_mask = ~0);
|
||||
|
||||
u8 eromar_r();
|
||||
void eromar_w(u8 data);
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(SIS900_ETH, sis900_eth_device)
|
||||
|
||||
#endif
|
764
src/devices/machine/sis950_lpc.cpp
Normal file
764
src/devices/machine/sis950_lpc.cpp
Normal file
@ -0,0 +1,764 @@
|
||||
// license: BSD-3-Clause
|
||||
// copyright-holders: Angelo Salese
|
||||
/**************************************************************************************************
|
||||
|
||||
SiS950 LPC implementation (Super I/O & southbridge)
|
||||
|
||||
TODO:
|
||||
- Convert most stuff declared here to generic interfaces;
|
||||
- Flash ROM handling
|
||||
\- Doesn't survive a soft reset;
|
||||
- Fix EISA;
|
||||
- INIT register (reset & A20 control + fast gates + fast reset timing control);
|
||||
- Override PS/2 ports if USB legacy mode is enabled;
|
||||
- NMI & SMI handling;
|
||||
- SMBus handling;
|
||||
- RTC extended bank enable;
|
||||
\- Doesn't survive a CMOS write after fast reset;
|
||||
- Shadow registers for PIC and PIT;
|
||||
- IRQ remaps
|
||||
\- INTA GUI
|
||||
\- INTB AUDIO and MODEM
|
||||
\- INTC ethernet
|
||||
\- INTD USB
|
||||
- IRQ software traps ($6e-$6f);
|
||||
\- Documentation mentions that those can be read-back too, huh?
|
||||
- Understand what's the caveat of "changing device ID number" via BIOS control $40 bit 6;
|
||||
|
||||
**************************************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "sis950_lpc.h"
|
||||
#include "bus/pc_kbd/keyboards.h"
|
||||
#include "speaker.h"
|
||||
|
||||
#define LOG_IO (1U << 1) // log PCI register accesses
|
||||
#define LOG_TODO (1U << 2) // log unimplemented registers
|
||||
#define LOG_MAP (1U << 3) // log full remaps
|
||||
#define LOG_LPC (1U << 4) // log LPC legacy regs
|
||||
#define LOG_IRQ (1U << 5) // log IRQ remaps
|
||||
|
||||
#define VERBOSE (LOG_GENERAL | LOG_IO | LOG_TODO | LOG_IRQ)
|
||||
//#define LOG_OUTPUT_FUNC osd_printf_warning
|
||||
|
||||
#include "logmacro.h"
|
||||
|
||||
#define LOGIO(...) LOGMASKED(LOG_IO, __VA_ARGS__)
|
||||
#define LOGMAP(...) LOGMASKED(LOG_MAP, __VA_ARGS__)
|
||||
#define LOGTODO(...) LOGMASKED(LOG_TODO, __VA_ARGS__)
|
||||
#define LOGLPC(...) LOGMASKED(LOG_LPC, __VA_ARGS__)
|
||||
#define LOGIRQ(...) LOGMASKED(LOG_IRQ, __VA_ARGS__)
|
||||
|
||||
DEFINE_DEVICE_TYPE(SIS950_LPC, sis950_lpc_device, "sis950_lpc", "SiS 950 LPC Super-South Bridge")
|
||||
|
||||
sis950_lpc_device::sis950_lpc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: pci_device(mconfig, SIS950_LPC, tag, owner, clock)
|
||||
, m_host_cpu(*this, finder_base::DUMMY_TAG)
|
||||
, m_flash_rom(*this, finder_base::DUMMY_TAG)
|
||||
, m_pic_master(*this, "pic_master")
|
||||
, m_pic_slave(*this, "pic_slave")
|
||||
, m_dmac_master(*this, "dmac_master")
|
||||
, m_dmac_slave(*this, "dmac_slave")
|
||||
, m_pit(*this, "pit")
|
||||
, m_keybc(*this, "keybc")
|
||||
, m_speaker(*this, "speaker")
|
||||
, m_rtc(*this, "rtc")
|
||||
, m_ps2_con(*this, "ps2_con")
|
||||
, m_aux_con(*this, "aux_con")
|
||||
, m_uart(*this, "uart")
|
||||
, m_acpi(*this, "acpi")
|
||||
, m_smbus(*this, "smbus")
|
||||
, m_fast_reset_cb(*this)
|
||||
{
|
||||
}
|
||||
|
||||
void sis950_lpc_device::device_start()
|
||||
{
|
||||
pci_device::device_start();
|
||||
|
||||
m_fast_reset_cb.resolve_safe();
|
||||
}
|
||||
|
||||
void sis950_lpc_device::device_reset()
|
||||
{
|
||||
pci_device::device_reset();
|
||||
|
||||
command = 0x000c;
|
||||
status = 0x0200;
|
||||
|
||||
m_bios_control = 1;
|
||||
m_acpi_base = 0;
|
||||
m_flash_control = 0x40;
|
||||
m_keybc_reg = 0x51;
|
||||
m_dma_channel = -1;
|
||||
// m_cur_eop = false;
|
||||
m_dma_high_byte = 0;
|
||||
m_init_reg = 0;
|
||||
m_rtc_reg = 0x10;
|
||||
// remapping is disabled for all as default
|
||||
std::fill(std::begin(m_irq_remap), std::end(m_irq_remap), 0x80);
|
||||
|
||||
m_lpc_legacy.fast_init = 0;
|
||||
remap_cb();
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(sis950_lpc_device::cpu_a20_w)
|
||||
{
|
||||
// TODO: confirm "A20M# being always high"
|
||||
// if (BIT(m_init_reg, 1))
|
||||
// state = ASSERT_LINE;
|
||||
m_host_cpu->set_input_line(INPUT_LINE_A20, state);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(sis950_lpc_device::cpu_reset_w)
|
||||
{
|
||||
// TODO: masked via INIT $46 bit 0
|
||||
m_host_cpu->set_input_line(INPUT_LINE_RESET, state);
|
||||
}
|
||||
|
||||
void sis950_lpc_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
constexpr XTAL lpc_pit_clock = XTAL(14'318'181);
|
||||
|
||||
// confirmed 82C54
|
||||
PIT8254(config, m_pit, 0);
|
||||
// heartbeat IRQ
|
||||
m_pit->set_clk<0>(lpc_pit_clock / 12);
|
||||
m_pit->out_handler<0>().set(FUNC(sis950_lpc_device::pit_out0));
|
||||
// DRAM refresh
|
||||
m_pit->set_clk<1>(lpc_pit_clock / 12);
|
||||
m_pit->out_handler<1>().set(FUNC(sis950_lpc_device::pit_out1));
|
||||
// PIO port C pin 4, and speaker polling enough
|
||||
m_pit->set_clk<2>(lpc_pit_clock / 12);
|
||||
m_pit->out_handler<2>().set(FUNC(sis950_lpc_device::pit_out2));
|
||||
|
||||
// TODO: unknown part #
|
||||
AM9517A(config, m_dmac_master, lpc_pit_clock / 3);
|
||||
m_dmac_master->out_hreq_callback().set(m_dmac_slave, FUNC(am9517a_device::dreq0_w));
|
||||
// m_dmac_master->out_eop_callback().set(FUNC(sis950_lpc_device::at_dma8237_out_eop));
|
||||
m_dmac_master->in_memr_callback().set(FUNC(sis950_lpc_device::pc_dma_read_byte));
|
||||
m_dmac_master->out_memw_callback().set(FUNC(sis950_lpc_device::pc_dma_write_byte));
|
||||
// TODO: ior/iow/dack/eop callbacks
|
||||
|
||||
AM9517A(config, m_dmac_slave, lpc_pit_clock / 3);
|
||||
m_dmac_slave->out_hreq_callback().set(FUNC(sis950_lpc_device::pc_dma_hrq_changed));
|
||||
m_dmac_slave->in_memr_callback().set(FUNC(sis950_lpc_device::pc_dma_read_word));
|
||||
m_dmac_slave->out_memw_callback().set(FUNC(sis950_lpc_device::pc_dma_write_word));
|
||||
// TODO: ior/iow/dack callbacks
|
||||
|
||||
// Confirmed 82C59s
|
||||
PIC8259(config, m_pic_master, 0);
|
||||
m_pic_master->out_int_callback().set_inputline(m_host_cpu, 0);
|
||||
m_pic_master->in_sp_callback().set_constant(1);
|
||||
m_pic_master->read_slave_ack_callback().set(
|
||||
[this](offs_t offset) -> u8
|
||||
{
|
||||
if (offset == 2)
|
||||
return m_pic_slave->acknowledge();
|
||||
|
||||
return 0;
|
||||
});
|
||||
|
||||
PIC8259(config, m_pic_slave, 0);
|
||||
m_pic_slave->out_int_callback().set(m_pic_master, FUNC(pic8259_device::ir2_w));
|
||||
m_pic_slave->in_sp_callback().set_constant(0);
|
||||
|
||||
// TODO: EISA, from virtual bridge
|
||||
|
||||
PC_KBDC(config, m_ps2_con, pc_at_keyboards, STR_KBD_MICROSOFT_NATURAL);
|
||||
m_ps2_con->out_clock_cb().set(m_keybc, FUNC(ps2_keyboard_controller_device::kbd_clk_w));
|
||||
m_ps2_con->out_data_cb().set(m_keybc, FUNC(ps2_keyboard_controller_device::kbd_data_w));
|
||||
|
||||
PC_KBDC(config, m_aux_con, ps2_mice, STR_HLE_PS2_MOUSE);
|
||||
m_aux_con->out_clock_cb().set(m_keybc, FUNC(ps2_keyboard_controller_device::aux_clk_w));
|
||||
m_aux_con->out_data_cb().set(m_keybc, FUNC(ps2_keyboard_controller_device::aux_data_w));
|
||||
|
||||
// TODO: selectable between PCI clock / 4 (33 MHz) or 7.159 MHz, via reg $47 bit 5
|
||||
PS2_KEYBOARD_CONTROLLER(config, m_keybc, DERIVED_CLOCK(1, 4));
|
||||
// TODO: default ibm BIOS doesn't cope with this too well
|
||||
m_keybc->set_default_bios_tag("compaq");
|
||||
m_keybc->hot_res().set(FUNC(sis950_lpc_device::cpu_reset_w));
|
||||
m_keybc->gate_a20().set(FUNC(sis950_lpc_device::cpu_a20_w));
|
||||
m_keybc->kbd_irq().set(m_pic_master, FUNC(pic8259_device::ir1_w));
|
||||
m_keybc->kbd_clk().set(m_ps2_con, FUNC(pc_kbdc_device::clock_write_from_mb));
|
||||
m_keybc->kbd_data().set(m_ps2_con, FUNC(pc_kbdc_device::data_write_from_mb));
|
||||
m_keybc->aux_irq().set(m_pic_slave, FUNC(pic8259_device::ir4_w));
|
||||
m_keybc->aux_clk().set(m_aux_con, FUNC(pc_kbdc_device::clock_write_from_mb));
|
||||
m_keybc->aux_data().set(m_aux_con, FUNC(pc_kbdc_device::data_write_from_mb));
|
||||
|
||||
// TODO: unknown RTC type
|
||||
// Has external RTC bank select at $48, using this one as convenience
|
||||
DS12885EXT(config, m_rtc, XTAL(32'768));
|
||||
m_rtc->irq().set(m_pic_slave, FUNC(pic8259_device::ir0_w));
|
||||
m_rtc->set_century_index(0x32);
|
||||
|
||||
// serial fragment
|
||||
// TODO: unconfirmed type / clock
|
||||
INS8250(config, m_uart, XTAL(18'432'000) / 10);
|
||||
m_uart->out_tx_callback().set("com1", FUNC(rs232_port_device::write_txd));
|
||||
m_uart->out_dtr_callback().set("com1", FUNC(rs232_port_device::write_dtr));
|
||||
m_uart->out_rts_callback().set("com1", FUNC(rs232_port_device::write_rts));
|
||||
// m_uart->out_int_callback().set()
|
||||
// m_uart->out_baudout_callback().set([this](int state){ if (m_8251dtr_state) m_uart->rclk_w(state); }); // TODO: Fix INS8250 BAUDOUT pin support
|
||||
|
||||
rs232_port_device &rs232(RS232_PORT(config, "com1", default_rs232_devices, nullptr));
|
||||
rs232.rxd_handler().set(m_uart, FUNC(ins8250_uart_device::rx_w));
|
||||
rs232.dcd_handler().set(m_uart, FUNC(ins8250_uart_device::dcd_w));
|
||||
rs232.dsr_handler().set(m_uart, FUNC(ins8250_uart_device::dsr_w));
|
||||
rs232.ri_handler().set(m_uart, FUNC(ins8250_uart_device::ri_w));
|
||||
rs232.cts_handler().set(m_uart, FUNC(ins8250_uart_device::cts_w));
|
||||
|
||||
// TODO: left/right speaker connection
|
||||
SPEAKER(config, "mono").front_center();
|
||||
SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.50);
|
||||
}
|
||||
|
||||
void sis950_lpc_device::config_map(address_map &map)
|
||||
{
|
||||
pci_device::config_map(map);
|
||||
map(0x10, 0x4f).unmaprw();
|
||||
map(0x10, 0x75).rw(FUNC(sis950_lpc_device::unmap_log_r), FUNC(sis950_lpc_device::unmap_log_w));
|
||||
|
||||
// LPC control regs
|
||||
map(0x40, 0x40).rw(FUNC(sis950_lpc_device::bios_control_r), FUNC(sis950_lpc_device::bios_control_w));
|
||||
map(0x41, 0x41).rw(FUNC(sis950_lpc_device::irq_remap_r<IRQ_INTA>), FUNC(sis950_lpc_device::irq_remap_w<IRQ_INTA>));
|
||||
map(0x42, 0x42).rw(FUNC(sis950_lpc_device::irq_remap_r<IRQ_INTB>), FUNC(sis950_lpc_device::irq_remap_w<IRQ_INTB>));
|
||||
map(0x43, 0x43).rw(FUNC(sis950_lpc_device::irq_remap_r<IRQ_INTC>), FUNC(sis950_lpc_device::irq_remap_w<IRQ_INTC>));
|
||||
map(0x44, 0x44).rw(FUNC(sis950_lpc_device::irq_remap_r<IRQ_INTD>), FUNC(sis950_lpc_device::irq_remap_w<IRQ_INTD>));
|
||||
|
||||
map(0x45, 0x45).rw(FUNC(sis950_lpc_device::flash_ctrl_r), FUNC(sis950_lpc_device::flash_ctrl_w));
|
||||
map(0x46, 0x46).rw(FUNC(sis950_lpc_device::init_enable_r), FUNC(sis950_lpc_device::init_enable_w));
|
||||
map(0x47, 0x47).rw(FUNC(sis950_lpc_device::keybc_reg_r), FUNC(sis950_lpc_device::keybc_reg_w));
|
||||
map(0x48, 0x48).rw(FUNC(sis950_lpc_device::rtc_reg_r), FUNC(sis950_lpc_device::rtc_reg_w));
|
||||
|
||||
// DMA control regs
|
||||
// map(0x49, 0x49) Distributed DMA channel enable
|
||||
// map(0x4a, 0x4b) Distributed DMA Master config
|
||||
|
||||
// Shadow regs (r/o)
|
||||
// map(0x4c, 0x4f) PIC master ICW*
|
||||
// map(0x50, 0x53) PIC slave ICW*
|
||||
// map(0x54, 0x55) PIC master OCW2-3
|
||||
// map(0x56, 0x57) PIC slave OCW2-3 (NB: assume documentation 0x54-0x55 to be a typo)
|
||||
// map(0x58, 0x5f) PIT counters 0-1-2 low/high, $5e -> control 43h, $5f -> read count pointer statuses
|
||||
// map(0x60, 0x60) EISA port $70
|
||||
|
||||
map(0x61, 0x61).rw(FUNC(sis950_lpc_device::irq_remap_r<IRQ_IDE>), FUNC(sis950_lpc_device::irq_remap_w<IRQ_IDE>));
|
||||
// map(0x62, 0x62) <reserved>, hardwired to 0x80 (PIT irq remap?)
|
||||
map(0x62, 0x62).lr8(NAME([] () { return 0x80; }));
|
||||
map(0x63, 0x63).rw(FUNC(sis950_lpc_device::irq_remap_r<IRQ_GPE>), FUNC(sis950_lpc_device::irq_remap_w<IRQ_GPE>));
|
||||
|
||||
// map(0x64, 0x64) PCI bus priority timer
|
||||
// map(0x65, 0x65) PHOLD# timer
|
||||
|
||||
// map(0x66, 0x66) <reserved>
|
||||
// map(0x67, 0x67) Serial IRQ 1 & 12 latch control (FDC super I/O)
|
||||
// map(0x68, 0x69) <reserved>
|
||||
|
||||
map(0x63, 0x63).rw(FUNC(sis950_lpc_device::irq_remap_r<IRQ_ACPI>), FUNC(sis950_lpc_device::irq_remap_w<IRQ_ACPI>));
|
||||
// map(0x6b, 0x6b) <reserved>
|
||||
map(0x6c, 0x6c).rw(FUNC(sis950_lpc_device::irq_remap_r<IRQ_SMBUS>), FUNC(sis950_lpc_device::irq_remap_w<IRQ_SMBUS>));
|
||||
map(0x6d, 0x6d).rw(FUNC(sis950_lpc_device::irq_remap_r<IRQ_SWDOG>), FUNC(sis950_lpc_device::irq_remap_w<IRQ_SWDOG>));
|
||||
|
||||
// map(0x6e, 0x6f) SW irq triggers
|
||||
// map(0x70, 0x70) Serial irq control
|
||||
// map(0x71, 0x73) Serial irq enable
|
||||
|
||||
// $74 should be ACPI lower base bank, but marked as <reserved> regardless
|
||||
// (by logic that should go to NOP too)
|
||||
map(0x74, 0x74).lr8(NAME([] () { return 0; }));
|
||||
map(0x75, 0x75).rw(FUNC(sis950_lpc_device::acpi_base_r), FUNC(sis950_lpc_device::acpi_base_w));
|
||||
}
|
||||
|
||||
u8 sis950_lpc_device::bios_control_r()
|
||||
{
|
||||
LOGIO("Read BIOS control [$40] %02x\n", m_bios_control);
|
||||
return m_bios_control;
|
||||
}
|
||||
|
||||
void sis950_lpc_device::bios_control_w(u8 data)
|
||||
{
|
||||
// Mostly 0x9a or 0x9b
|
||||
LOGIO("Write BIOS control [$40] %02x\n", data);
|
||||
m_bios_control = data;
|
||||
remap_cb();
|
||||
}
|
||||
|
||||
template <unsigned N> u8 sis950_lpc_device::irq_remap_r()
|
||||
{
|
||||
return m_irq_remap[N];
|
||||
}
|
||||
|
||||
template <unsigned N> void sis950_lpc_device::irq_remap_w(u8 data)
|
||||
{
|
||||
m_irq_remap[N] = data;
|
||||
LOGIRQ("%s IRQ remap write %02x (%s)\n", std::array<char const *, 9> {{
|
||||
"INTA",
|
||||
"INTB",
|
||||
"INTC",
|
||||
"INTD",
|
||||
"IDEIRQ",
|
||||
"GPEIRQ",
|
||||
"ACPI/SCI",
|
||||
"SMBus",
|
||||
"Software Watchdog"
|
||||
}}[N], data, BIT(data, 7) ? "disable" : "enable");
|
||||
}
|
||||
|
||||
u8 sis950_lpc_device::flash_ctrl_r()
|
||||
{
|
||||
LOGIO("Read Flash control [$45] %02x\n", m_flash_control);
|
||||
return m_flash_control;
|
||||
}
|
||||
|
||||
void sis950_lpc_device::flash_ctrl_w(u8 data)
|
||||
{
|
||||
LOGIO("Write Flash control [$45] %02x\n", data);
|
||||
m_flash_control = data;
|
||||
remap_cb();
|
||||
}
|
||||
|
||||
u8 sis950_lpc_device::init_enable_r()
|
||||
{
|
||||
LOGIO("Read INIT enable [$46] %02x\n", m_init_reg);
|
||||
return m_init_reg;
|
||||
}
|
||||
|
||||
/*
|
||||
* 11-- ---- HW (fast?) reset
|
||||
* --x- ---- INIT enable
|
||||
* ---x ---- Fast Gate A20 emulation
|
||||
* ---- x--- Fast Reset latency control
|
||||
* ---- -x-- Fast Reset emulation
|
||||
* ---- --x- (0) enable A20M# (1) A20M# always high (?)
|
||||
* ---- ---x Keyboard HW reset
|
||||
*/
|
||||
void sis950_lpc_device::init_enable_w(u8 data)
|
||||
{
|
||||
LOGIO("Write INIT enable [$46] %02x\n", data);
|
||||
// HW fast reset
|
||||
// TODO: is 0->1 implementation correct?
|
||||
// it will otherwise keep resetting itself, which may be a side effect of something else
|
||||
// (perhaps PS/2 controller can intercept this? Or it's a full on LPC reset like using an actual MAME soft reset implies?)
|
||||
if ((data & 0xc0) == 0xc0)// && (m_init_reg & 0xc0) == 0)
|
||||
{
|
||||
//const int fast_reset_time = BIT(data, 3) ? 6 : 2;
|
||||
LOGIO("Fast reset issued\n");
|
||||
//m_host_cpu->pulse_input_line(INPUT_LINE_RESET, attotime::from_usec(fast_reset_time));
|
||||
m_fast_reset_cb(1);
|
||||
}
|
||||
|
||||
m_init_reg = data;
|
||||
}
|
||||
|
||||
u8 sis950_lpc_device::keybc_reg_r()
|
||||
{
|
||||
LOGIO("Read keyboard register [$47] %02x\n", m_keybc_reg);
|
||||
return m_keybc_reg;
|
||||
}
|
||||
|
||||
/*
|
||||
* x--- ---- legacy USB (ports $60-$64 overrides)
|
||||
* -x-- ---- PS/2 mouse lock enable
|
||||
* --x- ---- Keyboard controller clock select (0) PCI Clock / 4 (1) 7.159 MHz
|
||||
* ---x ---- Keyboard lock enable
|
||||
* ---- x--- Integrated keyboard controller enable
|
||||
* ---- -x-- Integrated PS/2 mouse enable (needs bit 3 enabled)
|
||||
* ---- --x- Keyboard hot key status (needs bit 3 enabled, ctrl+alt+backspace)
|
||||
* ---- ---x Keyboard hot key control
|
||||
*/
|
||||
void sis950_lpc_device::keybc_reg_w(u8 data)
|
||||
{
|
||||
LOGIO("Write keyboard register [$47] %02x\n", data);
|
||||
m_keybc_reg = data;
|
||||
}
|
||||
|
||||
u8 sis950_lpc_device::rtc_reg_r()
|
||||
{
|
||||
LOGIO("Read RTC register [$48] %02x\n", m_keybc_reg);
|
||||
return m_rtc_reg | 0x10;
|
||||
}
|
||||
|
||||
/*
|
||||
* x--- ---- RTC extended bank enable
|
||||
* -x-- ---- APC enable
|
||||
* --x- ---- Instant Power-Off enable (thru APC)
|
||||
* ---x ---- Internal RTC status (r/o, always on?)
|
||||
* ---- xxxx <reserved>
|
||||
*/
|
||||
void sis950_lpc_device::rtc_reg_w(u8 data)
|
||||
{
|
||||
LOGIO("Write RTC register [$48] %02x\n", data);
|
||||
m_rtc_reg = data;
|
||||
}
|
||||
|
||||
u8 sis950_lpc_device::acpi_base_r()
|
||||
{
|
||||
LOGIO("Read ACPI base [$75] %04x\n", m_acpi_base);
|
||||
return m_acpi_base >> 8;
|
||||
}
|
||||
|
||||
void sis950_lpc_device::acpi_base_w(u8 data)
|
||||
{
|
||||
u16 new_value = data << 8;
|
||||
LOGIO("Write ACPI base [$75] %04x\n", new_value);
|
||||
m_acpi_base = new_value;
|
||||
remap_cb();
|
||||
}
|
||||
|
||||
template <unsigned N> void sis950_lpc_device::memory_map(address_map &map)
|
||||
{
|
||||
map(0x00000000, 0x0001ffff).lrw8(
|
||||
NAME([this] (offs_t offset) { return m_flash_rom->read(offset | N * 0x20000); }),
|
||||
NAME([this] (offs_t offset, u8 data) { m_flash_rom->write(offset | N * 0x20000, data); })
|
||||
);
|
||||
}
|
||||
|
||||
void sis950_lpc_device::io_map(address_map &map)
|
||||
{
|
||||
// Legacy ISA (page 177)
|
||||
// map(0x0000, 0x000f) DMA1
|
||||
map(0x0000, 0x001f).rw(m_dmac_master, FUNC(am9517a_device::read), FUNC(am9517a_device::write));
|
||||
// map(0x0020, 0x0021) INT1
|
||||
map(0x0020, 0x003f).rw(m_pic_master, FUNC(pic8259_device::read), FUNC(pic8259_device::write));
|
||||
// map(0x0040, 0x0043) PIT
|
||||
map(0x0040, 0x0043).rw(m_pit, FUNC(pit8254_device::read), FUNC(pit8254_device::write));
|
||||
map(0x0060, 0x0060).rw(m_keybc, FUNC(ps2_keyboard_controller_device::data_r), FUNC(ps2_keyboard_controller_device::data_w));
|
||||
// map(0x0061, 0x0061) NMI Status Register
|
||||
map(0x0061, 0x0061).rw(FUNC(sis950_lpc_device::nmi_status_r), FUNC(sis950_lpc_device::nmi_control_w));
|
||||
// undocumented but read, assume LPC complaint
|
||||
map(0x0064, 0x0064).rw(m_keybc, FUNC(ps2_keyboard_controller_device::status_r), FUNC(ps2_keyboard_controller_device::command_w));
|
||||
// map(0x0070, 0x0070) CMOS and NMI Mask
|
||||
map(0x0070, 0x0070).w(FUNC(sis950_lpc_device::rtc_index_w));
|
||||
map(0x0071, 0x0071).rw(FUNC(sis950_lpc_device::rtc_data_r), FUNC(sis950_lpc_device::rtc_data_w));
|
||||
// map(0x0080, 0x008f) DMA low page registers
|
||||
map(0x0080, 0x008f).rw(FUNC(sis950_lpc_device::at_page8_r), FUNC(sis950_lpc_device::at_page8_w));
|
||||
// map(0x0092, 0x0092) INIT and A20
|
||||
map(0x0092, 0x0092).rw(FUNC(sis950_lpc_device::lpc_fast_init_r), FUNC(sis950_lpc_device::lpc_fast_init_w));
|
||||
// map(0x00a0, 0x00a1) INT2
|
||||
map(0x00a0, 0x00bf).rw(m_pic_slave, FUNC(pic8259_device::read), FUNC(pic8259_device::write));
|
||||
// map(0x00c0, 0x00df) DMA2
|
||||
map(0x00c0, 0x00df).lrw8(
|
||||
NAME([this] (offs_t offset) { return m_dmac_slave->read( offset / 2 ); }),
|
||||
NAME([this] (offs_t offset, u8 data) { m_dmac_slave->write( offset / 2, data ); })
|
||||
);
|
||||
|
||||
map(0x00e0, 0x00ef).noprw();
|
||||
// map(0x00f0, 0x00f0) COPRO error
|
||||
// map(0x0480, 0x048f) DMA high page registers
|
||||
// map(0x04d0, 0x04d1) IRQ edge/level control registers
|
||||
|
||||
// http://bxr.su/DragonFly/share/man/man4/it.4
|
||||
// 0x0290, 0xc00, 0xd00, 0x228: Motherboard Super I/O HW monitoring
|
||||
|
||||
// map(0x0295, 0x0295) - index register, $d-$e lower/upper RPM readback for fans (alternating on read)
|
||||
// map(0x0296, 0x0296) - data ^
|
||||
|
||||
// Intel LPC interface specs (legacy host decode ranges, not necessarily present on '950)
|
||||
|
||||
// map(0x002e, 0x002f) Super I/O config (config-index & data ports)
|
||||
// map(0x004e, 0x004f) alt Super I/O config (ISA converter index-data ports)
|
||||
// map(0x0062, 0x0062) - ACPI embedded controller
|
||||
// map(0x0066, 0x0066) /
|
||||
|
||||
// map(0x0200, 0x020f) game ports ($201 as shutms11 default)
|
||||
|
||||
// map(0x0220, 0x0227) serial 2
|
||||
// map(0x0228, 0x022f) serial 2
|
||||
// map(0x0220, 0x0233) sb compatible i/f 1
|
||||
// map(0x0240, 0x0253) sb compatible i/f 2
|
||||
// map(0x0260, 0x0273) sb compatible i/f 3
|
||||
// map(0x0280, 0x0293) sb compatible i/f 4
|
||||
|
||||
// map(0x0238, 0x023f) serial 3
|
||||
|
||||
// map(0x0278, 0x027f) parallel port 2 & PnP
|
||||
// map(0x02e8, 0x02ef) serial 3
|
||||
// map(0x02f8, 0x02ff) serial 1
|
||||
|
||||
// map(0x0300, 0x0301) - MIDI ($330 as shutms11 default)
|
||||
// map(0x0310, 0x0311) /
|
||||
// map(0x0320, 0x0321) /
|
||||
// map(0x0330, 0x0331) /
|
||||
|
||||
// map(0x0338, 0x033f) serial 4
|
||||
// map(0x0370, 0x0377) FDC 2
|
||||
|
||||
// map(0x0378, 0x037f) parallel port 1
|
||||
// map(0x0388, 0x0389) ADLIB
|
||||
// map(0x03bc, 0x03bf) parallel port 3
|
||||
// map(0x03e8, 0x03ef) serial 4
|
||||
// map(0x03f0, 0x03f7) FDC 1
|
||||
map(0x03f8, 0x03ff).rw(m_uart, FUNC(ins8250_device::ins8250_r), FUNC(ins8250_device::ins8250_w)); // COM1
|
||||
|
||||
// map(0x0530, 0x0537) - MSS (TCP Maximum Segment Size?)
|
||||
// map(0x0604, 0x060b) /
|
||||
// map(0x0e80, 0x0e87) /
|
||||
// map(0x0f40, 0x0f47) /
|
||||
|
||||
// map(0x0678, 0x067f) ECP parallel port 1
|
||||
// map(0x0778, 0x0779) ECP parallel port 2 & PnP
|
||||
// map(0x07bc, 0x07bf) ECP parallel port 3
|
||||
}
|
||||
|
||||
void sis950_lpc_device::map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
|
||||
uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space)
|
||||
{
|
||||
io_space->install_device(0, 0x07ff, *this, &sis950_lpc_device::io_map);
|
||||
|
||||
LOGMAP("LPC Remapping table (BIOS: %02x, flash: %02x)\n", m_bios_control, m_flash_control);
|
||||
|
||||
// ACPI enable
|
||||
if (BIT(m_bios_control, 7))
|
||||
{
|
||||
LOGMAP("- ACPI enable (%02x) %04x-%04x\n", m_bios_control, m_acpi_base, m_acpi_base + 0xff);
|
||||
// shutms11 BIOS POST maps this at $5000
|
||||
m_acpi->map_device(memory_window_start, memory_window_end, 0, memory_space, io_window_start, io_window_end, m_acpi_base, io_space);
|
||||
io_space->install_device(m_acpi_base | 0x80, m_acpi_base | 0xff, *m_smbus, &sis950_smbus_device::map);
|
||||
}
|
||||
|
||||
// TODO: disable flash access write thru reg $45
|
||||
// TODO: BIOS positive decode
|
||||
// (bios_control bit 1), which should disable BIOS mapping to E and F segment
|
||||
|
||||
memory_space->install_device(0x000e0000, 0x000fffff, *this, &sis950_lpc_device::memory_map<3>);
|
||||
// extended BIOS enable
|
||||
if (m_bios_control & 1)
|
||||
{
|
||||
LOGMAP("- Extend BIOS on\n");
|
||||
memory_space->install_device(0xfff80000, 0xfff9ffff, *this, &sis950_lpc_device::memory_map<0>);
|
||||
memory_space->install_device(0xfffa0000, 0xfffbffff, *this, &sis950_lpc_device::memory_map<1>);
|
||||
memory_space->install_device(0xfffc0000, 0xfffdffff, *this, &sis950_lpc_device::memory_map<2>);
|
||||
}
|
||||
memory_space->install_device(0xfffe0000, 0xffffffff, *this, &sis950_lpc_device::memory_map<3>);
|
||||
}
|
||||
|
||||
u8 sis950_lpc_device::lpc_fast_init_r()
|
||||
{
|
||||
LOGLPC("LPC fast init read [$92]\n");
|
||||
return m_lpc_legacy.fast_init;
|
||||
}
|
||||
|
||||
void sis950_lpc_device::lpc_fast_init_w(offs_t offset, u8 data)
|
||||
{
|
||||
LOGLPC("LPC fast init write [$92] %02x\n", data);
|
||||
if (data & 0xfd)
|
||||
LOG("Warning: unemulated LPC fast init type %02x", data);
|
||||
|
||||
// TODO: pinpoint exact disable INIT condition and if that will be reflected on reading reg too
|
||||
m_host_cpu->set_input_line(INPUT_LINE_A20, BIT(data, 1));
|
||||
|
||||
m_lpc_legacy.fast_init = data;
|
||||
}
|
||||
|
||||
/*
|
||||
* Debugging
|
||||
*/
|
||||
u8 sis950_lpc_device::unmap_log_r(offs_t offset)
|
||||
{
|
||||
LOGTODO("LPC Unemulated [%02x] R\n", offset + 0x10);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sis950_lpc_device::unmap_log_w(offs_t offset, u8 data)
|
||||
{
|
||||
LOGTODO("LPC Unemulated [%02x] %02x W\n", offset + 0x10, data);
|
||||
}
|
||||
|
||||
/*
|
||||
* Start of legacy handling, to be moved out
|
||||
*/
|
||||
|
||||
WRITE_LINE_MEMBER( sis950_lpc_device::pit_out0 )
|
||||
{
|
||||
m_pic_master->ir0_w(state);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER( sis950_lpc_device::pit_out1 )
|
||||
{
|
||||
if(state)
|
||||
m_refresh = !m_refresh;
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER( sis950_lpc_device::pit_out2 )
|
||||
{
|
||||
m_pit_out2 = state ? 1 : 0;
|
||||
m_speaker->level_w(m_at_spkrdata & m_pit_out2);
|
||||
}
|
||||
|
||||
/*
|
||||
* x--- ---- Set if a PCI device or main memory module asserts PERR#/SERR# line
|
||||
* -x-- ---- Set when IOCHK# is asserted on ISA bus
|
||||
* --x- ---- Counter 2 out signal state (PIT ch. 2)
|
||||
* ---x ---- Refresh bit toggle (PIT ch. 1)
|
||||
* ---- xxxx <reads back NMI control enable>
|
||||
*/
|
||||
uint8_t sis950_lpc_device::nmi_status_r()
|
||||
{
|
||||
uint8_t data = m_at_speaker;
|
||||
data &= ~0xd0; // AT BIOS don't likes this being set
|
||||
|
||||
data |= m_refresh ? 0x10 : 0;
|
||||
|
||||
if (m_pit_out2)
|
||||
data |= 0x20;
|
||||
else
|
||||
data &= ~0x20; // ps2m30 wants this
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void sis950_lpc_device::at_speaker_set_spkrdata(uint8_t data)
|
||||
{
|
||||
m_at_spkrdata = data ? 1 : 0;
|
||||
m_speaker->level_w(m_at_spkrdata & m_pit_out2);
|
||||
}
|
||||
|
||||
/*
|
||||
* xxxx ---- <must be zero when writing to this port>
|
||||
* ---- x--- (0) enable IOCHK# NMI (1) clear and disable IOCHK# NMI
|
||||
* ---- -x-- (0) enable PCI SERR# (1) clear and disable PCI SERR#
|
||||
* ---- --x- Speaker output enable
|
||||
* ---- ---x Timer counter 2 enable
|
||||
*/
|
||||
void sis950_lpc_device::nmi_control_w(uint8_t data)
|
||||
{
|
||||
m_at_speaker = data;
|
||||
m_pit->write_gate2(BIT(data, 0));
|
||||
at_speaker_set_spkrdata(BIT(data, 1));
|
||||
m_channel_check = BIT(data, 3);
|
||||
if (m_channel_check)
|
||||
m_host_cpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE);
|
||||
}
|
||||
|
||||
void sis950_lpc_device::rtc_index_w(uint8_t data)
|
||||
{
|
||||
m_rtc_index = data & 0x7f;
|
||||
// bit 7: NMI enable
|
||||
}
|
||||
|
||||
u8 sis950_lpc_device::rtc_data_r()
|
||||
{
|
||||
const u8 rtc_address = m_rtc_index | (m_rtc_reg & 0x80);
|
||||
return m_rtc->read_direct(rtc_address);
|
||||
}
|
||||
|
||||
void sis950_lpc_device::rtc_data_w(u8 data)
|
||||
{
|
||||
const u8 rtc_address = m_rtc_index | (m_rtc_reg & 0x80);
|
||||
m_rtc->write_direct(rtc_address, data);
|
||||
}
|
||||
|
||||
uint8_t sis950_lpc_device::at_page8_r(offs_t offset)
|
||||
{
|
||||
uint8_t data = m_at_pages[offset % 0x10];
|
||||
|
||||
switch(offset % 8)
|
||||
{
|
||||
case 1:
|
||||
data = m_dma_offset[BIT(offset, 3)][2];
|
||||
break;
|
||||
case 2:
|
||||
data = m_dma_offset[BIT(offset, 3)][3];
|
||||
break;
|
||||
case 3:
|
||||
data = m_dma_offset[BIT(offset, 3)][1];
|
||||
break;
|
||||
case 7:
|
||||
data = m_dma_offset[BIT(offset, 3)][0];
|
||||
break;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
void sis950_lpc_device::at_page8_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
m_at_pages[offset % 0x10] = data;
|
||||
|
||||
switch(offset % 8)
|
||||
{
|
||||
case 0:
|
||||
// matches boot_state_infos_phoenix
|
||||
//m_boot_state_hook((offs_t)0, data);
|
||||
break;
|
||||
case 1:
|
||||
m_dma_offset[BIT(offset, 3)][2] = data;
|
||||
break;
|
||||
case 2:
|
||||
m_dma_offset[BIT(offset, 3)][3] = data;
|
||||
break;
|
||||
case 3:
|
||||
m_dma_offset[BIT(offset, 3)][1] = data;
|
||||
break;
|
||||
case 7:
|
||||
m_dma_offset[BIT(offset, 3)][0] = data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER( sis950_lpc_device::pc_dma_hrq_changed )
|
||||
{
|
||||
m_host_cpu->set_input_line(INPUT_LINE_HALT, state ? ASSERT_LINE : CLEAR_LINE);
|
||||
|
||||
// Assert HLDA
|
||||
m_dmac_slave->hack_w( state );
|
||||
}
|
||||
|
||||
#if 0
|
||||
WRITE_LINE_MEMBER( sis950_lpc_device::iochck_w )
|
||||
{
|
||||
// if (!state && !m_channel_check && m_nmi_enabled)
|
||||
if (!state && !m_channel_check)
|
||||
m_host_cpu->set_input_line(INPUT_LINE_NMI, ASSERT_LINE);
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t sis950_lpc_device::pc_dma_read_byte(offs_t offset)
|
||||
{
|
||||
address_space& prog_space = m_host_cpu->space(AS_PROGRAM); // get the right address space
|
||||
if(m_dma_channel == -1)
|
||||
return 0xff;
|
||||
uint8_t result;
|
||||
offs_t page_offset = ((offs_t) m_dma_offset[0][m_dma_channel]) << 16;
|
||||
|
||||
result = prog_space.read_byte(page_offset + offset);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void sis950_lpc_device::pc_dma_write_byte(offs_t offset, uint8_t data)
|
||||
{
|
||||
address_space& prog_space = m_host_cpu->space(AS_PROGRAM); // get the right address space
|
||||
if(m_dma_channel == -1)
|
||||
return;
|
||||
offs_t page_offset = ((offs_t) m_dma_offset[0][m_dma_channel]) << 16;
|
||||
|
||||
prog_space.write_byte(page_offset + offset, data);
|
||||
}
|
||||
|
||||
|
||||
uint8_t sis950_lpc_device::pc_dma_read_word(offs_t offset)
|
||||
{
|
||||
address_space& prog_space = m_host_cpu->space(AS_PROGRAM); // get the right address space
|
||||
if(m_dma_channel == -1)
|
||||
return 0xff;
|
||||
uint16_t result;
|
||||
offs_t page_offset = ((offs_t) m_dma_offset[1][m_dma_channel & 3]) << 16;
|
||||
|
||||
result = prog_space.read_word((page_offset & 0xfe0000) | (offset << 1));
|
||||
m_dma_high_byte = result & 0xFF00;
|
||||
|
||||
return result & 0xFF;
|
||||
}
|
||||
|
||||
|
||||
void sis950_lpc_device::pc_dma_write_word(offs_t offset, uint8_t data)
|
||||
{
|
||||
address_space& prog_space = m_host_cpu->space(AS_PROGRAM); // get the right address space
|
||||
if(m_dma_channel == -1)
|
||||
return;
|
||||
offs_t page_offset = ((offs_t) m_dma_offset[1][m_dma_channel & 3]) << 16;
|
||||
|
||||
prog_space.write_word((page_offset & 0xfe0000) | (offset << 1), m_dma_high_byte | data);
|
||||
}
|
176
src/devices/machine/sis950_lpc.h
Normal file
176
src/devices/machine/sis950_lpc.h
Normal file
@ -0,0 +1,176 @@
|
||||
// license: BSD-3-Clause
|
||||
// copyright-holders: Angelo Salese
|
||||
|
||||
#ifndef MAME_MACHINE_SIS950_LPC_H
|
||||
#define MAME_MACHINE_SIS950_LPC_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pci.h"
|
||||
|
||||
#include "bus/ata/ataintf.h"
|
||||
#include "bus/isa/isa.h"
|
||||
#include "bus/pc_kbd/pc_kbdc.h"
|
||||
#include "bus/rs232/rs232.h"
|
||||
#include "lpc-acpi.h"
|
||||
#include "sis950_smbus.h"
|
||||
|
||||
#include "cpu/i386/i386.h"
|
||||
|
||||
#include "machine/am9517a.h"
|
||||
#include "machine/at.h"
|
||||
#include "machine/at_keybc.h"
|
||||
#include "machine/ds128x.h"
|
||||
#include "machine/ins8250.h"
|
||||
#include "machine/intelfsh.h"
|
||||
#include "machine/pc_lpt.h"
|
||||
#include "machine/pic8259.h"
|
||||
#include "machine/pit8253.h"
|
||||
#include "machine/ram.h"
|
||||
#include "machine/nvram.h"
|
||||
|
||||
#include "sound/spkrdev.h"
|
||||
|
||||
|
||||
class sis950_lpc_device : public pci_device
|
||||
{
|
||||
public:
|
||||
template <typename T, typename U> sis950_lpc_device(
|
||||
const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock,
|
||||
T &&cpu_tag, U &&flash_tag
|
||||
) : sis950_lpc_device(mconfig, tag, owner, clock)
|
||||
{
|
||||
// Revision 0 -> A0
|
||||
set_ids(0x10390008, 0x00, 0x060100, 0x00);
|
||||
//set_multifunction_device(true);
|
||||
m_host_cpu.set_tag(std::forward<T>(cpu_tag));
|
||||
m_flash_rom.set_tag(std::forward<U>(flash_tag));
|
||||
}
|
||||
|
||||
sis950_lpc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
static constexpr feature_type unemulated_features() { return feature::MOUSE; }
|
||||
|
||||
auto fast_reset_cb() { return m_fast_reset_cb.bind(); }
|
||||
|
||||
protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
|
||||
// virtual void reset_all_mappings() override;
|
||||
|
||||
virtual void map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
|
||||
uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) override;
|
||||
|
||||
virtual void config_map(address_map &map) override;
|
||||
|
||||
template <unsigned N> void memory_map(address_map &map);
|
||||
void io_map(address_map &map);
|
||||
|
||||
private:
|
||||
required_device<cpu_device> m_host_cpu;
|
||||
required_device<intelfsh8_device> m_flash_rom;
|
||||
required_device<pic8259_device> m_pic_master;
|
||||
required_device<pic8259_device> m_pic_slave;
|
||||
required_device<am9517a_device> m_dmac_master;
|
||||
required_device<am9517a_device> m_dmac_slave;
|
||||
required_device<pit8254_device> m_pit;
|
||||
required_device<ps2_keyboard_controller_device> m_keybc;
|
||||
required_device<speaker_sound_device> m_speaker;
|
||||
required_device<ds12885ext_device> m_rtc;
|
||||
required_device<pc_kbdc_device> m_ps2_con;
|
||||
required_device<pc_kbdc_device> m_aux_con;
|
||||
required_device<ins8250_device> m_uart;
|
||||
required_device<lpc_acpi_device> m_acpi;
|
||||
required_device<sis950_smbus_device> m_smbus;
|
||||
|
||||
devcb_write_line m_fast_reset_cb;
|
||||
|
||||
// PCI interface
|
||||
u8 bios_control_r();
|
||||
void bios_control_w(u8 data);
|
||||
u8 flash_ctrl_r();
|
||||
void flash_ctrl_w(u8 data);
|
||||
u8 acpi_base_r();
|
||||
void acpi_base_w(u8 data);
|
||||
u8 init_enable_r();
|
||||
void init_enable_w(u8 data);
|
||||
u8 keybc_reg_r();
|
||||
void keybc_reg_w(u8 data);
|
||||
u8 rtc_reg_r();
|
||||
void rtc_reg_w(u8 data);
|
||||
void rtc_index_w(u8 data);
|
||||
u8 rtc_data_r();
|
||||
void rtc_data_w(u8 data);
|
||||
template <unsigned N> u8 irq_remap_r();
|
||||
template <unsigned N> void irq_remap_w(u8 data);
|
||||
u8 unmap_log_r(offs_t offset);
|
||||
void unmap_log_w(offs_t offset, u8 data);
|
||||
|
||||
u8 m_bios_control = 0;
|
||||
u8 m_flash_control = 0;
|
||||
u16 m_acpi_base = 0x0000;
|
||||
u8 m_init_reg = 0;
|
||||
u8 m_keybc_reg = 0;
|
||||
u8 m_rtc_reg = 0;
|
||||
u8 m_rtc_index = 0;
|
||||
|
||||
enum {
|
||||
IRQ_INTA = 0,
|
||||
IRQ_INTB,
|
||||
IRQ_INTC,
|
||||
IRQ_INTD,
|
||||
IRQ_IDE,
|
||||
IRQ_GPE,
|
||||
// or SCI
|
||||
IRQ_ACPI,
|
||||
IRQ_SMBUS,
|
||||
IRQ_SWDOG
|
||||
};
|
||||
u8 m_irq_remap[9]{};
|
||||
|
||||
// LPC vendor specific, verify if it's common for all
|
||||
u8 lpc_fast_init_r();
|
||||
void lpc_fast_init_w(offs_t offset, u8 data);
|
||||
struct {
|
||||
u8 fast_init;
|
||||
} m_lpc_legacy;
|
||||
|
||||
// SB implementation, to be moved out
|
||||
DECLARE_WRITE_LINE_MEMBER(pit_out0);
|
||||
DECLARE_WRITE_LINE_MEMBER(pit_out1);
|
||||
DECLARE_WRITE_LINE_MEMBER(pit_out2);
|
||||
uint8_t pc_dma_read_byte(offs_t offset);
|
||||
void pc_dma_write_byte(offs_t offset, uint8_t data);
|
||||
uint8_t pc_dma_read_word(offs_t offset);
|
||||
void pc_dma_write_word(offs_t offset, uint8_t data);
|
||||
DECLARE_WRITE_LINE_MEMBER(pc_dma_hrq_changed);
|
||||
void pc_select_dma_channel(int channel, bool state);
|
||||
|
||||
uint8_t m_at_pages[0x10]{};
|
||||
uint8_t m_dma_offset[2][4]{};
|
||||
uint8_t m_at_speaker = 0;
|
||||
uint8_t m_refresh = 0;
|
||||
bool m_pit_out2 = 0;
|
||||
bool m_at_spkrdata = 0;
|
||||
uint8_t m_channel_check = 0;
|
||||
int m_dma_channel = -1;
|
||||
// bool m_cur_eop = false;
|
||||
uint16_t m_dma_high_byte = 0;
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(cpu_a20_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(cpu_reset_w);
|
||||
|
||||
uint8_t at_page8_r(offs_t offset);
|
||||
void at_page8_w(offs_t offset, uint8_t data);
|
||||
u8 nmi_status_r();
|
||||
void nmi_control_w(uint8_t data);
|
||||
|
||||
void at_speaker_set_spkrdata(uint8_t data);
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(SIS950_LPC, sis950_lpc_device)
|
||||
|
||||
|
||||
#endif
|
108
src/devices/machine/sis950_smbus.cpp
Normal file
108
src/devices/machine/sis950_smbus.cpp
Normal file
@ -0,0 +1,108 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Angelo Salese
|
||||
/**************************************************************************************************
|
||||
|
||||
SiS 950 SMBus implementation
|
||||
|
||||
TODO:
|
||||
- Stub, needs an smbus_interface, bare minimum to make shutms11 happy;
|
||||
|
||||
**************************************************************************************************/
|
||||
#include "emu.h"
|
||||
#include "sis950_smbus.h"
|
||||
|
||||
#define LOG_CMD (1U << 1) // log commands
|
||||
|
||||
#define VERBOSE (LOG_GENERAL | LOG_CMD)
|
||||
//#define LOG_OUTPUT_FUNC osd_printf_warning
|
||||
|
||||
#include "logmacro.h"
|
||||
|
||||
#define LOGCMD(...) LOGMASKED(LOG_CMD, __VA_ARGS__)
|
||||
|
||||
DEFINE_DEVICE_TYPE(SIS950_SMBUS, sis950_smbus_device, "sis950_smbus", "SiS950 SMBus interface")
|
||||
|
||||
void sis950_smbus_device::map(address_map &map)
|
||||
{
|
||||
map(0x00, 0x00).rw(FUNC(sis950_smbus_device::smb_sts_r), FUNC(sis950_smbus_device::smb_sts_w));
|
||||
|
||||
map(0x03, 0x03).rw(FUNC(sis950_smbus_device::smbhost_cnt_r), FUNC(sis950_smbus_device::smbhost_cnt_w));
|
||||
|
||||
#if 0
|
||||
map(0x02, 0x02).rw(FUNC(sis950_smbus_device::hst_cnt_r), FUNC(sis950_smbus_device::hst_cnt_w));
|
||||
map(0x03, 0x03).rw(FUNC(sis950_smbus_device::hst_cmd_r), FUNC(sis950_smbus_device::hst_cmd_w));
|
||||
map(0x04, 0x04).rw(FUNC(sis950_smbus_device::xmit_slva_r), FUNC(sis950_smbus_device::xmit_slva_w));
|
||||
map(0x05, 0x05).rw(FUNC(sis950_smbus_device::hst_d0_r), FUNC(sis950_smbus_device::hst_d0_w));
|
||||
map(0x06, 0x06).rw(FUNC(sis950_smbus_device::hst_d1_r), FUNC(sis950_smbus_device::hst_d1_w));
|
||||
map(0x07, 0x07).rw(FUNC(sis950_smbus_device::host_block_db_r), FUNC(sis950_smbus_device::host_block_db_w));
|
||||
map(0x08, 0x08).rw(FUNC(sis950_smbus_device::pec_r), FUNC(sis950_smbus_device::pec_w));
|
||||
map(0x09, 0x09).rw(FUNC(sis950_smbus_device::rcv_slva_r), FUNC(sis950_smbus_device::rcv_slva_w));
|
||||
map(0x0a, 0x0b).rw(FUNC(sis950_smbus_device::slv_data_r), FUNC(sis950_smbus_device::slv_data_w));
|
||||
map(0x0c, 0x0c).rw(FUNC(sis950_smbus_device::aux_sts_r), FUNC(sis950_smbus_device::aux_sts_w));
|
||||
map(0x0d, 0x0d).rw(FUNC(sis950_smbus_device::aux_ctl_r), FUNC(sis950_smbus_device::aux_ctl_w));
|
||||
map(0x0e, 0x0e).rw(FUNC(sis950_smbus_device::smlink_pin_ctl_r), FUNC(sis950_smbus_device::smlink_pin_ctl_w));
|
||||
map(0x0f, 0x0f).rw(FUNC(sis950_smbus_device::smbus_pin_ctl_r), FUNC(sis950_smbus_device::smbus_pin_ctl_w));
|
||||
map(0x10, 0x10).rw(FUNC(sis950_smbus_device::slv_sts_r), FUNC(sis950_smbus_device::slv_sts_w));
|
||||
map(0x11, 0x11).rw(FUNC(sis950_smbus_device::slv_cmd_r), FUNC(sis950_smbus_device::slv_cmd_w));
|
||||
map(0x14, 0x14).r(FUNC(sis950_smbus_device::notify_daddr_r));
|
||||
map(0x16, 0x16).r(FUNC(sis950_smbus_device::notify_dlow_r));
|
||||
map(0x17, 0x17).r(FUNC(sis950_smbus_device::notify_dhigh_r));
|
||||
#endif
|
||||
}
|
||||
|
||||
sis950_smbus_device::sis950_smbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, SIS950_SMBUS, tag, owner, clock)
|
||||
{
|
||||
}
|
||||
|
||||
void sis950_smbus_device::device_start()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void sis950_smbus_device::device_reset()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
u8 sis950_smbus_device::smb_sts_r()
|
||||
{
|
||||
LOGCMD("%s: smb_sts_r (%02x)\n", tag(), m_status);
|
||||
|
||||
return m_status;
|
||||
}
|
||||
|
||||
void sis950_smbus_device::smb_sts_w(u8 data)
|
||||
{
|
||||
m_status &= ~data;
|
||||
LOGCMD("%s: smb_sts_w = %02x\n", tag(), data);
|
||||
}
|
||||
|
||||
// reads back bits 0-2 only
|
||||
u8 sis950_smbus_device::smbhost_cnt_r()
|
||||
{
|
||||
return m_cmd;
|
||||
}
|
||||
|
||||
/*
|
||||
* --x- ---- kill (reset state, TODO)
|
||||
* ---x ---- start transaction
|
||||
* ---- -xxx command protocol
|
||||
* ---- -000 quick command
|
||||
* ---- -001 send/receive byte
|
||||
* ---- -010 read/write byte data
|
||||
* ---- -011 read/write word data
|
||||
* ---- -100 process call
|
||||
* ---- -101 read/write block data
|
||||
* ---- -11x <reserved>
|
||||
*/
|
||||
void sis950_smbus_device::smbhost_cnt_w(u8 data)
|
||||
{
|
||||
m_cmd = data & 7;
|
||||
LOGCMD("%s: smbhost_cnt_w = %02x\n", tag(), data);
|
||||
|
||||
// TODO: process commands properly
|
||||
// For now we just reflect shutms11 wanting bit 3 on after each transaction
|
||||
if (BIT(data, 4))
|
||||
m_status |= 8;
|
||||
}
|
32
src/devices/machine/sis950_smbus.h
Normal file
32
src/devices/machine/sis950_smbus.h
Normal file
@ -0,0 +1,32 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Angelo Salese
|
||||
|
||||
#ifndef MAME_MACHINE_SIS950_SMBUS_H
|
||||
#define MAME_MACHINE_SIS950_SMBUS_H
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
class sis950_smbus_device : public device_t {
|
||||
public:
|
||||
|
||||
sis950_smbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
void map(address_map &map);
|
||||
|
||||
protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
private:
|
||||
u8 smb_sts_r();
|
||||
void smb_sts_w(u8 data);
|
||||
u8 smbhost_cnt_r();
|
||||
void smbhost_cnt_w(u8 data);
|
||||
|
||||
u8 m_status = 0;
|
||||
u8 m_cmd = 0;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(SIS950_SMBUS, sis950_smbus_device)
|
||||
|
||||
#endif // MAME_MACHINE_PCI_SMBUS_H
|
@ -1698,6 +1698,12 @@ uint8_t vga_device::gc_reg_read(uint8_t index)
|
||||
return res;
|
||||
}
|
||||
|
||||
uint8_t vga_device::seq_reg_read(uint8_t index)
|
||||
{
|
||||
logerror("Reading unmapped sequencer read register %02x (SVGA?)\n", index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t vga_device::port_03c0_r(offs_t offset)
|
||||
{
|
||||
uint8_t data = 0xff;
|
||||
@ -1758,6 +1764,8 @@ uint8_t vga_device::port_03c0_r(offs_t offset)
|
||||
case 5:
|
||||
if (vga.sequencer.index < vga.svga_intf.seq_regcount)
|
||||
data = vga.sequencer.data[vga.sequencer.index];
|
||||
else
|
||||
data = seq_reg_read(vga.sequencer.index);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
|
@ -73,10 +73,11 @@ protected:
|
||||
void vga_vh_mono(bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
virtual uint8_t pc_vga_choosevideomode();
|
||||
void recompute_params_clock(int divisor, int xtal);
|
||||
uint8_t crtc_reg_read(uint8_t index);
|
||||
virtual uint8_t crtc_reg_read(uint8_t index);
|
||||
virtual void recompute_params();
|
||||
void crtc_reg_write(uint8_t index, uint8_t data);
|
||||
void seq_reg_write(uint8_t index, uint8_t data);
|
||||
virtual void crtc_reg_write(uint8_t index, uint8_t data);
|
||||
virtual uint8_t seq_reg_read(uint8_t index);
|
||||
virtual void seq_reg_write(uint8_t index, uint8_t data);
|
||||
uint8_t vga_vblank();
|
||||
uint8_t vga_crtc_r(offs_t offset);
|
||||
void vga_crtc_w(offs_t offset, uint8_t data);
|
||||
|
@ -473,7 +473,6 @@ galpanic.cpp
|
||||
galpanic_ms.cpp
|
||||
galspnbl.cpp
|
||||
gambl186.cpp
|
||||
gamecstl.cpp
|
||||
gamemasters.cpp
|
||||
gameplan.cpp
|
||||
gammagic.cpp
|
||||
@ -1193,6 +1192,7 @@ silvmil.cpp
|
||||
simpl156.cpp
|
||||
simple_st0016.cpp
|
||||
simpsons.cpp
|
||||
sis630.cpp
|
||||
skeetsht.cpp
|
||||
skimaxx.cpp
|
||||
skopro.cpp
|
||||
|
@ -1,506 +0,0 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:R. Belmont
|
||||
// thanks-to: Diego Nappino
|
||||
/*
|
||||
Cristaltec "Game Cristal" (MAME bootleg)
|
||||
|
||||
Skeleton driver by R. Belmont, based on taitowlf.cpp by Ville Linde
|
||||
|
||||
Notes:
|
||||
- Specs: P3-866, SiS 630 motherboard + integrated graphics card,
|
||||
SiS 7018 sound, Windows 98SE, DirectX 8.1.
|
||||
- Windows image can be booted with m55hipl driver.
|
||||
It will try to install an "unnamed card" (svga_et4k?) then uses its own shell
|
||||
"ialoader.exe" to boot the frontend, located in C:\WINDOWS.
|
||||
It will eventually hang after throwing a "DirectX missing" error, trying to install
|
||||
the ET4K drivers won't work (will BSoD at start of boot sequence).
|
||||
- In order to bypass the shell launcher, you should:
|
||||
1. edit C:\WINDOWS\system.ini and change shell property to explorer.exe
|
||||
2. remove the autoexec.bat contents, it will otherwise copy a bunch of .ini
|
||||
files from C:\dat to C:\WINDOWS, and replacing the system.ini shell launcher.
|
||||
- (gamecstl) Device Manager installed devices:
|
||||
- two Samsung SyncMaster 900SL monitors (?);
|
||||
- SiS 630 display adapter;
|
||||
- Samsung CD-ROM SC-152L;
|
||||
- SiS 5513 Dual PCI IDE Controller;
|
||||
- COM1, COM2, LPT1 enabled;
|
||||
- a QDI USBDisk USB Mass Storage SCSI driver;
|
||||
- a SiS 7001 PCI to USB Open Host Controller + USB root hub x 2;
|
||||
- C:\drvs contains a collection of drivers, mostly the ones described above.
|
||||
- Other parts of Windows are otherwise more or less stock, except for a footprint
|
||||
inside C:\WINDOWS\temp:
|
||||
1. has a Portuguese version of the Intel Processor Identification Utility,
|
||||
most likely used for binding the emulator to the CPU serial via CPUID;
|
||||
2. has u3spwd.exe (USB Flash Disk), likely used to copy the necessary files for
|
||||
making the frontend to work;
|
||||
- Input is via a custom COM1 port JAMMA adaptor.
|
||||
- The custom emulator is a heavily modified version of MAME32. If you extract the
|
||||
disk image, it's in C:\GH4\GH4.EXE. It's UPX compressed, so unpack it before doing
|
||||
any forensics. The emulator does run on Windows as new as XP Pro SP2 but you can't
|
||||
control it due to the lack of the custom input.
|
||||
- C:\GH4\mvs contains movie clips of the emulated games.
|
||||
These are MS-CRAM encoded, 288x208 at 20 fps, stereo MS ADPCM with 11025 Hz sample rate,
|
||||
36 seconds length.
|
||||
Mentioning this because SiS 630 has several HW registers dedicated to video playback,
|
||||
which will be most likely used once we get there.
|
||||
|
||||
Updates 27/11/2007 (Diego Nappino):
|
||||
The COM1 port is opened at 19200 bps, No parity, 8 bit data, 1 stop bit.
|
||||
The protocol is based on a 6 bytes frame with a leading byte valued 0x05 and a trailing one at 0x02
|
||||
The four middle bytes are used, in negative logic (0xFF = No button pressed), to implement the inputs.
|
||||
Each bit meaning as follows:
|
||||
|
||||
Byte 1 Byte 2 Byte 3 Byte 4
|
||||
Bit 0 P1-Credit P1-Button C P2-Left UNUSED
|
||||
Bit 1 P1-Start P1-Button D P2-Right UNUSED
|
||||
Bit 2 P1-Down P1-Button E P2-Button A SERVICE
|
||||
Bit 3 P1-Up TEST P2-Button B UNUSED
|
||||
Bit 4 P1-Left P2-Credit P2-Button C UNUSED
|
||||
Bit 5 P1-Right P2-Start P2-Button D UNUSED
|
||||
Bit 6 P1-Button A P2-Down P2-Button E UNUSED
|
||||
Bit 7 P1-Button B P2-Up VIDEO-MODE UNUSED
|
||||
|
||||
The JAMMA adaptor sends a byte frame each time an input changes.
|
||||
So for example, if the P1-Button A and P1-Button B are both pressed, it will send:
|
||||
|
||||
0x05 0xFC 0xFF 0xFF 0xFF 0x02
|
||||
|
||||
And when the buttons are both released
|
||||
|
||||
0x05 0xFF 0xFF 0xFF 0xFF 0x02
|
||||
|
||||
CPUID info:
|
||||
|
||||
Original set:
|
||||
CPUID Level: EAX: EBX: ECX: EDX:
|
||||
00000000 00000003 756E6547 6C65746E 49656E69
|
||||
00000001 0000068A 00000002 00000000 0387F9FF
|
||||
00000002 03020101 00000000 00000000 0C040882
|
||||
00000003 00000000 00000000 CA976D2E 000082F6
|
||||
80000000 00000000 00000000 CA976D2E 000082F6
|
||||
C0000000 00000000 00000000 CA976D2E 000082F6
|
||||
|
||||
Version 2:
|
||||
CPUID Level: EAX: EBX: ECX: EDX:
|
||||
00000000 00000003 756E6547 6C65746E 49656E69
|
||||
00000001 0000068A 00000002 00000000 0387F9FF
|
||||
00000002 03020101 00000000 00000000 0C040882
|
||||
00000003 00000000 00000000 B8BA1941 00038881
|
||||
80000000 00000000 00000000 B8BA1941 00038881
|
||||
C0000000 00000000 00000000 B8BA1941 00038881
|
||||
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
#include "cpu/i386/i386.h"
|
||||
#include "machine/idectrl.h"
|
||||
#include "machine/lpci.h"
|
||||
#include "machine/pckeybrd.h"
|
||||
#include "machine/pcshare.h"
|
||||
#include "emupal.h"
|
||||
#include "screen.h"
|
||||
|
||||
|
||||
class gamecstl_state : public pcat_base_state
|
||||
{
|
||||
public:
|
||||
gamecstl_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: pcat_base_state(mconfig, type, tag)
|
||||
, m_cga_ram(*this, "cga_ram")
|
||||
, m_gfxdecode(*this, "gfxdecode")
|
||||
, m_palette(*this, "palette")
|
||||
{ }
|
||||
|
||||
void gamecstl(machine_config &config);
|
||||
|
||||
void init_gamecstl();
|
||||
|
||||
private:
|
||||
required_shared_ptr<uint32_t> m_cga_ram;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<palette_device> m_palette;
|
||||
std::unique_ptr<uint32_t[]> m_bios_ram;
|
||||
uint8_t m_mtxc_config_reg[256];
|
||||
uint8_t m_piix4_config_reg[4][256];
|
||||
|
||||
void pnp_config_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
|
||||
void pnp_data_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
|
||||
void bios_ram_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
virtual void video_start() override;
|
||||
uint32_t screen_update_gamecstl(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
void draw_char(bitmap_ind16 &bitmap, const rectangle &cliprect, gfx_element *gfx, int ch, int att, int x, int y);
|
||||
void intel82439tx_init();
|
||||
void gamecstl_io(address_map &map);
|
||||
void gamecstl_map(address_map &map);
|
||||
|
||||
uint8_t mtxc_config_r(int function, int reg);
|
||||
void mtxc_config_w(int function, int reg, uint8_t data);
|
||||
uint32_t intel82439tx_pci_r(int function, int reg, uint32_t mem_mask);
|
||||
void intel82439tx_pci_w(int function, int reg, uint32_t data, uint32_t mem_mask);
|
||||
uint8_t piix4_config_r(int function, int reg);
|
||||
void piix4_config_w(int function, int reg, uint8_t data);
|
||||
uint32_t intel82371ab_pci_r(int function, int reg, uint32_t mem_mask);
|
||||
void intel82371ab_pci_w(int function, int reg, uint32_t data, uint32_t mem_mask);
|
||||
uint32_t pci_3dfx_r(int function, int reg, uint32_t mem_mask);
|
||||
void pci_3dfx_w(int function, int reg, uint32_t data, uint32_t mem_mask);
|
||||
};
|
||||
|
||||
|
||||
static const rgb_t cga_palette[16] =
|
||||
{
|
||||
rgb_t( 0x00, 0x00, 0x00 ), rgb_t( 0x00, 0x00, 0xaa ), rgb_t( 0x00, 0xaa, 0x00 ), rgb_t( 0x00, 0xaa, 0xaa ),
|
||||
rgb_t( 0xaa, 0x00, 0x00 ), rgb_t( 0xaa, 0x00, 0xaa ), rgb_t( 0xaa, 0x55, 0x00 ), rgb_t( 0xaa, 0xaa, 0xaa ),
|
||||
rgb_t( 0x55, 0x55, 0x55 ), rgb_t( 0x55, 0x55, 0xff ), rgb_t( 0x55, 0xff, 0x55 ), rgb_t( 0x55, 0xff, 0xff ),
|
||||
rgb_t( 0xff, 0x55, 0x55 ), rgb_t( 0xff, 0x55, 0xff ), rgb_t( 0xff, 0xff, 0x55 ), rgb_t( 0xff, 0xff, 0xff ),
|
||||
};
|
||||
|
||||
void gamecstl_state::video_start()
|
||||
{
|
||||
int i;
|
||||
for (i=0; i < 16; i++)
|
||||
m_palette->set_pen_color(i, cga_palette[i]);
|
||||
}
|
||||
|
||||
void gamecstl_state::draw_char(bitmap_ind16 &bitmap, const rectangle &cliprect, gfx_element *gfx, int ch, int att, int x, int y)
|
||||
{
|
||||
int index = 0;
|
||||
uint8_t const *const dp = gfx->get_data(ch);
|
||||
|
||||
for (int j=y; j < y+8; j++)
|
||||
{
|
||||
uint16_t *const p = &bitmap.pix(j);
|
||||
|
||||
for (int i=x; i < x+8; i++)
|
||||
{
|
||||
uint8_t pen = dp[index++];
|
||||
if (pen)
|
||||
p[i] = gfx->colorbase() + (att & 0xf);
|
||||
else
|
||||
p[i] = gfx->colorbase() + ((att >> 4) & 0x7);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t gamecstl_state::screen_update_gamecstl(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
gfx_element *gfx = m_gfxdecode->gfx(0);
|
||||
uint32_t const *const cga = m_cga_ram;
|
||||
int index = 0;
|
||||
|
||||
bitmap.fill(0, cliprect);
|
||||
|
||||
for (int j=0; j < 25; j++)
|
||||
{
|
||||
for (int i=0; i < 80; i+=2)
|
||||
{
|
||||
int att0 = (cga[index] >> 8) & 0xff;
|
||||
int ch0 = (cga[index] >> 0) & 0xff;
|
||||
int att1 = (cga[index] >> 24) & 0xff;
|
||||
int ch1 = (cga[index] >> 16) & 0xff;
|
||||
|
||||
draw_char(bitmap, cliprect, gfx, ch0, att0, i*8, j*8);
|
||||
draw_char(bitmap, cliprect, gfx, ch1, att1, (i*8)+8, j*8);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Intel 82439TX System Controller (MTXC)
|
||||
|
||||
uint8_t gamecstl_state::mtxc_config_r(int function, int reg)
|
||||
{
|
||||
logerror("MTXC: read %d, %02X\n", function, reg);
|
||||
return m_mtxc_config_reg[reg];
|
||||
}
|
||||
|
||||
void gamecstl_state::mtxc_config_w(int function, int reg, uint8_t data)
|
||||
{
|
||||
logerror("%s:MTXC: write %d, %02X, %02X\n", machine().describe_context(), function, reg, data);
|
||||
|
||||
switch(reg)
|
||||
{
|
||||
case 0x59: // PAM0
|
||||
{
|
||||
if (data & 0x10) // enable RAM access to region 0xf0000 - 0xfffff
|
||||
{
|
||||
membank("bank1")->set_base(m_bios_ram.get());
|
||||
}
|
||||
else // disable RAM access (reads go to BIOS ROM)
|
||||
{
|
||||
membank("bank1")->set_base(memregion("bios")->base() + 0x30000);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_mtxc_config_reg[reg] = data;
|
||||
}
|
||||
|
||||
void gamecstl_state::intel82439tx_init()
|
||||
{
|
||||
m_mtxc_config_reg[0x60] = 0x02;
|
||||
m_mtxc_config_reg[0x61] = 0x02;
|
||||
m_mtxc_config_reg[0x62] = 0x02;
|
||||
m_mtxc_config_reg[0x63] = 0x02;
|
||||
m_mtxc_config_reg[0x64] = 0x02;
|
||||
m_mtxc_config_reg[0x65] = 0x02;
|
||||
}
|
||||
|
||||
uint32_t gamecstl_state::intel82439tx_pci_r(int function, int reg, uint32_t mem_mask)
|
||||
{
|
||||
uint32_t r = 0;
|
||||
if (ACCESSING_BITS_24_31)
|
||||
{
|
||||
r |= mtxc_config_r(function, reg + 3) << 24;
|
||||
}
|
||||
if (ACCESSING_BITS_16_23)
|
||||
{
|
||||
r |= mtxc_config_r(function, reg + 2) << 16;
|
||||
}
|
||||
if (ACCESSING_BITS_8_15)
|
||||
{
|
||||
r |= mtxc_config_r(function, reg + 1) << 8;
|
||||
}
|
||||
if (ACCESSING_BITS_0_7)
|
||||
{
|
||||
r |= mtxc_config_r(function, reg + 0) << 0;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void gamecstl_state::intel82439tx_pci_w(int function, int reg, uint32_t data, uint32_t mem_mask)
|
||||
{
|
||||
if (ACCESSING_BITS_24_31)
|
||||
{
|
||||
mtxc_config_w(function, reg + 3, (data >> 24) & 0xff);
|
||||
}
|
||||
if (ACCESSING_BITS_16_23)
|
||||
{
|
||||
mtxc_config_w(function, reg + 2, (data >> 16) & 0xff);
|
||||
}
|
||||
if (ACCESSING_BITS_8_15)
|
||||
{
|
||||
mtxc_config_w(function, reg + 1, (data >> 8) & 0xff);
|
||||
}
|
||||
if (ACCESSING_BITS_0_7)
|
||||
{
|
||||
mtxc_config_w(function, reg + 0, (data >> 0) & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
// Intel 82371AB PCI-to-ISA / IDE bridge (PIIX4)
|
||||
|
||||
uint8_t gamecstl_state::piix4_config_r(int function, int reg)
|
||||
{
|
||||
logerror("PIIX4: read %d, %02X\n", function, reg);
|
||||
return m_piix4_config_reg[function][reg];
|
||||
}
|
||||
|
||||
void gamecstl_state::piix4_config_w(int function, int reg, uint8_t data)
|
||||
{
|
||||
logerror("%s:PIIX4: write %d, %02X, %02X\n", machine().describe_context(), function, reg, data);
|
||||
m_piix4_config_reg[function][reg] = data;
|
||||
}
|
||||
|
||||
uint32_t gamecstl_state::intel82371ab_pci_r(int function, int reg, uint32_t mem_mask)
|
||||
{
|
||||
uint32_t r = 0;
|
||||
if (ACCESSING_BITS_24_31)
|
||||
{
|
||||
r |= piix4_config_r(function, reg + 3) << 24;
|
||||
}
|
||||
if (ACCESSING_BITS_16_23)
|
||||
{
|
||||
r |= piix4_config_r(function, reg + 2) << 16;
|
||||
}
|
||||
if (ACCESSING_BITS_8_15)
|
||||
{
|
||||
r |= piix4_config_r(function, reg + 1) << 8;
|
||||
}
|
||||
if (ACCESSING_BITS_0_7)
|
||||
{
|
||||
r |= piix4_config_r(function, reg + 0) << 0;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void gamecstl_state::intel82371ab_pci_w(int function, int reg, uint32_t data, uint32_t mem_mask)
|
||||
{
|
||||
if (ACCESSING_BITS_24_31)
|
||||
{
|
||||
piix4_config_w(function, reg + 3, (data >> 24) & 0xff);
|
||||
}
|
||||
if (ACCESSING_BITS_16_23)
|
||||
{
|
||||
piix4_config_w(function, reg + 2, (data >> 16) & 0xff);
|
||||
}
|
||||
if (ACCESSING_BITS_8_15)
|
||||
{
|
||||
piix4_config_w(function, reg + 1, (data >> 8) & 0xff);
|
||||
}
|
||||
if (ACCESSING_BITS_0_7)
|
||||
{
|
||||
piix4_config_w(function, reg + 0, (data >> 0) & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
// ISA Plug-n-Play
|
||||
void gamecstl_state::pnp_config_w(offs_t offset, uint32_t data, uint32_t mem_mask)
|
||||
{
|
||||
if (ACCESSING_BITS_8_15)
|
||||
{
|
||||
// osd_printf_debug("PNP Config: %02X\n", (data >> 8) & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
void gamecstl_state::pnp_data_w(offs_t offset, uint32_t data, uint32_t mem_mask)
|
||||
{
|
||||
if (ACCESSING_BITS_8_15)
|
||||
{
|
||||
// osd_printf_debug("PNP Data: %02X\n", (data >> 8) & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void gamecstl_state::bios_ram_w(offs_t offset, uint32_t data, uint32_t mem_mask)
|
||||
{
|
||||
if (m_mtxc_config_reg[0x59] & 0x20) // write to RAM if this region is write-enabled
|
||||
{
|
||||
COMBINE_DATA(m_bios_ram.get() + offset);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void gamecstl_state::gamecstl_map(address_map &map)
|
||||
{
|
||||
map(0x00000000, 0x0009ffff).ram();
|
||||
map(0x000a0000, 0x000affff).ram();
|
||||
map(0x000b0000, 0x000b7fff).ram().share("cga_ram");
|
||||
map(0x000e0000, 0x000effff).ram();
|
||||
map(0x000f0000, 0x000fffff).bankr("bank1");
|
||||
map(0x000f0000, 0x000fffff).w(FUNC(gamecstl_state::bios_ram_w));
|
||||
map(0x00100000, 0x01ffffff).ram();
|
||||
map(0xfffc0000, 0xffffffff).rom().region("bios", 0); /* System BIOS */
|
||||
}
|
||||
|
||||
void gamecstl_state::gamecstl_io(address_map &map)
|
||||
{
|
||||
pcat32_io_common(map);
|
||||
map(0x00e8, 0x00eb).noprw();
|
||||
map(0x00ec, 0x00ef).noprw();
|
||||
map(0x01f0, 0x01f7).rw("ide", FUNC(ide_controller_device::cs0_r), FUNC(ide_controller_device::cs0_w));
|
||||
map(0x0300, 0x03af).noprw();
|
||||
map(0x03b0, 0x03df).noprw();
|
||||
map(0x0278, 0x027b).w(FUNC(gamecstl_state::pnp_config_w));
|
||||
map(0x03f0, 0x03f7).rw("ide", FUNC(ide_controller_device::cs1_r), FUNC(ide_controller_device::cs1_w));
|
||||
map(0x0a78, 0x0a7b).w(FUNC(gamecstl_state::pnp_data_w));
|
||||
map(0x0cf8, 0x0cff).rw("pcibus", FUNC(pci_bus_legacy_device::read), FUNC(pci_bus_legacy_device::write));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static const gfx_layout CGA_charlayout =
|
||||
{
|
||||
8,8, /* 8 x 16 characters */
|
||||
256, /* 256 characters */
|
||||
1, /* 1 bits per pixel */
|
||||
{ 0 }, /* no bitplanes; 1 bit per pixel */
|
||||
/* x offsets */
|
||||
{ 0,1,2,3,4,5,6,7 },
|
||||
/* y offsets */
|
||||
{ 0*8,1*8,2*8,3*8,
|
||||
4*8,5*8,6*8,7*8 },
|
||||
8*8 /* every char takes 8 bytes */
|
||||
};
|
||||
|
||||
static GFXDECODE_START( gfx_cga )
|
||||
/* Support up to four CGA fonts */
|
||||
GFXDECODE_ENTRY( "gfx1", 0x0000, CGA_charlayout, 0, 256 ) /* Font 0 */
|
||||
GFXDECODE_ENTRY( "gfx1", 0x0800, CGA_charlayout, 0, 256 ) /* Font 1 */
|
||||
GFXDECODE_ENTRY( "gfx1", 0x1000, CGA_charlayout, 0, 256 ) /* Font 2 */
|
||||
GFXDECODE_ENTRY( "gfx1", 0x1800, CGA_charlayout, 0, 256 ) /* Font 3*/
|
||||
GFXDECODE_END
|
||||
|
||||
static INPUT_PORTS_START(gamecstl)
|
||||
INPUT_PORTS_END
|
||||
|
||||
void gamecstl_state::machine_start()
|
||||
{
|
||||
}
|
||||
|
||||
void gamecstl_state::machine_reset()
|
||||
{
|
||||
membank("bank1")->set_base(memregion("bios")->base() + 0x30000);
|
||||
}
|
||||
|
||||
void gamecstl_state::gamecstl(machine_config &config)
|
||||
{
|
||||
PENTIUM3(config, m_maincpu, 200000000);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &gamecstl_state::gamecstl_map);
|
||||
m_maincpu->set_addrmap(AS_IO, &gamecstl_state::gamecstl_io);
|
||||
m_maincpu->set_irq_acknowledge_callback("pic8259_1", FUNC(pic8259_device::inta_cb));
|
||||
|
||||
pcat_common(config);
|
||||
|
||||
// TODO: wrong, needs SiS 630 instead
|
||||
pci_bus_legacy_device &pcibus(PCI_BUS_LEGACY(config, "pcibus", 0, 0));
|
||||
pcibus.set_device(0, FUNC(gamecstl_state::intel82439tx_pci_r), FUNC(gamecstl_state::intel82439tx_pci_w));
|
||||
pcibus.set_device(7, FUNC(gamecstl_state::intel82371ab_pci_r), FUNC(gamecstl_state::intel82371ab_pci_w));
|
||||
|
||||
ide_controller_device &ide(IDE_CONTROLLER(config, "ide").options(ata_devices, "hdd", nullptr, true));
|
||||
ide.irq_handler().set("pic8259_2", FUNC(pic8259_device::ir6_w));
|
||||
|
||||
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
|
||||
screen.set_refresh_hz(60);
|
||||
screen.set_vblank_time(ATTOSECONDS_IN_USEC(0));
|
||||
screen.set_size(640, 480);
|
||||
screen.set_visarea(0, 639, 0, 199);
|
||||
screen.set_screen_update(FUNC(gamecstl_state::screen_update_gamecstl));
|
||||
screen.set_palette(m_palette);
|
||||
|
||||
GFXDECODE(config, m_gfxdecode, m_palette, gfx_cga);
|
||||
PALETTE(config, m_palette).set_entries(16);
|
||||
}
|
||||
|
||||
void gamecstl_state::init_gamecstl()
|
||||
{
|
||||
m_bios_ram = std::make_unique<uint32_t[]>(0x10000/4);
|
||||
|
||||
intel82439tx_init();
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
// not the correct BIOS, f205v owes me a dump of it...
|
||||
ROM_START(gamecstl)
|
||||
ROM_REGION32_LE(0x40000, "bios", 0)
|
||||
ROM_LOAD( "bios.bin", 0x000000, 0x040000, BAD_DUMP CRC(27834ce9) SHA1(134c546dd75138c6f4bc5729b40e20e118454df9) )
|
||||
|
||||
ROM_REGION(0x08100, "gfx1", 0)
|
||||
ROM_LOAD( "cga.chr", 0x00000, 0x01000, BAD_DUMP CRC(42009069) SHA1(ed08559ce2d7f97f68b9f540bddad5b6295294dd))
|
||||
|
||||
DISK_REGION( "ide:0:hdd:image" )
|
||||
// Note: has filled NVRAM directory
|
||||
DISK_IMAGE( "gamecstl", 0, SHA1(b431af3c42c48ba07972d77a3d24e60ee1e4359e) )
|
||||
ROM_END
|
||||
|
||||
ROM_START(gamecst2)
|
||||
ROM_REGION32_LE(0x40000, "bios", 0)
|
||||
ROM_LOAD( "bios.bin", 0x000000, 0x040000, BAD_DUMP CRC(27834ce9) SHA1(134c546dd75138c6f4bc5729b40e20e118454df9) )
|
||||
|
||||
ROM_REGION(0x08100, "gfx1", 0)
|
||||
ROM_LOAD( "cga.chr", 0x00000, 0x01000, BAD_DUMP CRC(42009069) SHA1(ed08559ce2d7f97f68b9f540bddad5b6295294dd))
|
||||
|
||||
DISK_REGION( "ide:0:hdd:image" )
|
||||
DISK_IMAGE( "gamecst2", 0, SHA1(14e1b311cb474801c7bdda3164a0c220fb102159) )
|
||||
ROM_END
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
GAME(2002, gamecstl, 0, gamecstl, gamecstl, gamecstl_state, init_gamecstl, ROT0, "Cristaltec", "GameCristal", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
|
||||
GAME(2002, gamecst2, gamecstl, gamecstl, gamecstl, gamecstl_state, init_gamecstl, ROT0, "Cristaltec", "GameCristal (version 2.613)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
|
305
src/mame/drivers/sis630.cpp
Normal file
305
src/mame/drivers/sis630.cpp
Normal file
@ -0,0 +1,305 @@
|
||||
// license: BSD-3-Clause
|
||||
// copyright-holders: Angelo Salese, R. Belmont
|
||||
// thanks-to: Diego Nappino
|
||||
/**************************************************************************************************
|
||||
|
||||
SiS 630 chipset based PC
|
||||
|
||||
TODO (main):
|
||||
- PS/2 loses IRQs, mouse is unusable, "ibm" BIOS doesn't work at all;
|
||||
- '900 Ethernet (missing ROM dump);
|
||||
- USB controllers (OpenHCI complaint);
|
||||
- Floppy drive, unsupported SMC37C673 default;
|
||||
- ACPI is not fully lpc-acpi complaint;
|
||||
- EISA slots;
|
||||
- PnP from LPC;
|
||||
- SMBus;
|
||||
- Super I/O handling in LPC (HW motherboard monitor, cfr. I/O $294 reads in shutms11 fan tests);
|
||||
|
||||
TODO (usability, to be moved in a SW list):
|
||||
- windows xp sp3: tests HW then does an ACPI devtrap write ($48), will eventually BSoD with
|
||||
ACPI STOP #a5 error with param $11
|
||||
\- To bypass hold F7 while the "to install SCSI drivers [...] press F6" appears.
|
||||
And by F7 I really mean it :shrug:
|
||||
|
||||
- windows xp sp3: BSoD during install with a STOP #0a IRQL_NOT_LESS_OR_EQUAL;
|
||||
|
||||
- windows neptune: BSoD during ethernet check (after time clock setup)
|
||||
with a STOP #a0 INTERNAL_POWER_ERROR with param1 0x5 ("reserved"!?)
|
||||
|
||||
- gamecstl Kontron BIOS:
|
||||
\- hangs at PC=0xf3cf2, again wanting a SMI# from devtrap_en_w;
|
||||
\- No PS/2 inputs;
|
||||
|
||||
- gamecstl dump (tested from shutms11, also see notes below):
|
||||
\- Currently black screens before booting normal Windows, reading $5004 from the LPC ACPI
|
||||
(flip EAX to non-zero to bypass).
|
||||
NB: it also writes to $5048 once (devtrap_en_w), which should generate a SMI# event;
|
||||
\- Doesn't accept any PS/2 input, tries to install a "PCI standard CPU Host Bridge" (?),
|
||||
hangs there;
|
||||
\- GUI is never recognized no matter what, punts with DirectX not installed;
|
||||
|
||||
- xubuntu 6.10: throws several SCSIDEV unhandled $46 & $51 commands
|
||||
(get configuration/read disc information),
|
||||
eventually punts to prompt with a "can't access tty: job control turned off" (on live CD) or
|
||||
hangs at "Configuring network interfaces" (on actual install);
|
||||
|
||||
- xubuntu 10.10: stalls after '900 ethernet check;
|
||||
|
||||
- Haiku 0.1: hangs throwing an "unhandled READ TOC format 2",
|
||||
serial COM1 prints a "vm_mark_page_range_inuse: page 0x9f in non-free state 7!"
|
||||
|
||||
- Red Hat 6.2: Triple Faults on x87 exception check
|
||||
\- prints the type of mounted floating point exception if bypassed.
|
||||
|
||||
===================================================================================================
|
||||
|
||||
Cristaltec "Game Cristal" (MAME bootleg)
|
||||
|
||||
Skeleton driver by R. Belmont, based on taitowlf.cpp by Ville Linde
|
||||
|
||||
Notes:
|
||||
- Specs: P3-866, SiS 630 motherboard + integrated graphics card,
|
||||
SiS 7018 sound, DirectX 8.1.
|
||||
- Image is just a more or less stock Windows 98SE with a customized shell
|
||||
"Ialoader.exe" (sic) to boot the frontend, located in C:\WINDOWS
|
||||
It will eventually hang after throwing a "DirectX missing" error.
|
||||
- In order to bypass the shell launcher, you should:
|
||||
1. edit C:\WINDOWS\system.ini and change shell property to explorer.exe
|
||||
2. remove the autoexec.bat contents, it will otherwise copy a bunch of .ini
|
||||
files from C:\dat to C:\WINDOWS, and replacing the system.ini shell launcher.
|
||||
Alternatively you can also execute "open.exe" from MS-DOS, that removes above customization
|
||||
too.
|
||||
- (gamecstl) Device Manager installed devices:
|
||||
- two Samsung SyncMaster 900SL monitors ('630 + '301?);
|
||||
- SiS 630 display adapter;
|
||||
- Samsung CD-ROM SC-152L;
|
||||
- SiS 5513 Dual PCI IDE Controller;
|
||||
- COM1, COM2, LPT1 enabled;
|
||||
- a QDI USBDisk USB Mass Storage SCSI driver;
|
||||
- a SiS 7001 PCI to USB Open Host Controller + USB root hub x 2;
|
||||
- C:\drvs contains a collection of drivers, mostly the ones described above.
|
||||
- C:\WINDOWS\temp has a couple footprints:
|
||||
1. has a Portuguese version of the Intel Processor Identification Utility,
|
||||
most likely used for binding the emulator to the CPU serial via CPUID;
|
||||
2. has u3spwd.exe (USB Flash Disk), likely used to copy the necessary files for
|
||||
making the frontend to work;
|
||||
- Input is via a custom COM1 port JAMMA adaptor.
|
||||
- The custom emulator is a heavily modified version of MAME32. If you extract the
|
||||
disk image, it's in C:\GH4\GH4.EXE. It's UPX compressed, so unpack it before doing
|
||||
any forensics. The emulator does run on Windows as new as XP Pro SP2 but you can't
|
||||
control it due to the lack of the custom input.
|
||||
- C:\GH4\mvs contains movie clips of the emulated games.
|
||||
These are MS-CRAM encoded, 288x208 at 20 fps, stereo MS ADPCM with 11025 Hz sample rate,
|
||||
36 seconds length.
|
||||
Mentioning this because SiS 630 has several HW registers dedicated to video playback,
|
||||
which will be most likely used once we get there.
|
||||
- C:\GH4\rdir contains filled NVRAM directory of the supported games.
|
||||
These are probably copied from a factory default (like skipping NVRAM errors in spang & mk),
|
||||
needs to be extensively checked if they can be flushed and given a working state with no
|
||||
arbitrary user data (i.e. the mk games sports about 3 hours of playtime each)
|
||||
|
||||
Updates 27/11/2007 (Diego Nappino):
|
||||
The COM1 port is opened at 19200 bps, No parity, 8 bit data, 1 stop bit.
|
||||
The protocol is based on a 6 bytes frame with a leading byte valued 0x05 and a trailing one at 0x02
|
||||
The four middle bytes are used, in negative logic (0xFF = No button pressed), to implement the inputs.
|
||||
Each bit meaning as follows:
|
||||
|
||||
Byte 1 Byte 2 Byte 3 Byte 4
|
||||
Bit 0 P1-Credit P1-Button C P2-Left UNUSED
|
||||
Bit 1 P1-Start P1-Button D P2-Right UNUSED
|
||||
Bit 2 P1-Down P1-Button E P2-Button A SERVICE
|
||||
Bit 3 P1-Up TEST P2-Button B UNUSED
|
||||
Bit 4 P1-Left P2-Credit P2-Button C UNUSED
|
||||
Bit 5 P1-Right P2-Start P2-Button D UNUSED
|
||||
Bit 6 P1-Button A P2-Down P2-Button E UNUSED
|
||||
Bit 7 P1-Button B P2-Up VIDEO-MODE UNUSED
|
||||
|
||||
The JAMMA adaptor sends a byte frame each time an input changes.
|
||||
So for example, if the P1-Button A and P1-Button B are both pressed, it will send:
|
||||
|
||||
0x05 0xFC 0xFF 0xFF 0xFF 0x02
|
||||
|
||||
And when the buttons are both released
|
||||
|
||||
0x05 0xFF 0xFF 0xFF 0xFF 0x02
|
||||
|
||||
CPUID info:
|
||||
|
||||
Original set:
|
||||
CPUID Level: EAX: EBX: ECX: EDX:
|
||||
00000000 00000003 756E6547 6C65746E 49656E69
|
||||
00000001 0000068A 00000002 00000000 0387F9FF
|
||||
00000002 03020101 00000000 00000000 0C040882
|
||||
00000003 00000000 00000000 CA976D2E 000082F6
|
||||
80000000 00000000 00000000 CA976D2E 000082F6
|
||||
C0000000 00000000 00000000 CA976D2E 000082F6
|
||||
|
||||
Version 2:
|
||||
CPUID Level: EAX: EBX: ECX: EDX:
|
||||
00000000 00000003 756E6547 6C65746E 49656E69
|
||||
00000001 0000068A 00000002 00000000 0387F9FF
|
||||
00000002 03020101 00000000 00000000 0C040882
|
||||
00000003 00000000 00000000 B8BA1941 00038881
|
||||
80000000 00000000 00000000 B8BA1941 00038881
|
||||
C0000000 00000000 00000000 B8BA1941 00038881
|
||||
|
||||
**************************************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "cpu/i386/i386.h"
|
||||
#include "bus/isa/isa_cards.h"
|
||||
#include "bus/pc_kbd/keyboards.h"
|
||||
#include "machine/intelfsh.h"
|
||||
#include "machine/pci.h"
|
||||
#include "machine/sis5513_ide.h"
|
||||
#include "machine/sis630_host.h"
|
||||
#include "machine/sis630_gui.h"
|
||||
#include "machine/sis7001_usb.h"
|
||||
#include "machine/sis7018_audio.h"
|
||||
#include "machine/sis900_eth.h"
|
||||
#include "machine/sis950_lpc.h"
|
||||
#include "machine/sis950_smbus.h"
|
||||
//#include "machine/fdc37c93x.h"
|
||||
|
||||
class sis630_state : public driver_device
|
||||
{
|
||||
public:
|
||||
sis630_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_maincpu(*this, "maincpu")
|
||||
, m_ide_00_1(*this, "pci:00.1")
|
||||
, m_lpc_01_0(*this, "pci:01.0")
|
||||
{ }
|
||||
|
||||
void sis630(machine_config &config);
|
||||
void gamecstl(machine_config &config);
|
||||
|
||||
private:
|
||||
|
||||
required_device<pentium3_device> m_maincpu;
|
||||
required_device<sis5513_ide_device> m_ide_00_1;
|
||||
required_device<sis950_lpc_device> m_lpc_01_0;
|
||||
|
||||
// void main_io(address_map &map);
|
||||
// void main_map(address_map &map);
|
||||
};
|
||||
|
||||
|
||||
static INPUT_PORTS_START(sis630)
|
||||
INPUT_PORTS_END
|
||||
|
||||
void sis630_state::sis630(machine_config &config)
|
||||
{
|
||||
// Slot 1/Socket 370, Coppermine FC-PGA @ 500~850+/100 MHz or Celeron PPGA 300~600+ MHz
|
||||
// TODO: lowered rate for debugging aid, needs a slot option anyway
|
||||
PENTIUM3(config, m_maincpu, 100'000'000);
|
||||
// m_maincpu->set_addrmap(AS_PROGRAM, &sis630_state::main_map);
|
||||
// m_maincpu->set_addrmap(AS_IO, &sis630_state::main_io);
|
||||
m_maincpu->set_irq_acknowledge_callback("pci:01.0:pic_master", FUNC(pic8259_device::inta_cb));
|
||||
// m_maincpu->smiact().set("pci:00.0", FUNC(sis950_lpc_device::smi_act_w));
|
||||
|
||||
// TODO: unknown flash ROM types
|
||||
// Needs a $80000 sized ROM
|
||||
AMD_29F400T(config, "flash");
|
||||
|
||||
PCI_ROOT(config, "pci", 0);
|
||||
// up to 512MB, 2 x DIMM sockets
|
||||
SIS630_HOST(config, "pci:00.0", 0, "maincpu", 256*1024*1024);
|
||||
SIS5513_IDE(config, m_ide_00_1, 0, "maincpu");
|
||||
// TODO: both on same line as default, should also trigger towards LPC
|
||||
m_ide_00_1->irq_pri().set("pci:01.0:pic_slave", FUNC(pic8259_device::ir6_w));
|
||||
//FUNC(sis950_lpc_device::pc_irq14_w));
|
||||
m_ide_00_1->irq_sec().set("pci:01.0:pic_slave", FUNC(pic8259_device::ir7_w));
|
||||
//FUNC(sis950_lpc_device::pc_mirq0_w));
|
||||
|
||||
SIS950_LPC (config, m_lpc_01_0, XTAL(33'000'000), "maincpu", "flash");
|
||||
m_lpc_01_0->fast_reset_cb().set([this] (int state) {
|
||||
if (state)
|
||||
machine().schedule_soft_reset();
|
||||
});
|
||||
LPC_ACPI (config, "pci:01.0:acpi", 0);
|
||||
SIS950_SMBUS(config, "pci:01.0:smbus", 0);
|
||||
|
||||
SIS900_ETH(config, "pci:01.1", 0);
|
||||
// USB config: 2 on back, 3 on front. Front is fn 2
|
||||
SIS7001_USB(config, "pci:01.2", 0, 3);
|
||||
SIS7001_USB(config, "pci:01.3", 0, 2);
|
||||
SIS7018_AUDIO(config, "pci:01.4", 0);
|
||||
// documentation doesn't mention modem part #, derived from Shuttle MS11 MB manual
|
||||
// SIS7013_MODEM_AC97(config, "pci:01.6"
|
||||
|
||||
// "Virtual PCI-to-PCI Bridge"
|
||||
SIS630_BRIDGE(config, "pci:02.0", 0, "pci:02.0:00.0");
|
||||
// GUI must go under the virtual bridge
|
||||
// This will be correctly identified as bus #1-dev #0-func #0 by the Award BIOS
|
||||
SIS630_GUI(config, "pci:02.0:00.0", 0);
|
||||
|
||||
// optional stuff (according to Kontron 786LCD manual)
|
||||
// "pci:08.0" SCSI controller (vendor=1000 NCR / LSI Logic / Symbios Logic device=0012 53C895A)
|
||||
// "pci:09.0" IEEE1394 controller (vendor=1033 NEC device=00ce uPD72872 / μPD72872)
|
||||
|
||||
// TODO: 3 expansion PCI slots (PC104+)
|
||||
// "pci:09.x" to "pci:12.x"?
|
||||
// (PIC-MG)
|
||||
// "pci:20.x" to "pci:17.x"?
|
||||
|
||||
// TODO: 1 parallel + 2 serial ports
|
||||
// TODO: 1 game port ('7018?)
|
||||
|
||||
// TODO: AMR (Audio/modem riser) + UPT (Panel Link-TV out), assume [E]ISA complaint, needs specific slot options
|
||||
// ISA16_SLOT(config, "isa1", 0, "pci:01.0:isabus", pc_isa16_cards, nullptr, false);
|
||||
// ISA16_SLOT(config, "isa2", 0, "pci:01.0:isabus", pc_isa16_cards, nullptr, false);
|
||||
}
|
||||
|
||||
// Kontron 786LCD/3.5 based
|
||||
void sis630_state::gamecstl(machine_config &config)
|
||||
{
|
||||
sis630_state::sis630(config);
|
||||
// TODO: Actually Celeron, as also stated by the BIOS
|
||||
PENTIUM3(config.replace(), m_maincpu, 100'000'000);
|
||||
|
||||
// tries to install '900 on Windows boot, which implies it doesn't have it
|
||||
// (leave it on for now since it has specific option in Setup BIOS)
|
||||
//config.device_remove("pci:01.1");
|
||||
|
||||
// TODO: mapped RAM config
|
||||
// TODO: add custom inputs
|
||||
// TODO: eventually remove PS/2 connector defaults
|
||||
// subdevice<pc_kbdc_device>("pci:01.0:ps2_con")->set_default_option(nullptr);
|
||||
// subdevice<pc_kbdc_device>("pci:01.0:aux_con")->set_default_option(nullptr);
|
||||
}
|
||||
|
||||
ROM_START(shutms11)
|
||||
ROM_REGION32_LE(0x80000, "flash", ROMREGION_ERASEFF )
|
||||
ROM_SYSTEM_BIOS(0, "ms11s11d", "ms11s11d")
|
||||
ROMX_LOAD( "ms11s11d.bin", 0x040000, 0x040000, CRC(27077a58) SHA1(32327ebf328cb0c2dec819c3710acc83527803c5), ROM_BIOS(0) )
|
||||
ROM_SYSTEM_BIOS(1, "ms11s134", "ms11s134")
|
||||
ROMX_LOAD( "ms11s134.bin", 0x040000, 0x040000, CRC(d739c4f3) SHA1(2301e57163ac4d9b7eddcabce52fa7d01b22330e), ROM_BIOS(1) )
|
||||
ROM_END
|
||||
|
||||
ROM_START(gamecstl)
|
||||
ROM_REGION32_LE(0x80000, "flash", ROMREGION_ERASEFF )
|
||||
// from gamecstl HDD dump, under "C:\drvs\bios\bios1_9"
|
||||
ROM_LOAD( "prod19.rom", 0x040000, 0x040000, BAD_DUMP CRC(9262306c) SHA1(5cd805622ecb4d326591b5f2cf918fe5cb1bce8e) )
|
||||
ROM_CONTINUE( 0x000000, 0x040000 )
|
||||
|
||||
DISK_REGION( "pci:00.1:ide1:0:hdd:image" )
|
||||
DISK_IMAGE( "gamecstl", 0, SHA1(b431af3c42c48ba07972d77a3d24e60ee1e4359e) )
|
||||
ROM_END
|
||||
|
||||
ROM_START(gamecst2)
|
||||
ROM_REGION32_LE(0x80000, "pci:01.0:flash", ROMREGION_ERASEFF )
|
||||
ROM_LOAD( "prod19.rom", 0x040000, 0x040000, BAD_DUMP CRC(9262306c) SHA1(5cd805622ecb4d326591b5f2cf918fe5cb1bce8e) )
|
||||
ROM_CONTINUE( 0x000000, 0x040000 )
|
||||
|
||||
DISK_REGION( "pci:00.1:ide1:0:hdd:image" )
|
||||
DISK_IMAGE( "gamecst2", 0, SHA1(14e1b311cb474801c7bdda3164a0c220fb102159) )
|
||||
ROM_END
|
||||
|
||||
|
||||
COMP( 2000, shutms11, 0, 0, sis630, sis630, sis630_state, empty_init, "Shuttle", "MS11 PC", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS )
|
||||
|
||||
// Arcade based games
|
||||
GAME( 2002, gamecstl, 0, gamecstl, sis630, sis630_state, empty_init, ROT0, "Cristaltec", "GameCristal", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS )
|
||||
GAME( 2002, gamecst2, gamecstl, gamecstl, sis630, sis630_state, empty_init, ROT0, "Cristaltec", "GameCristal (version 2.613)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS )
|
@ -14952,10 +14952,6 @@ gambl186d // EGD
|
||||
@source:gamecom.cpp
|
||||
gamecom // Tiger Game.com
|
||||
|
||||
@source:gamecstl.cpp
|
||||
gamecst2 // MAME based bootleg, version 2.613
|
||||
gamecstl // MAME based bootleg
|
||||
|
||||
@source:gamecube.cpp
|
||||
gcjp // (c) 2001 Nintendo
|
||||
gcus // (c) 2001 Nintendo
|
||||
@ -38979,6 +38975,11 @@ simpsons2pj // GX072 (c) 1991 (Japan)
|
||||
simpsons4pa // GX072 (c) 1991 (Asia)
|
||||
simpsons4pe // GX072 (c) 1991 (World)
|
||||
|
||||
@source:sis630.cpp
|
||||
gamecst2 // MAME based bootleg, version 2.613
|
||||
gamecstl // MAME based bootleg
|
||||
shutms11 // (c) 2000
|
||||
|
||||
@source:sitcom.cpp
|
||||
sitcom //
|
||||
sitcomtmr //
|
||||
|
@ -967,6 +967,7 @@ sg1000.cpp
|
||||
sh4robot.cpp
|
||||
shine.cpp
|
||||
si5500.cpp
|
||||
sis630.cpp
|
||||
sitcom.cpp
|
||||
sk1.cpp
|
||||
sk101bl.cpp
|
||||
|
Loading…
Reference in New Issue
Block a user