summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--src/devices/machine/dp83932c.cpp88
-rw-r--r--src/devices/machine/dp83932c.h4
2 files changed, 58 insertions, 34 deletions
diff --git a/src/devices/machine/dp83932c.cpp b/src/devices/machine/dp83932c.cpp
index efe877ca4d2..e6ddf1c11c3 100644
--- a/src/devices/machine/dp83932c.cpp
+++ b/src/devices/machine/dp83932c.cpp
@@ -149,7 +149,7 @@ int dp83932c_device::recv_start_cb(u8 *buf, int length)
if (m_reg[CRDA] & 1)
{
// re-read the previous descriptor link field
- m_reg[CRDA] = m_bus->read_word(EA(m_reg[URDA], m_reg[LLFA]));
+ m_reg[CRDA] = read_bus_word(EA(m_reg[URDA], m_reg[LLFA]));
if (m_reg[CRDA] & 1)
{
logerror("no receive descriptor available\n");
@@ -182,19 +182,19 @@ int dp83932c_device::recv_start_cb(u8 *buf, int length)
// write status to rda
// TODO: don't write the rda if rba limit exceeded (buffer overflow)
offs_t const rda = EA(m_reg[URDA], m_reg[CRDA]);
- m_bus->write_word(rda + 0 * width, m_reg[RCR]);
- m_bus->write_word(rda + 1 * width, length);
- m_bus->write_word(rda + 2 * width, m_reg[CRBA0]);
- m_bus->write_word(rda + 3 * width, m_reg[CRBA1]);
- m_bus->write_word(rda + 4 * width, m_reg[RSC]);
+ write_bus_word(rda + 0 * width, m_reg[RCR]);
+ write_bus_word(rda + 1 * width, length);
+ write_bus_word(rda + 2 * width, m_reg[CRBA0]);
+ write_bus_word(rda + 3 * width, m_reg[CRBA1]);
+ write_bus_word(rda + 4 * width, m_reg[RSC]);
m_reg[LLFA] = m_reg[CRDA] + 5 * width;
- m_reg[CRDA] = m_bus->read_word(rda + 5 * width);
+ m_reg[CRDA] = read_bus_word(rda + 5 * width);
// check for end of list
if (m_reg[CRDA] & 1)
m_reg[ISR] |= ISR_RDE;
else
- m_bus->write_word(rda + 6 * width, 0);
+ write_bus_word(rda + 6 * width, 0);
// handle buffer exhaustion
if (rbwc < m_reg[EOBC])
@@ -231,11 +231,8 @@ void dp83932c_device::reg_w(offs_t offset, u16 data)
m_reg[CR] &= ~CR_RST;
}
-
- return;
}
-
- if (data & CR_RST)
+ else if (data & CR_RST)
{
LOGMASKED(LOG_COMMAND, "enter software reset\n");
@@ -243,12 +240,22 @@ void dp83932c_device::reg_w(offs_t offset, u16 data)
m_reg[CR] &= ~(CR_LCAM | CR_RRRA | CR_TXP | CR_HTX);
m_reg[CR] |= (CR_RST | CR_RXDIS);
-
- return;
}
-
- m_reg[offset] |= data & regmask[offset];
- m_command->adjust(attotime::zero, data & regmask[offset]);
+ else
+ {
+ u16 cmd_to_run = data & regmask[offset];
+ if (m_reg[CR] & CR_TXP)
+ {
+ // Per section 3.5.4 in the datasheet, TDAs can be dynamically added.
+ // The TXP command will be re-sent by the host, but doesn't do anything
+ // unless the SONIC finished the last commmand right before the TDA was
+ // appended to the list. So, null the CR_TXP bit if it was already set
+ // so we don't smash the currently running transmission.
+ cmd_to_run &= ~CR_TXP;
+ }
+ m_reg[offset] |= data & regmask[offset];
+ m_command->adjust(attotime::zero, cmd_to_run);
+ }
break;
case RCR:
@@ -349,9 +356,9 @@ void dp83932c_device::transmit()
// read control information from tda and load registers
u16 const tcr = m_reg[TCR];
- m_reg[TCR] = m_bus->read_word(tda + word++ * width) & TCR_TPC;
- m_reg[TPS] = m_bus->read_word(tda + word++ * width);
- m_reg[TFC] = m_bus->read_word(tda + word++ * width);
+ m_reg[TCR] = read_bus_word(tda + word++ * width) & TCR_TPC;
+ m_reg[TPS] = read_bus_word(tda + word++ * width);
+ m_reg[TFC] = read_bus_word(tda + word++ * width);
// check for programmable interrupt
if ((m_reg[TCR] & TCR_PINT) && !(tcr & TCR_PINT))
@@ -365,9 +372,9 @@ void dp83932c_device::transmit()
for (unsigned fragment = 0; fragment < m_reg[TFC]; fragment++)
{
// read fragment address and size
- m_reg[TSA0] = m_bus->read_word(tda + word++ * width);
- m_reg[TSA1] = m_bus->read_word(tda + word++ * width);
- m_reg[TFS] = m_bus->read_word(tda + word++ * width);
+ m_reg[TSA0] = read_bus_word(tda + word++ * width);
+ m_reg[TSA1] = read_bus_word(tda + word++ * width);
+ m_reg[TFS] = read_bus_word(tda + word++ * width);
offs_t const tsa = EA(m_reg[TSA1], m_reg[TSA0]);
@@ -407,13 +414,13 @@ void dp83932c_device::send_complete_cb(int result)
}
// write descriptor status
- m_bus->write_word(EA(m_reg[UTDA], m_reg[TTDA]), m_reg[TCR] & TCR_TPS);
+ write_bus_word(EA(m_reg[UTDA], m_reg[TTDA]), m_reg[TCR] & TCR_TPS);
// check for halt
if (!(m_reg[CR] & CR_HTX))
{
// load next descriptor address
- m_reg[CTDA] = m_bus->read_word(EA(m_reg[UTDA], m_reg[CTDA]));
+ m_reg[CTDA] = read_bus_word(EA(m_reg[UTDA], m_reg[CTDA]));
// check for end of list
if (m_reg[CTDA] & 1)
@@ -440,10 +447,10 @@ void dp83932c_device::read_rra(bool command)
offs_t const rrp = EA(m_reg[URRA], m_reg[RRP]);
- m_reg[CRBA0] = m_bus->read_word(rrp + 0 * width);
- m_reg[CRBA1] = m_bus->read_word(rrp + 1 * width);
- m_reg[RBWC0] = m_bus->read_word(rrp + 2 * width);
- m_reg[RBWC1] = m_bus->read_word(rrp + 3 * width);
+ m_reg[CRBA0] = read_bus_word(rrp + 0 * width);
+ m_reg[CRBA1] = read_bus_word(rrp + 1 * width);
+ m_reg[RBWC0] = read_bus_word(rrp + 2 * width);
+ m_reg[RBWC1] = read_bus_word(rrp + 3 * width);
LOG("read_rra crba 0x%08x rbwc 0x%08x\n",
EA(m_reg[CRBA1], m_reg[CRBA0]), EA(m_reg[RBWC1], m_reg[RBWC0]));
@@ -472,10 +479,10 @@ void dp83932c_device::load_cam()
{
offs_t const cdp = EA(m_reg[URRA], m_reg[CDP]);
- u16 const cep = m_bus->read_word(cdp + 0 * width) & 0xf;
- u16 const cap0 = m_bus->read_word(cdp + 1 * width);
- u16 const cap1 = m_bus->read_word(cdp + 2 * width);
- u16 const cap2 = m_bus->read_word(cdp + 3 * width);
+ u16 const cep = read_bus_word(cdp + 0 * width) & 0xf;
+ u16 const cap0 = read_bus_word(cdp + 1 * width);
+ u16 const cap1 = read_bus_word(cdp + 2 * width);
+ u16 const cap2 = read_bus_word(cdp + 3 * width);
// FIXME: documented byte/word order doesn't match emulation
@@ -491,7 +498,7 @@ void dp83932c_device::load_cam()
}
// read cam enable
- m_reg[CE] = m_bus->read_word(EA(m_reg[URRA], m_reg[CDP]));
+ m_reg[CE] = read_bus_word(EA(m_reg[URRA], m_reg[CDP]));
LOG("load_cam enable 0x%04x\n", m_reg[CE]);
m_reg[CR] &= ~CR_LCAM;
@@ -572,3 +579,16 @@ void dp83932c_device::dump_bytes(u8 *buf, int length)
buf[i * 8 + 4], buf[i * 8 + 5], buf[i * 8 + 6], buf[i * 8 + 7]);
}
}
+
+u16 dp83932c_device::read_bus_word(offs_t address)
+{
+ return (m_reg[DCR] & DCR_DW) ? m_bus->read_dword(address) : m_bus->read_word(address);
+}
+
+void dp83932c_device::write_bus_word(offs_t address, u16 data)
+{
+ if (m_reg[DCR] & DCR_DW)
+ m_bus->write_dword(address, data);
+ else
+ m_bus->write_word(address, data);
+}
diff --git a/src/devices/machine/dp83932c.h b/src/devices/machine/dp83932c.h
index 1b379bcceeb..ef91d08313d 100644
--- a/src/devices/machine/dp83932c.h
+++ b/src/devices/machine/dp83932c.h
@@ -207,6 +207,10 @@ private:
bool m_int_state;
u16 m_reg[64];
u64 m_cam[16];
+
+ // These wrappers handle 16-bit data stored on 32-bit word boundaries when in 32-bit mode
+ u16 read_bus_word(offs_t address);
+ void write_bus_word(offs_t address, u16 data);
};
DECLARE_DEVICE_TYPE(DP83932C, dp83932c_device)