summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author R. Belmont <rb6502@users.noreply.github.com>2017-09-05 14:42:08 -0400
committer GitHub <noreply@github.com>2017-09-05 14:42:08 -0400
commit1908ac9eeec3d33b23743057beaac4f2213d0eb7 (patch)
tree6dc952cc02468e0ff289a61522ce71330c576f94
parent8772759a4c5788bd537d7d1876795e4fbcb51f92 (diff)
parent341a20ddfe94eccc8ef2959d027d97651a21a0b5 (diff)
Merge pull request #2631 from pmackinlay/i82586
i82586: fixed 82586 initialisation
-rw-r--r--src/devices/machine/i82586.cpp47
-rw-r--r--src/devices/machine/i82586.h17
2 files changed, 38 insertions, 26 deletions
diff --git a/src/devices/machine/i82586.cpp b/src/devices/machine/i82586.cpp
index 6efd2ee9dd7..4e55b61b8bd 100644
--- a/src/devices/machine/i82586.cpp
+++ b/src/devices/machine/i82586.cpp
@@ -13,7 +13,7 @@
*
* This implementation should cover all of the above reasonably well, but
* no testing of big endian mode in particular, and very limited testing
-* of the 82586 or 82596 in non-linear modes has been done so far.
+* of the 82596 in non-linear modes has been done so far.
*
* Some documents covering the above include:
*
@@ -22,7 +22,7 @@
* https://www.intel.com/assets/pdf/general/82596ca.pdf
*
* TODO
-* - testing for 82586 and 82596 big endian and non-linear modes
+* - testing for 82596 big endian and non-linear modes
* - more complete statistics capturing
* - 82596 monitor mode
* - throttle timers and diagnostic command
@@ -419,8 +419,10 @@ void i82586_base_device::cu_execute()
break;
case CB_TRANSMIT:
+ // always turn on the heartbeat indicator status after a successful transmission; not
+ // strictly correct, but allows one InterPro 2000 diagnostic to pass
if (cu_transmit(cb_cs))
- cb_cs |= CB_OK;
+ cb_cs |= CB_OK | CB_S6;
break;
case CB_TDREFLECT:
@@ -758,14 +760,18 @@ void i82586_device::device_reset()
void i82586_device::initialise()
{
- u16 scb_offset = m_space->read_word(m_scp_address + 2);
+ // read iscp address from scp
+ u32 iscp_address = m_space->read_dword(m_scp_address + 8);
+ LOG("initialise iscp address 0x%08x\n", iscp_address);
+
+ u16 scb_offset = m_space->read_word(iscp_address + 2);
- m_scb_base = m_space->read_dword(m_scp_address + 4);
- m_scb_address = (m_scb_base + scb_offset);
+ m_scb_base = m_space->read_dword(iscp_address + 4);
+ m_scb_address = m_scb_base + scb_offset;
LOG("initialise scb base address 0x%06x offset 0x%04x address 0x%08x\n", m_scb_base, scb_offset, m_scb_address);
// clear iscp busy byte
- m_space->write_byte(m_scp_address, 0);
+ m_space->write_byte(iscp_address, 0);
m_cx = true;
m_cna = true;
@@ -890,9 +896,9 @@ bool i82586_device::cu_transmit(u32 command)
{
u16 tbd_count;
- // ethernet frame buffer (rounded up to 8 byte boundary)
- u8 buf[1528];
- int length = 0;
+ // ethernet frame buffer
+ u8 buf[MAX_FRAME_SIZE];
+ u16 length = 0;
u16 tbd_offset = m_space->read_word(m_cba + 6);
@@ -1184,7 +1190,6 @@ void i82596_device::device_start()
save_item(NAME(m_cfg_bytes));
save_item(NAME(m_sysbus));
- save_item(NAME(m_iscp_address));
save_item(NAME(m_mac_multi_ia));
}
@@ -1230,9 +1235,9 @@ void i82596_device::port(u32 data)
void i82596_device::initialise()
{
- // read sysbus and iscp address from scp
+ // read iscp address and sysbus from scp
+ u32 iscp_address = m_space->read_dword(m_scp_address + 8);
m_sysbus = m_space->read_byte(m_scp_address + 2);
- m_iscp_address = m_space->read_dword(m_scp_address + 8);
LOG("initialise sysbus 0x%02x mode %s, %s triggering of bus throttle timers, lock function %s, interrupt active %s, 32-bit address pointers in linear mode per %s stepping)\n",
m_sysbus,
@@ -1241,29 +1246,29 @@ void i82596_device::initialise()
m_sysbus & SYSBUS_LOCK ? "disabled" : "enabled",
m_sysbus & SYSBUS_INT ? "low" : "high",
m_sysbus & SYSBUS_BE ? "B" : "A1");
- LOG("initialise iscp address 0x%08x\n", m_iscp_address);
+ LOG("initialise iscp address 0x%08x\n", iscp_address);
switch (mode())
{
case MODE_82586:
case MODE_32SEGMENTED:
{
- u16 scb_offset = m_space->read_word(m_iscp_address + 2);
+ u16 scb_offset = m_space->read_word(iscp_address + 2);
- m_scb_base = m_space->read_dword(m_iscp_address + 4);
+ m_scb_base = m_space->read_dword(iscp_address + 4);
m_scb_address = m_scb_base + scb_offset;
LOG("initialise scb base address 0x%08x offset 0x%04x address 0x%08x\n", m_scb_base, scb_offset, m_scb_address);
}
break;
case MODE_LINEAR:
- m_scb_address = m_space->read_dword(m_iscp_address + 4);
+ m_scb_address = m_space->read_dword(iscp_address + 4);
LOG("initialise scb address 0x%08x\n", m_scb_address);
break;
}
// clear iscp busy byte
- m_space->write_byte(m_iscp_address, 0);
+ m_space->write_byte(iscp_address, 0);
m_cx = true;
m_cna = true;
@@ -1505,9 +1510,9 @@ bool i82596_device::cu_transmit(u32 command)
u32 tbd_address;
u16 tcb_count, tbd_count;
- // ethernet frame buffer (rounded up to 8 byte boundary)
- u8 buf[1528];
- int length = 0;
+ // ethernet frame buffer
+ u8 buf[MAX_FRAME_SIZE];
+ u16 length = 0;
// need offset into tcb for linear mode
int offset = mode() == MODE_LINEAR ? 4 : 0;
diff --git a/src/devices/machine/i82586.h b/src/devices/machine/i82586.h
index 1f002951fc9..60ee47bd936 100644
--- a/src/devices/machine/i82586.h
+++ b/src/devices/machine/i82586.h
@@ -70,7 +70,13 @@ public:
enum cu_cb_cs_mask
{
- CB_MAXCOL = 0x00000007, // number of collisions (82596 only)
+ CB_MAXCOL = 0x0000000f, // number of collisions
+ CB_S5 = 0x00000020, // transmission unsuccessful due to maximum collision retries
+ CB_S6 = 0x00000040, // heart beat indicator
+ CB_S7 = 0x00000080, // transmission deferred due to traffic on link
+ CB_S8 = 0x00000100, // transmission unsuccessful due to dma underrun
+ CB_S9 = 0x00000200, // transmission unsuccessful due to loss of cts
+ CB_S10 = 0x00000400, // no carrier sense during transmission
CB_A = 0x00001000, // command aborted
CB_OK = 0x00002000, // error free completion
CB_B = 0x00004000, // busy executing command
@@ -147,6 +153,7 @@ public:
static const u32 SCP_ADDRESS = 0x00fffff4; // the default value of the system configuration pointer
static const u32 TBD_EMPTY = 0x0000ffff; // FIXME: datasheet says this field should be "all 1's", but InterPro sets only lower 16 bits (in linear mode)
static const u32 RBD_EMPTY = 0x0000ffff;
+ static const int MAX_FRAME_SIZE = 65536; // real device effectively has no limit, emulation relies on index wrapping
static const u32 FCS_RESIDUE = 0xdebb20e3; // the residue after computing the fcs over a complete frame (including fcs)
@@ -221,9 +228,10 @@ protected:
u32 m_cba; // current command block address
u32 m_rfd; // current receive frame descriptor address
- u64 m_mac_multi; // multicast address hash table
- u8 m_lb_buf[1528]; // storage for loopback frames
- int m_lb_length; // length of loopback frame
+ u64 m_mac_multi; // multicast address hash table
+
+ u8 m_lb_buf[MAX_FRAME_SIZE]; // storage for loopback frames
+ u16 m_lb_length; // length of loopback frame (relies on wrapping to match 64k max buffer size)
// configure parameters
enum lb_mode
@@ -350,7 +358,6 @@ private:
u8 m_cfg_bytes[CFG_SIZE];
u8 m_sysbus;
- u32 m_iscp_address;
u64 m_mac_multi_ia; // multi-ia address hash table
};