3c505: added lle [Patrick Mackinlay, Neko May]

LLE implementation of 3Com 3c505. Untested due to unresolved driver issues, but should replace existing HLE when tested working. (nw)
This commit is contained in:
Patrick Mackinlay 2019-04-02 09:57:16 +07:00
parent d0356891eb
commit f7fa5c89e1
3 changed files with 784 additions and 0 deletions

View File

@ -299,6 +299,7 @@ constexpr unsigned threecom3c505_device::ETH_BUFFER_SIZE;
// device type definition
DEFINE_DEVICE_TYPE(ISA16_3C505, threecom3c505_device, "3c505", "3Com 3C505 Network Adaptor")
DEFINE_DEVICE_TYPE(ISA16_3C505_LLE, isa16_3c505_device, "3c505_lle", "3Com EtherLink Plus")
//-------------------------------------------------
// threecom3c505_device - constructor
@ -1686,3 +1687,652 @@ int threecom3c505_device::setfilter(device_t *device, int node_id)
{
return 0;
}
/*
* The following device is a low-level reimplementation of the 3c505, which
* should entirely replace the HLE one above when it's been tested and proven
* working.
*
* TODO
* - testing (unable to install Domain/OS on Apollo, and not yet able to get
* 3c505.exe diagnostic program running on MS-DOS)
* - data DMA functionality unimplemented
* - externalize mac address
* - 8 bit isa slot support
* - revision 1.0 and 2.0 hardware/firmware variants
* - 8023 loopback mode
*/
#undef LOG
#undef VERBOSE
#define LOG_GENERAL (1U << 0)
#define LOG_REG (1U << 1)
#define VERBOSE (0)
#include "logmacro.h"
ROM_START(3c505)
ROM_REGION16_LE(0x04000, "system", 0)
// TODO: probably a revision 3.0 firmware dump
ROMX_LOAD("0729-12_a.3h", 0x00000, 0x02000, CRC(5415fccd) SHA1(6a42d7f3acdb3e0213e1037fee1864819ac33991), ROM_SKIP(1))
ROMX_LOAD("0729-62_a.3f", 0x00001, 0x02000, CRC(4240bd9d) SHA1(015d2f7282def85681bcf1a7c5a7f501a16d5a6c), ROM_SKIP(1))
ROM_REGION(0x02000, "host", 0)
ROM_SYSTEM_BIOS(0, "unused", "Unused")
ROM_SYSTEM_BIOS(1, "apollo", "Apollo")
ROMX_LOAD("3000_3c505_010728-00.bin", 0x00000, 0x02000, CRC(69b77ec6) SHA1(7ac36cc6fc90b90ddfc56c45303b514cbe18ae58), ROM_BIOS(1))
ROM_SYSTEM_BIOS(2, "netware", "3C505-NW EtherLink Plus NetWare Boot PROM")
ROMX_LOAD("3c505-nw.bin", 0x00000, 0x02000, NO_DUMP, ROM_BIOS(2))
ROM_END
static INPUT_PORTS_START(3c505)
PORT_START("IO_BASE")
PORT_DIPNAME(0x3f0, 0x300, "I/O Base")
PORT_DIPSETTING( 0x010, "010h")
PORT_DIPSETTING( 0x020, "020h")
PORT_DIPSETTING( 0x030, "030h")
PORT_DIPSETTING( 0x040, "040h")
PORT_DIPSETTING( 0x050, "050h")
PORT_DIPSETTING( 0x060, "060h")
PORT_DIPSETTING( 0x070, "070h")
PORT_DIPSETTING( 0x080, "080h")
PORT_DIPSETTING( 0x090, "090h")
PORT_DIPSETTING( 0x0a0, "0a0h")
PORT_DIPSETTING( 0x0b0, "0b0h")
PORT_DIPSETTING( 0x0c0, "0c0h")
PORT_DIPSETTING( 0x0d0, "0d0h")
PORT_DIPSETTING( 0x0e0, "0e0h")
PORT_DIPSETTING( 0x0f0, "0f0h")
PORT_DIPSETTING( 0x100, "0100h")
PORT_DIPSETTING( 0x110, "0110h")
PORT_DIPSETTING( 0x120, "0120h")
PORT_DIPSETTING( 0x130, "0130h")
PORT_DIPSETTING( 0x140, "0140h")
PORT_DIPSETTING( 0x150, "0150h")
PORT_DIPSETTING( 0x160, "0160h")
PORT_DIPSETTING( 0x170, "0170h")
PORT_DIPSETTING( 0x180, "0180h")
PORT_DIPSETTING( 0x190, "0190h")
PORT_DIPSETTING( 0x1a0, "01a0h")
PORT_DIPSETTING( 0x1b0, "01b0h")
PORT_DIPSETTING( 0x1c0, "01c0h")
PORT_DIPSETTING( 0x1d0, "01d0h")
PORT_DIPSETTING( 0x1e0, "01e0h")
PORT_DIPSETTING( 0x1f0, "01f0h")
PORT_DIPSETTING( 0x200, "0200h")
PORT_DIPSETTING( 0x210, "0210h")
PORT_DIPSETTING( 0x220, "0220h")
PORT_DIPSETTING( 0x230, "0230h")
PORT_DIPSETTING( 0x240, "0240h")
PORT_DIPSETTING( 0x250, "0250h")
PORT_DIPSETTING( 0x260, "0260h")
PORT_DIPSETTING( 0x270, "0270h")
PORT_DIPSETTING( 0x280, "0280h")
PORT_DIPSETTING( 0x290, "0290h")
PORT_DIPSETTING( 0x2a0, "02a0h")
PORT_DIPSETTING( 0x2b0, "02b0h")
PORT_DIPSETTING( 0x2c0, "02c0h")
PORT_DIPSETTING( 0x2d0, "02d0h")
PORT_DIPSETTING( 0x2e0, "02e0h")
PORT_DIPSETTING( 0x2f0, "02f0h")
PORT_DIPSETTING( 0x300, "0300h")
PORT_DIPSETTING( 0x310, "0310h")
PORT_DIPSETTING( 0x320, "0320h")
PORT_DIPSETTING( 0x330, "0330h")
PORT_DIPSETTING( 0x340, "0340h")
PORT_DIPSETTING( 0x350, "0350h")
PORT_DIPSETTING( 0x360, "0360h")
PORT_DIPSETTING( 0x370, "0370h")
PORT_DIPSETTING( 0x380, "0380h")
PORT_DIPSETTING( 0x390, "0390h")
PORT_DIPSETTING( 0x3a0, "03a0h")
PORT_DIPSETTING( 0x3b0, "03b0h")
PORT_DIPSETTING( 0x3c0, "03c0h")
PORT_DIPSETTING( 0x3d0, "03d0h")
PORT_DIPSETTING( 0x3e0, "03e0h")
PORT_DIPSETTING( 0x3f0, "03f0h")
PORT_START("IRQ_DRQ")
PORT_DIPNAME(0x0f, 0x0a, "IRQ")
// 8 or 16 bit slots
PORT_DIPSETTING( 0x03, "IRQ 3")
PORT_DIPSETTING( 0x04, "IRQ 4")
PORT_DIPSETTING( 0x05, "IRQ 5")
PORT_DIPSETTING( 0x06, "IRQ 6")
PORT_DIPSETTING( 0x07, "IRQ 7")
PORT_DIPSETTING( 0x09, "IRQ 9")
// 16 bit slots only
PORT_DIPSETTING( 0x0a, "IRQ 10")
PORT_DIPSETTING( 0x0b, "IRQ 11")
PORT_DIPSETTING( 0x0c, "IRQ 12")
PORT_DIPSETTING( 0x0e, "IRQ 14")
PORT_DIPSETTING( 0x0f, "IRQ 15")
// TODO: dma channel uses two jumpers for each channel: mode selection?
PORT_DIPNAME(0x70, 0x60, "DRQ")
PORT_DIPSETTING( 0x00, "none")
// 8 or 16 bit slots
PORT_DIPSETTING( 0x10, "DRQ 1")
PORT_DIPSETTING( 0x30, "DRQ 3")
// 16 bit slots only
PORT_DIPSETTING( 0x50, "DRQ 5")
PORT_DIPSETTING( 0x60, "DRQ 6")
PORT_DIPSETTING( 0x70, "DRQ 7")
// 8-position jumper block marked EN,13-19 corresponds to address line decode
PORT_START("ROM_OPTS")
PORT_DIPNAME(0x01, 0x01, "ROM Enable")
PORT_DIPSETTING( 0x00, DEF_STR(Off))
PORT_DIPSETTING( 0x01, DEF_STR(On))
PORT_DIPNAME(0xfe, 0x00, "ROM Base")
PORT_DIPSETTING( 0x00, "0000h")
PORT_DIPSETTING( 0x02, "2000h")
PORT_DIPSETTING( 0x04, "4000h")
PORT_DIPSETTING( 0x06, "6000h")
// TODO: additional addresses
PORT_START("TEST")
PORT_DIPNAME(0x01, 0x00, "TEST Mode")
PORT_DIPSETTING( 0x00, DEF_STR(Off))
PORT_DIPSETTING( 0x01, DEF_STR(On))
INPUT_PORTS_END
isa16_3c505_device::isa16_3c505_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, ISA16_3C505_LLE, tag, owner, clock)
, device_isa16_card_interface(mconfig, *this)
, m_cpu(*this, "cpu")
, m_net(*this, "net")
, m_ram(*this, "ram")
, m_led(*this, "led%u", 0U)
, m_iobase(*this, "IO_BASE")
, m_irqdrq(*this, "IRQ_DRQ")
, m_romopts(*this, "ROM_OPTS")
, m_test(*this, "TEST")
, m_installed(false)
{
}
const tiny_rom_entry *isa16_3c505_device::device_rom_region() const
{
return ROM_NAME(3c505);
}
void isa16_3c505_device::device_add_mconfig(machine_config &config)
{
I80186(config, m_cpu, 16_MHz_XTAL);
m_cpu->set_addrmap(AS_PROGRAM, &isa16_3c505_device::map_main);
m_cpu->set_addrmap(AS_IO, &isa16_3c505_device::map_io);
I82586(config, m_net, 8_MHz_XTAL);
m_net->set_addrmap(0, &isa16_3c505_device::map_main);
m_net->out_irq_cb().set(m_cpu, FUNC(i80186_cpu_device::int1_w));
// 1986 document indicates 128KiB is default, but 1988 document does not
// include it as an option
RAM(config, m_ram);
m_ram->set_default_size("256KiB");
m_ram->set_extra_options("128KiB,256KiB,384KiB,512KiB");
}
ioport_constructor isa16_3c505_device::device_input_ports() const
{
return INPUT_PORTS_NAME(3c505);
}
void isa16_3c505_device::device_start()
{
set_isa_device();
// install ram in both i80186 and i82586 address spaces
if (!m_ram->started())
throw device_missing_dependencies();
m_cpu->space(0).install_ram(0x00000, m_ram->mask() & 0xfffff, m_ram->pointer());
m_net->space(0).install_ram(0x00000, m_ram->mask() & 0xfffff, m_ram->pointer());
m_led.resolve();
save_item(NAME(m_acmdr));
save_item(NAME(m_acr));
save_item(NAME(m_asr));
save_item(NAME(m_hcmdr));
save_item(NAME(m_hcr));
save_item(NAME(m_hsr));
save_item(NAME(m_hdr));
//save_item(NAME(m_data);
save_item(NAME(m_cpu_irq_asserted));
save_item(NAME(m_isa_irq_asserted));
}
void isa16_3c505_device::device_reset()
{
if (!m_installed)
{
u16 const base = m_iobase->read();
m_isa->install16_device(base, base | 0xf,
read16_delegate(FUNC(isa16_3c505_device::host_r), this),
write16_delegate(FUNC(isa16_3c505_device::host_w), this));
m_isa_irq = m_irqdrq->read() & 0xf;
m_isa_drq = (m_irqdrq->read() >> 4) & 0x7;
if (m_romopts->read() & 1)
{
offs_t const rom_base = (m_romopts->read() & 0xfe) << 12;
m_isa->install_rom(this, rom_base, rom_base | 0x01fff, "host", "host");
}
m_installed = true;
}
m_cpu->reset();
// adapter registers
m_acmdr = 0;
m_acr = 0;
m_asr = ASR_ACRE | ASR_8_16;
if (m_test->read())
m_asr |= ASR_SWTC;
// host registers
m_hcmdr = 0;
m_hcr = 0;
m_hsr = HSR_HCRE;
m_hdr = 0;
m_data.clear();
update_rdy(m_acr, m_hcr);
m_cpu_irq_asserted = false;
m_isa_irq_asserted = false;
}
void isa16_3c505_device::map_main(address_map &map)
{
// i82586 upper 4 address lines are ignored
map.global_mask(0x0fffff);
map(0xfc000, 0xfffff).rom().region("system", 0);
}
void isa16_3c505_device::map_io(address_map &map)
{
/*
* A read or write to I/O location 00H will cause an active transition on
* the CA input.
*/
map(0x0000, 0x0000).lrw8("ca",
[this]()
{
m_net->ca(1);
m_net->ca(0);
return 0;
},
[this](u8 data)
{
m_net->ca(1);
m_net->ca(0);
});
/*
* A read or write to I/O location 80H will produce a CAS before RAS cycle
* in all banks simultaneously.
*/
map(0x0080, 0x0081).noprw();
map(0x0100, 0x0100).rw(FUNC(isa16_3c505_device::acmd_r), FUNC(isa16_3c505_device::acmd_w));
map(0x0102, 0x0102).r(FUNC(isa16_3c505_device::acr_r));
map(0x0103, 0x0103).rw(FUNC(isa16_3c505_device::asr_r), FUNC(isa16_3c505_device::acr_w));
map(0x0104, 0x0105).rw(FUNC(isa16_3c505_device::adata_r), FUNC(isa16_3c505_device::adata_w));
map(0x0180, 0x018f).lr16("mac",
[](offs_t offset)
{
// TODO: hard-code to Apollo Computer Inc. dummy address for now
static const u8 mac[] = { 0x08, 0x00, 0x1e, 0x12, 0x34, 0x56, 0xff, 0xff};
return mac[offset];
});
}
u8 isa16_3c505_device::acmd_r()
{
u8 const data = m_hcmdr;
m_asr &= ~ASR_HCRF;
m_hsr |= HSR_HCRE;
if (m_cpu_irq_asserted)
{
m_cpu_irq_asserted = false;
m_cpu->int0_w(0);
}
return data;
}
void isa16_3c505_device::acmd_w(u8 data)
{
LOGMASKED(LOG_REG, "acmd_w 0x%02x (%s)\n", data, machine().describe_context());
m_asr &= ~ASR_ACRE;
m_hsr |= HSR_ACRF;
m_acmdr = data;
if (m_hcr & HCR_CMDE)
update_irq(1);
}
void isa16_3c505_device::acr_w(u8 data)
{
LOGMASKED(LOG_REG, "acr_w 0x%02x (%s)\n", data, machine().describe_context());
// update adapter status flags
if ((data ^ m_acr) & ACR_ASF)
m_hsr = (m_hsr & ~HSR_ASF) | (data & ACR_ASF);
if ((data ^ m_acr) & ACR_LED1)
{
LOGMASKED(LOG_REG, "led #1 %s\n", (data & ACR_LED1) ? "on" : "off");
m_led[0] = !!(data & ACR_LED1);
}
if ((data ^ m_acr) & ACR_LED2)
{
LOGMASKED(LOG_REG, "led #2 %d\n", (data & ACR_LED2) ? "on" : "off");
m_led[1] = !!(data & ACR_LED2);
}
if (!(m_acr & ACR_R586) && (data & ACR_R586))
{
LOGMASKED(LOG_REG, "i82586 reset\n");
m_net->reset();
}
if ((data ^ m_acr) & ACR_FLSH)
{
if (data & ACR_FLSH)
{
LOGMASKED(LOG_REG, "adapter flushed data fifo (%d bytes)\n", m_data.queue_length());
m_data.clear();
}
update_rdy(data, m_hcr);
}
// loopback is active low
if ((m_acr & ACR_LPBK) && !(data & ACR_LPBK))
{
LOGMASKED(LOG_REG, "loopback enabled\n", m_data.queue_length());
// TODO: enable loopback on 8023
}
m_acr = data;
}
u16 isa16_3c505_device::adata_r()
{
if (!(m_asr & ASR_DIR) && !m_data.empty())
{
u16 const data = m_data.dequeue();
update_rdy(m_acr, m_hcr);
return data;
}
else
fatalerror("%s: adata_r read fifo while %s (%s)\n",
tag(), m_data.empty() ? "empty" : "write-only", machine().describe_context().c_str());
}
void isa16_3c505_device::adata_w(u16 data)
{
if ((m_asr & ASR_DIR) && !m_data.full())
{
m_data.enqueue(data);
update_rdy(m_acr, m_hcr);
}
else
fatalerror("%s: adata_w write fifo while %s (%s)\n",
tag(), m_data.full() ? "full" : "read-only", machine().describe_context().c_str());
}
READ16_MEMBER(isa16_3c505_device::host_r)
{
switch (offset)
{
case 0: return hcmd_r();
case 1: return m_hsr;
case 2: return hdata_r();
case 3: return m_hcr;
}
logerror("host_r unknown register %d (%s)\n", offset, machine().describe_context());
return space.unmap();
}
WRITE16_MEMBER(isa16_3c505_device::host_w)
{
switch (offset)
{
case 0:
hcmd_w(data);
break;
case 1:
m_hdr = data & HDR_BRST;
break;
case 2:
hdata_w(data);
break;
case 3:
hcr_w(data);
break;
default:
logerror("host_w unknown register %d data 0x%04x (%s)\n", offset, data, machine().describe_context());
break;
}
}
u8 isa16_3c505_device::hcmd_r()
{
u8 const data = m_acmdr;
m_asr |= ASR_ACRE;
m_hsr &= ~HSR_ACRF;
update_irq(0);
return data;
}
void isa16_3c505_device::hcmd_w(u8 data)
{
LOGMASKED(LOG_REG, "hcmd_w 0x%02x (%s)\n", data, machine().describe_context());
m_asr |= ASR_HCRF;
m_hsr &= ~HSR_HCRE;
m_hcmdr = data;
if (!m_cpu_irq_asserted)
{
m_cpu_irq_asserted = true;
m_cpu->int0_w(1);
}
}
void isa16_3c505_device::hcr_w(u8 data)
{
LOGMASKED(LOG_REG, "hcr_w 0x%02x (%s)\n", data, machine().describe_context());
// update host status flags
if ((data ^ m_hcr) & HCR_HSF)
m_asr = (m_asr & ~ASR_HSF) | (data & HCR_HSF);
// update direction flag
if ((data ^ m_hcr) & HCR_DIR)
{
if (data & HCR_DIR)
{
LOGMASKED(LOG_REG, "transfer from host to adapter\n");
// transfer from host to adapter
m_hsr |= HSR_DIR;
m_asr |= ASR_DIR;
update_rdy(m_acr, data);
}
else
{
LOGMASKED(LOG_REG, "transfer from adapter to host\n");
// transfer from adapter to host
m_hsr &= ~HSR_DIR;
m_asr &= ~ASR_DIR;
update_rdy(m_acr, data);
}
}
if ((data ^ m_hcr) & HCR_FLSH)
{
if (data & HCR_FLSH)
{
LOGMASKED(LOG_REG, "host flushed data fifo (%d bytes)\n", m_data.queue_length());
m_data.clear();
}
update_rdy(m_acr, data);
}
// attention condition
if (!(m_hcr & HCR_ATTN) && (data & HCR_ATTN))
{
if (!(data & HCR_FLSH))
{
LOGMASKED(LOG_REG, "soft reset\n");
// soft reset
m_cpu->set_input_line(INPUT_LINE_NMI, 1);
m_cpu->set_input_line(INPUT_LINE_NMI, 0);
}
else
{
LOGMASKED(LOG_REG, "hard reset\n");
// hard reset
reset();
}
}
m_hcr = data;
}
u16 isa16_3c505_device::hdata_r()
{
if ((m_hsr & HSR_DIR) && !m_data.empty())
{
u16 const data = m_data.dequeue();
update_rdy(m_acr, m_hcr);
return data;
}
else
fatalerror("%s: hdata_r read fifo while %s (%s)\n",
tag(), m_data.empty() ? "empty" : "write-only", machine().describe_context().c_str());
}
void isa16_3c505_device::hdata_w(u16 data)
{
if (!(m_hsr & HSR_DIR) && !m_data.full())
{
m_data.enqueue(data);
update_rdy(m_acr, m_hcr);
}
else
fatalerror("%s: hdata_w write fifo while %s (%s)\n",
tag(), m_data.full() ? "full" : "read-only", machine().describe_context().c_str());
}
void isa16_3c505_device::update_rdy(u8 const acr, u8 const hcr)
{
if (!(acr & ACR_FLSH) && !(hcr & HCR_FLSH))
{
if (hcr & HCR_DIR)
{
// adapter to host
if (m_data.empty())
m_hsr &= ~HSR_HRDY;
else
m_hsr |= HSR_HRDY;
if (m_data.full())
m_asr &= ~ASR_ARDY;
else
m_asr |= ASR_ARDY;
}
else
{
// host to adapter
if (m_data.empty())
m_asr &= ~ASR_ARDY;
else
m_asr |= ASR_ARDY;
if (m_data.full())
m_hsr &= ~HSR_HRDY;
else
m_hsr |= HSR_HRDY;
}
}
else
{
m_asr &= ~ASR_ARDY;
m_hsr &= ~HSR_HRDY;
}
}
void isa16_3c505_device::update_irq(int state)
{
if (bool(state) != m_isa_irq_asserted)
{
LOG("isa irq %d\n", state);
switch (m_isa_irq)
{
case 3: m_isa->irq3_w(state); break;
case 4: m_isa->irq4_w(state); break;
case 5: m_isa->irq5_w(state); break;
case 6: m_isa->irq6_w(state); break;
case 7: m_isa->irq7_w(state); break;
case 9: m_isa->irq2_w(state); break;
case 10: m_isa->irq10_w(state); break;
case 11: m_isa->irq11_w(state); break;
case 12: m_isa->irq12_w(state); break;
case 14: m_isa->irq14_w(state); break;
case 15: m_isa->irq15_w(state); break;
default:
fatalerror("%s: invalid isa irq %d\n", tag(), m_isa_irq);
}
m_isa_irq_asserted = bool(state);
}
}

View File

@ -13,6 +13,10 @@
#pragma once
#include "cpu/i86/i186.h"
#include "machine/i82586.h"
#include "machine/ram.h"
#include "bus/isa/isa.h"
// ======================> PCB data structure
@ -276,7 +280,136 @@ private:
int m_irq, m_drq;
};
class isa16_3c505_device
: public device_t
, public device_isa16_card_interface
{
public:
isa16_3c505_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
DECLARE_READ16_MEMBER(host_r);
DECLARE_WRITE16_MEMBER(host_w);
protected:
// device_t overrides
virtual const tiny_rom_entry *device_rom_region() const override;
virtual void device_add_mconfig(machine_config &config) override;
virtual ioport_constructor device_input_ports() const override;
virtual void device_start() override;
virtual void device_reset() override;
void map_main(address_map &map);
void map_io(address_map &map);
enum acr_mask : u8
{
ACR_ASF1 = 0x01, // adapter status flag 1
ACR_ASF2 = 0x02, // adapter status flag 2
ACR_ASF3 = 0x04, // adapter status flag 3
ACR_LED1 = 0x08, // led control 1
ACR_LED2 = 0x10, // led control 2
ACR_R586 = 0x20, // reset 82586
ACR_FLSH = 0x40, // flush data register
ACR_LPBK = 0x80, // loopback control
ACR_ASF = 0x07,
};
enum asr_mask : u8
{
ASR_HSF1 = 0x01, // host status flag 1
ASR_HSF2 = 0x02, // host status flag 2
ASR_SWTC = 0x04, // external switch
ASR_8_16 = 0x08, // 8/16 bit
ASR_DIR = 0x10, // direction flag
ASR_HCRF = 0x20, // host command register full
ASR_ACRE = 0x40, // adapter command register empty
ASR_ARDY = 0x80, // data register ready
ASR_HSF = 0x03,
};
enum hcr_mask : u8
{
HCR_HSF1 = 0x01, // host status flag 1
HCR_HSF2 = 0x02, // host status flag 2
HCR_CMDE = 0x04, // command register interrupt enable
HCR_TCEN = 0x08, // terminal count interrupt enable
HCR_DIR = 0x10, // direction flag
HCR_DMAE = 0x20, // dma enable
HCR_FLSH = 0x40, // flush data register
HCR_ATTN = 0x80, // attention
HCR_HSF = 0x03,
};
enum hsr_mask : u8
{
HSR_ASF1 = 0x01, // adapter status flag 1
HSR_ASF2 = 0x02, // adapter status flag 2
HSR_ASF3 = 0x04, // adapter status flag 3
HSR_DONE = 0x08, // dma done
HSR_DIR = 0x10, // direction
HSR_ACRF = 0x20, // adapter command register full
HSR_HCRE = 0x40, // host command register empty
HSR_HRDY = 0x80, // data register ready
HSR_ASF = 0x07,
};
enum hdr_mask : u8
{
HDR_BRST = 0x01, // dma burst
};
// adapter register helpers
u8 acmd_r();
u8 acr_r() { return m_acr; };
u8 asr_r() { return m_asr; };
u16 adata_r();
void acmd_w(u8 data);
void acr_w(u8 data);
void adata_w(u16 data);
// host register helpers
u8 hcmd_r();
u16 hdata_r();
void hcmd_w(u8 data);
void hcr_w(u8 data);
void hdata_w(u16 data);
void update_irq(int state);
void update_rdy(u8 const acr, u8 const hcr);
private:
required_device<i80186_cpu_device> m_cpu;
required_device<i82586_device> m_net;
required_device<ram_device> m_ram;
output_finder<2> m_led;
required_ioport m_iobase;
required_ioport m_irqdrq;
required_ioport m_romopts;
required_ioport m_test;
u8 m_acmdr; // adapter command register
u8 m_acr; // adapter control register
u8 m_asr; // adapter status register
u8 m_hcmdr; // host command register
u8 m_hcr; // host control register
u8 m_hsr; // host status register
u8 m_hdr; // host aux dma register
util::fifo<u16, 10> m_data;
unsigned m_isa_irq;
unsigned m_isa_drq;
bool m_cpu_irq_asserted;
bool m_isa_irq_asserted;
bool m_installed;
};
// device type definition
DECLARE_DEVICE_TYPE(ISA16_3C505, threecom3c505_device)
DECLARE_DEVICE_TYPE(ISA16_3C505_LLE, isa16_3c505_device)
#endif // MAME_BUS_ISA_3C505_H

View File

@ -176,6 +176,7 @@ void pc_isa16_cards(device_slot_interface &device)
device.option_add("gfxultrap", ISA16_SVGA_GFXULTRAPRO);
device.option_add("tgui9680",ISA16_SVGA_TGUI9680);
device.option_add("3c505", ISA16_3C505);
device.option_add("3c505_lle", ISA16_3C505_LLE);
device.option_add("mach64", ISA16_SVGA_MACH64);
device.option_add("sb16_lle", ISA16_SB16);
device.option_add("mcd", ISA16_MCD);