mirror of
https://github.com/holub/mame
synced 2025-05-29 00:53:09 +03:00
496 lines
11 KiB
C
496 lines
11 KiB
C
/**********************************************************************
|
|
|
|
Western Digital WD11C00-17 PC/XT Host Interface Logic Device
|
|
|
|
Copyright MESS Team.
|
|
Visit http://mamedev.org for licensing and usage restrictions.
|
|
|
|
**********************************************************************/
|
|
|
|
#include "machine/wd11c00_17.h"
|
|
|
|
|
|
|
|
//**************************************************************************
|
|
// MACROS / CONSTANTS
|
|
//**************************************************************************
|
|
|
|
#define LOG 1
|
|
|
|
|
|
// status register
|
|
#define STATUS_IRQ 0x20
|
|
#define STATUS_DRQ 0x10
|
|
#define STATUS_BUSY 0x08
|
|
#define STATUS_C_D 0x04
|
|
#define STATUS_I_O 0x02
|
|
#define STATUS_REQ 0x01
|
|
|
|
|
|
// mask register
|
|
#define MASK_IRQ 0x02
|
|
#define MASK_DMA 0x01
|
|
|
|
|
|
|
|
//**************************************************************************
|
|
// DEVICE DEFINITIONS
|
|
//**************************************************************************
|
|
|
|
const device_type WD11C00_17 = &device_creator<wd11c00_17_device>;
|
|
|
|
|
|
//-------------------------------------------------
|
|
// device_config_complete - perform any
|
|
// operations now that the configuration is
|
|
// complete
|
|
//-------------------------------------------------
|
|
|
|
void wd11c00_17_device::device_config_complete()
|
|
{
|
|
// inherit a copy of the static data
|
|
const wd11c00_17_interface *intf = reinterpret_cast<const wd11c00_17_interface *>(static_config());
|
|
if (intf != NULL)
|
|
*static_cast<wd11c00_17_interface *>(this) = *intf;
|
|
|
|
// or initialize to defaults if none provided
|
|
else
|
|
{
|
|
memset(&m_out_irq5_cb, 0, sizeof(m_out_irq5_cb));
|
|
memset(&m_out_drq3_cb, 0, sizeof(m_out_drq3_cb));
|
|
memset(&m_out_mr_cb, 0, sizeof(m_out_mr_cb));
|
|
memset(&m_out_busy_cb, 0, sizeof(m_out_busy_cb));
|
|
memset(&m_out_req_cb, 0, sizeof(m_out_req_cb));
|
|
memset(&m_out_ra3_cb, 0, sizeof(m_out_ra3_cb));
|
|
memset(&m_in_rd322_cb, 0, sizeof(m_in_rd322_cb));
|
|
memset(&m_in_ramcs_cb, 0, sizeof(m_in_ramcs_cb));
|
|
memset(&m_out_ramwr_cb, 0, sizeof(m_out_ramwr_cb));
|
|
memset(&m_in_cs1010_cb, 0, sizeof(m_in_cs1010_cb));
|
|
memset(&m_out_cs1010_cb, 0, sizeof(m_out_cs1010_cb));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//**************************************************************************
|
|
// INLINE HELPERS
|
|
//**************************************************************************
|
|
|
|
//-------------------------------------------------
|
|
// check_interrupt -
|
|
//-------------------------------------------------
|
|
|
|
inline void wd11c00_17_device::check_interrupt()
|
|
{
|
|
if (BIT(m_ra, 10))
|
|
{
|
|
m_status &= ~STATUS_DRQ;
|
|
}
|
|
|
|
int ra3 = BIT(m_ra, 3);
|
|
|
|
if (m_ra3 != ra3)
|
|
{
|
|
m_out_ra3_func(ra3 ? ASSERT_LINE : CLEAR_LINE);
|
|
m_ra3 = ra3;
|
|
}
|
|
|
|
int irq5 = ((m_status & STATUS_IRQ) && (m_mask & MASK_IRQ)) ? ASSERT_LINE : CLEAR_LINE;
|
|
|
|
if (m_irq5 != irq5)
|
|
{
|
|
m_out_irq5_func(irq5);
|
|
m_irq5 = irq5;
|
|
}
|
|
|
|
int drq3 = ((m_status & STATUS_DRQ) && (m_mask & MASK_DMA)) ? ASSERT_LINE : CLEAR_LINE;
|
|
|
|
if (m_drq3 != drq3)
|
|
{
|
|
m_out_drq3_func(drq3);
|
|
m_drq3 = drq3;
|
|
}
|
|
|
|
int busy = (m_status & STATUS_BUSY) ? 0 : 1;
|
|
|
|
if (m_busy != busy)
|
|
{
|
|
m_out_busy_func(busy);
|
|
m_busy = busy;
|
|
}
|
|
|
|
int req = (m_status & STATUS_REQ) ? 1 : 0;
|
|
|
|
if (m_req != req)
|
|
{
|
|
m_out_req_func(req);
|
|
m_req = req;
|
|
}
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// increment_address -
|
|
//-------------------------------------------------
|
|
|
|
inline void wd11c00_17_device::increment_address()
|
|
{
|
|
m_ra++;
|
|
check_interrupt();
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// read_data -
|
|
//-------------------------------------------------
|
|
|
|
inline UINT8 wd11c00_17_device::read_data()
|
|
{
|
|
UINT8 data = 0;
|
|
|
|
if (m_status & STATUS_BUSY)
|
|
{
|
|
data = m_in_ramcs_func(m_ra & 0x7ff);
|
|
|
|
increment_address();
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// write_data -
|
|
//-------------------------------------------------
|
|
|
|
inline void wd11c00_17_device::write_data(UINT8 data)
|
|
{
|
|
if (m_status & STATUS_BUSY)
|
|
{
|
|
m_out_ramwr_func(m_ra & 0x7ff, data);
|
|
|
|
increment_address();
|
|
}
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// software_reset -
|
|
//-------------------------------------------------
|
|
|
|
inline void wd11c00_17_device::software_reset()
|
|
{
|
|
m_out_mr_func(ASSERT_LINE);
|
|
m_out_mr_func(CLEAR_LINE);
|
|
|
|
device_reset();
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// select -
|
|
//-------------------------------------------------
|
|
|
|
inline void wd11c00_17_device::select()
|
|
{
|
|
m_status = STATUS_BUSY | STATUS_C_D | STATUS_REQ;
|
|
|
|
check_interrupt();
|
|
}
|
|
|
|
|
|
|
|
//**************************************************************************
|
|
// LIVE DEVICE
|
|
//**************************************************************************
|
|
|
|
//-------------------------------------------------
|
|
// wd11c00_17_device - constructor
|
|
//-------------------------------------------------
|
|
|
|
wd11c00_17_device::wd11c00_17_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
|
: device_t(mconfig, WD11C00_17, "Western Digital WD11C00-17", tag, owner, clock),
|
|
m_status(0),
|
|
m_irq5(CLEAR_LINE),
|
|
m_drq3(CLEAR_LINE),
|
|
m_busy(1),
|
|
m_req(0),
|
|
m_ra3(0)
|
|
{
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// device_start - device-specific startup
|
|
//-------------------------------------------------
|
|
|
|
void wd11c00_17_device::device_start()
|
|
{
|
|
// resolve callbacks
|
|
m_out_irq5_func.resolve(m_out_irq5_cb, *this);
|
|
m_out_drq3_func.resolve(m_out_drq3_cb, *this);
|
|
m_out_mr_func.resolve(m_out_mr_cb, *this);
|
|
m_out_busy_func.resolve(m_out_busy_cb, *this);
|
|
m_out_req_func.resolve(m_out_req_cb, *this);
|
|
m_out_ra3_func.resolve(m_out_ra3_cb, *this);
|
|
m_in_rd322_func.resolve(m_in_rd322_cb, *this);
|
|
m_in_ramcs_func.resolve(m_in_ramcs_cb, *this);
|
|
m_out_ramwr_func.resolve(m_out_ramwr_cb, *this);
|
|
m_in_cs1010_func.resolve(m_in_cs1010_cb, *this);
|
|
m_out_cs1010_func.resolve(m_out_cs1010_cb, *this);
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// device_reset - device-specific reset
|
|
//-------------------------------------------------
|
|
|
|
void wd11c00_17_device::device_reset()
|
|
{
|
|
m_status &= ~(STATUS_IRQ | STATUS_DRQ | STATUS_BUSY);
|
|
m_mask = 0;
|
|
m_ra = 0;
|
|
|
|
check_interrupt();
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// io_r -
|
|
//-------------------------------------------------
|
|
|
|
READ8_MEMBER( wd11c00_17_device::io_r )
|
|
{
|
|
UINT8 data = 0xff;
|
|
|
|
switch (offset)
|
|
{
|
|
case 0: // Read Data, Board to Host
|
|
if (LOG) logerror("%s WD11C00-17 '%s' Read Data %03x:", machine().describe_context(), tag(), m_ra);
|
|
data = read_data();
|
|
if (LOG) logerror("%02x\n", data);
|
|
break;
|
|
|
|
case 1: // Read Board Hardware Status
|
|
data = m_status;
|
|
check_interrupt();
|
|
break;
|
|
|
|
case 2: // Read Drive Configuration Information
|
|
data = m_in_rd322_func(0);
|
|
break;
|
|
|
|
case 3: // Not Used
|
|
break;
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// io_w -
|
|
//-------------------------------------------------
|
|
|
|
WRITE8_MEMBER( wd11c00_17_device::io_w )
|
|
{
|
|
switch (offset)
|
|
{
|
|
case 0: // Write Data, Host to Board
|
|
if (LOG) logerror("%s WD11C00-17 '%s' Write Data %03x:%02x\n", machine().describe_context(), tag(), m_ra, data);
|
|
write_data(data);
|
|
break;
|
|
|
|
case 1: // Board Software Reset
|
|
if (LOG) logerror("%s WD11C00-17 '%s' Software Reset\n", machine().describe_context(), tag());
|
|
software_reset();
|
|
break;
|
|
|
|
case 2: // Board Select
|
|
if (LOG) logerror("%s WD11C00-17 '%s' Select\n", machine().describe_context(), tag());
|
|
increment_address(); // HACK
|
|
select();
|
|
break;
|
|
|
|
case 3: // Set/Reset DMA, IRQ Masks
|
|
if (LOG) logerror("%s WD11C00-17 '%s' Mask IRQ %u DMA %u\n", machine().describe_context(), tag(), BIT(data, 1), BIT(data, 0));
|
|
m_mask = data;
|
|
check_interrupt();
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// dack_r -
|
|
//-------------------------------------------------
|
|
|
|
UINT8 wd11c00_17_device::dack_r()
|
|
{
|
|
return read_data();
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// dack_w -
|
|
//-------------------------------------------------
|
|
|
|
void wd11c00_17_device::dack_w(UINT8 data)
|
|
{
|
|
write_data(data);
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// read -
|
|
//-------------------------------------------------
|
|
|
|
READ8_MEMBER( wd11c00_17_device::read )
|
|
{
|
|
UINT8 data = 0;
|
|
|
|
switch (offset)
|
|
{
|
|
case 0x00:
|
|
if (LOG) logerror("%s WD11C00-17 '%s' Read RAM %03x:", machine().describe_context(), tag(), m_ra);
|
|
data = read_data();
|
|
if (LOG) logerror("%02x\n", data);
|
|
break;
|
|
|
|
case 0x20:
|
|
data = m_in_cs1010_func(m_ra >> 8);
|
|
break;
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// write -
|
|
//-------------------------------------------------
|
|
|
|
WRITE8_MEMBER( wd11c00_17_device::write )
|
|
{
|
|
switch (offset)
|
|
{
|
|
case 0x00:
|
|
if (LOG) logerror("%s WD11C00-17 '%s' Write RAM %03x:%02x\n", machine().describe_context(), tag(), m_ra, data);
|
|
write_data(data);
|
|
if (m_ra > 0x400) m_ecc_not_0 = 0; // HACK
|
|
break;
|
|
|
|
case 0x20:
|
|
m_out_cs1010_func(m_ra >> 8, data);
|
|
break;
|
|
|
|
case 0x60:
|
|
m_ra = (data & 0x07) << 8;
|
|
if (LOG) logerror("%s WD11C00-17 '%s' RA %03x\n", machine().describe_context(), tag(), m_ra);
|
|
check_interrupt();
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// ireq_w -
|
|
//-------------------------------------------------
|
|
|
|
WRITE_LINE_MEMBER( wd11c00_17_device::ireq_w )
|
|
{
|
|
if (LOG) logerror("%s WD11C00-17 '%s' IREQ %u\n", machine().describe_context(), tag(), state);
|
|
|
|
if (state) m_status |= STATUS_REQ; else m_status &= ~STATUS_REQ;
|
|
|
|
if (m_status & STATUS_BUSY)
|
|
{
|
|
if (state)
|
|
{
|
|
m_status |= STATUS_IRQ | STATUS_I_O;
|
|
}
|
|
else
|
|
{
|
|
if (m_status & STATUS_I_O)
|
|
{
|
|
m_status &= ~(STATUS_BUSY | STATUS_I_O);
|
|
}
|
|
}
|
|
}
|
|
|
|
check_interrupt();
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// io_w -
|
|
//-------------------------------------------------
|
|
|
|
WRITE_LINE_MEMBER( wd11c00_17_device::io_w )
|
|
{
|
|
if (LOG) logerror("%s WD11C00-17 '%s' I/O %u\n", machine().describe_context(), tag(), state);
|
|
|
|
if (state) m_status |= STATUS_I_O; else m_status &= ~STATUS_I_O;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// cd_w -
|
|
//-------------------------------------------------
|
|
|
|
WRITE_LINE_MEMBER( wd11c00_17_device::cd_w )
|
|
{
|
|
if (LOG) logerror("%s WD11C00-17 '%s' C/D %u\n", machine().describe_context(), tag(), state);
|
|
|
|
if (state) m_status |= STATUS_C_D; else m_status &= ~STATUS_C_D;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// clct_w -
|
|
//-------------------------------------------------
|
|
|
|
WRITE_LINE_MEMBER( wd11c00_17_device::clct_w )
|
|
{
|
|
if (LOG) logerror("%s WD11C00-17 '%s' CLCT %u\n", machine().describe_context(), tag(), state);
|
|
|
|
if (state)
|
|
{
|
|
m_ra &= 0xff00;
|
|
check_interrupt();
|
|
}
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// mode_w -
|
|
//-------------------------------------------------
|
|
|
|
WRITE_LINE_MEMBER( wd11c00_17_device::mode_w )
|
|
{
|
|
if (LOG) logerror("%s WD11C00-17 '%s' MODE %u\n", machine().describe_context(), tag(), state);
|
|
|
|
m_mode = state;
|
|
m_ecc_not_0 = state; // HACK
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// busy_r -
|
|
//-------------------------------------------------
|
|
|
|
READ_LINE_MEMBER( wd11c00_17_device::busy_r )
|
|
{
|
|
return (m_status & STATUS_BUSY) ? 0 : 1;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// ecc_not_0_r -
|
|
//-------------------------------------------------
|
|
|
|
READ_LINE_MEMBER( wd11c00_17_device::ecc_not_0_r )
|
|
{
|
|
return m_ecc_not_0;
|
|
}
|