// license:BSD-3-Clause
// copyright-holders: Samuele Zannoli
/*
Computer based on a motherboard utilizing the nForce chipset (also known as CRUSH11 or CRUSH12)
Start with the following components:
- An Asus A7N266-C motherboard using:
- nForce 415-D northbridge
- nForce MCP-D southbridge (with integrated APU)
- ITE IT8703F-A SuperIO
- Asus AS99127F chip
- An AMD Athlon XP processor
- An IDE hard disk
- A floppy disk drive
- A keyboard
- A ddr dimm memory module
Later add:
- A Nvidia NV25 based AGP video card
*/
#include "emu.h"
#include "bus/ata/atadev.h"
#include "cpu/i386/athlon.h"
#include "machine/pci.h"
#include "machine/pci-ide.h"
#include "machine/intelfsh.h"
#include "video/virge_pci.h"
#include "bus/rs232/rs232.h"
#include "bus/rs232/hlemouse.h"
#include "bus/rs232/null_modem.h"
#include "bus/rs232/sun_kbd.h"
#include "bus/rs232/terminal.h"
#include "includes/xbox_pci.h"
#include "includes/nforcepc.h"
#if 1
// for now let's use this as the contents of the spd chip in the ddr dimm memory module
static const uint8_t test_spd_data[] = {
0x80,0x08,0x07,0x0D,0x0A,0x01,0x40,0x00,0x04,0x75,0x75,0x00,0x82,0x10,0x00,0x01,
0x0E,0x04,0x0C,0x01,0x02,0x20,0xC0,0xA0,0x75,0x00,0x00,0x50,0x3C,0x50,0x2D,0x40,
0x90,0x90,0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x41,0x4B,0x30,0x32,0x75,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEA,
0xAD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x59,0x4D,0x44,0x35,0x33,0x32,
0x4D,0x36,0x34,0x36,0x43,0x36,0x2D,0x48,0x20,0x20,0x20
};
#else
// From a HYS72D64320HU-5-C (512MB PC3200 (400mHz) DDR CL3 ECC)
static const uint8_t test_spd_data[] = {
0x80,0x08,0x07,0x0d,0x0a,0x02,0x48,0x00,0x04,0x50,0x50,0x02,0x82,0x08,0x08,0x01,
0x0e,0x04,0x1c,0x01,0x02,0x20,0xc1,0x60,0x50,0x75,0x50,0x3c,0x28,0x3c,0x28,0x40,
0x60,0x60,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x37,0x41,0x28,0x28,0x50,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,
0xc1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x45,0x37,0x32,0x44,0x36,0x34,0x33,0x32,
0x30,0x48,0x55,0x35,0x43,0x20,0x20,0x20,0x20,0x20,0x20,0x02,0x4c,0x05,0x44,0x01,
0x08,0x56,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
#endif
/*
Pci devices
*/
// NVIDIA Corporation nForce CPU bridge
DEFINE_DEVICE_TYPE(CRUSH11, crush11_host_device, "crush11", "NVIDIA Corporation nForce CPU bridge")
void crush11_host_device::config_map(address_map &map)
{
pci_host_device::config_map(map);
map(0x10, 0x27).rw(FUNC(pci_device::address_base_r), FUNC(pci_device::address_base_w));
map(0x84, 0x87).rw(FUNC(crush11_host_device::ram_size_r), FUNC(crush11_host_device::ram_size_w));
map(0xf0, 0xf0).rw(FUNC(crush11_host_device::unknown_r), FUNC(crush11_host_device::unknown_w));
}
READ8_MEMBER(crush11_host_device::header_type_r)
{
return 0x80; // from lspci dump
}
crush11_host_device::crush11_host_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: pci_host_device(mconfig, CRUSH11, tag, owner, clock)
, cpu(*this, finder_base::DUMMY_TAG)
, biosrom(*this, finder_base::DUMMY_TAG)
, ram_size(0)
{
}
void crush11_host_device::device_start()
{
pci_host_device::device_start();
set_multifunction_device(true);
memory_space = &cpu->space(AS_DATA);
io_space = &cpu->space(AS_IO);
memory_window_start = 0;
memory_window_end = 0xffffffff;
memory_offset = 0;
io_window_start = 0;
io_window_end = 0xffff;
io_offset = 0;
status = 0x00b0;
}
void crush11_host_device::reset_all_mappings()
{
pci_host_device::reset_all_mappings();
}
void crush11_host_device::device_reset()
{
pci_host_device::device_reset();
}
void crush11_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);
memory_space->install_device(0, 0xffffffff, *this, &crush11_host_device::bios_map);
}
void crush11_host_device::bios_map(address_map &map)
{
map(0x000c0000, 0x000fffff).rw(biosrom, FUNC(intelfsh8_device::read), FUNC(intelfsh8_device::write));
map(0xfffc0000, 0xffffffff).rw(biosrom, FUNC(intelfsh8_device::read), FUNC(intelfsh8_device::write));
}
READ8_MEMBER(crush11_host_device::unknown_r)
{
return 4;
}
WRITE8_MEMBER(crush11_host_device::unknown_w)
{
logerror("test = %02x\n", data);
}
READ32_MEMBER(crush11_host_device::ram_size_r)
{
return ram_size * 1024 * 1024 - 1;
}
WRITE32_MEMBER(crush11_host_device::ram_size_w)
{
logerror("trying to set size = %d\n", data);
}
// For ddr ram
DEFINE_DEVICE_TYPE(CRUSH11_MEMORY, crush11_memory_device, "crush11_memory", "nForce memory")
void crush11_memory_device::config_map(address_map &map)
{
pci_device::config_map(map);
/*
bit 31 of a0,a4,a8,ac,b0 and b4 must be 0
bit 0 of c4 and c8 must be 0
*/
map(0xa0, 0xa3).nopr();
map(0xa4, 0xa7).nopr();
map(0xa8, 0xab).nopr();
map(0xac, 0xaf).nopr();
map(0xb0, 0xb3).nopr();
map(0xb4, 0xb7).nopr();
map(0xc4, 0xc7).nopr();
map(0xc8, 0xcb).nopr();
}
crush11_memory_device::crush11_memory_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, int ram_size)
: crush11_memory_device(mconfig, tag, owner, clock)
{
set_ram_size(ram_size);
}
crush11_memory_device::crush11_memory_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: pci_device(mconfig, CRUSH11_MEMORY, tag, owner, clock)
{
set_ids(0x10de01ac, 0, 0, 0);
}
void crush11_memory_device::device_start()
{
device_t *r = owner()->subdevice("00.0");
pci_device::device_start();
set_multifunction_device(true);
ram.resize(ddr_ram_size * 1024 * 1024 / 4);
host = dynamic_cast<crush11_host_device *>(r);
ram_space = host->get_cpu_space(AS_PROGRAM);
status = 0x0020;
}
void crush11_memory_device::device_reset()
{
pci_device::device_reset();
host->set_ram_size(ddr_ram_size);
}
void crush11_memory_device::set_ram_size(int ram_size)
{
ddr_ram_size = ram_size;
if (ddr_ram_size < 16)
ddr_ram_size = 16;
}
void crush11_memory_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)
{
ram_space->install_ram(0x00000000, ddr_ram_size * 1024 * 1024 - 1, &ram[0]);
}
/*
Ddevices connected to SMBus
*/
// access logger
DEFINE_DEVICE_TYPE(SMBUS_LOGGER, smbus_logger_device, "smbus_logger", "SMBUS LOGGER")
smbus_logger_device::smbus_logger_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, SMBUS_LOGGER, tag, owner, clock)
{
}
int smbus_logger_device::execute_command(int command, int rw, int data)
{
if (rw == 1)
{
logerror("smbus read from %02x R %02x\n", command, buffer[command]);
return buffer[command];
}
buffer[command] = (uint8_t)data;
logerror("smbus write to %02x W %02x\n", command, data);
return 0;
}
void smbus_logger_device::device_start()
{
memset(buffer, 0, sizeof(buffer));
}
void smbus_logger_device::device_reset()
{
}
// read-only data
DEFINE_DEVICE_TYPE(SMBUS_ROM, smbus_rom_device, "smbus_rom", "SMBUS ROM")
smbus_rom_device::smbus_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, SMBUS_ROM, tag, owner, clock)
{
}
smbus_rom_device::smbus_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, const uint8_t *data, int size) :
smbus_rom_device(mconfig, tag, owner, clock)
{
buffer = data;
buffer_size = size;
}
int smbus_rom_device::execute_command(int command, int rw, int data)
{
if ((rw == 1) && (command < buffer_size) && (buffer != nullptr))
{
logerror("smbus rom read from %02x %02x\n", command, buffer[command]);
return buffer[command];
}
return 0;
}
void smbus_rom_device::device_start()
{
}
void smbus_rom_device::device_reset()
{
}
// Asus AS99127F chip
DEFINE_DEVICE_TYPE(AS99127F, as99127f_device, "as99127f", "Asus AS99127F")
as99127f_device::as99127f_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, AS99127F, tag, owner, clock)
{
}
int as99127f_device::execute_command(int command, int rw, int data)
{
if (rw == 1)
{
logerror("smbus read from %02x R %02x\n", command, buffer[command]);
return buffer[command];
}
buffer[command] = (uint8_t)data;
logerror("smbus write to %02x W %02x\n", command, data);
return 0;
}
void as99127f_device::device_start()
{
memset(buffer, 0, sizeof(buffer));
// used to read voltages by bios, measured in mV
buffer[0x20] = 0x70; // multiplied by 0x10
buffer[0x2] = 0x7e; // multiplied by 0x10
buffer[0x23] = 0x96; // multiplied by 0x540 then divided by 0x32
buffer[0x24] = 0x9e; // multiplied by 0x260 then divided by 0xa
}
DEFINE_DEVICE_TYPE(AS99127F_SENSOR2, as99127f_sensor2_device, "as99127f_sensor2", "Asus AS99127F temperature sensor 2")
as99127f_sensor2_device::as99127f_sensor2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, AS99127F_SENSOR2, tag, owner, clock)
{
}
int as99127f_sensor2_device::execute_command(int command, int rw, int data)
{
if (rw == 1)
{
logerror("smbus read from %02x R %02x\n", command, buffer[command]);
return buffer[command];
}
buffer[command] = (uint8_t)data;
logerror("smbus write to %02x W %02x\n", command, data);
return 0;
}
void as99127f_sensor2_device::device_start()
{
memset(buffer, 0, sizeof(buffer));
}
DEFINE_DEVICE_TYPE(AS99127F_SENSOR3, as99127f_sensor3_device, "as99127f_sensor3", "Asus AS99127F temperature sensor 3")
as99127f_sensor3_device::as99127f_sensor3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, AS99127F_SENSOR3, tag, owner, clock)
{
}
int as99127f_sensor3_device::execute_command(int command, int rw, int data)
{
if (rw == 1)
{
logerror("smbus read from %02x R %02x\n", command, buffer[command]);
return buffer[command];
}
buffer[command] = (uint8_t)data;
logerror("smbus write to %02x W %02x\n", command, data);
return 0;
}
void as99127f_sensor3_device::device_start()
{
memset(buffer, 0, sizeof(buffer));
}
// ITE IT8703F-A SuperIO
DEFINE_DEVICE_TYPE(IT8703F, it8703f_device, "it8703f_device", "ITE IT8703F-A SuperIO")
it8703f_device::it8703f_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, IT8703F, tag, owner, clock)
, mode(OperatingMode::Run)
, config_key_step(0)
, config_index(0)
, logical_device(0)
, pin_reset_callback(*this)
, pin_gatea20_callback(*this)
, m_txd1_callback(*this)
, m_ndtr1_callback(*this)
, m_nrts1_callback(*this)
, m_txd2_callback(*this)
, m_ndtr2_callback(*this)
, m_nrts2_callback(*this)
, pc_lpt_lptdev(*this, "lpt")
, pc_serial1_comdev(*this, "uart_0")
, pc_serial2_comdev(*this, "uart_1")
, m_kbdc(*this, "pc_kbdc")
, enabled_game_port(false)
, enabled_midi_port(false)
{
memset(global_configuration_registers, 0, sizeof(global_configuration_registers));
global_configuration_registers[0x20] = 0x87; // identifies it8703f
global_configuration_registers[0x21] = 1;
global_configuration_registers[0x24] = 4;
memset(configuration_registers, 0, sizeof(configuration_registers));
configuration_registers[LogicalDevice::Parallel][0x74] = 4;
configuration_registers[LogicalDevice::Parallel][0xf0] = 0x3f;
for (int n = 0; n < 13; n++)
enabled_logical[n] = false;
}
void it8703f_device::device_start()
{
pin_reset_callback.resolve_safe();
pin_gatea20_callback.resolve_safe();
m_txd1_callback.resolve_safe();
m_ndtr1_callback.resolve_safe();
m_nrts1_callback.resolve_safe();
m_txd2_callback.resolve_safe();
m_ndtr2_callback.resolve_safe();
m_nrts2_callback.resolve_safe();
}
void it8703f_device::internal_memory_map(address_map &map)
{
}
void it8703f_device::internal_io_map(address_map &map)
{
map(0x002e, 0x002f).rw(FUNC(it8703f_device::read_it8703f), FUNC(it8703f_device::write_it8703f));
}
uint16_t it8703f_device::get_base_address(int logical, int index)
{
int position = index * 2 + 0x60;
return ((uint16_t)configuration_registers[logical][position] << 8) + (uint16_t)configuration_registers[logical][position + 1];
}
void it8703f_device::device_add_mconfig(machine_config &config)
{
// parallel port
PC_LPT(config, pc_lpt_lptdev);
pc_lpt_lptdev->irq_handler().set(FUNC(it8703f_device::irq_parallel_w));
// serial ports
NS16450(config, pc_serial1_comdev, XTAL(1'843'200)); // or NS16550 ?
pc_serial1_comdev->out_int_callback().set(FUNC(it8703f_device::irq_serial1_w));
pc_serial1_comdev->out_tx_callback().set(FUNC(it8703f_device::txd_serial1_w));
pc_serial1_comdev->out_dtr_callback().set(FUNC(it8703f_device::dtr_serial1_w));
pc_serial1_comdev->out_rts_callback().set(FUNC(it8703f_device::rts_serial1_w));
NS16450(config, pc_serial2_comdev, XTAL(1'843'200));
pc_serial2_comdev->out_int_callback().set(FUNC(it8703f_device::irq_serial2_w));
pc_serial2_comdev->out_tx_callback().set(FUNC(it8703f_device::txd_serial2_w));
pc_serial2_comdev->out_dtr_callback().set(FUNC(it8703f_device::dtr_serial2_w));
pc_serial2_comdev->out_rts_callback().set(FUNC(it8703f_device::rts_serial2_w));
// keyboard
KBDC8042(config, m_kbdc);
m_kbdc->set_keyboard_type(kbdc8042_device::KBDC8042_PS2);
m_kbdc->input_buffer_full_callback().set(FUNC(it8703f_device::irq_keyboard_w));
m_kbdc->system_reset_callback().set(FUNC(it8703f_device::kbdp20_gp20_reset_w));
m_kbdc->gate_a20_callback().set(FUNC(it8703f_device::kbdp21_gp25_gatea20_w));
}
READ8_MEMBER(it8703f_device::read_it8703f)
{
if (offset == 0)
{
if (mode == OperatingMode::Run)
return 0;
return config_index;
}
else if (offset == 1)
{
if (mode == OperatingMode::Run)
return 0;
if (config_index < 0x30)
return read_global_configuration_register(config_index);
else
return read_logical_configuration_register(config_index);
}
else
return 0;
}
WRITE8_MEMBER(it8703f_device::write_it8703f)
{
uint8_t byt;
if (offset == 0)
{
byt = data & 0xff;
if (mode == OperatingMode::Run)
{
if (byt != 0x87)
return;
config_key_step++;
if (config_key_step > 1)
{
config_key_step = 0;
mode = OperatingMode::Configuration;
}
}
else
{
if (byt == 0xaa)
{
mode = OperatingMode::Run;
return;
}
config_index = byt;
}
}
else if (offset == 1)
{
if (mode == OperatingMode::Run)
return;
byt = data & 0xff;
if (config_index < 0x30)
write_global_configuration_register(config_index, byt);
else
write_logical_configuration_register(config_index, byt);
}
else
return;
}
void it8703f_device::write_global_configuration_register(int index, int data)
{
global_configuration_registers[index] = data;
switch (index)
{
case 7:
logical_device = data;
logerror("Selected logical device %d\n", data);
break;
}
logerror("Write global configuration register %02X = %02X\n", index, data);
}
void it8703f_device::write_logical_configuration_register(int index, int data)
{
configuration_registers[logical_device][index] = data;
switch (logical_device)
{
case LogicalDevice::Serial1:
write_serial1_configuration_register(index, data);
break;
case LogicalDevice::Serial2:
write_serial2_configuration_register(index, data);
break;
case LogicalDevice::Parallel:
write_parallel_configuration_register(index, data);
break;
case LogicalDevice::Keyboard:
write_keyboard_configuration_register(index, data);
break;
case LogicalDevice::Gpio1:
if (index == 0x30)
{
if (data & 1)
enabled_game_port = true;
if (data & 2)
enabled_midi_port = true;
}
break;
}
}
void it8703f_device::write_parallel_configuration_register(int index, int data)
{
if (index == 0x30)
{
if (data & 1)
{
if (enabled_logical[LogicalDevice::Parallel] == false)
{
enabled_logical[LogicalDevice::Parallel] = true;
lpchost->remap();
}
logerror("Enabled LPT at %04X\n", get_base_address(LogicalDevice::Parallel, 0));
}
else
{
if (enabled_logical[LogicalDevice::Parallel] == true)
{
enabled_logical[LogicalDevice::Parallel] = false;
lpchost->remap();
}
}
}
}
void it8703f_device::write_serial1_configuration_register(int index, int data)
{
if (index == 0x30)
{
if (data & 1)
{
if (enabled_logical[LogicalDevice::Serial1] == false)
{
enabled_logical[LogicalDevice::Serial1] = true;
lpchost->remap();
}
logerror("Enabled Serial1 at %04X\n", get_base_address(LogicalDevice::Serial1, 0));
}
else
{
if (enabled_logical[LogicalDevice::Serial1] == true)
{
enabled_logical[LogicalDevice::Serial1] = false;
lpchost->remap();
}
}
}
}
void it8703f_device::write_serial2_configuration_register(int index, int data)
{
if (index == 0x30)
{
if (data & 1)
{
if (enabled_logical[LogicalDevice::Serial2] == false)
{
enabled_logical[LogicalDevice::Serial2] = true;
lpchost->remap();
}
logerror("Enabled Serial2 at %04X\n", get_base_address(LogicalDevice::Serial2, 0));
}
else
{
if (enabled_logical[LogicalDevice::Serial2] == true)
{
enabled_logical[LogicalDevice::Serial2] = false;
lpchost->remap();
}
}
}
}
void it8703f_device::write_keyboard_configuration_register(int index, int data)
{
if (index == 0x30)
{
if (data & 1)
{
if (enabled_logical[LogicalDevice::Keyboard] == false)
{
enabled_logical[LogicalDevice::Keyboard] = true;
lpchost->remap();
}
logerror("Enabled Keyboard\n");
}
else
{
if (enabled_logical[LogicalDevice::Keyboard] == true)
{
enabled_logical[LogicalDevice::Keyboard] = false;
lpchost->remap();
}
}
}
}
uint16_t it8703f_device::read_global_configuration_register(int index)
{
uint16_t ret = 0;
ret = global_configuration_registers[index];
switch (index)
{
case 7:
ret = logical_device;
break;
}
logerror("Read global configuration register %02X = %02X\n", index, ret);
return ret;
}
uint16_t it8703f_device::read_logical_configuration_register(int index)
{
uint16_t ret = 0;
switch (logical_device)
{
case LogicalDevice::Parallel:
ret = read_parallel_configuration_register(index);
break;
case LogicalDevice::Serial1:
ret = read_serial1_configuration_register(index);
break;
case LogicalDevice::Serial2:
ret = read_serial2_configuration_register(index);
break;
case LogicalDevice::Keyboard:
ret = read_keyboard_configuration_register(index);
break;
default:
ret = configuration_registers[logical_device][index];
break;
}
return ret;
}
WRITE_LINE_MEMBER(it8703f_device::irq_parallel_w)
{
if (enabled_logical[LogicalDevice::Parallel] == false)
return;
lpchost->set_virtual_line(configuration_registers[LogicalDevice::Parallel][0x70], state ? ASSERT_LINE : CLEAR_LINE);
}
WRITE_LINE_MEMBER(it8703f_device::irq_serial1_w)
{
if (enabled_logical[LogicalDevice::Serial1] == false)
return;
lpchost->set_virtual_line(configuration_registers[LogicalDevice::Serial1][0x70], state ? ASSERT_LINE : CLEAR_LINE);
}
WRITE_LINE_MEMBER(it8703f_device::txd_serial1_w)
{
if (enabled_logical[LogicalDevice::Serial1] == false)
return;
m_txd1_callback(state);
}
WRITE_LINE_MEMBER(it8703f_device::dtr_serial1_w)
{
if (enabled_logical[LogicalDevice::Serial1] == false)
return;
m_ndtr1_callback(state);
}
WRITE_LINE_MEMBER(it8703f_device::rts_serial1_w)
{
if (enabled_logical[LogicalDevice::Serial1] == false)
return;
m_nrts1_callback(state);
}
WRITE_LINE_MEMBER(it8703f_device::irq_serial2_w)
{
if (enabled_logical[LogicalDevice::Serial2] == false)
return;
lpchost->set_virtual_line(configuration_registers[LogicalDevice::Serial2][0x70], state ? ASSERT_LINE : CLEAR_LINE);
}
WRITE_LINE_MEMBER(it8703f_device::txd_serial2_w)
{
if (enabled_logical[LogicalDevice::Serial2] == false)
return;
m_txd2_callback(state);
}
WRITE_LINE_MEMBER(it8703f_device::dtr_serial2_w)
{
if (enabled_logical[LogicalDevice::Serial2] == false)
return;
m_ndtr2_callback(state);
}
WRITE_LINE_MEMBER(it8703f_device::rts_serial2_w)
{
if (enabled_logical[LogicalDevice::Serial2] == false)
return;
m_nrts2_callback(state);
}
WRITE_LINE_MEMBER(it8703f_device::rxd1_w)
{
pc_serial1_comdev->rx_w(state);
}
WRITE_LINE_MEMBER(it8703f_device::ndcd1_w)
{
pc_serial1_comdev->dcd_w(state);
}
WRITE_LINE_MEMBER(it8703f_device::ndsr1_w)
{
pc_serial1_comdev->dsr_w(state);
}
WRITE_LINE_MEMBER(it8703f_device::nri1_w)
{
pc_serial1_comdev->ri_w(state);
}
WRITE_LINE_MEMBER(it8703f_device::ncts1_w)
{
pc_serial1_comdev->cts_w(state);
}
WRITE_LINE_MEMBER(it8703f_device::rxd2_w)
{
pc_serial2_comdev->rx_w(state);
}
WRITE_LINE_MEMBER(it8703f_device::ndcd2_w)
{
pc_serial2_comdev->dcd_w(state);
}
WRITE_LINE_MEMBER(it8703f_device::ndsr2_w)
{
pc_serial2_comdev->dsr_w(state);
}
WRITE_LINE_MEMBER(it8703f_device::nri2_w)
{
pc_serial2_comdev->ri_w(state);
}
WRITE_LINE_MEMBER(it8703f_device::ncts2_w)
{
pc_serial2_comdev->cts_w(state);
}
WRITE_LINE_MEMBER(it8703f_device::irq_keyboard_w)
{
if (enabled_logical[LogicalDevice::Keyboard] == false)
return;
lpchost->set_virtual_line(configuration_registers[LogicalDevice::Keyboard][0x70], state ? ASSERT_LINE : CLEAR_LINE);
}
WRITE_LINE_MEMBER(it8703f_device::kbdp21_gp25_gatea20_w)
{
if (enabled_logical[LogicalDevice::Keyboard] == false)
return;
pin_gatea20_callback(state);
}
WRITE_LINE_MEMBER(it8703f_device::kbdp20_gp20_reset_w)
{
if (enabled_logical[LogicalDevice::Keyboard] == false)
return;
pin_reset_callback(state);
}
void it8703f_device::map_lpt(address_map& map)
{
map(0x0, 0x3).rw(FUNC(it8703f_device::lpt_read), FUNC(it8703f_device::lpt_write));
}
READ8_MEMBER(it8703f_device::lpt_read)
{
return pc_lpt_lptdev->read(space, offset, mem_mask);
}
WRITE8_MEMBER(it8703f_device::lpt_write)
{
pc_lpt_lptdev->write(space, offset, data, mem_mask);
}
void it8703f_device::map_lpt_addresses()
{
uint16_t base = get_base_address(LogicalDevice::Parallel, 0);
iospace->install_device(base, base + 3, *this, &it8703f_device::map_lpt);
}
void it8703f_device::map_serial1(address_map& map)
{
map(0x0, 0x7).rw(FUNC(it8703f_device::serial1_read), FUNC(it8703f_device::serial1_write));
}
READ8_MEMBER(it8703f_device::serial1_read)
{
return pc_serial1_comdev->ins8250_r(offset);
}
WRITE8_MEMBER(it8703f_device::serial1_write)
{
pc_serial1_comdev->ins8250_w(offset, data);
}
void it8703f_device::map_serial1_addresses()
{
uint16_t base = get_base_address(LogicalDevice::Serial1, 0);
iospace->install_device(base, base + 7, *this, &it8703f_device::map_serial1);
}
void it8703f_device::map_serial2(address_map& map)
{
map(0x0, 0x7).rw(FUNC(it8703f_device::serial2_read), FUNC(it8703f_device::serial2_write));
}
READ8_MEMBER(it8703f_device::serial2_read)
{
return pc_serial2_comdev->ins8250_r(offset);
}
WRITE8_MEMBER(it8703f_device::serial2_write)
{
pc_serial2_comdev->ins8250_w(offset, data);
}
void it8703f_device::map_serial2_addresses()
{
uint16_t base = get_base_address(LogicalDevice::Serial2, 0);
iospace->install_device(base, base + 7, *this, &it8703f_device::map_serial2);
}
void it8703f_device::map_keyboard(address_map &map)
{
map(0x0, 0x0).rw(FUNC(it8703f_device::at_keybc_r), FUNC(it8703f_device::at_keybc_w));
map(0x4, 0x4).rw(FUNC(it8703f_device::keybc_status_r), FUNC(it8703f_device::keybc_command_w));
}
void it8703f_device::unmap_keyboard(address_map &map)
{
map(0x0, 0x0).noprw();
map(0x4, 0x4).noprw();
}
READ8_MEMBER(it8703f_device::at_keybc_r)
{
switch (offset) //m_kbdc
{
case 0:
return m_kbdc->data_r(space, 0);
}
return 0xff;
}
WRITE8_MEMBER(it8703f_device::at_keybc_w)
{
switch (offset)
{
case 0:
m_kbdc->data_w(space, 0, data);
}
}
READ8_MEMBER(it8703f_device::keybc_status_r)
{
return m_kbdc->data_r(space, 4);
}
WRITE8_MEMBER(it8703f_device::keybc_command_w)
{
m_kbdc->data_w(space, 4, data);
}
void it8703f_device::map_keyboard_addresses()
{
uint16_t base = get_base_address(LogicalDevice::Keyboard, 0);
iospace->install_device(base, base + 7, *this, &it8703f_device::map_keyboard);
}
void it8703f_device::map_extra(address_space *memory_space, address_space *io_space)
{
memspace = memory_space;
iospace = io_space;
io_space->install_device(0, 0xffff, *this, &it8703f_device::internal_io_map);
if (enabled_logical[LogicalDevice::Parallel] == true)
map_lpt_addresses();
if (enabled_logical[LogicalDevice::Serial1] == true)
map_serial1_addresses();
if (enabled_logical[LogicalDevice::Serial2] == true)
map_serial2_addresses();
if (enabled_logical[LogicalDevice::Keyboard] == true)
map_keyboard_addresses();
}
void it8703f_device::set_host(int index, lpcbus_host_interface *host)
{
lpchost = host;
lpcindex = index;
}
/*
Machine state
*/
class nforcepc_state : public driver_device
{
public:
struct boot_state_info
{
uint8_t val;
const char *const message;
};
static const boot_state_info boot_state_infos_award[];
void nforcepc(machine_config &config);
nforcepc_state(const machine_config &mconfig, device_type type, const char *tag);
private:
void nforce_map(address_map &map);
void nforce_map_io(address_map &map);
DECLARE_WRITE8_MEMBER(boot_state_award_w);
IRQ_CALLBACK_MEMBER(irq_callback);
DECLARE_WRITE_LINE_MEMBER(maincpu_interrupt);
virtual void machine_start() override;
virtual void machine_reset() override;
required_device<cpu_device> m_maincpu;
required_device<mcpx_isalpc_device> isalpc;
required_device<as99127f_device> m_as99127f;
};
nforcepc_state::nforcepc_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
isalpc(*this, ":pci:01.0"),
m_as99127f(*this, ":pci:01.1:12d")
{
}
void nforcepc_state::machine_start()
{
m_as99127f->get_buffer()[0x4f] = 0x12;
}
void nforcepc_state::machine_reset()
{
}
const nforcepc_state::boot_state_info nforcepc_state::boot_state_infos_award[] = {
{ 0xC0, "First basic initialization" },
{ 0, nullptr }
};
WRITE8_MEMBER(nforcepc_state::boot_state_award_w)
{
const char *desc = "";
for (int i = 0; boot_state_infos_award[i].message; i++)
if (boot_state_infos_award[i].val == data)
{
desc = boot_state_infos_award[i].message;
break;
}
logerror("Boot state %02x - %s\n", data, desc);
}
IRQ_CALLBACK_MEMBER(nforcepc_state::irq_callback)
{
return isalpc->acknowledge();
}
WRITE_LINE_MEMBER(nforcepc_state::maincpu_interrupt)
{
m_maincpu->set_input_line(0, state ? HOLD_LINE : CLEAR_LINE);
}
void nforcepc_state::nforce_map(address_map &map)
{
map.unmap_value_high();
}
void nforcepc_state::nforce_map_io(address_map &map)
{
map.unmap_value_high();
}
static void isa_com(device_slot_interface& device)
{
device.option_add("microsoft_mouse", MSFT_HLE_SERIAL_MOUSE);
device.option_add("logitech_mouse", LOGITECH_HLE_SERIAL_MOUSE);
device.option_add("wheel_mouse", WHEEL_HLE_SERIAL_MOUSE);
device.option_add("msystems_mouse", MSYSTEMS_HLE_SERIAL_MOUSE);
device.option_add("rotatable_mouse", ROTATABLE_HLE_SERIAL_MOUSE);
device.option_add("terminal", SERIAL_TERMINAL);
device.option_add("null_modem", NULL_MODEM);
device.option_add("sun_kbd", SUN_KBD_ADAPTOR);
}
/*
Machine configuration
*/
void nforcepc_state::nforcepc(machine_config &config)
{
athlonxp_device &maincpu(ATHLONXP(config, "maincpu", 90000000));
maincpu.set_addrmap(AS_PROGRAM, &nforcepc_state::nforce_map);
maincpu.set_addrmap(AS_IO, &nforcepc_state::nforce_map_io);
maincpu.set_irq_acknowledge_callback(FUNC(nforcepc_state::irq_callback));
//maincpu.smiact().set("pci:01.0", FUNC(???_host_device::smi_act_w));
PCI_ROOT(config, ":pci", 0);
CRUSH11(config, ":pci:00.0", 0, "maincpu", "bios"); // 10de:01a4 NVIDIA Corporation nForce CPU bridge
CRUSH11_MEMORY(config, ":pci:00.1", 0, 2); // 10de:01ac NVIDIA Corporation nForce 220/420 Memory Controller
// 10de:01ad NVIDIA Corporation nForce 220/420 Memory Controller
// 10de:01ab NVIDIA Corporation nForce 420 Memory Controller (DDR)
mcpx_isalpc_device &isa(MCPX_ISALPC(config, ":pci:01.0", 0, 0x10430c11)); // 10de:01b2 NVIDIA Corporation nForce ISA Bridge (LPC bus)
isa.smi().set_inputline(":maincpu", INPUT_LINE_SMI);
isa.boot_state_hook().set(FUNC(nforcepc_state::boot_state_award_w));
isa.interrupt_output().set(FUNC(nforcepc_state::maincpu_interrupt));
it8703f_device &ite(IT8703F(config, ":pci:01.0:0", 0));
ite.pin_reset().set_inputline(":maincpu", INPUT_LINE_RESET);
ite.pin_gatea20().set_inputline(":maincpu", INPUT_LINE_A20);
ite.txd1().set(":serport0", FUNC(rs232_port_device::write_txd));
ite.ndtr1().set(":serport0", FUNC(rs232_port_device::write_dtr));
ite.nrts1().set(":serport0", FUNC(rs232_port_device::write_rts));
ite.txd2().set(":serport1", FUNC(rs232_port_device::write_txd));
ite.ndtr2().set(":serport1", FUNC(rs232_port_device::write_dtr));
ite.nrts2().set(":serport1", FUNC(rs232_port_device::write_rts));
MCPX_SMBUS(config, ":pci:01.1", 0); // 10de:01b4 NVIDIA Corporation nForce PCI System Management (SMBus)
SMBUS_ROM(config, ":pci:01.1:050", 0, test_spd_data, sizeof(test_spd_data)); // these 3 are on smbus number 0
SMBUS_LOGGER(config, ":pci:01.1:051", 0);
SMBUS_LOGGER(config, ":pci:01.1:052", 0);
SMBUS_LOGGER(config, ":pci:01.1:108", 0); // these 4 are on smbus number 1
AS99127F(config, ":pci:01.1:12d", 0);
AS99127F_SENSOR2(config, ":pci:01.1:148", 0);
AS99127F_SENSOR3(config, ":pci:01.1:149", 0);
mcpx_ohci_device &ohci(MCPX_OHCI(config, ":pci:02.0", 0)); // 10de:01c2 NVIDIA Corporation nForce USB Controller
ohci.interrupt_handler().set(":pci:01.0", FUNC(mcpx_isalpc_device::irq1));
MCPX_OHCI(config, ":pci:03.0", 0); // 10de:01c2 NVIDIA Corporation nForce USB Controller
MCPX_ETH(config, ":pci:04.0", 0); // 10de:01c3 NVIDIA Corporation nForce Ethernet Controller
MCPX_APU(config, ":pci:05.0", 0, m_maincpu); // 10de:01b0 NVIDIA Corporation nForce Audio Processing Unit
MCPX_AC97_AUDIO(config, ":pci:06.0", 0); // 10de:01b1 NVIDIA Corporation nForce AC'97 Audio Controller
PCI_BRIDGE(config, ":pci:08.0", 0, 0x10de01b8, 0); // 10de:01b8 NVIDIA Corporation nForce PCI-to-PCI bridge
// 10ec:8139 Realtek Semiconductor Co., Ltd. RTL-8139/8139C/8139C+ (behind bridge)
mcpx_ide_device &ide(MCPX_IDE(config, ":pci:09.0", 0)); // 10de:01bc NVIDIA Corporation nForce IDE
ide.pri_interrupt_handler().set(":pci:01.0", FUNC(mcpx_isalpc_device::irq14));
ide.sec_interrupt_handler().set(":pci:01.0", FUNC(mcpx_isalpc_device::irq15));
/*subdevice<ide_controller_32_device>(":pci:09.0:ide")->options(ata_devices, "hdd", "cdrom", true);*/
NV2A_AGP(config, ":pci:1e.0", 0, 0x10de01b7, 0); // 10de:01b7 NVIDIA Corporation nForce AGP to PCI Bridge
VIRGEDX_PCI(config, ":pci:0a.0", 0);
SST_49LF020(config, "bios", 0);
rs232_port_device& serport0(RS232_PORT(config, "serport0", isa_com, nullptr));
serport0.rxd_handler().set(":pci:01.0:0", FUNC(it8703f_device::rxd1_w));
serport0.dcd_handler().set(":pci:01.0:0", FUNC(it8703f_device::ndcd1_w));
serport0.dsr_handler().set(":pci:01.0:0", FUNC(it8703f_device::ndsr1_w));
serport0.ri_handler().set(":pci:01.0:0", FUNC(it8703f_device::nri1_w));
serport0.cts_handler().set(":pci:01.0:0", FUNC(it8703f_device::ncts1_w));
rs232_port_device& serport1(RS232_PORT(config, "serport1", isa_com, nullptr));
serport1.rxd_handler().set(":pci:01.0:0", FUNC(it8703f_device::rxd2_w));
serport1.dcd_handler().set(":pci:01.0:0", FUNC(it8703f_device::ndcd2_w));
serport1.dsr_handler().set(":pci:01.0:0", FUNC(it8703f_device::ndsr2_w));
serport1.ri_handler().set(":pci:01.0:0", FUNC(it8703f_device::nri2_w));
serport1.cts_handler().set(":pci:01.0:0", FUNC(it8703f_device::ncts2_w));
}
ROM_START(nforcepc)
ROM_REGION32_LE(0x40000, "bios", 0) /* PC bios */
ROM_SYSTEM_BIOS(0, "a7n266c", "a7n266c") // Motherboard dump. Chip: SST49LF020 Package: PLCC32 Label had 3 lines of text: "A7NC3" "1001.D" "GSQ98"
ROMX_LOAD("a7n266c.bin", 0, 0x40000, CRC(f4f0e4fc) SHA1(87f11545db178914623e41fb51e328da479a2efc), ROM_BIOS(0))
ROM_SYSTEM_BIOS(1, "a7n266c1001d", "a7n266c1001d") // bios version 1001.D downloaded from Asus website
ROMX_LOAD("a7nc101d.awd", 0, 0x40000, CRC(ead1147c) SHA1(27227df98e0c5fb9fecdb4bb6ef72df19766c330), ROM_BIOS(1))
ROM_SYSTEM_BIOS(2, "a7n266c1001e", "a7n266c1001e") // bios version 1001.E
ROMX_LOAD("a7nc101e.awd", 0, 0x40000, CRC(a029cd42) SHA1(e257915534bc725f389e57945b45c81e7ef40dcc), ROM_BIOS(2))
ROM_SYSTEM_BIOS(3, "a7n266c1002c", "a7n266c1002c") // beta bios version 1002C.003 ?
ROMX_LOAD("1002c.003", 0, 0x40000, CRC(57ced539) SHA1(525d15523be3b373a10c1f6ae355803613506ce2), ROM_BIOS(3))
ROM_SYSTEM_BIOS(4, "a7n266c1003", "a7n266c1003") // bios version 1003
ROMX_LOAD("a7nc1003.awd", 0, 0x40000, CRC(ac27f751) SHA1(96d5539ee2a40ea58a32013c16109159a3c41bb8), ROM_BIOS(4))
ROM_SYSTEM_BIOS(5, "a7n266c1004", "a7n266c1004") // bios version 1004
ROMX_LOAD("a7nc1004.awd", 0, 0x40000, CRC(04124e4f) SHA1(8778a6722eddaf83101f89834969f0037af65cb9), ROM_BIOS(5))
ROM_SYSTEM_BIOS(6, "a7n266c1005", "a7n266c1005") // beta bios version 1005.005 ?
ROMX_LOAD("1005nc.005", 0, 0x40000, CRC(9ca5a9c9) SHA1(5ffb57b9f1e0e163b33c093a3e017020b247b3d3), ROM_BIOS(6))
ROM_END
static INPUT_PORTS_START(nforcepc)
PORT_INCLUDE(at_keyboard)
INPUT_PORTS_END
COMP(2002, nforcepc, 0, 0, nforcepc, nforcepc, nforcepc_state, empty_init, "Nvidia", "Nvidia nForce PC (CRUSH11/12)", MACHINE_IS_SKELETON)