summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/bus/scsi
diff options
context:
space:
mode:
author smf- <smf-@users.noreply.github.com>2014-04-14 11:50:39 +0000
committer smf- <smf-@users.noreply.github.com>2014-04-14 11:50:39 +0000
commita039e59ae2be4a92be8afae9018f481f2ff14f3e (patch)
tree280d142f4620c02e4a734f04a837485940841b18 /src/emu/bus/scsi
parent51360b13702d031b1d1c764e044209d43f24a6a0 (diff)
SCSI Port using WRITELINE and DEVCB2. The slot number and SCSI ID are separate so you can for example have -harddisk1 as ID 6 and -harddisk 2 as ID 5. The HLE'd CD & HD have configuration switches to set the ID, real emulated hardware will specify the ID using it's own method. [smf]
Diffstat (limited to 'src/emu/bus/scsi')
-rw-r--r--src/emu/bus/scsi/acb4070.c1
-rw-r--r--src/emu/bus/scsi/acb4070.h2
-rw-r--r--src/emu/bus/scsi/cdu76s.c45
-rw-r--r--src/emu/bus/scsi/cdu76s.h32
-rw-r--r--src/emu/bus/scsi/d9060hd.c1
-rw-r--r--src/emu/bus/scsi/d9060hd.h2
-rw-r--r--src/emu/bus/scsi/s1410.c1
-rw-r--r--src/emu/bus/scsi/s1410.h3
-rw-r--r--src/emu/bus/scsi/sa1403d.h3
-rw-r--r--src/emu/bus/scsi/scsi.c690
-rw-r--r--src/emu/bus/scsi/scsi.h313
-rw-r--r--src/emu/bus/scsi/scsicd.c42
-rw-r--r--src/emu/bus/scsi/scsicd.h33
-rw-r--r--src/emu/bus/scsi/scsihd.c40
-rw-r--r--src/emu/bus/scsi/scsihd.h33
-rw-r--r--src/emu/bus/scsi/scsihle.c590
-rw-r--r--src/emu/bus/scsi/scsihle.h91
17 files changed, 1913 insertions, 9 deletions
diff --git a/src/emu/bus/scsi/acb4070.c b/src/emu/bus/scsi/acb4070.c
index f24ab4247a6..52ed15ef339 100644
--- a/src/emu/bus/scsi/acb4070.c
+++ b/src/emu/bus/scsi/acb4070.c
@@ -3,7 +3,6 @@
*
*/
-#include "emu.h"
#include "acb4070.h"
// device type definition
diff --git a/src/emu/bus/scsi/acb4070.h b/src/emu/bus/scsi/acb4070.h
index 0064b3175ee..8c90d2aab74 100644
--- a/src/emu/bus/scsi/acb4070.h
+++ b/src/emu/bus/scsi/acb4070.h
@@ -3,7 +3,7 @@
#ifndef __ACB4070__
#define __ACB4070__
-#include "machine/scsihd.h"
+#include "scsihd.h"
class acb4070_device : public scsihd_device
{
diff --git a/src/emu/bus/scsi/cdu76s.c b/src/emu/bus/scsi/cdu76s.c
new file mode 100644
index 00000000000..943fe831de0
--- /dev/null
+++ b/src/emu/bus/scsi/cdu76s.c
@@ -0,0 +1,45 @@
+#include "cdu76s.h"
+
+void sony_cdu76s_device::ExecCommand()
+{
+ switch ( command[0] )
+ {
+ case 0x12: // INQUIRY
+ logerror("CDU76S: INQUIRY\n");
+ m_phase = SCSI_PHASE_DATAIN;
+ m_status_code = SCSI_STATUS_CODE_GOOD;
+ m_transfer_length = SCSILengthFromUINT8( &command[ 4 ] );
+ break;
+ }
+}
+
+void sony_cdu76s_device::ReadData( UINT8 *data, int dataLength )
+{
+ switch ( command[0] )
+ {
+ case 0x12: // INQUIRY
+ memset( data, 0, dataLength );
+ data[0] = 0x05; // device is present, device is CD/DVD (MMC-3)
+ data[1] = 0x80; // media is removable
+ data[2] = 0x05; // device complies with SPC-3 standard
+ data[3] = 0x02; // response data format = SPC-3 standard
+ // some Konami games freak out if this isn't "Sony", so we'll lie
+ // this is the actual drive on my Nagano '98 board
+ strcpy((char *)&data[8], "Sony");
+ strcpy((char *)&data[16], "CDU-76S");
+ strcpy((char *)&data[32], "1.0");
+ break;
+
+ default:
+ scsicd_device::ReadData( data, dataLength );
+ break;
+ }
+}
+
+// device type definition
+const device_type CDU76S = &device_creator<sony_cdu76s_device>;
+
+sony_cdu76s_device::sony_cdu76s_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ scsicd_device(mconfig, CDU76S, "Sony CDU-76S", tag, owner, clock, "cdu76s", __FILE__)
+{
+}
diff --git a/src/emu/bus/scsi/cdu76s.h b/src/emu/bus/scsi/cdu76s.h
new file mode 100644
index 00000000000..83c8f07dfe2
--- /dev/null
+++ b/src/emu/bus/scsi/cdu76s.h
@@ -0,0 +1,32 @@
+/***************************************************************************
+
+ cdu76s.h
+
+ Sony CDU-76S
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __CDU76S_H__
+#define __CDU76S_H__
+
+#include "scsicd.h"
+#include "machine/t10mmc.h"
+
+class sony_cdu76s_device : public scsicd_device
+{
+public:
+ sony_cdu76s_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ virtual void ExecCommand();
+ virtual void ReadData( UINT8 *data, int dataLength );
+};
+
+// device type definition
+extern const device_type CDU76S;
+
+#endif
diff --git a/src/emu/bus/scsi/d9060hd.c b/src/emu/bus/scsi/d9060hd.c
index fdf966b0d36..1b9413d8e68 100644
--- a/src/emu/bus/scsi/d9060hd.c
+++ b/src/emu/bus/scsi/d9060hd.c
@@ -3,7 +3,6 @@
*
*/
-#include "emu.h"
#include "d9060hd.h"
// device type definition
diff --git a/src/emu/bus/scsi/d9060hd.h b/src/emu/bus/scsi/d9060hd.h
index e17e2238fe6..fd87746f6f1 100644
--- a/src/emu/bus/scsi/d9060hd.h
+++ b/src/emu/bus/scsi/d9060hd.h
@@ -3,7 +3,7 @@
#ifndef __D9060HD__
#define __D9060HD__
-#include "machine/scsihd.h"
+#include "scsihd.h"
class d9060hd_device : public scsihd_device
{
diff --git a/src/emu/bus/scsi/s1410.c b/src/emu/bus/scsi/s1410.c
index 195be0c04f5..35e62e161f9 100644
--- a/src/emu/bus/scsi/s1410.c
+++ b/src/emu/bus/scsi/s1410.c
@@ -86,7 +86,6 @@ Notes:
*/
-#include "emu.h"
#include "s1410.h"
#include "cpu/z80/z80.h"
#include "imagedev/harddriv.h"
diff --git a/src/emu/bus/scsi/s1410.h b/src/emu/bus/scsi/s1410.h
index 9985c10d405..d392ef93270 100644
--- a/src/emu/bus/scsi/s1410.h
+++ b/src/emu/bus/scsi/s1410.h
@@ -14,8 +14,7 @@
#ifndef __S1410__
#define __S1410__
-#include "emu.h"
-#include "machine/scsihd.h"
+#include "scsihd.h"
class s1410_device : public scsihd_device
{
diff --git a/src/emu/bus/scsi/sa1403d.h b/src/emu/bus/scsi/sa1403d.h
index ec4548ee9c3..44897e7156a 100644
--- a/src/emu/bus/scsi/sa1403d.h
+++ b/src/emu/bus/scsi/sa1403d.h
@@ -14,9 +14,8 @@
#ifndef __SA1403D__
#define __SA1403D__
-#include "emu.h"
+#include "scsihd.h"
#include "imagedev/harddriv.h"
-#include "machine/scsihd.h"
class sa1403d_device : public scsihd_device
{
diff --git a/src/emu/bus/scsi/scsi.c b/src/emu/bus/scsi/scsi.c
new file mode 100644
index 00000000000..13b730c3422
--- /dev/null
+++ b/src/emu/bus/scsi/scsi.c
@@ -0,0 +1,690 @@
+// license:MAME
+// copyright-holders:smf
+
+#include "scsi.h"
+
+SCSI_PORT_DEVICE::SCSI_PORT_DEVICE(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, SCSI_PORT, "SCSI Port", tag, owner, clock, "scsi", __FILE__),
+ m_bsy_handler(*this),
+ m_sel_handler(*this),
+ m_cd_handler(*this),
+ m_io_handler(*this),
+ m_msg_handler(*this),
+ m_req_handler(*this),
+ m_ack_handler(*this),
+ m_atn_handler(*this),
+ m_rst_handler(*this),
+ m_data0_handler(*this),
+ m_data1_handler(*this),
+ m_data2_handler(*this),
+ m_data3_handler(*this),
+ m_data4_handler(*this),
+ m_data5_handler(*this),
+ m_data6_handler(*this),
+ m_data7_handler(*this),
+ m_bsy_in(0),
+ m_sel_in(0),
+ m_cd_in(0),
+ m_io_in(0),
+ m_msg_in(0),
+ m_req_in(0),
+ m_ack_in(0),
+ m_rst_in(0),
+ m_data0_in(0),
+ m_data1_in(0),
+ m_data2_in(0),
+ m_data3_in(0),
+ m_data4_in(0),
+ m_data5_in(0),
+ m_data6_in(0),
+ m_data7_in(0),
+ m_bsy_out(0),
+ m_sel_out(0),
+ m_cd_out(0),
+ m_io_out(0),
+ m_msg_out(0),
+ m_req_out(0),
+ m_ack_out(0),
+ m_rst_out(0),
+ m_data0_out(0),
+ m_data1_out(0),
+ m_data2_out(0),
+ m_data3_out(0),
+ m_data4_out(0),
+ m_data5_out(0),
+ m_data6_out(0),
+ m_data7_out(0)
+{
+}
+
+static MACHINE_CONFIG_FRAGMENT( scsi_port )
+ MCFG_DEVICE_ADD( SCSI_PORT_DEVICE1, SCSI_PORT_SLOT, 0 )
+ MCFG_DEVICE_ADD( SCSI_PORT_DEVICE2, SCSI_PORT_SLOT, 0 )
+ MCFG_DEVICE_ADD( SCSI_PORT_DEVICE3, SCSI_PORT_SLOT, 0 )
+ MCFG_DEVICE_ADD( SCSI_PORT_DEVICE4, SCSI_PORT_SLOT, 0 )
+ MCFG_DEVICE_ADD( SCSI_PORT_DEVICE5, SCSI_PORT_SLOT, 0 )
+ MCFG_DEVICE_ADD( SCSI_PORT_DEVICE6, SCSI_PORT_SLOT, 0 )
+ MCFG_DEVICE_ADD( SCSI_PORT_DEVICE7, SCSI_PORT_SLOT, 0 )
+MACHINE_CONFIG_END
+
+machine_config_constructor SCSI_PORT_DEVICE::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( scsi_port );
+}
+
+void SCSI_PORT_DEVICE::device_start()
+{
+ const char *deviceName[] =
+ {
+ SCSI_PORT_DEVICE1,
+ SCSI_PORT_DEVICE2,
+ SCSI_PORT_DEVICE3,
+ SCSI_PORT_DEVICE4,
+ SCSI_PORT_DEVICE5,
+ SCSI_PORT_DEVICE6,
+ SCSI_PORT_DEVICE7
+ };
+
+ m_device_count = 0;
+
+ for (int i = 0; i < 7; i++)
+ {
+ SCSI_PORT_SLOT_device *slot = subdevice<SCSI_PORT_SLOT_device>(deviceName[i]);
+ m_slot[i] = slot;
+
+ if (slot != NULL)
+ m_device_count = i + 1;
+ }
+
+ m_bsy_handler.resolve_safe();
+ m_sel_handler.resolve_safe();
+ m_cd_handler.resolve_safe();
+ m_io_handler.resolve_safe();
+ m_msg_handler.resolve_safe();
+ m_req_handler.resolve_safe();
+ m_ack_handler.resolve_safe();
+ m_atn_handler.resolve_safe();
+ m_rst_handler.resolve_safe();
+ m_data0_handler.resolve_safe();
+ m_data1_handler.resolve_safe();
+ m_data2_handler.resolve_safe();
+ m_data3_handler.resolve_safe();
+ m_data4_handler.resolve_safe();
+ m_data5_handler.resolve_safe();
+ m_data6_handler.resolve_safe();
+ m_data7_handler.resolve_safe();
+}
+
+void SCSI_PORT_DEVICE::update_bsy()
+{
+ int bsy = m_bsy_in;
+ for (int i = 0; i < m_device_count; i++)
+ {
+ bsy |= m_slot[i]->m_bsy;
+ }
+
+ if (m_bsy_out != bsy)
+ {
+ m_bsy_out = bsy;
+ m_bsy_handler(bsy);
+
+ for (int i = 0; i < m_device_count; i++)
+ {
+ scsi_port_interface *dev = m_slot[i]->dev();
+ if (dev != NULL)
+ dev->input_bsy(bsy);
+ }
+ }
+}
+
+void SCSI_PORT_DEVICE::update_sel()
+{
+ int sel = m_sel_in;
+ for (int i = 0; i < m_device_count; i++)
+ {
+ sel |= m_slot[i]->m_sel;
+ }
+
+ if (m_sel_out != sel)
+ {
+ m_sel_out = sel;
+ m_sel_handler(sel);
+
+ for (int i = 0; i < m_device_count; i++)
+ {
+ scsi_port_interface *dev = m_slot[i]->dev();
+ if (dev != NULL)
+ dev->input_sel(sel);
+ }
+ }
+}
+
+void SCSI_PORT_DEVICE::update_cd()
+{
+ int cd = m_cd_in;
+ for (int i = 0; i < m_device_count; i++)
+ {
+ cd |= m_slot[i]->m_cd;
+ }
+
+ if (m_cd_out != cd)
+ {
+ m_cd_out = cd;
+ m_cd_handler(cd);
+
+ for (int i = 0; i < m_device_count; i++)
+ {
+ scsi_port_interface *dev = m_slot[i]->dev();
+ if (dev != NULL)
+ dev->input_cd(cd);
+ }
+ }
+}
+
+void SCSI_PORT_DEVICE::update_io()
+{
+ int io = m_io_in;
+ for (int i = 0; i < m_device_count; i++)
+ {
+ io |= m_slot[i]->m_io;
+ }
+
+ if (m_io_out != io)
+ {
+ m_io_out = io;
+ m_io_handler(io);
+
+ for (int i = 0; i < m_device_count; i++)
+ {
+ scsi_port_interface *dev = m_slot[i]->dev();
+ if (dev != NULL)
+ dev->input_io(io);
+ }
+ }
+}
+
+void SCSI_PORT_DEVICE::update_msg()
+{
+ int msg = m_msg_in;
+ for (int i = 0; i < m_device_count; i++)
+ {
+ msg |= m_slot[i]->m_msg;
+ }
+
+ if (m_msg_out != msg)
+ {
+ m_msg_out = msg;
+ m_msg_handler(msg);
+
+ for (int i = 0; i < m_device_count; i++)
+ {
+ scsi_port_interface *dev = m_slot[i]->dev();
+ if (dev != NULL)
+ dev->input_msg(msg);
+ }
+ }
+}
+
+void SCSI_PORT_DEVICE::update_req()
+{
+ int req = m_req_in;
+ for (int i = 0; i < m_device_count; i++)
+ {
+ req |= m_slot[i]->m_req;
+ }
+
+ if (m_req_out != req)
+ {
+ m_req_out = req;
+ m_req_handler(req);
+
+ for (int i = 0; i < m_device_count; i++)
+ {
+ scsi_port_interface *dev = m_slot[i]->dev();
+ if (dev != NULL)
+ dev->input_req(req);
+ }
+ }
+}
+
+void SCSI_PORT_DEVICE::update_ack()
+{
+ int ack = m_ack_in;
+ for (int i = 0; i < m_device_count; i++)
+ {
+ ack |= m_slot[i]->m_ack;
+ }
+
+ if (m_ack_out != ack)
+ {
+ m_ack_out = ack;
+ m_ack_handler(ack);
+
+ for (int i = 0; i < m_device_count; i++)
+ {
+ scsi_port_interface *dev = m_slot[i]->dev();
+ if (dev != NULL)
+ dev->input_ack(ack);
+ }
+ }
+}
+
+void SCSI_PORT_DEVICE::update_atn()
+{
+ int atn = m_atn_in;
+ for (int i = 0; i < m_device_count; i++)
+ {
+ atn |= m_slot[i]->m_atn;
+ }
+
+ if (m_atn_out != atn)
+ {
+ m_atn_out = atn;
+ m_atn_handler(atn);
+
+ for (int i = 0; i < m_device_count; i++)
+ {
+ scsi_port_interface *dev = m_slot[i]->dev();
+ if (dev != NULL)
+ dev->input_atn(atn);
+ }
+ }
+}
+
+void SCSI_PORT_DEVICE::update_rst()
+{
+ int rst = m_rst_in;
+ for (int i = 0; i < m_device_count; i++)
+ {
+ rst |= m_slot[i]->m_rst;
+ }
+
+ if (m_rst_out != rst)
+ {
+ m_rst_out = rst;
+ m_rst_handler(rst);
+
+ for (int i = 0; i < m_device_count; i++)
+ {
+ scsi_port_interface *dev = m_slot[i]->dev();
+ if (dev != NULL)
+ dev->input_rst(rst);
+ }
+ }
+}
+
+void SCSI_PORT_DEVICE::update_data0()
+{
+ int data0 = m_data0_in;
+ for (int i = 0; i < m_device_count; i++)
+ {
+ data0 |= m_slot[i]->m_data0;
+ }
+
+ if (m_data0_out != data0)
+ {
+ m_data0_out = data0;
+ m_data0_handler(data0);
+
+ for (int i = 0; i < m_device_count; i++)
+ {
+ scsi_port_interface *dev = m_slot[i]->dev();
+ if (dev != NULL)
+ dev->input_data0(data0);
+ }
+ }
+}
+
+void SCSI_PORT_DEVICE::update_data1()
+{
+ int data1 = m_data1_in;
+ for (int i = 0; i < m_device_count; i++)
+ {
+ data1 |= m_slot[i]->m_data1;
+ }
+
+ if (m_data1_out != data1)
+ {
+ m_data1_out = data1;
+ m_data1_handler(data1);
+
+ for (int i = 0; i < m_device_count; i++)
+ {
+ scsi_port_interface *dev = m_slot[i]->dev();
+ if (dev != NULL)
+ dev->input_data1(data1);
+ }
+ }
+}
+
+void SCSI_PORT_DEVICE::update_data2()
+{
+ int data2 = m_data2_in;
+ for (int i = 0; i < m_device_count; i++)
+ {
+ data2 |= m_slot[i]->m_data2;
+ }
+
+ if (m_data2_out != data2)
+ {
+ m_data2_out = data2;
+ m_data2_handler(data2);
+
+ for (int i = 0; i < m_device_count; i++)
+ {
+ scsi_port_interface *dev = m_slot[i]->dev();
+ if (dev != NULL)
+ dev->input_data2(data2);
+ }
+ }
+}
+
+void SCSI_PORT_DEVICE::update_data3()
+{
+ int data3 = m_data3_in;
+ for (int i = 0; i < m_device_count; i++)
+ {
+ data3 |= m_slot[i]->m_data3;
+ }
+
+ if (m_data3_out != data3)
+ {
+ m_data3_out = data3;
+ m_data3_handler(data3);
+
+ for (int i = 0; i < m_device_count; i++)
+ {
+ scsi_port_interface *dev = m_slot[i]->dev();
+ if (dev != NULL)
+ dev->input_data3(data3);
+ }
+ }
+}
+
+void SCSI_PORT_DEVICE::update_data4()
+{
+ int data4 = m_data4_in;
+ for (int i = 0; i < m_device_count; i++)
+ {
+ data4 |= m_slot[i]->m_data4;
+ }
+
+ if (m_data4_out != data4)
+ {
+ m_data4_out = data4;
+ m_data4_handler(data4);
+
+ for (int i = 0; i < m_device_count; i++)
+ {
+ scsi_port_interface *dev = m_slot[i]->dev();
+ if (dev != NULL)
+ dev->input_data4(data4);
+ }
+ }
+}
+
+void SCSI_PORT_DEVICE::update_data5()
+{
+ int data5 = m_data5_in;
+ for (int i = 0; i < m_device_count; i++)
+ {
+ data5 |= m_slot[i]->m_data5;
+ }
+
+ if (m_data5_out != data5)
+ {
+ m_data5_out = data5;
+ m_data5_handler(data5);
+
+ for (int i = 0; i < m_device_count; i++)
+ {
+ scsi_port_interface *dev = m_slot[i]->dev();
+ if (dev != NULL)
+ dev->input_data5(data5);
+ }
+ }
+}
+
+void SCSI_PORT_DEVICE::update_data6()
+{
+ int data6 = m_data6_in;
+ for (int i = 0; i < m_device_count; i++)
+ {
+ data6 |= m_slot[i]->m_data6;
+ }
+
+ if (m_data6_out != data6)
+ {
+ m_data6_out = data6;
+ m_data6_handler(data6);
+
+ for (int i = 0; i < m_device_count; i++)
+ {
+ scsi_port_interface *dev = m_slot[i]->dev();
+ if (dev != NULL)
+ dev->input_data6(data6);
+ }
+ }
+}
+
+void SCSI_PORT_DEVICE::update_data7()
+{
+ int data7 = m_data7_in;
+ for (int i = 0; i < m_device_count; i++)
+ {
+ data7 |= m_slot[i]->m_data7;
+ }
+
+ if (m_data7_out != data7)
+ {
+ m_data7_out = data7;
+ m_data7_handler(data7);
+
+ for (int i = 0; i < m_device_count; i++)
+ {
+ scsi_port_interface *dev = m_slot[i]->dev();
+ if (dev != NULL)
+ dev->input_data7(data7);
+ }
+ }
+}
+
+WRITE_LINE_MEMBER( SCSI_PORT_DEVICE::write_bsy )
+{
+ if (m_bsy_in != state)
+ {
+ m_bsy_in = state;
+ update_bsy();
+ }
+}
+
+WRITE_LINE_MEMBER( SCSI_PORT_DEVICE::write_sel )
+{
+ if (m_sel_in != state)
+ {
+ m_sel_in = state;
+ update_sel();
+ }
+}
+
+WRITE_LINE_MEMBER( SCSI_PORT_DEVICE::write_cd )
+{
+ if (m_cd_in != state)
+ {
+ m_cd_in = state;
+ update_cd();
+ }
+}
+
+WRITE_LINE_MEMBER( SCSI_PORT_DEVICE::write_io )
+{
+ if (m_io_in != state)
+ {
+ m_io_in = state;
+ update_io();
+ }
+}
+
+WRITE_LINE_MEMBER( SCSI_PORT_DEVICE::write_msg )
+{
+ if (m_msg_in != state)
+ {
+ m_msg_in = state;
+ update_msg();
+ }
+}
+
+WRITE_LINE_MEMBER( SCSI_PORT_DEVICE::write_req )
+{
+ if (m_req_in != state)
+ {
+ m_req_in = state;
+ update_req();
+ }
+}
+
+WRITE_LINE_MEMBER( SCSI_PORT_DEVICE::write_ack )
+{
+ if (m_ack_in != state)
+ {
+ m_ack_in = state;
+ update_ack();
+ }
+}
+
+WRITE_LINE_MEMBER( SCSI_PORT_DEVICE::write_atn )
+{
+ if (m_atn_in != state)
+ {
+ m_atn_in = state;
+ update_atn();
+ }
+}
+
+WRITE_LINE_MEMBER( SCSI_PORT_DEVICE::write_rst )
+{
+ if (m_rst_in != state)
+ {
+ m_rst_in = state;
+ update_rst();
+ }
+}
+
+WRITE_LINE_MEMBER( SCSI_PORT_DEVICE::write_data0 )
+{
+ if (m_data0_in != state)
+ {
+ m_data0_in = state;
+ update_data0();
+ }
+}
+
+WRITE_LINE_MEMBER( SCSI_PORT_DEVICE::write_data1 )
+{
+ if (m_data1_in != state)
+ {
+ m_data1_in = state;
+ update_data1();
+ }
+}
+
+WRITE_LINE_MEMBER( SCSI_PORT_DEVICE::write_data2 )
+{
+ if (m_data2_in != state)
+ {
+ m_data2_in = state;
+ update_data2();
+ }
+}
+
+WRITE_LINE_MEMBER( SCSI_PORT_DEVICE::write_data3 )
+{
+ if (m_data3_in != state)
+ {
+ m_data3_in = state;
+ update_data3();
+ }
+}
+
+WRITE_LINE_MEMBER( SCSI_PORT_DEVICE::write_data4 )
+{
+ if (m_data4_in != state)
+ {
+ m_data4_in = state;
+ update_data4();
+ }
+}
+
+WRITE_LINE_MEMBER( SCSI_PORT_DEVICE::write_data5 )
+{
+ if (m_data5_in != state)
+ {
+ m_data5_in = state;
+ update_data5();
+ }
+}
+
+WRITE_LINE_MEMBER( SCSI_PORT_DEVICE::write_data6 )
+{
+ if (m_data6_in != state)
+ {
+ m_data6_in = state;
+ update_data6();
+ }
+}
+
+WRITE_LINE_MEMBER( SCSI_PORT_DEVICE::write_data7 )
+{
+ if (m_data7_in != state)
+ {
+ m_data7_in = state;
+ update_data7();
+ }
+}
+
+const device_type SCSI_PORT = &device_creator<SCSI_PORT_DEVICE>;
+
+SCSI_PORT_SLOT_device::SCSI_PORT_SLOT_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, SCSI_PORT_SLOT, "SCSI Connector", tag, owner, clock, "scsi_slot", __FILE__),
+ device_slot_interface(mconfig, *this),
+ m_dev(NULL),
+ m_bsy(0),
+ m_sel(0),
+ m_cd(0),
+ m_io(0),
+ m_msg(0),
+ m_req(0),
+ m_ack(0),
+ m_rst(0),
+ m_data0(0),
+ m_data1(0),
+ m_data2(0),
+ m_data3(0),
+ m_data4(0),
+ m_data5(0),
+ m_data6(0),
+ m_data7(0)
+{
+ m_port = dynamic_cast<SCSI_PORT_DEVICE *>(device().owner());
+}
+
+void SCSI_PORT_SLOT_device::device_config_complete()
+{
+ m_dev = dynamic_cast<scsi_port_interface *>(get_card_device());
+}
+
+void SCSI_PORT_SLOT_device::device_start()
+{
+}
+
+const device_type SCSI_PORT_SLOT = &device_creator<SCSI_PORT_SLOT_device>;
+
+scsi_port_interface::scsi_port_interface(const machine_config &mconfig, device_t &device)
+ : device_slot_card_interface(mconfig, device)
+{
+ m_slot = dynamic_cast<SCSI_PORT_SLOT_device *>(device.owner());
+}
+
+scsi_port_interface::~scsi_port_interface()
+{
+}
diff --git a/src/emu/bus/scsi/scsi.h b/src/emu/bus/scsi/scsi.h
new file mode 100644
index 00000000000..4bb34c5a602
--- /dev/null
+++ b/src/emu/bus/scsi/scsi.h
@@ -0,0 +1,313 @@
+// license:MAME
+// copyright-holders:smf
+
+#pragma once
+
+#ifndef _SCSI_H_
+#define _SCSI_H_
+
+#include "emu.h"
+#include "machine/buffer.h"
+#include "machine/latch.h"
+
+#define SCSI_PORT_DEVICE1 "1"
+#define SCSI_PORT_DEVICE2 "2"
+#define SCSI_PORT_DEVICE3 "3"
+#define SCSI_PORT_DEVICE4 "4"
+#define SCSI_PORT_DEVICE5 "5"
+#define SCSI_PORT_DEVICE6 "6"
+#define SCSI_PORT_DEVICE7 "7"
+
+#define MCFG_SCSI_BSY_HANDLER(_devcb) \
+ devcb = &SCSI_PORT_DEVICE::set_bsy_handler(*device, DEVCB2_##_devcb);
+
+#define MCFG_SCSI_SEL_HANDLER(_devcb) \
+ devcb = &SCSI_PORT_DEVICE::set_sel_handler(*device, DEVCB2_##_devcb);
+
+#define MCFG_SCSI_CD_HANDLER(_devcb) \
+ devcb = &SCSI_PORT_DEVICE::set_cd_handler(*device, DEVCB2_##_devcb);
+
+#define MCFG_SCSI_IO_HANDLER(_devcb) \
+ devcb = &SCSI_PORT_DEVICE::set_io_handler(*device, DEVCB2_##_devcb);
+
+#define MCFG_SCSI_MSG_HANDLER(_devcb) \
+ devcb = &SCSI_PORT_DEVICE::set_msg_handler(*device, DEVCB2_##_devcb);
+
+#define MCFG_SCSI_REQ_HANDLER(_devcb) \
+ devcb = &SCSI_PORT_DEVICE::set_req_handler(*device, DEVCB2_##_devcb);
+
+#define MCFG_SCSI_ACK_HANDLER(_devcb) \
+ devcb = &SCSI_PORT_DEVICE::set_ack_handler(*device, DEVCB2_##_devcb);
+
+#define MCFG_SCSI_ATN_HANDLER(_devcb) \
+ devcb = &SCSI_PORT_DEVICE::set_atn_handler(*device, DEVCB2_##_devcb);
+
+#define MCFG_SCSI_RST_HANDLER(_devcb) \
+ devcb = &SCSI_PORT_DEVICE::set_rst_handler(*device, DEVCB2_##_devcb);
+
+#define MCFG_SCSI_DATA0_HANDLER(_devcb) \
+ devcb = &SCSI_PORT_DEVICE::set_data0_handler(*device, DEVCB2_##_devcb);
+
+#define MCFG_SCSI_DATA1_HANDLER(_devcb) \
+ devcb = &SCSI_PORT_DEVICE::set_data1_handler(*device, DEVCB2_##_devcb);
+
+#define MCFG_SCSI_DATA2_HANDLER(_devcb) \
+ devcb = &SCSI_PORT_DEVICE::set_data2_handler(*device, DEVCB2_##_devcb);
+
+#define MCFG_SCSI_DATA3_HANDLER(_devcb) \
+ devcb = &SCSI_PORT_DEVICE::set_data3_handler(*device, DEVCB2_##_devcb);
+
+#define MCFG_SCSI_DATA4_HANDLER(_devcb) \
+ devcb = &SCSI_PORT_DEVICE::set_data4_handler(*device, DEVCB2_##_devcb);
+
+#define MCFG_SCSI_DATA5_HANDLER(_devcb) \
+ devcb = &SCSI_PORT_DEVICE::set_data5_handler(*device, DEVCB2_##_devcb);
+
+#define MCFG_SCSI_DATA6_HANDLER(_devcb) \
+ devcb = &SCSI_PORT_DEVICE::set_data6_handler(*device, DEVCB2_##_devcb);
+
+#define MCFG_SCSI_DATA7_HANDLER(_devcb) \
+ devcb = &SCSI_PORT_DEVICE::set_data7_handler(*device, DEVCB2_##_devcb);
+
+#define MCFG_SCSI_OUTPUT_LATCH_ADD(_tag, scsi_port_tag) \
+ MCFG_DEVICE_ADD(_tag, OUTPUT_LATCH, 0) \
+ MCFG_OUTPUT_LATCH_BIT0_HANDLER(DEVWRITELINE(scsi_port_tag, SCSI_PORT_DEVICE, write_data0)) \
+ MCFG_OUTPUT_LATCH_BIT1_HANDLER(DEVWRITELINE(scsi_port_tag, SCSI_PORT_DEVICE, write_data1)) \
+ MCFG_OUTPUT_LATCH_BIT2_HANDLER(DEVWRITELINE(scsi_port_tag, SCSI_PORT_DEVICE, write_data2)) \
+ MCFG_OUTPUT_LATCH_BIT3_HANDLER(DEVWRITELINE(scsi_port_tag, SCSI_PORT_DEVICE, write_data3)) \
+ MCFG_OUTPUT_LATCH_BIT4_HANDLER(DEVWRITELINE(scsi_port_tag, SCSI_PORT_DEVICE, write_data4)) \
+ MCFG_OUTPUT_LATCH_BIT5_HANDLER(DEVWRITELINE(scsi_port_tag, SCSI_PORT_DEVICE, write_data5)) \
+ MCFG_OUTPUT_LATCH_BIT6_HANDLER(DEVWRITELINE(scsi_port_tag, SCSI_PORT_DEVICE, write_data6)) \
+ MCFG_OUTPUT_LATCH_BIT7_HANDLER(DEVWRITELINE(scsi_port_tag, SCSI_PORT_DEVICE, write_data7))
+
+#define MCFG_SCSI_DATA_INPUT_BUFFER(_tag) \
+ MCFG_SCSI_DATA0_HANDLER(DEVWRITELINE(_tag, input_buffer_device, write_bit0)) \
+ MCFG_SCSI_DATA1_HANDLER(DEVWRITELINE(_tag, input_buffer_device, write_bit1)) \
+ MCFG_SCSI_DATA2_HANDLER(DEVWRITELINE(_tag, input_buffer_device, write_bit2)) \
+ MCFG_SCSI_DATA3_HANDLER(DEVWRITELINE(_tag, input_buffer_device, write_bit3)) \
+ MCFG_SCSI_DATA4_HANDLER(DEVWRITELINE(_tag, input_buffer_device, write_bit4)) \
+ MCFG_SCSI_DATA5_HANDLER(DEVWRITELINE(_tag, input_buffer_device, write_bit5)) \
+ MCFG_SCSI_DATA6_HANDLER(DEVWRITELINE(_tag, input_buffer_device, write_bit6)) \
+ MCFG_SCSI_DATA7_HANDLER(DEVWRITELINE(_tag, input_buffer_device, write_bit7))
+
+class SCSI_PORT_SLOT_device;
+class scsi_port_interface;
+
+class SCSI_PORT_DEVICE : public device_t
+{
+ friend class scsi_port_interface;
+
+public:
+ // construction/destruction
+ SCSI_PORT_DEVICE(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ template<class _Object> static devcb2_base &set_bsy_handler(device_t &device, _Object object) { return downcast<SCSI_PORT_DEVICE &>(device).m_bsy_handler.set_callback(object); }
+ template<class _Object> static devcb2_base &set_sel_handler(device_t &device, _Object object) { return downcast<SCSI_PORT_DEVICE &>(device).m_sel_handler.set_callback(object); }
+ template<class _Object> static devcb2_base &set_cd_handler(device_t &device, _Object object) { return downcast<SCSI_PORT_DEVICE &>(device).m_cd_handler.set_callback(object); }
+ template<class _Object> static devcb2_base &set_io_handler(device_t &device, _Object object) { return downcast<SCSI_PORT_DEVICE &>(device).m_io_handler.set_callback(object); }
+ template<class _Object> static devcb2_base &set_msg_handler(device_t &device, _Object object) { return downcast<SCSI_PORT_DEVICE &>(device).m_msg_handler.set_callback(object); }
+ template<class _Object> static devcb2_base &set_req_handler(device_t &device, _Object object) { return downcast<SCSI_PORT_DEVICE &>(device).m_req_handler.set_callback(object); }
+ template<class _Object> static devcb2_base &set_ack_handler(device_t &device, _Object object) { return downcast<SCSI_PORT_DEVICE &>(device).m_ack_handler.set_callback(object); }
+ template<class _Object> static devcb2_base &set_atn_handler(device_t &device, _Object object) { return downcast<SCSI_PORT_DEVICE &>(device).m_atn_handler.set_callback(object); }
+ template<class _Object> static devcb2_base &set_rst_handler(device_t &device, _Object object) { return downcast<SCSI_PORT_DEVICE &>(device).m_rst_handler.set_callback(object); }
+ template<class _Object> static devcb2_base &set_data0_handler(device_t &device, _Object object) { return downcast<SCSI_PORT_DEVICE &>(device).m_data0_handler.set_callback(object); }
+ template<class _Object> static devcb2_base &set_data1_handler(device_t &device, _Object object) { return downcast<SCSI_PORT_DEVICE &>(device).m_data1_handler.set_callback(object); }
+ template<class _Object> static devcb2_base &set_data2_handler(device_t &device, _Object object) { return downcast<SCSI_PORT_DEVICE &>(device).m_data2_handler.set_callback(object); }
+ template<class _Object> static devcb2_base &set_data3_handler(device_t &device, _Object object) { return downcast<SCSI_PORT_DEVICE &>(device).m_data3_handler.set_callback(object); }
+ template<class _Object> static devcb2_base &set_data4_handler(device_t &device, _Object object) { return downcast<SCSI_PORT_DEVICE &>(device).m_data4_handler.set_callback(object); }
+ template<class _Object> static devcb2_base &set_data5_handler(device_t &device, _Object object) { return downcast<SCSI_PORT_DEVICE &>(device).m_data5_handler.set_callback(object); }
+ template<class _Object> static devcb2_base &set_data6_handler(device_t &device, _Object object) { return downcast<SCSI_PORT_DEVICE &>(device).m_data6_handler.set_callback(object); }
+ template<class _Object> static devcb2_base &set_data7_handler(device_t &device, _Object object) { return downcast<SCSI_PORT_DEVICE &>(device).m_data7_handler.set_callback(object); }
+
+ DECLARE_WRITE_LINE_MEMBER( write_bsy );
+ DECLARE_WRITE_LINE_MEMBER( write_sel );
+ DECLARE_WRITE_LINE_MEMBER( write_cd );
+ DECLARE_WRITE_LINE_MEMBER( write_io );
+ DECLARE_WRITE_LINE_MEMBER( write_msg );
+ DECLARE_WRITE_LINE_MEMBER( write_req );
+ DECLARE_WRITE_LINE_MEMBER( write_ack );
+ DECLARE_WRITE_LINE_MEMBER( write_atn );
+ DECLARE_WRITE_LINE_MEMBER( write_rst );
+ DECLARE_WRITE_LINE_MEMBER( write_data0 );
+ DECLARE_WRITE_LINE_MEMBER( write_data1 );
+ DECLARE_WRITE_LINE_MEMBER( write_data2 );
+ DECLARE_WRITE_LINE_MEMBER( write_data3 );
+ DECLARE_WRITE_LINE_MEMBER( write_data4 );
+ DECLARE_WRITE_LINE_MEMBER( write_data5 );
+ DECLARE_WRITE_LINE_MEMBER( write_data6 );
+ DECLARE_WRITE_LINE_MEMBER( write_data7 );
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual machine_config_constructor device_mconfig_additions() const;
+
+ void update_bsy();
+ void update_sel();
+ void update_cd();
+ void update_io();
+ void update_msg();
+ void update_req();
+ void update_ack();
+ void update_atn();
+ void update_rst();
+ void update_data0();
+ void update_data1();
+ void update_data2();
+ void update_data3();
+ void update_data4();
+ void update_data5();
+ void update_data6();
+ void update_data7();
+
+private:
+ devcb2_write_line m_bsy_handler;
+ devcb2_write_line m_sel_handler;
+ devcb2_write_line m_cd_handler;
+ devcb2_write_line m_io_handler;
+ devcb2_write_line m_msg_handler;
+ devcb2_write_line m_req_handler;
+ devcb2_write_line m_ack_handler;
+ devcb2_write_line m_atn_handler;
+ devcb2_write_line m_rst_handler;
+ devcb2_write_line m_data0_handler;
+ devcb2_write_line m_data1_handler;
+ devcb2_write_line m_data2_handler;
+ devcb2_write_line m_data3_handler;
+ devcb2_write_line m_data4_handler;
+ devcb2_write_line m_data5_handler;
+ devcb2_write_line m_data6_handler;
+ devcb2_write_line m_data7_handler;
+
+ SCSI_PORT_SLOT_device *m_slot[7];
+ int m_device_count;
+
+ int m_bsy_in;
+ int m_sel_in;
+ int m_cd_in;
+ int m_io_in;
+ int m_msg_in;
+ int m_req_in;
+ int m_ack_in;
+ int m_atn_in;
+ int m_rst_in;
+ int m_data0_in;
+ int m_data1_in;
+ int m_data2_in;
+ int m_data3_in;
+ int m_data4_in;
+ int m_data5_in;
+ int m_data6_in;
+ int m_data7_in;
+ int m_bsy_out;
+ int m_sel_out;
+ int m_cd_out;
+ int m_io_out;
+ int m_msg_out;
+ int m_req_out;
+ int m_ack_out;
+ int m_atn_out;
+ int m_rst_out;
+ int m_data0_out;
+ int m_data1_out;
+ int m_data2_out;
+ int m_data3_out;
+ int m_data4_out;
+ int m_data5_out;
+ int m_data6_out;
+ int m_data7_out;
+};
+
+extern const device_type SCSI_PORT;
+
+class scsi_port_interface;
+
+class SCSI_PORT_SLOT_device : public device_t,
+ public device_slot_interface
+{
+ friend class SCSI_PORT_DEVICE;
+ friend class scsi_port_interface;
+
+public:
+ SCSI_PORT_SLOT_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ scsi_port_interface *dev() { return m_dev; }
+ SCSI_PORT_DEVICE *port() { return m_port; }
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_config_complete();
+
+protected:
+ scsi_port_interface *m_dev;
+ SCSI_PORT_DEVICE *m_port;
+
+ int m_bsy;
+ int m_sel;
+ int m_cd;
+ int m_io;
+ int m_msg;
+ int m_req;
+ int m_ack;
+ int m_atn;
+ int m_rst;
+ int m_data0;
+ int m_data1;
+ int m_data2;
+ int m_data3;
+ int m_data4;
+ int m_data5;
+ int m_data6;
+ int m_data7;
+};
+
+extern const device_type SCSI_PORT_SLOT;
+
+class scsi_port_interface : public device_slot_card_interface
+{
+public:
+ scsi_port_interface(const machine_config &mconfig, device_t &device);
+ virtual ~scsi_port_interface();
+
+ virtual DECLARE_WRITE_LINE_MEMBER( input_bsy ) {}
+ virtual DECLARE_WRITE_LINE_MEMBER( input_sel ) {}
+ virtual DECLARE_WRITE_LINE_MEMBER( input_cd ) {}
+ virtual DECLARE_WRITE_LINE_MEMBER( input_io ) {}
+ virtual DECLARE_WRITE_LINE_MEMBER( input_msg ) {}
+ virtual DECLARE_WRITE_LINE_MEMBER( input_req ) {}
+ virtual DECLARE_WRITE_LINE_MEMBER( input_ack ) {}
+ virtual DECLARE_WRITE_LINE_MEMBER( input_atn ) {}
+ virtual DECLARE_WRITE_LINE_MEMBER( input_rst ) {}
+ virtual DECLARE_WRITE_LINE_MEMBER( input_data0 ) {}
+ virtual DECLARE_WRITE_LINE_MEMBER( input_data1 ) {}
+ virtual DECLARE_WRITE_LINE_MEMBER( input_data2 ) {}
+ virtual DECLARE_WRITE_LINE_MEMBER( input_data3 ) {}
+ virtual DECLARE_WRITE_LINE_MEMBER( input_data4 ) {}
+ virtual DECLARE_WRITE_LINE_MEMBER( input_data5 ) {}
+ virtual DECLARE_WRITE_LINE_MEMBER( input_data6 ) {}
+ virtual DECLARE_WRITE_LINE_MEMBER( input_data7 ) {}
+
+ DECLARE_WRITE_LINE_MEMBER( output_bsy ) { if (m_slot->m_bsy != state) { m_slot->m_bsy = state; m_slot->port()->update_bsy(); } }
+ DECLARE_WRITE_LINE_MEMBER( output_sel ) { if (m_slot->m_sel != state) { m_slot->m_sel = state; m_slot->port()->update_sel(); } }
+ DECLARE_WRITE_LINE_MEMBER( output_cd ) { if (m_slot->m_cd != state) { m_slot->m_cd = state; m_slot->port()->update_cd(); } }
+ DECLARE_WRITE_LINE_MEMBER( output_io ) { if (m_slot->m_io != state) { m_slot->m_io = state; m_slot->port()->update_io(); } }
+ DECLARE_WRITE_LINE_MEMBER( output_msg ) { if (m_slot->m_msg != state) { m_slot->m_msg = state; m_slot->port()->update_msg(); } }
+ DECLARE_WRITE_LINE_MEMBER( output_req ) { if (m_slot->m_req != state) { m_slot->m_req = state; m_slot->port()->update_req(); } }
+ DECLARE_WRITE_LINE_MEMBER( output_ack ) { if (m_slot->m_ack != state) { m_slot->m_ack = state; m_slot->port()->update_ack(); } }
+ DECLARE_WRITE_LINE_MEMBER( output_atn ) { if (m_slot->m_atn != state) { m_slot->m_atn = state; m_slot->port()->update_atn(); } }
+ DECLARE_WRITE_LINE_MEMBER( output_rst ) { if (m_slot->m_rst != state) { m_slot->m_rst = state; m_slot->port()->update_rst(); } }
+ DECLARE_WRITE_LINE_MEMBER( output_data0 ) { if (m_slot->m_data0 != state) { m_slot->m_data0 = state; m_slot->port()->update_data0(); } }
+ DECLARE_WRITE_LINE_MEMBER( output_data1 ) { if (m_slot->m_data1 != state) { m_slot->m_data1 = state; m_slot->port()->update_data1(); } }
+ DECLARE_WRITE_LINE_MEMBER( output_data2 ) { if (m_slot->m_data2 != state) { m_slot->m_data2 = state; m_slot->port()->update_data2(); } }
+ DECLARE_WRITE_LINE_MEMBER( output_data3 ) { if (m_slot->m_data3 != state) { m_slot->m_data3 = state; m_slot->port()->update_data3(); } }
+ DECLARE_WRITE_LINE_MEMBER( output_data4 ) { if (m_slot->m_data4 != state) { m_slot->m_data4 = state; m_slot->port()->update_data4(); } }
+ DECLARE_WRITE_LINE_MEMBER( output_data5 ) { if (m_slot->m_data5 != state) { m_slot->m_data5 = state; m_slot->port()->update_data5(); } }
+ DECLARE_WRITE_LINE_MEMBER( output_data6 ) { if (m_slot->m_data6 != state) { m_slot->m_data6 = state; m_slot->port()->update_data6(); } }
+ DECLARE_WRITE_LINE_MEMBER( output_data7 ) { if (m_slot->m_data7 != state) { m_slot->m_data7 = state; m_slot->port()->update_data7(); } }
+
+private:
+ SCSI_PORT_SLOT_device *m_slot;
+};
+
+#endif
diff --git a/src/emu/bus/scsi/scsicd.c b/src/emu/bus/scsi/scsicd.c
new file mode 100644
index 00000000000..0ae5b97dce6
--- /dev/null
+++ b/src/emu/bus/scsi/scsicd.c
@@ -0,0 +1,42 @@
+// license:MAME
+// copyright-holders:smf
+/***************************************************************************
+
+ scsicd.c - Implementation of a SCSI CD-ROM device
+
+***************************************************************************/
+
+#include "scsicd.h"
+
+// device type definition
+const device_type SCSICD = &device_creator<scsicd_device>;
+
+scsicd_device::scsicd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ scsihle_device(mconfig, SCSICD, "SCSI CD", tag, owner, clock, "scsicd", __FILE__)
+{
+}
+
+scsicd_device::scsicd_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) :
+ scsihle_device(mconfig, type, name, tag, owner, clock, shortname, source)
+{
+}
+
+void scsicd_device::device_start()
+{
+ m_image = subdevice<cdrom_image_device>("image");
+ m_cdda = subdevice<cdda_device>("cdda");
+
+ scsihle_device::device_start();
+}
+
+cdrom_interface scsicd_device::cd_intf = { "cdrom", NULL };
+
+static MACHINE_CONFIG_FRAGMENT(scsi_cdrom)
+ MCFG_CDROM_ADD("image", scsicd_device::cd_intf)
+ MCFG_SOUND_ADD("cdda", CDDA, 0)
+MACHINE_CONFIG_END
+
+machine_config_constructor scsicd_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME(scsi_cdrom);
+}
diff --git a/src/emu/bus/scsi/scsicd.h b/src/emu/bus/scsi/scsicd.h
new file mode 100644
index 00000000000..67e10df2572
--- /dev/null
+++ b/src/emu/bus/scsi/scsicd.h
@@ -0,0 +1,33 @@
+// license:MAME
+// copyright-holders:smf
+/***************************************************************************
+
+ scsicd.h
+
+***************************************************************************/
+
+#ifndef _SCSICD_H_
+#define _SCSICD_H_
+
+#include "scsihle.h"
+#include "machine/t10mmc.h"
+
+class scsicd_device : public scsihle_device,
+ public t10mmc
+{
+public:
+ // construction/destruction
+ scsicd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ scsicd_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
+ virtual machine_config_constructor device_mconfig_additions() const;
+
+ static struct cdrom_interface cd_intf;
+
+protected:
+ virtual void device_start();
+};
+
+// device type definition
+extern const device_type SCSICD;
+
+#endif
diff --git a/src/emu/bus/scsi/scsihd.c b/src/emu/bus/scsi/scsihd.c
new file mode 100644
index 00000000000..637dacfcab9
--- /dev/null
+++ b/src/emu/bus/scsi/scsihd.c
@@ -0,0 +1,40 @@
+// license:MAME
+// copyright-holders:smf
+/***************************************************************************
+
+ scsihd.c - Implementation of a SCSI hard disk drive
+
+***************************************************************************/
+
+#include "scsihd.h"
+
+// device type definition
+const device_type SCSIHD = &device_creator<scsihd_device>;
+
+scsihd_device::scsihd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : scsihle_device(mconfig, SCSIHD, "SCSI HD", tag, owner, clock, "scsihd", __FILE__)
+{
+}
+
+scsihd_device::scsihd_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) :
+ scsihle_device(mconfig, type, name, tag, owner, clock, shortname, source)
+{
+}
+
+void scsihd_device::device_start()
+{
+ m_image = subdevice<harddisk_image_device>("image");
+
+ scsihle_device::device_start();
+}
+
+harddisk_interface scsihd_device::hd_intf = { "scsi_hdd", NULL };
+
+static MACHINE_CONFIG_FRAGMENT(scsi_harddisk)
+ MCFG_HARDDISK_CONFIG_ADD("image", scsihd_device::hd_intf)
+MACHINE_CONFIG_END
+
+machine_config_constructor scsihd_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME(scsi_harddisk);
+}
diff --git a/src/emu/bus/scsi/scsihd.h b/src/emu/bus/scsi/scsihd.h
new file mode 100644
index 00000000000..de64e099c4b
--- /dev/null
+++ b/src/emu/bus/scsi/scsihd.h
@@ -0,0 +1,33 @@
+// license:MAME
+// copyright-holders:smf
+/***************************************************************************
+
+ scsihd.h
+
+***************************************************************************/
+
+#ifndef _SCSIHD_H_
+#define _SCSIHD_H_
+
+#include "scsihle.h"
+#include "machine/t10sbc.h"
+
+class scsihd_device : public scsihle_device,
+ public t10sbc
+{
+public:
+ // construction/destruction
+ scsihd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ scsihd_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
+ virtual machine_config_constructor device_mconfig_additions() const;
+
+ static struct harddisk_interface hd_intf;
+
+protected:
+ virtual void device_start();
+};
+
+// device type definition
+extern const device_type SCSIHD;
+
+#endif
diff --git a/src/emu/bus/scsi/scsihle.c b/src/emu/bus/scsi/scsihle.c
new file mode 100644
index 00000000000..eb32ee292d9
--- /dev/null
+++ b/src/emu/bus/scsi/scsihle.c
@@ -0,0 +1,590 @@
+// license:MAME
+// copyright-holders:smf
+/*
+
+scsihle.c
+
+Base class for HLE'd SCSI devices.
+
+*/
+
+#include "scsihle.h"
+
+scsihle_device::scsihle_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) :
+ device_t(mconfig, type, name, tag, owner, clock, shortname, source),
+ scsi_port_interface(mconfig, *this),
+ m_scsi_id(*this, "SCSI_ID"),
+ m_input_data(0)
+{
+}
+
+static INPUT_PORTS_START(scsihle)
+ PORT_START("SCSI_ID")
+ PORT_CONFNAME(0x07, 0x07, "SCSI ID")
+ PORT_CONFSETTING( 0x00, "0")
+ PORT_CONFSETTING( 0x01, "1")
+ PORT_CONFSETTING( 0x02, "2")
+ PORT_CONFSETTING( 0x03, "3")
+ PORT_CONFSETTING( 0x04, "4")
+ PORT_CONFSETTING( 0x05, "5")
+ PORT_CONFSETTING( 0x06, "6")
+ PORT_CONFSETTING( 0x07, "7")
+INPUT_PORTS_END
+
+DEVICE_INPUT_DEFAULTS_START( SCSI_ID_0 )
+ DEVICE_INPUT_DEFAULTS( "SCSI_ID", 7, 0 )
+DEVICE_INPUT_DEFAULTS_END
+
+DEVICE_INPUT_DEFAULTS_START( SCSI_ID_1 )
+ DEVICE_INPUT_DEFAULTS( "SCSI_ID", 7, 1 )
+DEVICE_INPUT_DEFAULTS_END
+
+DEVICE_INPUT_DEFAULTS_START( SCSI_ID_2 )
+ DEVICE_INPUT_DEFAULTS( "SCSI_ID", 7, 2 )
+DEVICE_INPUT_DEFAULTS_END
+
+DEVICE_INPUT_DEFAULTS_START( SCSI_ID_3 )
+ DEVICE_INPUT_DEFAULTS( "SCSI_ID", 7, 3 )
+DEVICE_INPUT_DEFAULTS_END
+
+DEVICE_INPUT_DEFAULTS_START( SCSI_ID_4 )
+ DEVICE_INPUT_DEFAULTS( "SCSI_ID", 7, 4 )
+DEVICE_INPUT_DEFAULTS_END
+
+DEVICE_INPUT_DEFAULTS_START( SCSI_ID_5 )
+ DEVICE_INPUT_DEFAULTS( "SCSI_ID", 7, 5 )
+DEVICE_INPUT_DEFAULTS_END
+
+DEVICE_INPUT_DEFAULTS_START( SCSI_ID_6 )
+ DEVICE_INPUT_DEFAULTS( "SCSI_ID", 7, 6 )
+DEVICE_INPUT_DEFAULTS_END
+
+DEVICE_INPUT_DEFAULTS_START( SCSI_ID_7 )
+ DEVICE_INPUT_DEFAULTS( "SCSI_ID", 7, 7 )
+DEVICE_INPUT_DEFAULTS_END
+
+ioport_constructor scsihle_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(scsihle);
+}
+
+void scsihle_device::device_start()
+{
+ t10_start(*this);
+
+ req_timer = timer_alloc(0);
+ sel_timer = timer_alloc(1);
+ dataout_timer = timer_alloc(2);
+}
+
+void scsihle_device::device_reset()
+{
+ scsiID = m_scsi_id->read();
+ t10_reset();
+}
+
+int scsihle_device::GetDeviceID()
+{
+ return scsiID;
+}
+
+#define BSY_DELAY_NS 50
+#define REQ_DELAY_NS 90
+
+static const char *const phasenames[] =
+{
+ "data out", "data in", "command", "status", "none", "none", "message out", "message in", "bus free","select"
+};
+
+// scsihle
+#define SCSI_CMD_BUFFER_WRITE ( 0x3b )
+#define SCSI_CMD_BUFFER_READ ( 0x3c )
+
+// scsihd
+#define SCSI_CMD_FORMAT_UNIT 0x04
+#define SCSI_CMD_SEARCH_DATA_EQUAL 0x31
+#define SCSI_CMD_READ_DEFECT 0x37
+
+
+#define IS_COMMAND(cmd) (command[0]==cmd)
+
+#define FORMAT_UNIT_TIMEOUT 5
+
+/*
+ LOGLEVEL
+ 0 no logging,
+ 1 just commands
+ 2 1 + data
+ 3 2 + line changes
+*/
+
+#define LOGLEVEL 0
+
+#define LOG(level, ...) if(LOGLEVEL>=level) logerror(__VA_ARGS__)
+
+void scsihle_device::data_out(UINT8 data)
+{
+// printf( "%s data out %02x\n", tag(), data );
+ output_data0(BIT(data, 0));
+ output_data1(BIT(data, 1));
+ output_data2(BIT(data, 2));
+ output_data3(BIT(data, 3));
+ output_data4(BIT(data, 4));
+ output_data5(BIT(data, 5));
+ output_data6(BIT(data, 6));
+ output_data7(BIT(data, 7));
+}
+
+void scsihle_device::scsi_out_req_delay(UINT8 state)
+{
+ req_timer->adjust(attotime::from_nsec(REQ_DELAY_NS),state);
+}
+
+void scsihle_device::dump_bytes(UINT8 *buff, int count)
+{
+ int byteno;
+
+ for(byteno=0; byteno<count; byteno++)
+ {
+ logerror("%02X ",buff[byteno]);
+ }
+}
+
+void scsihle_device::dump_command_bytes()
+{
+ logerror("sending command 0x%02X to ScsiID %d\n",command[0],scsiID);
+ dump_bytes(command,cmd_idx);
+ logerror("\n\n");
+}
+
+void scsihle_device::dump_data_bytes(int count)
+{
+ logerror("Data buffer[0..%d]\n",count);
+ dump_bytes(buffer,count);
+ logerror("\n\n");
+}
+
+void scsihle_device::scsibus_read_data()
+{
+ data_last = (bytes_left >= m_sector_bytes) ? m_sector_bytes : bytes_left;
+
+ LOG(2,"SCSIBUS:scsibus_read_data bytes_left=%04X, data_last=%04X\n",bytes_left,data_last);
+
+ data_idx=0;
+
+ if (data_last > 0)
+ {
+ ReadData(buffer, data_last);
+ bytes_left-=data_last;
+
+ data_out(buffer[ data_idx++ ]);
+ }
+}
+
+void scsihle_device::scsibus_write_data()
+{
+ if (data_last > 0)
+ {
+ WriteData(buffer, data_last);
+ bytes_left -= data_last;
+ }
+
+ data_idx=0;
+}
+
+void scsihle_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
+{
+ switch (tid)
+ {
+ case 0:
+ output_req(param);
+ break;
+
+ case 1:
+ output_bsy(param);
+ break;
+
+ case 2:
+ // Some drives, notably the ST225N and ST125N, accept fromat unit commands
+ // with flags set indicating that bad block data should be transfered but
+ // don't then implemnt a data in phase, this timeout it to catch these !
+ if (IS_COMMAND(SCSI_CMD_FORMAT_UNIT) && (data_idx==0))
+ {
+ scsi_change_phase(SCSI_PHASE_STATUS);
+ }
+ break;
+ }
+}
+
+void scsihle_device::scsibus_exec_command()
+{
+ int command_local = 0;
+
+ if (LOGLEVEL)
+ dump_command_bytes();
+
+ //is_linked=command[cmd_idx-1] & 0x01;
+ is_linked=0;
+
+ // Check for locally executed commands, and if found execute them
+ switch (command[0])
+ {
+ // Format unit
+ case SCSI_CMD_FORMAT_UNIT:
+ LOG(1,"SCSIBUS: format unit command[1]=%02X & 0x10\n",(command[1] & 0x10));
+ command_local=1;
+ if ((command[1] & 0x10)==0x10)
+ m_phase = SCSI_PHASE_DATAOUT;
+ else
+ m_phase = SCSI_PHASE_STATUS;
+
+ m_status_code = SCSI_STATUS_CODE_GOOD;
+ bytes_left=4;
+ dataout_timer->adjust(attotime::from_seconds(FORMAT_UNIT_TIMEOUT));
+ break;
+
+ case SCSI_CMD_SEARCH_DATA_EQUAL:
+ LOG(1,"SCSIBUS: Search_data_equaln");
+ command_local=1;
+ bytes_left=0;
+ m_phase = SCSI_PHASE_STATUS;
+ m_status_code = SCSI_STATUS_CODE_GOOD;
+ break;
+
+ case SCSI_CMD_READ_DEFECT:
+ LOG(1,"SCSIBUS: read defect list\n");
+ command_local=1;
+
+ buffer[0] = 0x00;
+ buffer[1] = command[2];
+ buffer[3] = 0x00; // defect list len msb
+ buffer[4] = 0x00; // defect list len lsb
+
+ bytes_left=4;
+ m_phase = SCSI_PHASE_DATAIN;
+ m_status_code = SCSI_STATUS_CODE_GOOD;
+ break;
+
+ // write buffer
+ case SCSI_CMD_BUFFER_WRITE:
+ LOG(1,"SCSIBUS: write_buffer\n");
+ command_local=1;
+ bytes_left=(command[7]<<8)+command[8];
+ m_phase = SCSI_PHASE_DATAOUT;
+ m_status_code = SCSI_STATUS_CODE_GOOD;
+ break;
+
+ // read buffer
+ case SCSI_CMD_BUFFER_READ:
+ LOG(1,"SCSIBUS: read_buffer\n");
+ command_local=1;
+ bytes_left = (command[7]<<8) + command[8];
+ m_phase = SCSI_PHASE_DATAIN;
+ m_status_code = SCSI_STATUS_CODE_GOOD;
+ break;
+ }
+
+
+ // Check for locally executed command, if not then pass it on
+ // to the disk driver
+ if (!command_local)
+ {
+ SetCommand(command, cmd_idx);
+ ExecCommand();
+ GetLength(&bytes_left);
+ data_idx=0;
+ }
+
+ scsi_change_phase(m_phase);
+
+ LOG(1,"SCSIBUS:bytes_left=%02X data_idx=%02X\n",bytes_left,data_idx);
+
+ // This is correct as we need to read from disk for commands other than just read data
+ if ((m_phase == SCSI_PHASE_DATAIN) && (!command_local))
+ scsibus_read_data();
+}
+
+UINT8 scsihle_device::scsibus_driveno(UINT8 drivesel)
+{
+ switch (drivesel)
+ {
+ case 0x01: return 0;
+ case 0x02: return 1;
+ case 0x04: return 2;
+ case 0x08: return 3;
+ case 0x10: return 4;
+ case 0x20: return 5;
+ case 0x40: return 6;
+ case 0x80: return 7;
+ default: return 0;
+ }
+}
+
+void scsihle_device::scsi_change_phase(UINT8 newphase)
+{
+ LOG(1,"scsi_change_phase() from=%s, to=%s\n",phasenames[m_phase],phasenames[newphase]);
+
+ m_phase=newphase;
+ cmd_idx=0;
+ data_idx=0;
+
+ switch(m_phase)
+ {
+ case SCSI_PHASE_BUS_FREE:
+ output_bsy(0);
+ // sel
+ output_cd(0);
+ output_io(0);
+ output_msg(0);
+ output_req(0);
+ // ack
+ // atn
+ // rst
+ data_out(0);
+ LOG(1,"SCSIBUS: done\n\n");
+ break;
+
+ case SCSI_PHASE_COMMAND:
+ output_cd(1);
+ output_io(0);
+ output_msg(0);
+ scsi_out_req_delay(1);
+ data_out(0);
+ LOG(1,"\nSCSIBUS: Command begin\n");
+ break;
+
+ case SCSI_PHASE_DATAOUT:
+ output_cd(0);
+ output_io(0);
+ output_msg(0);
+ scsi_out_req_delay(1);
+ data_out(0);
+ break;
+
+ case SCSI_PHASE_DATAIN:
+ output_cd(0);
+ output_io(1);
+ output_msg(0);
+ scsi_out_req_delay(1);
+ break;
+
+ case SCSI_PHASE_STATUS:
+ output_cd(1);
+ output_io(1);
+ output_msg(0);
+ scsi_out_req_delay(1);
+ data_out(m_status_code);
+ break;
+
+ case SCSI_PHASE_MESSAGE_OUT:
+ output_cd(1);
+ output_io(0);
+ output_msg(1);
+ scsi_out_req_delay(1);
+ data_out(0);
+ break;
+
+ case SCSI_PHASE_MESSAGE_IN:
+ output_cd(1);
+ output_io(1);
+ output_msg(1);
+ scsi_out_req_delay(1);
+ data_out(0); // no errors for the time being !
+ break;
+ }
+}
+
+WRITE_LINE_MEMBER( scsihle_device::input_sel )
+{
+// printf( "sel %d %d %02x\n", state, m_phase, m_input_data );
+ switch (m_phase)
+ {
+ case SCSI_PHASE_BUS_FREE:
+ // Note this assumes we only have one initiator and therefore
+ // only one line active.
+ if (scsibus_driveno(m_input_data) == scsiID)
+ {
+ void *hdfile = NULL;
+ // Check to see if device had image file mounted, if not, do not set busy,
+ // and stay busfree.
+ GetDevice(&hdfile);
+ if (hdfile != NULL)
+ {
+ if (!state)
+ {
+ scsi_change_phase(SCSI_PHASE_COMMAND);
+ }
+ else
+ {
+ sel_timer->adjust(attotime::from_nsec(BSY_DELAY_NS),1);
+ }
+ }
+ }
+ break;
+ }
+}
+
+WRITE_LINE_MEMBER( scsihle_device::input_ack )
+{
+ switch (m_phase)
+ {
+ case SCSI_PHASE_COMMAND:
+ if (!state)
+ {
+ command[ cmd_idx++ ] = m_input_data;
+
+ // If the command is ready go and execute it
+ if (cmd_idx == get_scsi_cmd_len(command[0]))
+ {
+ scsibus_exec_command();
+ }
+ else
+ {
+ scsi_out_req_delay(1);
+ }
+ }
+ else
+ {
+ scsi_out_req_delay(0);
+ }
+ break;
+
+ case SCSI_PHASE_DATAIN:
+ if (!state)
+ {
+ // check to see if we have reached the end of the block buffer
+ // and that there is more data to read from the scsi disk
+ if (data_idx == m_sector_bytes && bytes_left > 0)
+ {
+ scsibus_read_data();
+ scsi_out_req_delay(1);
+ }
+ else if (data_idx == data_last && bytes_left == 0)
+ {
+ scsi_change_phase(SCSI_PHASE_STATUS);
+ }
+ else
+ {
+ data_out(buffer[data_idx++]);
+ scsi_out_req_delay(1);
+ }
+ }
+ else
+ {
+ scsi_out_req_delay(0);
+ }
+ break;
+
+ case SCSI_PHASE_DATAOUT:
+ if (!state)
+ {
+ //LOG(1,"SCSIBUS:bytes_left=%02X data_idx=%02X\n",bytes_left,data_idx);
+ buffer[data_idx++] = m_input_data;
+
+ if (IS_COMMAND(SCSI_CMD_FORMAT_UNIT))
+ {
+ // If we have the first byte, then cancel the dataout timout
+ if (data_idx == 1)
+ dataout_timer->adjust(attotime::never);
+
+ // When we have the first 3 bytes, calculate how many more are in the
+ // bad block list.
+ if (data_idx == 3)
+ {
+ bytes_left += ((buffer[2]<<8) + buffer[3]);
+ LOG(1, "format_unit reading an extra %d bytes\n", bytes_left - 4);
+ dump_data_bytes(4);
+ }
+ }
+
+ // If the data buffer is full flush it to the SCSI disk
+
+ data_last = (bytes_left >= m_sector_bytes) ? m_sector_bytes : bytes_left;
+
+ if (data_idx == data_last)
+ scsibus_write_data();
+
+ if (data_idx == 0 && bytes_left == 0)
+ {
+ scsi_change_phase(SCSI_PHASE_STATUS);
+ }
+ else
+ {
+ scsi_out_req_delay(1);
+ }
+ }
+ else
+ {
+ scsi_out_req_delay(0);
+ }
+ break;
+
+ case SCSI_PHASE_STATUS:
+ if (!state)
+ {
+ if (cmd_idx > 0)
+ {
+ scsi_change_phase(SCSI_PHASE_MESSAGE_IN);
+ }
+ else
+ {
+ scsi_out_req_delay(1);
+ }
+ }
+ else
+ {
+ cmd_idx++;
+ scsi_out_req_delay(0);
+ }
+ break;
+
+ case SCSI_PHASE_MESSAGE_IN:
+ if (!state)
+ {
+ if (cmd_idx > 0)
+ {
+ if (is_linked)
+ scsi_change_phase(SCSI_PHASE_COMMAND);
+ else
+ scsi_change_phase(SCSI_PHASE_BUS_FREE);
+ }
+ else
+ {
+ scsi_out_req_delay(1);
+ }
+ }
+ else
+ {
+ cmd_idx++;
+ scsi_out_req_delay(0);
+ }
+ break;
+ }
+}
+
+WRITE_LINE_MEMBER( scsihle_device::input_rst )
+{
+ if (state)
+ {
+ scsi_change_phase(SCSI_PHASE_BUS_FREE);
+ cmd_idx = 0;
+ data_idx = 0;
+ is_linked = 0;
+ }
+}
+
+// get the length of a SCSI command based on it's command byte type
+int scsihle_device::get_scsi_cmd_len(int cbyte)
+{
+ int group;
+
+ group = (cbyte>>5) & 7;
+
+ if (group == 0 || group == 3 || group == 6 || group == 7) return 6;
+ if (group == 1 || group == 2) return 10;
+ if (group == 5) return 12;
+
+ fatalerror("scsihle: Unknown SCSI command group %d, command byte=%02X\n", group,cbyte);
+
+ return 6;
+}
diff --git a/src/emu/bus/scsi/scsihle.h b/src/emu/bus/scsi/scsihle.h
new file mode 100644
index 00000000000..37a90beca9c
--- /dev/null
+++ b/src/emu/bus/scsi/scsihle.h
@@ -0,0 +1,91 @@
+// license:MAME
+// copyright-holders:smf
+/*
+
+scsihle.h
+
+Base class for HLE'd SCSI devices.
+
+*/
+
+#ifndef _SCSIHLE_H_
+#define _SCSIHLE_H_
+
+#include "scsi.h"
+#include "machine/t10spc.h"
+
+class scsihle_device : public device_t,
+ public scsi_port_interface,
+ public virtual t10spc
+{
+public:
+ // construction/destruction
+ scsihle_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
+
+ virtual int GetDeviceID(); // hack for legacy_scsi_host_adapter::get_device
+
+ virtual DECLARE_WRITE_LINE_MEMBER( input_sel );
+ virtual DECLARE_WRITE_LINE_MEMBER( input_ack );
+ virtual DECLARE_WRITE_LINE_MEMBER( input_rst );
+ virtual DECLARE_WRITE_LINE_MEMBER( input_data0 ) { if (state) m_input_data |= 0x01; else m_input_data &= ~0x01; }
+ virtual DECLARE_WRITE_LINE_MEMBER( input_data1 ) { if (state) m_input_data |= 0x02; else m_input_data &= ~0x02; }
+ virtual DECLARE_WRITE_LINE_MEMBER( input_data2 ) { if (state) m_input_data |= 0x04; else m_input_data &= ~0x04; }
+ virtual DECLARE_WRITE_LINE_MEMBER( input_data3 ) { if (state) m_input_data |= 0x08; else m_input_data &= ~0x08; }
+ virtual DECLARE_WRITE_LINE_MEMBER( input_data4 ) { if (state) m_input_data |= 0x10; else m_input_data &= ~0x10; }
+ virtual DECLARE_WRITE_LINE_MEMBER( input_data5 ) { if (state) m_input_data |= 0x20; else m_input_data &= ~0x20; }
+ virtual DECLARE_WRITE_LINE_MEMBER( input_data6 ) { if (state) m_input_data |= 0x40; else m_input_data &= ~0x40; }
+ virtual DECLARE_WRITE_LINE_MEMBER( input_data7 ) { if (state) m_input_data |= 0x80; else m_input_data &= ~0x80; }
+
+protected:
+ // device-level overrides
+ virtual ioport_constructor device_input_ports() const;
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+private:
+ required_ioport m_scsi_id;
+ void data_out(UINT8 data);
+ void scsi_out_req_delay(UINT8 state);
+ void scsi_change_phase(UINT8 newphase);
+ int get_scsi_cmd_len(int cbyte);
+ UINT8 scsibus_driveno(UINT8 drivesel);
+ void scsibus_read_data();
+ void scsibus_write_data();
+ void scsibus_exec_command();
+ void dump_command_bytes();
+ void dump_data_bytes(int count);
+ void dump_bytes(UINT8 *buff, int count);
+
+ emu_timer *req_timer;
+ emu_timer *sel_timer;
+ emu_timer *dataout_timer;
+
+ UINT8 cmd_idx;
+ UINT8 is_linked;
+
+ UINT8 buffer[ 1024 ];
+ UINT16 data_idx;
+ int bytes_left;
+ int data_last;
+
+ int scsiID;
+ UINT8 m_input_data;
+};
+
+extern const input_device_default DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_0)[];
+extern const input_device_default DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_1)[];
+extern const input_device_default DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_2)[];
+extern const input_device_default DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_3)[];
+extern const input_device_default DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_4)[];
+extern const input_device_default DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_5)[];
+extern const input_device_default DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_6)[];
+extern const input_device_default DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_7)[];
+
+#define MCFG_SCSIDEV_ADD(_tag, _option, _type, _id) \
+ MCFG_DEVICE_MODIFY(_tag ) \
+ MCFG_SLOT_OPTION_ADD( _option, _type ) \
+ MCFG_SLOT_OPTION_DEVICE_INPUT_DEFAULTS( _option, _id ) \
+ MCFG_SLOT_DEFAULT_OPTION( _option ) \
+
+#endif