diff options
author | 2014-04-14 11:50:39 +0000 | |
---|---|---|
committer | 2014-04-14 11:50:39 +0000 | |
commit | a039e59ae2be4a92be8afae9018f481f2ff14f3e (patch) | |
tree | 280d142f4620c02e4a734f04a837485940841b18 /src/emu/bus/scsi | |
parent | 51360b13702d031b1d1c764e044209d43f24a6a0 (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.c | 1 | ||||
-rw-r--r-- | src/emu/bus/scsi/acb4070.h | 2 | ||||
-rw-r--r-- | src/emu/bus/scsi/cdu76s.c | 45 | ||||
-rw-r--r-- | src/emu/bus/scsi/cdu76s.h | 32 | ||||
-rw-r--r-- | src/emu/bus/scsi/d9060hd.c | 1 | ||||
-rw-r--r-- | src/emu/bus/scsi/d9060hd.h | 2 | ||||
-rw-r--r-- | src/emu/bus/scsi/s1410.c | 1 | ||||
-rw-r--r-- | src/emu/bus/scsi/s1410.h | 3 | ||||
-rw-r--r-- | src/emu/bus/scsi/sa1403d.h | 3 | ||||
-rw-r--r-- | src/emu/bus/scsi/scsi.c | 690 | ||||
-rw-r--r-- | src/emu/bus/scsi/scsi.h | 313 | ||||
-rw-r--r-- | src/emu/bus/scsi/scsicd.c | 42 | ||||
-rw-r--r-- | src/emu/bus/scsi/scsicd.h | 33 | ||||
-rw-r--r-- | src/emu/bus/scsi/scsihd.c | 40 | ||||
-rw-r--r-- | src/emu/bus/scsi/scsihd.h | 33 | ||||
-rw-r--r-- | src/emu/bus/scsi/scsihle.c | 590 | ||||
-rw-r--r-- | src/emu/bus/scsi/scsihle.h | 91 |
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 |