summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/sis950_lpc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/sis950_lpc.cpp')
-rw-r--r--src/devices/machine/sis950_lpc.cpp177
1 files changed, 99 insertions, 78 deletions
diff --git a/src/devices/machine/sis950_lpc.cpp b/src/devices/machine/sis950_lpc.cpp
index 8d00dcfa787..7e33c07058f 100644
--- a/src/devices/machine/sis950_lpc.cpp
+++ b/src/devices/machine/sis950_lpc.cpp
@@ -2,28 +2,30 @@
// 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;
+SiS950 LPC implementation (Super I/O & southbridge)
+
+TODO:
+- Convert most stuff declared here to generic interfaces;
+ \- Despite what the datasheet claims it really looks like that a separate Super I/O provides
+ the usual x86 resources;
+- 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 for PCI_SLOT
+ \- 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 catch of "changing device ID number" via BIOS control $40 bit 6;
**************************************************************************************************/
@@ -63,9 +65,11 @@ sis950_lpc_device::sis950_lpc_device(const machine_config &mconfig, const char *
, m_dmac_slave(*this, "dmac_slave")
, m_pit(*this, "pit")
, m_keybc(*this, "keybc")
+ , m_isabus(*this, "isabus")
, m_speaker(*this, "speaker")
, m_rtc(*this, "rtc")
- , m_uart(*this, "uart")
+ , m_ps2_con(*this, "ps2_con")
+ , m_aux_con(*this, "aux_con")
, m_acpi(*this, "acpi")
, m_smbus(*this, "smbus")
, m_fast_reset_cb(*this)
@@ -158,18 +162,26 @@ void sis950_lpc_device::device_add_mconfig(machine_config &config)
// TODO: EISA, from virtual bridge
- // TODO: selectable between PCI clock / 4 (33 MHz) or 7.159 MHz, via reg $47 bit 5
- KBDC8042(config, m_keybc);
- m_keybc->set_keyboard_type(kbdc8042_device::KBDC8042_PS2);
- m_keybc->set_interrupt_type(kbdc8042_device::KBDC8042_DOUBLE);
- m_keybc->input_buffer_full_callback().set(m_pic_master, FUNC(pic8259_device::ir1_w));
- m_keybc->input_buffer_full_mouse_callback().set(m_pic_slave, FUNC(pic8259_device::ir4_w));
- m_keybc->system_reset_callback().set(FUNC(sis950_lpc_device::cpu_reset_w));
- m_keybc->gate_a20_callback().set(FUNC(sis950_lpc_device::cpu_a20_w));
- m_keybc->set_keyboard_tag("at_keyboard");
-
- at_keyboard_device &at_keyb(AT_KEYB(config, "at_keyboard", pc_keyboard_device::KEYBOARD_TYPE::AT, 1));
- at_keyb.keypress().set(m_keybc, FUNC(kbdc8042_device::keyboard_w));
+ // TODO: selectable between PCI clock / 4 or 7.159 MHz, via reg $47 bit 5
+ PS2_KEYBOARD_CONTROLLER(config, m_keybc, DERIVED_CLOCK(1, 4));
+ 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));
+
+ 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));
+
+ // TODO: doesn't work (wrong PS/2 BIOS?), worked around by disabling for now
+ PC_KBDC(config, m_aux_con, ps2_mice, nullptr);
+ 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: unknown RTC type
// Has external RTC bank select at $48, using this one as convenience
@@ -177,25 +189,32 @@ void sis950_lpc_device::device_add_mconfig(machine_config &config)
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);
+
+ ISA16(config, m_isabus, 0);
+ m_isabus->irq3_callback().set(FUNC(sis950_lpc_device::pc_irq3_w));
+ m_isabus->irq4_callback().set(FUNC(sis950_lpc_device::pc_irq4_w));
+ m_isabus->irq6_callback().set(FUNC(sis950_lpc_device::pc_irq6_w));
+ m_isabus->irq5_callback().set(FUNC(sis950_lpc_device::pc_irq5_w));
+ m_isabus->irq7_callback().set(FUNC(sis950_lpc_device::pc_irq7_w));
+ m_isabus->irq2_callback().set(FUNC(sis950_lpc_device::pc_irq9_w));
+ m_isabus->irq10_callback().set(FUNC(sis950_lpc_device::pc_irq10_w));
+ m_isabus->irq11_callback().set(FUNC(sis950_lpc_device::pc_irq11_w));
+ m_isabus->irq12_callback().set(FUNC(sis950_lpc_device::pc_irq12m_w));
+ m_isabus->irq14_callback().set(FUNC(sis950_lpc_device::pc_irq14_w));
+ m_isabus->irq15_callback().set(FUNC(sis950_lpc_device::pc_irq15_w));
+ m_isabus->iochck_callback().set(FUNC(sis950_lpc_device::iochck_w));
+}
+
+void sis950_lpc_device::device_config_complete()
+{
+ auto isabus = m_isabus.finder_target();
+ isabus.first.subdevice<isa16_device>(isabus.second)->set_memspace(m_host_cpu, AS_PROGRAM);
+ isabus.first.subdevice<isa16_device>(isabus.second)->set_iospace(m_host_cpu, AS_IO);
+
+ pci_device::device_config_complete();
}
void sis950_lpc_device::config_map(address_map &map)
@@ -391,26 +410,6 @@ void sis950_lpc_device::acpi_base_w(u8 data)
remap_cb();
}
-u8 sis950_lpc_device::at_keybc_r(offs_t offset)
-{
- return m_keybc->data_r(0);
-}
-
-void sis950_lpc_device::at_keybc_w(offs_t offset, u8 data)
-{
- m_keybc->data_w(0, data);
-}
-
-u8 sis950_lpc_device::keybc_status_r(offs_t offset)
-{
- return (m_keybc->data_r(4) & 0xfb) | 0x10; // bios needs bit 2 to be 0 as powerup and bit 4 to be 1
-}
-
-void sis950_lpc_device::keybc_command_w(offs_t offset, u8 data)
-{
- m_keybc->data_w(4, data);
-}
-
template <unsigned N> void sis950_lpc_device::memory_map(address_map &map)
{
map(0x00000000, 0x0001ffff).lrw8(
@@ -428,11 +427,11 @@ void sis950_lpc_device::io_map(address_map &map)
map(0x0020, 0x0021).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(FUNC(sis950_lpc_device::at_keybc_r), FUNC(sis950_lpc_device::at_keybc_w));
+ 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(FUNC(sis950_lpc_device::keybc_status_r), FUNC(sis950_lpc_device::keybc_command_w));
+ // undocumented but read, assume LPC compliant
+ 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));
@@ -448,7 +447,9 @@ void sis950_lpc_device::io_map(address_map &map)
NAME([this] (offs_t offset, u8 data) { m_dmac_slave->write( offset / 2, data ); })
);
- map(0x00e0, 0x00ef).noprw();
+ // map(0x00e0, 0x00ef) MCA bus (cfr. Bochs) or PnP
+ map(0x00eb, 0x00eb).lw8(NAME([] (offs_t offset, u8 data) { }));
+
// map(0x00f0, 0x00f0) COPRO error
// map(0x0480, 0x048f) DMA high page registers
// map(0x04d0, 0x04d1) IRQ edge/level control registers
@@ -479,6 +480,8 @@ void sis950_lpc_device::io_map(address_map &map)
// map(0x0278, 0x027f) parallel port 2 & PnP
// map(0x02e8, 0x02ef) serial 3
+ // unmap high: beos5 keeps PnP here for a COM3 that doesn't exist in shutms11
+ map(0x02e8, 0x02ef).lr8(NAME([] () { return 0xff; }));
// map(0x02f8, 0x02ff) serial 1
// map(0x0300, 0x0301) - MIDI ($330 as shutms11 default)
@@ -494,7 +497,7 @@ void sis950_lpc_device::io_map(address_map &map)
// 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(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) /
@@ -509,6 +512,8 @@ void sis950_lpc_device::io_map(address_map &map)
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)
{
+ m_isabus->remap(AS_PROGRAM, 0, 1 << 24);
+ m_isabus->remap(AS_IO, 0, 0xffff);
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);
@@ -571,6 +576,24 @@ void sis950_lpc_device::unmap_log_w(offs_t offset, u8 data)
}
/*
+ * IRQ sharing
+ */
+
+void sis950_lpc_device::pc_irq1_w(int state) { m_pic_master->ir1_w(state); }
+void sis950_lpc_device::pc_irq3_w(int state) { m_pic_master->ir3_w(state); }
+void sis950_lpc_device::pc_irq4_w(int state) { m_pic_master->ir4_w(state); }
+void sis950_lpc_device::pc_irq5_w(int state) { m_pic_master->ir5_w(state); }
+void sis950_lpc_device::pc_irq6_w(int state) { m_pic_master->ir6_w(state); }
+void sis950_lpc_device::pc_irq7_w(int state) { m_pic_master->ir7_w(state); }
+void sis950_lpc_device::pc_irq8n_w(int state) { m_pic_slave->ir0_w(state); }
+void sis950_lpc_device::pc_irq9_w(int state) { m_pic_slave->ir1_w(state); }
+void sis950_lpc_device::pc_irq10_w(int state) { m_pic_slave->ir2_w(state); }
+void sis950_lpc_device::pc_irq11_w(int state) { m_pic_slave->ir3_w(state); }
+void sis950_lpc_device::pc_irq12m_w(int state) { m_pic_slave->ir4_w(state); }
+void sis950_lpc_device::pc_irq14_w(int state) { m_pic_slave->ir6_w(state); }
+void sis950_lpc_device::pc_irq15_w(int state) { m_pic_slave->ir7_w(state); }
+
+/*
* Start of legacy handling, to be moved out
*/
@@ -710,14 +733,12 @@ void sis950_lpc_device::pc_dma_hrq_changed(int state)
m_dmac_slave->hack_w( state );
}
-#if 0
void sis950_lpc_device::iochck_w(int state)
{
// 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)
{