summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/ncr5380.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/ncr5380.cpp')
-rw-r--r--src/devices/machine/ncr5380.cpp420
1 files changed, 0 insertions, 420 deletions
diff --git a/src/devices/machine/ncr5380.cpp b/src/devices/machine/ncr5380.cpp
deleted file mode 100644
index adc309f6b60..00000000000
--- a/src/devices/machine/ncr5380.cpp
+++ /dev/null
@@ -1,420 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:R. Belmont
-/*
- * ncr5380.c
- *
- * NCR 5380 SCSI controller, as seen in many 680x0 Macs,
- * official Apple add-on cards for the Apple II series,
- * and probably some PC and Amiga cards as well.
- *
- * Emulation by R. Belmont.
- *
- * References:
- * Zilog 5380 manual
- * "Inside Macintosh: Devices" (formerly online at http://www.manolium.org/dev/techsupport/insidemac/Devices/Devices-2.html )
- *
- * NOTES:
- * This implementation is tied closely to the drivers found in the Mac Plus ROM and the routines in Mac
- * System 6 and 7 that it patches out the ROM traps with. While attempts have been made to
- * have the behavior work according to the manual and not the specific Apple driver code,
- * there are almost certainly areas where that is true.
- *
- */
-
-#include "emu.h"
-#include "ncr5380.h"
-
-//#define VERBOSE 1
-#include "logmacro.h"
-
-
-static const char *const rnames[] =
-{
- "Current data",
- "Initiator cmd",
- "Mode",
- "Target cmd",
- "Bus status",
- "Bus and status",
- "Input data",
- "Reset parity"
-};
-
-static const char *const wnames[] =
-{
- "Output data",
- "Initiator cmd",
- "Mode",
- "Target cmd",
- "Select enable",
- "Start DMA",
- "DMA target",
- "DMA initiator rec"
-};
-
-// get the length of a SCSI command based on it's command byte type
-static int get_cmd_len(int cbyte)
-{
- int group;
-
- group = (cbyte>>5) & 7;
-
- if (group == 0) return 6;
- if (group == 1 || group == 2) return 10;
- if (group == 5) return 12;
-
- fatalerror("NCR5380: Unknown SCSI command group %d\n", group);
-
- // never executed
- //return 6;
-}
-
-
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(NCR5380, ncr5380_device, "ncr5380", "NCR 5380 SCSI")
-
-//-------------------------------------------------
-// ncr5380_device - constructor/destructor
-//-------------------------------------------------
-
-ncr5380_device::ncr5380_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- legacy_scsi_host_adapter(mconfig, NCR5380, tag, owner, clock),
- m_irq_cb(*this)
-{
-}
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void ncr5380_device::device_start()
-{
- legacy_scsi_host_adapter::device_start();
-
- memset(m_5380_Registers, 0, sizeof(m_5380_Registers));
- memset(m_5380_Data, 0, sizeof(m_5380_Data));
-
- m_next_req_flag = 0;
- m_irq_cb.resolve_safe();
-
- save_item(NAME(m_5380_Registers));
- save_item(NAME(m_5380_Command));
- save_item(NAME(m_5380_Data));
- save_item(NAME(m_last_id));
- save_item(NAME(m_cmd_ptr));
- save_item(NAME(m_d_ptr));
- save_item(NAME(m_d_limit));
- save_item(NAME(m_next_req_flag));
-}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void ncr5380_device::device_reset()
-{
- memset(m_5380_Registers, 0, sizeof(m_5380_Registers));
- memset(m_5380_Data, 0, sizeof(m_5380_Data));
-
- m_next_req_flag = 0;
- m_cmd_ptr = 0;
- m_d_ptr = 0;
- m_d_limit = 0;
- m_last_id = 0;
-}
-
-//-------------------------------------------------
-// device_stop - device-specific stop/shutdown
-//-------------------------------------------------
-void ncr5380_device::device_stop()
-{
-}
-
-//-------------------------------------------------
-// Public API
-//-------------------------------------------------
-uint8_t ncr5380_device::ncr5380_read_reg(uint32_t offset)
-{
- int reg = offset & 7;
- uint8_t rv;
-
- switch( reg )
- {
- case R5380_CURDATA:
- case R5380_INPUTDATA:
- rv = m_5380_Registers[reg];
-
- // if we're in the data transfer phase or DMA, readback device data instead
- if (((m_5380_Registers[R5380_BUSSTATUS] & 0x1c) == 0x04) || (m_5380_Registers[R5380_BUSSTATUS] & 0x40))
- {
- rv = m_5380_Data[m_d_ptr];
-
- // if the limit's less than 512, only read "limit" bytes
- if (m_d_limit < 512)
- {
- if (m_d_ptr < (m_d_limit-1))
- {
- m_d_ptr++;
- }
- else
- {
- m_next_req_flag = 1;
- }
- }
- else
- {
- if (m_d_ptr < 511)
- {
- m_d_ptr++;
- }
- else
- {
- m_d_limit -= 512;
- m_d_ptr = 0;
-
- m_next_req_flag = 1;
-
- // don't issue a "false" read
- if (m_d_limit > 0)
- {
- read_data(m_5380_Data, (m_d_limit < 512) ? m_d_limit : 512);
- }
- else
- {
- // if this is DMA, signal DMA end
- if (m_5380_Registers[R5380_BUSSTATUS] & 0x40)
- {
- m_5380_Registers[R5380_BUSSTATUS] |= 0x80;
- }
-
- // drop /REQ
- m_5380_Registers[R5380_BUSSTATUS] &= ~0x20;
-
- // clear phase match
- m_5380_Registers[R5380_BUSANDSTAT] &= ~0x08;
- }
- }
- }
-
- }
- break;
-
- default:
- rv = m_5380_Registers[reg];
-
- // temporarily drop /REQ
- if ((reg == R5380_BUSSTATUS) && (m_next_req_flag))
- {
- rv &= ~0x20;
- m_next_req_flag = 0;
- }
- break;
- }
-
- LOG("%s NCR5380: read %s (reg %d) = %02x\n", machine().describe_context(), rnames[reg], reg, rv);
-
- return rv;
-}
-
-void ncr5380_device::ncr5380_write_reg(uint32_t offset, uint8_t data)
-{
- int reg = offset & 7;
-
- LOG("%s NCR5380: %02x to %s (reg %d)\n", machine().describe_context(), data, wnames[reg], reg);
-
- switch( reg )
- {
- case R5380_OUTDATA:
- // if we're in the command phase, collect the command bytes
- if ((m_5380_Registers[R5380_BUSSTATUS] & 0x1c) == 0x08)
- {
- m_5380_Command[m_cmd_ptr++] = data;
- }
-
- // if we're in the select phase, this is the target id
- if (m_5380_Registers[R5380_INICOMMAND] == 0x04)
- {
- data &= 0x7f; // clear the high bit
- if (data == 0x40)
- {
- m_last_id = 6;
- }
- else if (data == 0x20)
- {
- m_last_id = 5;
- }
- else if (data == 0x10)
- {
- m_last_id = 4;
- }
- else if (data == 0x08)
- {
- m_last_id = 3;
- }
- else if (data == 0x04)
- {
- m_last_id = 2;
- }
- else if (data == 0x02)
- {
- m_last_id = 1;
- }
- else if (data == 0x01)
- {
- m_last_id = 0;
- }
- }
-
- // if this is a write, accumulate accordingly
- if (((m_5380_Registers[R5380_BUSSTATUS] & 0x1c) == 0x00) && (m_5380_Registers[R5380_INICOMMAND] == 1))
- {
- m_5380_Data[m_d_ptr] = data;
-
- // if we've hit a sector, flush
- if (m_d_ptr == 511)
- {
- write_data(&m_5380_Data[0], 512);
-
- m_d_limit -= 512;
- m_d_ptr = 0;
-
- // no more data? set DMA END flag
- if (m_d_limit <= 0)
- {
- m_5380_Registers[R5380_BUSANDSTAT] = 0xc8;
- }
- }
- else
- {
- m_d_ptr++;
- }
-
- // make sure we don't upset the status readback
- data = 0;
- }
- break;
-
- case R5380_INICOMMAND:
- if (data == 0) // dropping the bus
- {
- // make sure it's not busy
- m_5380_Registers[R5380_BUSSTATUS] &= ~0x40;
-
- // are we in the command phase?
- if ((m_5380_Registers[R5380_BUSSTATUS] & 0x1c) == 0x08)
- {
- // is the current command complete?
- if (get_cmd_len(m_5380_Command[0]) == m_cmd_ptr)
- {
- LOG("%s NCR5380: Command (to ID %d): %x %x %x %x %x %x %x %x %x %x\n", machine().describe_context(), m_last_id, m_5380_Command[0], m_5380_Command[1], m_5380_Command[2], m_5380_Command[3], m_5380_Command[4], m_5380_Command[5], m_5380_Command[6], m_5380_Command[7], m_5380_Command[8], m_5380_Command[9]);
-
- send_command(&m_5380_Command[0], 16);
- m_d_limit = get_length();
-
- LOG("NCR5380: Command returned %d bytes\n", m_d_limit);
-
- m_d_ptr = 0;
-
- // is data available?
- if (m_d_limit > 0)
- {
- // make sure for transfers under 512 bytes that we always pad with a zero
- if (m_d_limit < 512)
- {
- m_5380_Data[m_d_limit] = 0;
- }
-
- // read back the amount available, or 512 bytes, whichever is smaller
- read_data(m_5380_Data, (m_d_limit < 512) ? m_d_limit : 512);
-
- // raise REQ to indicate data is available
- m_5380_Registers[R5380_BUSSTATUS] |= 0x20;
- }
- }
- }
-
- }
-
- if (data == 5) // want the bus?
- {
- // if the device exists, make the bus busy.
- // otherwise don't.
-
- if (select(m_last_id))
- {
- LOG("NCR5380: Giving the bus for ID %d\n", m_last_id);
- m_5380_Registers[R5380_BUSSTATUS] |= 0x40;
- }
- else
- {
- LOG("NCR5380: Rejecting the bus for ID %d\n", m_last_id);
- m_5380_Registers[R5380_BUSSTATUS] &= ~0x40;
- }
- }
-
- if (data == 1) // data bus (prelude to command?)
- {
- // raise REQ
- m_5380_Registers[R5380_BUSSTATUS] |= 0x20;
- }
-
- if (data & 0x10) // ACK drops REQ
- {
- // drop REQ
- m_5380_Registers[R5380_BUSSTATUS] &= ~0x20;
- }
- break;
-
- case R5380_MODE:
- if (data == 2) // DMA
- {
- // put us in DMA mode
- m_5380_Registers[R5380_BUSANDSTAT] |= 0x40;
- }
-
- if (data == 1) // arbitrate?
- {
- m_5380_Registers[R5380_INICOMMAND] |= 0x40; // set arbitration in progress
- m_5380_Registers[R5380_INICOMMAND] &= ~0x20; // clear "lost arbitration"
- }
-
- if (data == 0)
- {
- // drop DMA mode
- m_5380_Registers[R5380_BUSANDSTAT] &= ~0x40;
- }
- break;
-
- case R5380_TARGETCMD:
- // sync the bus phase with what was just written
- m_5380_Registers[R5380_BUSSTATUS] &= ~0x1c;
- m_5380_Registers[R5380_BUSSTATUS] |= (data & 7)<<2;
-
- // and set the "phase match" flag
- m_5380_Registers[R5380_BUSANDSTAT] |= 0x08;
-
- // and set /REQ
- m_5380_Registers[R5380_BUSSTATUS] |= 0x20;
-
- // if we're entering the command phase, start accumulating the data
- if ((m_5380_Registers[R5380_BUSSTATUS] & 0x1c) == 0x08)
- {
- m_cmd_ptr = 0;
- }
- break;
-
- default:
- break;
- }
-
- m_5380_Registers[reg] = data;
-
- // note: busandstat overlaps startdma, so we need to do this here!
- if (reg == R5380_STARTDMA)
- {
- m_5380_Registers[R5380_BUSANDSTAT] = 0x48;
- }
-}