Retiring my original NCR5380 implementation. [R. Belmont, AJR]

This commit is contained in:
arbee 2021-05-08 16:55:52 -04:00
parent 3ee1c18a65
commit e13ea1cd39
5 changed files with 0 additions and 504 deletions

View File

@ -3788,18 +3788,6 @@ if (MACHINES["I8255"]~=null) then
}
end
---------------------------------------------------
--
--@src/devices/machine/ncr5380.h,MACHINES["NCR5380"] = true
---------------------------------------------------
if (MACHINES["NCR5380"]~=null) then
files {
MAME_DIR .. "src/devices/machine/ncr5380.cpp",
MAME_DIR .. "src/devices/machine/ncr5380.h",
}
end
---------------------------------------------------
--
--@src/devices/machine/ncr5380n.h,MACHINES["NCR5380N"] = true

View File

@ -589,7 +589,6 @@ MACHINES["MSM5832"] = true
MACHINES["MSM58321"] = true
MACHINES["MSM6242"] = true
MACHINES["MSM6253"] = true
--MACHINES["NCR5380"] = true
MACHINES["NCR5380N"] = true
MACHINES["NCR5390"] = true
MACHINES["NCR539x"] = true

View File

@ -620,7 +620,6 @@ MACHINES["MSM58321"] = true
MACHINES["MSM6242"] = true
--MACHINES["MSM6253"] = true
MACHINES["MYB3K_KEYBOARD"] = true
MACHINES["NCR5380"] = true
MACHINES["NCR5380N"] = true
MACHINES["NCR5385"] = true
MACHINES["NCR5390"] = true

View File

@ -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;
}
}

View File

@ -1,70 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:R. Belmont
/*
* ncr5380.h SCSI controller
*
*/
#ifndef MAME_MACHINE_NCR5380_H
#define MAME_MACHINE_NCR5380_H
#pragma once
#include "legscsi.h"
// 5380 registers
enum
{
R5380_CURDATA = 0, // current SCSI data (read only)
R5380_OUTDATA = 0, // output data (write only)
R5380_INICOMMAND, // initiator command
R5380_MODE, // mode
R5380_TARGETCMD, // target command
R5380_SELENABLE, // select enable (write only)
R5380_BUSSTATUS = R5380_SELENABLE, // bus status (read only)
R5380_STARTDMA, // start DMA send (write only)
R5380_BUSANDSTAT = R5380_STARTDMA, // bus and status (read only)
R5380_DMATARGET, // DMA target (write only)
R5380_INPUTDATA = R5380_DMATARGET, // input data (read only)
R5380_DMAINIRECV, // DMA initiator receive (write only)
R5380_RESETPARITY = R5380_DMAINIRECV // reset parity/interrupt (read only)
};
// special Mac Plus registers - they implemented it weird
#define R5380_OUTDATA_DTACK (R5380_OUTDATA | 0x10)
#define R5380_CURDATA_DTACK (R5380_CURDATA | 0x10)
// device stuff
class ncr5380_device : public legacy_scsi_host_adapter
{
public:
// construction/destruction
ncr5380_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
auto irq_callback() { return m_irq_cb.bind(); }
// our API
uint8_t ncr5380_read_reg(uint32_t offset);
void ncr5380_write_reg(uint32_t offset, uint8_t data);
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
virtual void device_stop() override;
private:
uint8_t m_5380_Registers[8];
uint8_t m_last_id;
uint8_t m_5380_Command[32];
int32_t m_cmd_ptr, m_d_ptr, m_d_limit, m_next_req_flag;
uint8_t m_5380_Data[512];
devcb_write_line m_irq_cb; /* irq callback */
};
// device type definition
DECLARE_DEVICE_TYPE(NCR5380, ncr5380_device)
#endif // MAME_MACHINE_NCR5380_H