summaryrefslogtreecommitdiffstatshomepage
path: root/src/mess/drivers/wangpc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mess/drivers/wangpc.c')
-rw-r--r--src/mess/drivers/wangpc.c1310
1 files changed, 1310 insertions, 0 deletions
diff --git a/src/mess/drivers/wangpc.c b/src/mess/drivers/wangpc.c
new file mode 100644
index 00000000000..95b9d4e1cdc
--- /dev/null
+++ b/src/mess/drivers/wangpc.c
@@ -0,0 +1,1310 @@
+/*
+
+ Wang Professional Computer
+
+ http://www.seasip.info/VintagePC/wangpc.html
+
+ chdman -createblankhd q540.chd 512 8 17 512
+
+*/
+
+/*
+
+ TODO:
+
+ - hard disk
+
+*/
+
+#include "includes/wangpc.h"
+
+
+
+//**************************************************************************
+// MACROS/CONSTANTS
+//**************************************************************************
+
+#define LOG 0
+
+enum
+{
+ LED_DIAGNOSTIC = 0
+};
+
+
+
+//**************************************************************************
+// DIRECT MEMORY ACCESS
+//**************************************************************************
+
+void wangpc_state::select_drive(int drive, bool select)
+{
+ if (LOG) logerror("%s: %sselect drive %u\n", machine().describe_context(), select ? "" : "De", drive + 1);
+
+ int state = select ? 0 : 1;
+
+ if (!drive)
+ {
+ m_ds1 = state;
+ }
+ else
+ {
+ m_ds2 = state;
+ }
+}
+
+void wangpc_state::set_motor(int drive, bool motor)
+{
+ if (LOG) logerror("%s: Motor %u %s\n", machine().describe_context(), drive + 1, motor ? "on" : "off");
+
+ int state = motor ? 0 : 1;
+
+ if (!drive)
+ {
+ floppy_mon_w(m_floppy0, state);
+ }
+ else
+ {
+ floppy_mon_w(m_floppy1, state);
+ }
+}
+
+void wangpc_state::fdc_reset()
+{
+ if (LOG) logerror("%s: FDC reset\n", machine().describe_context());
+
+ upd765_reset_w(m_fdc, 1);
+ upd765_reset_w(m_fdc, 0);
+}
+
+void wangpc_state::fdc_tc()
+{
+ if (LOG) logerror("%s: FDC TC\n", machine().describe_context());
+
+ upd765_tc_w(m_fdc, 1);
+ upd765_tc_w(m_fdc, 0);
+}
+
+WRITE8_MEMBER( wangpc_state::fdc_ctrl_w )
+{
+ /*
+
+ bit description
+
+ 0 Enable /EOP
+ 1 Disable /DREQ2
+ 2 Clear drive 1 door disturbed interrupt
+ 3 Clear drive 2 door disturbed interrupt
+ 4
+ 5
+ 6
+ 7
+
+ */
+
+ m_enable_eop = BIT(data, 0);
+ m_disable_dreq2 = BIT(data, 1);
+
+ if (BIT(data, 2)) m_fdc_dd0 = 0;
+ if (BIT(data, 3)) m_fdc_dd1 = 0;
+
+ if (LOG)
+ {
+ logerror("%s: Enable /EOP %u\n", machine().describe_context(), m_enable_eop);
+ logerror("%s: Disable /DREQ2 %u\n", machine().describe_context(), m_disable_dreq2);
+ }
+
+ update_fdc_tc();
+ update_fdc_drq();
+}
+
+
+READ8_MEMBER( wangpc_state::deselect_drive1_r )
+{
+ select_drive(0, false);
+
+ return 0xff;
+}
+
+
+WRITE8_MEMBER( wangpc_state::deselect_drive1_w )
+{
+ select_drive(0, false);
+}
+
+
+READ8_MEMBER( wangpc_state::select_drive1_r )
+{
+ select_drive(0, true);
+
+ return 0xff;
+}
+
+
+WRITE8_MEMBER( wangpc_state::select_drive1_w )
+{
+ select_drive(0, true);
+}
+
+
+READ8_MEMBER( wangpc_state::deselect_drive2_r )
+{
+ select_drive(1, false);
+
+ return 0xff;
+}
+
+
+WRITE8_MEMBER( wangpc_state::deselect_drive2_w )
+{
+ select_drive(1, false);
+}
+
+
+READ8_MEMBER( wangpc_state::select_drive2_r )
+{
+ select_drive(1, true);
+
+ return 0xff;
+}
+
+
+WRITE8_MEMBER( wangpc_state::select_drive2_w )
+{
+ select_drive(1, true);
+}
+
+
+READ8_MEMBER( wangpc_state::motor1_off_r )
+{
+ set_motor(0, false);
+
+ return 0xff;
+}
+
+
+WRITE8_MEMBER( wangpc_state::motor1_off_w )
+{
+ set_motor(0, false);
+}
+
+
+READ8_MEMBER( wangpc_state::motor1_on_r )
+{
+ set_motor(0, true);
+
+ return 0xff;
+}
+
+
+WRITE8_MEMBER( wangpc_state::motor1_on_w )
+{
+ set_motor(0, true);
+}
+
+
+READ8_MEMBER( wangpc_state::motor2_off_r )
+{
+ set_motor(1, false);
+
+ return 0xff;
+}
+
+
+WRITE8_MEMBER( wangpc_state::motor2_off_w )
+{
+ set_motor(1, false);
+}
+
+
+READ8_MEMBER( wangpc_state::motor2_on_r )
+{
+ set_motor(1, true);
+
+ return 0xff;
+}
+
+
+WRITE8_MEMBER( wangpc_state::motor2_on_w )
+{
+ set_motor(1, true);
+}
+
+
+READ8_MEMBER( wangpc_state::fdc_reset_r )
+{
+ fdc_reset();
+
+ return 0xff;
+}
+
+
+WRITE8_MEMBER( wangpc_state::fdc_reset_w )
+{
+ fdc_reset();
+}
+
+
+READ8_MEMBER( wangpc_state::fdc_tc_r )
+{
+ fdc_tc();
+
+ return 0xff;
+}
+
+
+WRITE8_MEMBER( wangpc_state::fdc_tc_w )
+{
+ fdc_tc();
+}
+
+
+
+//-------------------------------------------------
+// dma_page_w -
+//-------------------------------------------------
+
+WRITE8_MEMBER( wangpc_state::dma_page_w )
+{
+ if (LOG) logerror("%s: DMA page %u: %06x\n", machine().describe_context(), offset + 1, (data & 0x0f) << 16);
+
+ m_dma_page[offset + 1] = data & 0x0f;
+}
+
+
+//-------------------------------------------------
+// status_r -
+//-------------------------------------------------
+
+READ8_MEMBER( wangpc_state::status_r )
+{
+ /*
+
+ bit description
+
+ 0 Memory Parity Flag
+ 1 I/O Error Flag
+ 2 Unassigned
+ 3 FDC Interrupt Flag
+ 4 Door disturbed on drive 1
+ 5 Door disturbed on drive 2
+ 6 Door open on drive 1
+ 7 Door open on drive 2
+
+ */
+
+ UINT8 data = 0x03;
+
+ // floppy interrupts
+ data |= upd765_int_r(m_fdc) << 3;
+ data |= m_fdc_dd0 << 4;
+ data |= m_fdc_dd1 << 5;
+ data |= m_floppy0->exists() ? 0 : 0x40;
+ data |= m_floppy1->exists() ? 0 : 0x80;
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// timer0_int_clr_w -
+//-------------------------------------------------
+
+WRITE8_MEMBER( wangpc_state::timer0_irq_clr_w )
+{
+ //if (LOG) logerror("%s: Timer 0 IRQ clear\n", machine().describe_context());
+
+ pic8259_ir0_w(m_pic, CLEAR_LINE);
+}
+
+
+//-------------------------------------------------
+// timer2_irq_clr_r -
+//-------------------------------------------------
+
+READ8_MEMBER( wangpc_state::timer2_irq_clr_r )
+{
+ //if (LOG) logerror("%s: Timer 2 IRQ clear\n", machine().describe_context());
+
+ m_timer2_irq = 1;
+ check_level1_interrupts();
+
+ return 0xff;
+}
+
+
+//-------------------------------------------------
+// nmi_mask_w -
+//-------------------------------------------------
+
+WRITE8_MEMBER( wangpc_state::nmi_mask_w )
+{
+ if (LOG) logerror("%s: NMI mask %02x\n", machine().describe_context(), data);
+}
+
+
+//-------------------------------------------------
+// led_on_r -
+//-------------------------------------------------
+
+READ8_MEMBER( wangpc_state::led_on_r )
+{
+ if (LOG) logerror("%s: Diagnostic LED on\n", machine().describe_context());
+
+ output_set_led_value(LED_DIAGNOSTIC, 1);
+
+ return 0xff;
+}
+
+
+//-------------------------------------------------
+// fpu_mask_w -
+//-------------------------------------------------
+
+WRITE8_MEMBER( wangpc_state::fpu_mask_w )
+{
+ if (LOG) logerror("%s: FPU mask %02x\n", machine().describe_context(), data);
+}
+
+
+//-------------------------------------------------
+// dma_eop_clr_r -
+//-------------------------------------------------
+
+READ8_MEMBER( wangpc_state::dma_eop_clr_r )
+{
+ if (LOG) logerror("%s: EOP clear\n", machine().describe_context());
+
+ m_dma_eop = 1;
+
+ check_level2_interrupts();
+
+ return 0xff;
+}
+
+
+//-------------------------------------------------
+// uart_tbre_clr_w -
+//-------------------------------------------------
+
+WRITE8_MEMBER( wangpc_state::uart_tbre_clr_w )
+{
+ if (LOG) logerror("%s: TBRE clear\n", machine().describe_context());
+
+ m_uart_tbre = 0;
+
+ check_level2_interrupts();
+}
+
+
+//-------------------------------------------------
+// uart_r -
+//-------------------------------------------------
+
+READ8_MEMBER( wangpc_state::uart_r )
+{
+ m_uart_dr = 0;
+
+ check_level2_interrupts();
+
+ UINT8 data = m_uart->read(space, 0);
+
+ if (LOG) logerror("%s: UART read %02x\n", machine().describe_context(), data);
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// uart_w -
+//-------------------------------------------------
+
+WRITE8_MEMBER( wangpc_state::uart_w )
+{
+ if (LOG) logerror("%s: UART write %02x\n", machine().describe_context(), data);
+
+ switch (data)
+ {
+ case 0x10: m_led[0] = 1; break;
+ case 0x11: m_led[0] = 0; break;
+ case 0x12: m_led[1] = 1; break;
+ case 0x13: m_led[1] = 0; break;
+ case 0x14: m_led[2] = 1; break;
+ case 0x15: m_led[2] = 0; break;
+ case 0x16: m_led[3] = 1; break;
+ case 0x17: m_led[3] = 0; break;
+ case 0x18: m_led[4] = 1; break;
+ case 0x19: m_led[4] = 0; break;
+ case 0x1a: m_led[5] = 1; break;
+ case 0x1b: m_led[5] = 0; break;
+ case 0x1c: m_led[0] = m_led[1] = m_led[2] = m_led[3] = m_led[4] = m_led[5] = 1; break;
+ case 0x1d: m_led[0] = m_led[1] = m_led[2] = m_led[3] = m_led[4] = m_led[5] = 0; break;
+ }
+
+ if (LOG) popmessage("%u%u%u%u%u%u", m_led[0], m_led[1], m_led[2], m_led[3], m_led[4], m_led[5]);
+
+ m_uart_tbre = 0;
+ check_level2_interrupts();
+
+ m_uart->write(space, 0, data);
+}
+
+
+//-------------------------------------------------
+// centronics_r -
+//-------------------------------------------------
+
+READ8_MEMBER( wangpc_state::centronics_r )
+{
+ m_dav = 1;
+ check_level1_interrupts();
+
+ return m_centronics->read(space, 0);
+}
+
+
+//-------------------------------------------------
+// centronics_w -
+//-------------------------------------------------
+
+WRITE8_MEMBER( wangpc_state::centronics_w )
+{
+ m_acknlg = 1;
+ check_level1_interrupts();
+
+ m_centronics->write(space, 0, data);
+
+ m_centronics->strobe_w(0);
+ m_centronics->strobe_w(1);
+}
+
+
+//-------------------------------------------------
+// busy_clr_r -
+//-------------------------------------------------
+
+READ8_MEMBER( wangpc_state::busy_clr_r )
+{
+ if (LOG) logerror("%s: BUSY clear\n", machine().describe_context());
+
+ m_busy = 1;
+ check_level1_interrupts();
+
+ return 0xff;
+}
+
+
+//-------------------------------------------------
+// acknlg_clr_w -
+//-------------------------------------------------
+
+WRITE8_MEMBER( wangpc_state::acknlg_clr_w )
+{
+ if (LOG) logerror("%s: ACKNLG clear\n", machine().describe_context());
+
+ m_acknlg = 1;
+ check_level1_interrupts();
+}
+
+
+//-------------------------------------------------
+// led_off_r -
+//-------------------------------------------------
+
+READ8_MEMBER( wangpc_state::led_off_r )
+{
+ if (LOG) logerror("%s: Diagnostic LED off\n", machine().describe_context());
+
+ output_set_led_value(LED_DIAGNOSTIC, 0);
+
+ return 0xff;
+}
+
+
+//-------------------------------------------------
+// parity_nmi_clr_w -
+//-------------------------------------------------
+
+WRITE8_MEMBER( wangpc_state::parity_nmi_clr_w )
+{
+ if (LOG) logerror("%s: Parity NMI clear\n", machine().describe_context());
+}
+
+
+//-------------------------------------------------
+// option_id_r -
+//-------------------------------------------------
+
+READ8_MEMBER( wangpc_state::option_id_r )
+{
+ /*
+
+ bit description
+
+ 0
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7 FDC Interrupt Flag
+
+ */
+
+ UINT8 data = 0;
+
+ // FDC interrupt
+ data |= (m_fdc_dd0 | m_fdc_dd1 | upd765_int_r(m_fdc)) << 7;
+
+ return data;
+}
+
+
+
+//**************************************************************************
+// ADDRESS MAPS
+//**************************************************************************
+
+//-------------------------------------------------
+// ADDRESS_MAP( wangpc_mem )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( wangpc_mem, AS_PROGRAM, 16, wangpc_state )
+ ADDRESS_MAP_UNMAP_HIGH
+ AM_RANGE(0x00000, 0x1ffff) AM_RAM
+ AM_RANGE(0x40000, 0xf3fff) AM_DEVREADWRITE(WANGPC_BUS_TAG, wangpcbus_device, mrdc_r, amwc_w)
+ AM_RANGE(0xfc000, 0xfffff) AM_ROM AM_REGION(I8086_TAG, 0)
+ADDRESS_MAP_END
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( wangpc_io )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( wangpc_io, AS_IO, 16, wangpc_state )
+ ADDRESS_MAP_UNMAP_HIGH
+ AM_RANGE(0x1000, 0x1001) AM_WRITE8(fdc_ctrl_w, 0x00ff)
+ AM_RANGE(0x1004, 0x1005) AM_READWRITE8(deselect_drive1_r, deselect_drive1_w, 0x00ff)
+ AM_RANGE(0x1006, 0x1007) AM_READWRITE8(select_drive1_r, select_drive1_w, 0x00ff)
+ AM_RANGE(0x1008, 0x1009) AM_READWRITE8(deselect_drive2_r, deselect_drive2_w, 0x00ff)
+ AM_RANGE(0x100a, 0x100b) AM_READWRITE8(select_drive2_r, select_drive2_w, 0x00ff)
+ AM_RANGE(0x100c, 0x100d) AM_READWRITE8(motor1_off_r, motor1_off_w, 0x00ff)
+ AM_RANGE(0x100e, 0x100f) AM_READWRITE8(motor1_on_r, motor1_on_w, 0x00ff)
+ AM_RANGE(0x1010, 0x1011) AM_READWRITE8(motor2_off_r, motor2_off_w, 0x00ff)
+ AM_RANGE(0x1012, 0x1013) AM_READWRITE8(motor2_on_r, motor2_on_w, 0x00ff)
+ AM_RANGE(0x1014, 0x1015) AM_DEVREAD8_LEGACY(UPD765_TAG, upd765_status_r, 0x00ff)
+ AM_RANGE(0x1016, 0x1017) AM_DEVREADWRITE8_LEGACY(UPD765_TAG, upd765_data_r, upd765_data_w, 0x00ff)
+ AM_RANGE(0x1018, 0x1019) AM_MIRROR(0x0002) AM_READWRITE8(fdc_reset_r, fdc_reset_w, 0x00ff)
+ AM_RANGE(0x101c, 0x101d) AM_MIRROR(0x0002) AM_READWRITE8(fdc_tc_r, fdc_tc_w, 0x00ff)
+ AM_RANGE(0x1020, 0x1027) AM_DEVREADWRITE8(I8255A_TAG, i8255_device, read, write, 0x00ff)
+ AM_RANGE(0x1028, 0x1029) //AM_WRITE(?)
+ AM_RANGE(0x1040, 0x1047) AM_DEVREADWRITE8_LEGACY(I8253_TAG, pit8253_r, pit8253_w, 0x00ff)
+ AM_RANGE(0x1060, 0x1063) AM_DEVREADWRITE8_LEGACY(I8259A_TAG, pic8259_r, pic8259_w, 0x00ff)
+ AM_RANGE(0x1080, 0x1087) AM_DEVREAD8(SCN2661_TAG, mc2661_device, read, 0x00ff)
+ AM_RANGE(0x1088, 0x108f) AM_DEVWRITE8(SCN2661_TAG, mc2661_device, write, 0x00ff)
+ AM_RANGE(0x10a0, 0x10bf) AM_DEVREADWRITE8(AM9517A_TAG, am9517a_device, read, write, 0x00ff)
+ AM_RANGE(0x10c2, 0x10c7) AM_WRITE8(dma_page_w, 0x00ff)
+ AM_RANGE(0x10e0, 0x10e1) AM_READWRITE8(status_r, timer0_irq_clr_w, 0x00ff)
+ AM_RANGE(0x10e2, 0x10e3) AM_READWRITE8(timer2_irq_clr_r, nmi_mask_w, 0x00ff)
+ AM_RANGE(0x10e4, 0x10e5) AM_READWRITE8(led_on_r, fpu_mask_w, 0x00ff)
+ AM_RANGE(0x10e6, 0x10e7) AM_READWRITE8(dma_eop_clr_r, uart_tbre_clr_w, 0x00ff)
+ AM_RANGE(0x10e8, 0x10e9) AM_READWRITE8(uart_r, uart_w, 0x00ff)
+ AM_RANGE(0x10ea, 0x10eb) AM_READWRITE8(centronics_r, centronics_w, 0x00ff)
+ AM_RANGE(0x10ec, 0x10ed) AM_READWRITE8(busy_clr_r, acknlg_clr_w, 0x00ff)
+ AM_RANGE(0x10ee, 0x10ef) AM_READWRITE8(led_off_r, parity_nmi_clr_w, 0x00ff)
+ AM_RANGE(0x10fe, 0x10ff) AM_READ8(option_id_r, 0x00ff)
+ AM_RANGE(0x1100, 0x1fff) AM_DEVREADWRITE(WANGPC_BUS_TAG, wangpcbus_device, sad_r, sad_w)
+ADDRESS_MAP_END
+
+
+
+//**************************************************************************
+// INPUT PORTS
+//**************************************************************************
+
+//-------------------------------------------------
+// INPUT_PORTS( wangpc )
+//-------------------------------------------------
+
+static INPUT_PORTS_START( wangpc )
+ // keyboard defined in machine/wangpckb.c
+
+ PORT_START("SW")
+ PORT_DIPNAME( 0x0f, 0x0f, "CPU Baud Rate" ) PORT_DIPLOCATION("SW:1,2,3,4")
+ PORT_DIPSETTING( 0x0f, "19200" )
+ PORT_DIPSETTING( 0x0e, "9600" )
+ PORT_DIPSETTING( 0x0d, "7200" )
+ PORT_DIPSETTING( 0x0c, "4800" )
+ PORT_DIPSETTING( 0x0b, "3600" )
+ PORT_DIPSETTING( 0x0a, "2400" )
+ PORT_DIPSETTING( 0x09, "2000" )
+ PORT_DIPSETTING( 0x08, "1800" )
+ PORT_DIPSETTING( 0x07, "1200" )
+ PORT_DIPSETTING( 0x06, "600" )
+ PORT_DIPSETTING( 0x05, "300" )
+ PORT_DIPSETTING( 0x04, "150" )
+ PORT_DIPSETTING( 0x03, "134.5" )
+ PORT_DIPSETTING( 0x02, "110" )
+ PORT_DIPSETTING( 0x01, "75" )
+ PORT_DIPSETTING( 0x00, "50 (Loop on Power-Up)" )
+INPUT_PORTS_END
+
+
+
+//**************************************************************************
+// DEVICE CONFIGURATION
+//**************************************************************************
+
+//-------------------------------------------------
+// I8237_INTERFACE( dmac_intf )
+//-------------------------------------------------
+
+void wangpc_state::update_fdc_tc()
+{
+ if (m_enable_eop)
+ upd765_tc_w(m_fdc, m_fdc_tc);
+ else
+ upd765_tc_w(m_fdc, 0);
+}
+
+WRITE_LINE_MEMBER( wangpc_state::hrq_w )
+{
+ m_maincpu->set_input_line(INPUT_LINE_HALT, state ? ASSERT_LINE : CLEAR_LINE);
+
+ m_dmac->hack_w(state);
+}
+
+WRITE_LINE_MEMBER( wangpc_state::eop_w )
+{
+ if (m_dack == 2)
+ {
+ m_fdc_tc = !state;
+ update_fdc_tc();
+ }
+
+ if (!state)
+ {
+ if (LOG) logerror("EOP set\n");
+
+ m_dma_eop = 0;
+ check_level2_interrupts();
+ }
+
+ m_bus->tc_w(state);
+}
+
+READ8_MEMBER( wangpc_state::memr_r )
+{
+ address_space *program = m_maincpu->memory().space(AS_PROGRAM);
+ offs_t addr = (m_dma_page[m_dack] << 16) | offset;
+
+ return program->read_byte(addr);
+}
+
+WRITE8_MEMBER( wangpc_state::memw_w )
+{
+ address_space *program = m_maincpu->memory().space(AS_PROGRAM);
+ offs_t addr = (m_dma_page[m_dack] << 16) | offset;
+
+ program->write_byte(addr, data);
+}
+
+READ8_MEMBER( wangpc_state::ior2_r )
+{
+ if (m_disable_dreq2)
+ return m_bus->dack_r(space, 2);
+ else
+ return upd765_dack_r(m_fdc, 0);
+}
+
+WRITE8_MEMBER( wangpc_state::iow2_w )
+{
+ if (m_disable_dreq2)
+ m_bus->dack_w(space, 2, data);
+ else
+ upd765_dack_w(m_fdc, 0, data);
+}
+
+WRITE_LINE_MEMBER( wangpc_state::dack0_w )
+{
+ if (!state) m_dack = 0;
+}
+
+WRITE_LINE_MEMBER( wangpc_state::dack1_w )
+{
+ if (!state) m_dack = 1;
+}
+
+WRITE_LINE_MEMBER( wangpc_state::dack2_w )
+{
+ if (!state) m_dack = 2;
+}
+
+WRITE_LINE_MEMBER( wangpc_state::dack3_w )
+{
+ if (!state) m_dack = 3;
+}
+
+static AM9517A_INTERFACE( dmac_intf )
+{
+ DEVCB_DRIVER_LINE_MEMBER(wangpc_state, hrq_w),
+ DEVCB_DRIVER_LINE_MEMBER(wangpc_state, eop_w),
+ DEVCB_DRIVER_MEMBER(wangpc_state, memr_r),
+ DEVCB_DRIVER_MEMBER(wangpc_state, memw_w),
+ { DEVCB_NULL,
+ DEVCB_DEVICE_MEMBER(WANGPC_BUS_TAG, wangpcbus_device, dack1_r),
+ DEVCB_DRIVER_MEMBER(wangpc_state, ior2_r),
+ DEVCB_DEVICE_MEMBER(WANGPC_BUS_TAG, wangpcbus_device, dack3_r) },
+ { DEVCB_NULL,
+ DEVCB_DEVICE_MEMBER(WANGPC_BUS_TAG, wangpcbus_device, dack1_w),
+ DEVCB_DRIVER_MEMBER(wangpc_state, iow2_w),
+ DEVCB_DEVICE_MEMBER(WANGPC_BUS_TAG, wangpcbus_device, dack3_w) },
+ { DEVCB_DRIVER_LINE_MEMBER(wangpc_state, dack0_w),
+ DEVCB_DRIVER_LINE_MEMBER(wangpc_state, dack1_w),
+ DEVCB_DRIVER_LINE_MEMBER(wangpc_state, dack2_w),
+ DEVCB_DRIVER_LINE_MEMBER(wangpc_state, dack3_w) }
+};
+
+
+//-------------------------------------------------
+// pic8259_interface pic_intf
+//-------------------------------------------------
+
+void wangpc_state::check_level1_interrupts()
+{
+ int state = !m_timer2_irq || m_epci->rxrdy_r() || m_epci->txemt_r() || !m_acknlg || !m_dav || !m_busy;
+
+ pic8259_ir1_w(m_pic, state);
+}
+
+void wangpc_state::check_level2_interrupts()
+{
+ int state = !m_dma_eop || m_uart_dr || m_uart_tbre || m_fdc_dd0 || m_fdc_dd1 || upd765_int_r(m_fdc) || m_fpu_irq || m_bus_irq2;
+
+ pic8259_ir2_w(m_pic, state);
+}
+
+static IRQ_CALLBACK( wangpc_irq_callback )
+{
+ wangpc_state *state = device->machine().driver_data<wangpc_state>();
+
+ return pic8259_acknowledge(state->m_pic);
+}
+
+static const struct pic8259_interface pic_intf =
+{
+ DEVCB_CPU_INPUT_LINE(I8086_TAG, INPUT_LINE_IRQ0),
+ DEVCB_LINE_VCC,
+ DEVCB_NULL
+};
+
+
+//-------------------------------------------------
+// I8255A_INTERFACE( ppi_intf )
+//-------------------------------------------------
+
+READ8_MEMBER( wangpc_state::ppi_pa_r )
+{
+ /*
+
+ bit description
+
+ 0 /POWER ON
+ 1 /SMART
+ 2 /DATA AVAILABLE
+ 3 SLCT
+ 4 BUSY
+ 5 /FAULT
+ 6 PE
+ 7 ACKNOWLEDGE
+
+ */
+
+ UINT8 data = 0x08 | 0x02 | 0x01;
+
+ data |= m_dav << 2;
+ data |= m_centronics->busy_r() << 4;
+ data |= m_centronics->fault_r() << 5;
+ data |= m_centronics->pe_r() << 6;
+ data |= m_acknlg << 7;
+
+ return data;
+}
+
+READ8_MEMBER( wangpc_state::ppi_pb_r )
+{
+ /*
+
+ bit description
+
+ 0 /TIMER 2 INTERRUPT
+ 1 /SERIAL INTERRUPT
+ 2 /PARALLEL PORT INTERRUPT
+ 3 /DMA INTERRUPT
+ 4 KBD INTERRUPT TRANSMIT
+ 5 KBD INTERRUPT RECEIVE
+ 6 FLOPPY DISK INTERRUPT
+ 7 8087 INTERRUPT
+
+ */
+
+ UINT8 data = 0;
+
+ // timer 2 interrupt
+ data |= m_timer2_irq;
+
+ // serial interrupt
+ data |= !(m_epci->rxrdy_r() | m_epci->txemt_r()) << 1;
+
+ // parallel port interrupt
+ data |= m_acknlg << 2;
+
+ // DMA interrupt
+ data |= m_dma_eop << 3;
+
+ // keyboard interrupt
+ data |= m_uart_tbre << 4;
+ data |= m_uart_dr << 5;
+
+ // FDC interrupt
+ data |= upd765_int_r(m_fdc) << 6;
+
+ // 8087 interrupt
+ data |= m_fpu_irq << 7;
+
+ return data;
+}
+
+READ8_MEMBER( wangpc_state::ppi_pc_r )
+{
+ /*
+
+ bit description
+
+ 0
+ 1
+ 2
+ 3
+ 4 SW1
+ 5 SW2
+ 6 SW3
+ 7 SW4
+
+ */
+
+ return ioport("SW")->read() << 4;
+}
+
+WRITE8_MEMBER( wangpc_state::ppi_pc_w )
+{
+ /*
+
+ bit description
+
+ 0 /USR0 (pin 14)
+ 1 /USR1 (pin 36)
+ 2 /RESET (pin 31)
+ 3 Unassigned
+ 4
+ 5
+ 6
+ 7
+
+ */
+
+ m_centronics->autofeed_w(BIT(data, 0));
+ m_centronics->init_prime_w(BIT(data, 2));
+}
+
+static I8255A_INTERFACE( ppi_intf )
+{
+ DEVCB_DRIVER_MEMBER(wangpc_state, ppi_pa_r),
+ DEVCB_NULL,
+ DEVCB_DRIVER_MEMBER(wangpc_state, ppi_pb_r),
+ DEVCB_NULL,
+ DEVCB_DRIVER_MEMBER(wangpc_state, ppi_pc_r),
+ DEVCB_DRIVER_MEMBER(wangpc_state, ppi_pc_w)
+};
+
+
+//-------------------------------------------------
+// pit8253_config pit_intf
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( wangpc_state::pit2_w )
+{
+ if (state)
+ {
+ m_timer2_irq = 0;
+ check_level1_interrupts();
+ }
+}
+
+static const struct pit8253_config pit_intf =
+{
+ {
+ {
+ 500000,
+ DEVCB_LINE_VCC,
+ DEVCB_DEVICE_LINE(I8259A_TAG, pic8259_ir0_w)
+ }, {
+ 2000000,
+ DEVCB_LINE_VCC,
+ DEVCB_NULL
+ }, {
+ 500000,
+ DEVCB_LINE_VCC,
+ DEVCB_DRIVER_LINE_MEMBER(wangpc_state, pit2_w)
+ }
+ }
+};
+
+
+//-------------------------------------------------
+// IM6402_INTERFACE( uart_intf )
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( wangpc_state::uart_dr_w )
+{
+ if (state)
+ {
+ if (LOG) logerror("DR set\n");
+
+ m_uart_dr = 1;
+ check_level2_interrupts();
+ }
+}
+
+WRITE_LINE_MEMBER( wangpc_state::uart_tbre_w )
+{
+ if (state)
+ {
+ if (LOG) logerror("TBRE set\n");
+
+ m_uart_tbre = 1;
+ check_level2_interrupts();
+ }
+}
+
+static IM6402_INTERFACE( uart_intf )
+{
+ 0, // HACK should be 62500
+ 62500,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_DRIVER_LINE_MEMBER(wangpc_state, uart_dr_w),
+ DEVCB_DRIVER_LINE_MEMBER(wangpc_state, uart_tbre_w),
+ DEVCB_NULL
+};
+
+
+//-------------------------------------------------
+// SCN2661_INTERFACE( epci_intf )
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( wangpc_state::epci_irq_w )
+{
+ check_level1_interrupts();
+}
+
+static MC2661_INTERFACE( epci_intf )
+{
+ 0,
+ 0,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_DRIVER_LINE_MEMBER(wangpc_state, epci_irq_w),
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_DRIVER_LINE_MEMBER(wangpc_state, epci_irq_w),
+ DEVCB_NULL,
+ DEVCB_NULL
+};
+
+
+//-------------------------------------------------
+// upd765_interface fdc_intf
+//-------------------------------------------------
+
+static const floppy_interface floppy_intf =
+{
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ FLOPPY_STANDARD_5_25_DSDD,
+ LEGACY_FLOPPY_OPTIONS_NAME(pc),
+ "floppy_5_25",
+ NULL
+};
+
+WRITE_LINE_MEMBER( wangpc_state::fdc_int_w )
+{
+ if (LOG) logerror("FDC INT %u\n", state);
+
+ check_level2_interrupts();
+}
+
+WRITE_LINE_MEMBER( wangpc_state::fdc_drq_w )
+{
+ if (LOG) logerror("FDC DRQ %u\n", state);
+
+ m_fdc_drq = state;
+ update_fdc_drq();
+}
+
+void wangpc_state::update_fdc_drq()
+{
+ if (m_disable_dreq2)
+ m_dmac->dreq2_w(1);
+ else
+ m_dmac->dreq2_w(!m_fdc_drq);
+}
+
+static UPD765_GET_IMAGE( wangpc_fdc_get_image )
+{
+ wangpc_state *state = device->machine().driver_data<wangpc_state>();
+
+ if (!state->m_ds1) return state->m_floppy0;
+ if (!state->m_ds2) return state->m_floppy1;
+
+ return NULL;
+}
+
+static const upd765_interface fdc_intf =
+{
+ DEVCB_DRIVER_LINE_MEMBER(wangpc_state, fdc_int_w),
+ DEVCB_DRIVER_LINE_MEMBER(wangpc_state, fdc_drq_w),
+ wangpc_fdc_get_image,
+ UPD765_RDY_PIN_NOT_CONNECTED,
+ { NULL, NULL, NULL, NULL }
+};
+
+
+//-------------------------------------------------
+// centronics_interface centronics_intf
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( wangpc_state::ack_w )
+{
+ if (LOG) logerror("ACKNLG %u\n", state);
+
+ m_acknlg = state;
+
+ check_level1_interrupts();
+}
+
+WRITE_LINE_MEMBER( wangpc_state::busy_w )
+{
+ if (LOG) logerror("BUSY %u\n", state);
+
+ m_busy = state;
+
+ check_level1_interrupts();
+}
+
+static const centronics_interface centronics_intf =
+{
+ DEVCB_DRIVER_LINE_MEMBER(wangpc_state, ack_w),
+ DEVCB_DRIVER_LINE_MEMBER(wangpc_state, busy_w),
+ DEVCB_NULL
+};
+
+
+//-------------------------------------------------
+// WANGPC_BUS_INTERFACE( kb_intf )
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( wangpc_state::bus_irq2_w )
+{
+ if (LOG) logerror("Bus IRQ2 %u\n", state);
+
+ m_bus_irq2 = state;
+
+ check_level2_interrupts();
+}
+
+static WANGPC_BUS_INTERFACE( bus_intf )
+{
+ DEVCB_DRIVER_LINE_MEMBER(wangpc_state, bus_irq2_w),
+ DEVCB_DEVICE_LINE(I8259A_TAG, pic8259_ir3_w),
+ DEVCB_DEVICE_LINE(I8259A_TAG, pic8259_ir4_w),
+ DEVCB_DEVICE_LINE(I8259A_TAG, pic8259_ir5_w),
+ DEVCB_DEVICE_LINE(I8259A_TAG, pic8259_ir6_w),
+ DEVCB_DEVICE_LINE(I8259A_TAG, pic8259_ir7_w),
+ DEVCB_DEVICE_LINE_MEMBER(AM9517A_TAG, am9517a_device, dreq1_w),
+ DEVCB_DEVICE_LINE_MEMBER(AM9517A_TAG, am9517a_device, dreq2_w),
+ DEVCB_DEVICE_LINE_MEMBER(AM9517A_TAG, am9517a_device, dreq3_w),
+ DEVCB_CPU_INPUT_LINE(I8086_TAG, INPUT_LINE_NMI)
+};
+
+static SLOT_INTERFACE_START( wangpc_cards )
+ SLOT_INTERFACE("emb", WANGPC_EMB) // extended memory board
+ SLOT_INTERFACE("lic", WANGPC_LIC) // local interconnect option card
+ SLOT_INTERFACE("lvc", WANGPC_LVC) // low-resolution video controller
+ SLOT_INTERFACE("mcc", WANGPC_MCC) // multiport communications controller
+ SLOT_INTERFACE("mvc", WANGPC_MVC) // medium-resolution video controller
+ SLOT_INTERFACE("rtc", WANGPC_RTC) // remote telecommunications controller
+ SLOT_INTERFACE("tig", WANGPC_TIG) // text/image/graphics controller
+ SLOT_INTERFACE("wdc", WANGPC_WDC) // Winchester disk controller
+SLOT_INTERFACE_END
+
+
+
+//**************************************************************************
+// MACHINE INITIALIZATION
+//**************************************************************************
+
+//-------------------------------------------------
+// MACHINE_START( wangpc )
+//-------------------------------------------------
+
+void wangpc_state::machine_start()
+{
+ // register CPU IRQ callback
+ device_set_irq_callback(m_maincpu, wangpc_irq_callback);
+
+ // connect serial keyboard
+ m_uart->connect(m_kb);
+
+ // connect floppy callbacks
+ floppy_install_unload_proc(m_floppy0, wangpc_state::on_disk0_change);
+ floppy_install_load_proc(m_floppy0, wangpc_state::on_disk0_change);
+ floppy_install_unload_proc(m_floppy1, wangpc_state::on_disk1_change);
+ floppy_install_load_proc(m_floppy1, wangpc_state::on_disk1_change);
+
+ // state saving
+ save_item(NAME(m_dma_page));
+ save_item(NAME(m_dack));
+ save_item(NAME(m_timer2_irq));
+ save_item(NAME(m_acknlg));
+ save_item(NAME(m_dav));
+ save_item(NAME(m_busy));
+ save_item(NAME(m_dma_eop));
+ save_item(NAME(m_uart_dr));
+ save_item(NAME(m_uart_tbre));
+ save_item(NAME(m_fpu_irq));
+ save_item(NAME(m_bus_irq2));
+ save_item(NAME(m_enable_eop));
+ save_item(NAME(m_disable_dreq2));
+ save_item(NAME(m_fdc_drq));
+ save_item(NAME(m_ds1));
+ save_item(NAME(m_ds2));
+}
+
+
+//-------------------------------------------------
+// MACHINE_RESET( wangpc )
+//-------------------------------------------------
+
+void wangpc_state::machine_reset()
+{
+ // initialize UART
+ m_uart->cls1_w(1);
+ m_uart->cls2_w(1);
+ m_uart->pi_w(1);
+ m_uart->sbs_w(1);
+ m_uart->crl_w(1);
+}
+
+
+//-------------------------------------------------
+// on_disk0_change -
+//-------------------------------------------------
+
+void wangpc_state::on_disk0_change(device_image_interface &image)
+{
+ wangpc_state *state = static_cast<wangpc_state *>(image.device().owner());
+
+ if (LOG) logerror("Door 1 disturbed\n");
+
+ state->m_fdc_dd0 = 1;
+
+ state->check_level2_interrupts();
+}
+
+
+//-------------------------------------------------
+// on_disk1_change -
+//-------------------------------------------------
+
+void wangpc_state::on_disk1_change(device_image_interface &image)
+{
+ wangpc_state *state = static_cast<wangpc_state *>(image.device().owner());
+
+ if (LOG) logerror("Door 2 disturbed\n");
+
+ state->m_fdc_dd1 = 1;
+
+ state->check_level2_interrupts();
+}
+
+
+
+//**************************************************************************
+// MACHINE DRIVERS
+//**************************************************************************
+
+//-------------------------------------------------
+// MACHINE_CONFIG( wangpc )
+//-------------------------------------------------
+
+static MACHINE_CONFIG_START( wangpc, wangpc_state )
+ MCFG_CPU_ADD(I8086_TAG, I8086, 8000000)
+ MCFG_CPU_PROGRAM_MAP(wangpc_mem)
+ MCFG_CPU_IO_MAP(wangpc_io)
+
+ // devices
+ MCFG_AM9517A_ADD(AM9517A_TAG, 4000000, dmac_intf)
+ MCFG_PIC8259_ADD(I8259A_TAG, pic_intf)
+ MCFG_I8255A_ADD(I8255A_TAG, ppi_intf)
+ MCFG_PIT8253_ADD(I8253_TAG, pit_intf)
+ MCFG_IM6402_ADD(IM6402_TAG, uart_intf)
+ MCFG_MC2661_ADD(SCN2661_TAG, 0, epci_intf)
+ MCFG_UPD765A_ADD(UPD765_TAG, fdc_intf)
+ MCFG_LEGACY_FLOPPY_2_DRIVES_ADD(floppy_intf)
+ MCFG_CENTRONICS_PRINTER_ADD(CENTRONICS_TAG, centronics_intf)
+ MCFG_WANGPC_KEYBOARD_ADD()
+
+ // bus
+ MCFG_WANGPC_BUS_ADD(bus_intf)
+ MCFG_WANGPC_BUS_SLOT_ADD("slot1", 1, wangpc_cards, NULL, NULL)
+ MCFG_WANGPC_BUS_SLOT_ADD("slot2", 2, wangpc_cards, "lvc", NULL)
+ MCFG_WANGPC_BUS_SLOT_ADD("slot3", 3, wangpc_cards, NULL, NULL)
+ MCFG_WANGPC_BUS_SLOT_ADD("slot4", 4, wangpc_cards, NULL, NULL)
+ MCFG_WANGPC_BUS_SLOT_ADD("slot5", 5, wangpc_cards, NULL, NULL)
+
+ // internal ram
+ MCFG_RAM_ADD(RAM_TAG)
+ MCFG_RAM_DEFAULT_SIZE("128K")
+
+ // software list
+ MCFG_SOFTWARE_LIST_ADD("flop_list", "wangpc")
+MACHINE_CONFIG_END
+
+
+
+//**************************************************************************
+// ROM DEFINITIONS
+//**************************************************************************
+
+//-------------------------------------------------
+// ROM( wangpc )
+//-------------------------------------------------
+
+ROM_START( wangpc )
+ ROM_REGION16_LE( 0x4000, I8086_TAG, 0)
+ ROM_LOAD16_BYTE( "0001 r2.l94", 0x0001, 0x2000, CRC(f9f41304) SHA1(1815295809ef11573d724ede47446f9ac7aee713) )
+ ROM_LOAD16_BYTE( "379-0000 r2.l115", 0x0000, 0x2000, CRC(67b37684) SHA1(70d9f68eb88cc2bc9f53f949cc77411c09a4266e) )
+ROM_END
+
+
+
+//**************************************************************************
+// GAME DRIVERS
+//**************************************************************************
+
+COMP( 1985, wangpc, 0, 0, wangpc, wangpc, driver_device, 0, "Wang Laboratories", "Wang Professional Computer", GAME_SUPPORTS_SAVE )