diff --git a/src/devices/machine/am9516.cpp b/src/devices/machine/am9516.cpp index ac0a5a87ffa..59cf387ac5e 100644 --- a/src/devices/machine/am9516.cpp +++ b/src/devices/machine/am9516.cpp @@ -16,13 +16,9 @@ * - Personal Computer Products Data Book, © 1989 Advanced Micro Devices * * TODO: - * - start after chaining - * - software request - * - single operation - * - second interrupt handling * - search modes * - chain load abort - * - wait states + * - hardware masks */ #include "emu.h" @@ -32,10 +28,9 @@ #define LOG_REGR (1U << 1) #define LOG_REGW (1U << 2) #define LOG_COMMAND (1U << 3) -#define LOG_STATE (1U << 4) -#define LOG_DMA (1U << 5) +#define LOG_DMA (1U << 4) -//#define VERBOSE (LOG_GENERAL|LOG_REGR|LOG_REGW|LOG_COMMAND) +//#define VERBOSE (LOG_GENERAL|LOG_REGR|LOG_REGW|LOG_COMMAND|LOG_DMA) #include "logmacro.h" enum master_mode_mask : u8 @@ -84,12 +79,20 @@ enum status_mask : u16 enum cmh_mask : u16 { - CMH_MCF = 0x0003, // match control - CMH_DACK = 0x0004, // dack control - CMH_MASK = 0x0008, // hardware mask - CMH_SRQ = 0x0010, // software request + CMH_MC = 0x0003, // match control + CMH_DC = 0x0004, // dack control + CMH_HM = 0x0008, // hardware mask + CMH_SR = 0x0010, // software request - CMH_WM = 0x001f, + CMH_WM = 0x001f, +}; + +enum cmh_mc_mask : u16 +{ + MC_00 = 0x0000, // stop on no match + MC_01 = 0x0020, // stop on no match + MC_10 = 0x0040, // stop on word match + MC_11 = 0x0060, // stop on byte match }; enum cml_mask : u16 @@ -108,6 +111,14 @@ enum cml_mask : u16 CML_CTC = 0x8000, // chain enable - terminal count }; +enum cml_tt_mask : u16 +{ + TT_00 = 0x0000, // single transfer + TT_01 = 0x0020, // demand dedicated bus hold + TT_10 = 0x0040, // demand dedicated bus release + TT_11 = 0x0060, // demand interleave +}; + enum aru_mask : u16 { ARU_WC = 0x0006, // wait control @@ -166,8 +177,7 @@ void am9516_device::device_start() save_item(NAME(m_eop_out_state)); save_item(NAME(m_eop_in_state)); - save_item(NAME(m_master_mode)); - save_item(NAME(m_chain_control)); + save_item(NAME(m_mode)); save_item(NAME(m_pointer)); save_item(NAME(m_temporary)); @@ -200,17 +210,18 @@ void am9516_device::device_start() ch.flyby_byte_w.resolve_safe(); ch.flyby_word_r.resolve_safe(0); ch.flyby_word_w.resolve_safe(); - - ch.run = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(am9516_device::operate), this)); } m_channel[0].is = 0; m_channel[1].is = IS_CHN; + + m_channel[0].run = timer_alloc(timer_expired_delegate(FUNC(am9516_device::operate<0>), this)); + m_channel[1].run = timer_alloc(timer_expired_delegate(FUNC(am9516_device::operate<1>), this)); } void am9516_device::device_reset() { - m_master_mode = 0; + m_mode = 0; for (channel &ch : m_channel) { @@ -280,7 +291,7 @@ u16 am9516_device::data_r() case 0x34: return m_channel[1].boc; case 0x36: return m_channel[0].boc; // master mode - case 0x38: return m_master_mode; + case 0x38: return m_mode; // pattern case 0x48: return m_channel[1].pattern; case 0x4a: return m_channel[0].pattern; @@ -297,7 +308,7 @@ u16 am9516_device::data_r() case 0x5a: return m_channel[0].iv; default: - LOG("data_r undefined register 0x%02 (%s)\n", + LOG("undefined register 0x%02 (%s)\n", m_pointer, machine().describe_context()); return 0; } @@ -344,9 +355,9 @@ void am9516_device::data_w(u16 data) case 0x36: m_channel[0].boc = data; break; // master mode case 0x38: - LOGMASKED(LOG_REGW, "data_w master mode 0x%04x (%s)\n", + LOGMASKED(LOG_REGW, "master mode 0x%04x (%s)\n", data, machine().describe_context()); - m_master_mode = data & 0xf; + m_mode = data & 0xf; return; // pattern case 0x48: m_channel[1].pattern = data; break; @@ -355,14 +366,14 @@ void am9516_device::data_w(u16 data) case 0x4c: m_channel[1].mask = data; break; case 0x4e: m_channel[0].mask = data; break; // channel mode - case 0x50: m_channel[1].cml = data; break; - case 0x52: m_channel[0].cml = data; break; + case 0x50: m_channel[1].cml = data; m_channel[1].log_mode(LOG_GENERAL); break; + case 0x52: m_channel[0].cml = data; m_channel[0].log_mode(LOG_GENERAL); break; // interrupt vector case 0x58: m_channel[1].iv = data; break; case 0x5a: m_channel[0].iv = data; break; default: - LOG("data_w undefined register 0x%02 data 0x%04x (%s)\n", + LOG("undefined register 0x%02 data 0x%04x (%s)\n", m_pointer, data, machine().describe_context()); return; } @@ -384,7 +395,7 @@ void am9516_device::data_w(u16 data) "interrupt vector", nullptr, }; - LOGMASKED(LOG_REGW, "data_w channel %d %s 0x%04x (%s)\n", + LOGMASKED(LOG_REGW, "channel %d %s 0x%04x (%s)\n", !(m_pointer & 2), reg_name[m_pointer >> 2], data, machine().describe_context()); } } @@ -426,9 +437,12 @@ void am9516_device::command(u8 data) BIT(data, 0), BIT(data, 1) ? "set" : "clear", machine().describe_context()); if (BIT(data, 1)) - ch.cmh |= CMH_SRQ; + { + ch.cmh |= CMH_SR; + ch.run->adjust(attotime::zero); + } else - ch.cmh &= ~CMH_SRQ; + ch.cmh &= ~CMH_SR; break; case 0x60: // set/clear flip bit @@ -446,16 +460,16 @@ void am9516_device::command(u8 data) BIT(data, 0), BIT(data, 1) ? "set" : "clear", machine().describe_context()); if (BIT(data, 1)) - ch.cmh |= CMH_MASK; + ch.cmh |= CMH_HM; else - ch.cmh &= ~CMH_MASK; + ch.cmh &= ~CMH_HM; break; case 0xa0: // start chain LOGMASKED(LOG_COMMAND, "channel %d start chain (%s)\n", BIT(data, 0), machine().describe_context()); - chain(BIT(data, 0)); + ch.chain(); break; default: @@ -465,161 +479,23 @@ void am9516_device::command(u8 data) } } -void am9516_device::chain(unsigned const c) -{ - channel &ch = m_channel[c]; - address_space &s(space(SYSTEM_MEM)); - - // TODO: abort on EOP - - // fetch reload word - u32 chain_address = ch.address(ch.cau, ch.cal); - m_chain_control = s.read_word(chain_address) & CC_WM; - LOGMASKED(LOG_REGW, "chain address 0x%06x reload word 0x%04x\n", chain_address, m_chain_control); - chain_address += 2; - - // current address a - if (m_chain_control & CC_CAA) - { - ch.caau = s.read_word(chain_address + 0) & ARU_WM; - ch.caal = s.read_word(chain_address + 2); - - LOGMASKED(LOG_REGW, "current address a 0x%04x 0x%04x\n", ch.caau, ch.caal); - - m_chain_control &= ~CC_CAA; - chain_address += 4; - } - - // current address b - if (m_chain_control & CC_CAB) - { - ch.cabu = s.read_word(chain_address + 0) & ARU_WM; - ch.cabl = s.read_word(chain_address + 2); - - LOGMASKED(LOG_REGW, "current address b 0x%04x 0x%04x\n", ch.cabu, ch.cabl); - - m_chain_control &= ~CC_CAB; - chain_address += 4; - } - - // current operation count - if (m_chain_control & CC_COC) - { - ch.coc = s.read_word(chain_address); - - LOGMASKED(LOG_REGW, "current operation count 0x%04x\n", ch.coc); - - m_chain_control &= ~CC_COC; - chain_address += 2; - } - - // base address a - if (m_chain_control & CC_BAA) - { - ch.baau = s.read_word(chain_address + 0) & ARU_WM; - ch.baal = s.read_word(chain_address + 2); - - LOGMASKED(LOG_REGW, "base address a 0x%04x 0x%04x\n", ch.baau, ch.baal); - - m_chain_control &= ~CC_BAA; - chain_address += 4; - } - - // base address b - if (m_chain_control & CC_BAB) - { - ch.babu = s.read_word(chain_address + 0) & ARU_WM; - ch.babl = s.read_word(chain_address + 2); - - LOGMASKED(LOG_REGW, "base address b 0x%04x 0x%04x\n", ch.babu, ch.babl); - - m_chain_control &= ~CC_BAB; - chain_address += 4; - } - - // base operation count - if (m_chain_control & CC_BOC) - { - ch.boc = s.read_word(chain_address); - - LOGMASKED(LOG_REGW, "base operation count 0x%04x\n", ch.boc); - - m_chain_control &= ~CC_BOC; - chain_address += 2; - } - - // pattern and mask - if (m_chain_control & CC_PM) - { - ch.pattern = s.read_word(chain_address + 0); - ch.mask = s.read_word(chain_address + 2); - - LOGMASKED(LOG_REGW, "pattern 0x%04x mask %04x\n", ch.pattern, ch.mask); - - m_chain_control &= ~CC_PM; - chain_address += 4; - } - - // interrupt vector - if (m_chain_control & CC_IV) - { - ch.iv = s.read_word(chain_address); - - LOGMASKED(LOG_REGW, "interrupt vector 0x%04x\n", ch.iv); - - m_chain_control &= ~CC_IV; - chain_address += 2; - } - - // channel mode - if (m_chain_control & CC_CM) - { - ch.cmh = s.read_word(chain_address + 0) & CMH_WM; - ch.cml = s.read_word(chain_address + 2); - - LOGMASKED(LOG_REGW, "channel mode 0x%04x %04x\n", ch.cmh, ch.cml); - - m_chain_control &= ~CC_CM; - chain_address += 4; - } - - // chain address - if (m_chain_control & CC_CA) - { - ch.cau = s.read_word(chain_address + 0) & (ARU_UA | ARU_WC); - ch.cal = s.read_word(chain_address + 2); - - LOGMASKED(LOG_REGW, "chain address 0x%04x %04x\n", ch.cau, ch.cal); - - m_chain_control &= ~CC_CA; - chain_address += 4; - } - else - { - // update chain address register - ch.cau = ((chain_address >> 8) & ARU_UA) | u8(ch.cau); - ch.cal = u16(chain_address); - } - - ch.status &= ~(S_CA | S_NAC); -} - WRITE_LINE_MEMBER(am9516_device::eop_w) { + LOGMASKED(LOG_DMA, "eop %s\n", state ? "cleared" : "asserted"); m_eop_in_state = !state; } template WRITE_LINE_MEMBER(am9516_device::dreq_w) { - LOGMASKED(LOG_DMA, "dreq_w<%d> %d\n", Channel, state); + LOGMASKED(LOG_DMA, "channel %d dreq %s\n", Channel, state ? "cleared" : "asserted"); channel &ch = m_channel[Channel]; if (!state) { ch.status |= S_HRQ; - if (!(ch.status & S_HM)) - ch.run->adjust(attotime::zero, Channel); + if (!(ch.status & S_HM) && ch.run->expire().is_never()) + ch.run->adjust(attotime::zero); } else ch.status &= ~S_HRQ; @@ -628,70 +504,89 @@ template WRITE_LINE_MEMBER(am9516_device::dreq_w) template void am9516_device::dreq_w<0>(int state); template void am9516_device::dreq_w<1>(int state); -void am9516_device::operate(s32 param) +template void am9516_device::operate(s32 param) { - channel &ch = m_channel[param]; + channel &ch = m_channel[Channel]; + + if (!(m_mode & MM0) || (ch.status & S_SIP)) + { + LOGMASKED(LOG_DMA, "channel %d bus access disabled\n", Channel); + return; + } + + if (!(ch.status & S_HRQ) && !(ch.cmh & CMH_SR)) + { + LOGMASKED(LOG_DMA, "channel %d no request pending\n", Channel); + return; + } + u16 status = 0; + unsigned cycles = 0; switch (ch.cml & CML_OPER) { // transfer case 0x1: // byte/byte flowthru - m_temporary = ch.read_byte(ch.cml & CML_FLIP); - ch.write_byte(u8(m_temporary), ch.cml & CML_FLIP); + cycles = 6; + m_temporary = ch.read_byte(cycles, ch.cml & CML_FLIP); + ch.write_byte(u8(m_temporary), cycles, ch.cml & CML_FLIP); ch.coc--; break; case 0x8: case 0x9: + cycles = 9; if (ch.cml & CML_FLIP) { // word/byte flowthru - m_temporary = ch.read_word(ch.cml & CML_FLIP); + m_temporary = ch.read_word(cycles, ch.cml & CML_FLIP); unsigned const shift = ch.cabu & AC_DEC; - ch.write_byte(u8(m_temporary >> (8 - shift)), ch.cml & CML_FLIP); - ch.write_byte(u8(m_temporary >> shift), ch.cml & CML_FLIP); + ch.write_byte(u8(m_temporary >> (8 - shift)), cycles, ch.cml & CML_FLIP); + ch.write_byte(u8(m_temporary >> shift), cycles, ch.cml & CML_FLIP); } else { // byte/word flowthru unsigned const shift = ch.cabu & AC_DEC; - m_temporary = u16(ch.read_byte(ch.cml & CML_FLIP)) << (8 - shift); - m_temporary |= u16(ch.read_byte(ch.cml & CML_FLIP)) << shift; + m_temporary = u16(ch.read_byte(cycles, ch.cml & CML_FLIP)) << (8 - shift); + m_temporary |= u16(ch.read_byte(cycles, ch.cml & CML_FLIP)) << shift; - ch.write_word(m_temporary, ch.cml & CML_FLIP); + ch.write_word(m_temporary, cycles, ch.cml & CML_FLIP); } ch.coc--; break; case 0x0: // word/word flowthru - m_temporary = ch.read_word(ch.cml & CML_FLIP); - ch.write_word(m_temporary, ch.cml & CML_FLIP); + cycles = 6; + m_temporary = ch.read_word(cycles, ch.cml & CML_FLIP); + ch.write_word(m_temporary, cycles, ch.cml & CML_FLIP); ch.coc--; break; case 0x3: // byte/byte flyby + cycles = 3; if (ch.cml & CML_FLIP) // from flyby to arb - ch.write_byte(ch.flyby_byte_r()); + ch.write_byte(ch.flyby_byte_r(), cycles); else // from ara to flyby - ch.flyby_byte_w(ch.read_byte()); + ch.flyby_byte_w(ch.read_byte(cycles)); ch.coc--; break; case 0x2: // word/word flyby + cycles = 3; if (ch.cml & CML_FLIP) // from flyby to arb - ch.write_word(ch.flyby_word_r()); + ch.write_word(ch.flyby_word_r(), cycles); else // from ara to flyby - ch.flyby_word_w(ch.read_word()); + ch.flyby_word_w(ch.read_word(cycles)); ch.coc--; break; @@ -737,6 +632,8 @@ void am9516_device::operate(s32 param) if (status & (S_MC | S_EOP | S_TC)) complete(param, status); + else if (ch.cml & CML_TT) + ch.run->adjust(attotime::from_ticks(cycles, clock())); } void am9516_device::complete(unsigned const c, u16 status) @@ -746,6 +643,8 @@ void am9516_device::complete(unsigned const c, u16 status) ch.status &= ~(S_MCH | S_MCL | S_MC | S_EOP | S_TC); ch.status |= status | S_NAC; + LOGMASKED(LOG_DMA, "channel %d complete status 0x%04x\n", c, ch.status); + m_eop(0); m_eop(1); @@ -754,38 +653,13 @@ void am9516_device::complete(unsigned const c, u16 status) || ((ch.status & S_EOP) && (ch.cml & CML_IEOP)) || ((ch.status & S_MC) && (ch.cml & CML_IMC))) { - LOG("completion interrupt channel %d\n", c); ch.interrupt(true); interrupt(); } - // FIXME: depending on bus mode and interrupt state, reloading - // may be delayed until interrupt is acknowledged - - // reload base to current - if (((ch.status & S_TC) && (ch.cml & CML_RTC)) - || ((ch.status & S_EOP) && (ch.cml & CML_REOP)) - || ((ch.status & S_MC) && (ch.cml & CML_RMC))) - { - LOG("reload base to current channel %d\n", c); - ch.caau = ch.baau; - ch.caal = ch.baal; - ch.cabu = ch.babu; - ch.cabl = ch.babl; - ch.coc = ch.boc; - - ch.status &= ~S_NAC; - } - - // reload chain - if (((ch.status & S_TC) && (ch.cml & CML_CTC)) - || ((ch.status & S_EOP) && (ch.cml & CML_CEOP)) - || ((ch.status & S_MC) && (ch.cml & CML_CMC))) - { - LOG("reload chain channel %d\n", c); - chain(c); - } + if (!(ch.status & S_SIP)) + ch.reload(); } void am9516_device::interrupt() @@ -796,6 +670,7 @@ void am9516_device::interrupt() if (m_int_state != int_state) { + LOG("interrupt %s\n", int_state ? "asserted" : "cleared"); m_int_state = int_state; m_int(!m_int_state); } @@ -807,7 +682,7 @@ u16 am9516_device::acknowledge() { if ((ch.status & S_CIE) && (ch.status & S_IP)) { - u16 const data = (m_master_mode & MM3) ? 0 : ch.is; + u16 const data = (m_mode & MM3) ? 0 : ch.is; ch.interrupt(false); interrupt(); @@ -819,6 +694,9 @@ u16 am9516_device::acknowledge() fatalerror("%s: interrupt acknowledge with no pending interrupts\n", tag()); } +#undef LOG_OUTPUT_FUNC +#define LOG_OUTPUT_FUNC udc.logerror + u32 am9516_device::channel::address(u16 &aru, u16 &arl, int delta) { u32 const current = u32(aru & ARU_UA) << 8 | arl; @@ -840,35 +718,43 @@ u32 am9516_device::channel::address(u16 &aru, u16 &arl, int delta) return current; } -u8 am9516_device::channel::read_byte(bool flip) +u8 am9516_device::channel::read_byte(unsigned &cycles, bool flip) { u16 &cau = flip ? cabu : caau; u16 &cal = flip ? cabl : caal; + cycles += wait_states[BIT(cau, 1, 2)]; + return udc.space((cau & ARU_AR) >> 6).read_byte(address(cau, cal, 1)); } -void am9516_device::channel::write_byte(u8 data, bool flip) +void am9516_device::channel::write_byte(u8 data, unsigned &cycles, bool flip) { u16 &cau = flip ? caau : cabu; u16 &cal = flip ? caal : cabl; + cycles += wait_states[BIT(cau, 1, 2)]; + udc.space((cau & ARU_AR) >> 6).write_byte(address(cau, cal, 1), data); } -u16 am9516_device::channel::read_word(bool flip) +u16 am9516_device::channel::read_word(unsigned &cycles, bool flip) { u16 &cau = flip ? cabu : caau; u16 &cal = flip ? cabl : caal; + cycles += wait_states[BIT(cau, 1, 2)]; + return udc.space((cau & ARU_AR) >> 6).read_word(address(cau, cal, 2)); } -void am9516_device::channel::write_word(u16 data, bool flip) +void am9516_device::channel::write_word(u16 data, unsigned &cycles, bool flip) { u16 &cau = flip ? caau : cabu; u16 &cal = flip ? caal : cabl; + cycles += wait_states[BIT(cau, 1, 2)]; + udc.space((cau & ARU_AR) >> 6).write_word(address(cau, cal, 2), data); } @@ -876,6 +762,7 @@ void am9516_device::channel::interrupt(bool assert) { if (assert && (status & S_IP)) { + LOG("second interrupt pending\n"); status |= S_SIP; return; } @@ -886,7 +773,12 @@ void am9516_device::channel::interrupt(bool assert) is &= IS_CHN; if (status & S_SIP) + { + LOG("second interrupt cleared\n"); status &= ~S_SIP; + + reload(); + } else return; } @@ -894,3 +786,232 @@ void am9516_device::channel::interrupt(bool assert) status |= S_IP; is |= bitswap(status, 5, 4, 3, 12, 2, 1, 0) << 9 | iv; } + +void am9516_device::channel::reload() +{ + // reload base to current + if (((status & S_TC) && (cml & CML_RTC)) + || ((status & S_EOP) && (cml & CML_REOP)) + || ((status & S_MC) && (cml & CML_RMC))) + { + LOGMASKED(LOG_DMA, "reload base to current\n"); + caau = baau; + caal = baal; + cabu = babu; + cabl = babl; + coc = boc; + + log_addr(LOG_DMA, "current address a", caau, caal); + log_addr(LOG_DMA, "current address b", cabu, cabl); + LOGMASKED(LOG_DMA, "current operation count 0x%04x\n", coc); + + status &= ~S_NAC; + } + + // reload chain + if (((status & S_TC) && (cml & CML_CTC)) + || ((status & S_EOP) && (cml & CML_CEOP)) + || ((status & S_MC) && (cml & CML_CMC))) + { + LOGMASKED(LOG_DMA, "reload chain\n"); + chain(); + } +} + +void am9516_device::channel::chain() +{ + address_space &s(udc.space(SYSTEM_MEM)); + + // TODO: abort on EOP + + // fetch reload word + u32 chain_address = address(cau, cal); + u16 reload = s.read_word(chain_address) & CC_WM; + LOGMASKED(LOG_REGW, "chain address 0x%06x reload word 0x%04x\n", chain_address, reload); + chain_address += 2; + + // current address a + if (reload & CC_CAA) + { + caau = s.read_word(chain_address + 0) & ARU_WM; + caal = s.read_word(chain_address + 2); + + LOGMASKED(LOG_REGW, "current address a 0x%04x 0x%04x\n", caau, caal); + log_addr(LOG_DMA, "current address a", caau, caal); + + chain_address += 4; + } + + // current address b + if (reload & CC_CAB) + { + cabu = s.read_word(chain_address + 0) & ARU_WM; + cabl = s.read_word(chain_address + 2); + + LOGMASKED(LOG_REGW, "current address b 0x%04x 0x%04x\n", cabu, cabl); + log_addr(LOG_DMA, "current address b", cabu, cabl); + + chain_address += 4; + } + + // current operation count + if (reload & CC_COC) + { + coc = s.read_word(chain_address); + + LOGMASKED(LOG_DMA, "current operation count 0x%04x\n", coc); + + chain_address += 2; + } + + // base address a + if (reload & CC_BAA) + { + baau = s.read_word(chain_address + 0) & ARU_WM; + baal = s.read_word(chain_address + 2); + + LOGMASKED(LOG_REGW, "base address a 0x%04x 0x%04x\n", baau, baal); + + chain_address += 4; + } + + // base address b + if (reload & CC_BAB) + { + babu = s.read_word(chain_address + 0) & ARU_WM; + babl = s.read_word(chain_address + 2); + + LOGMASKED(LOG_REGW, "base address b 0x%04x 0x%04x\n", babu, babl); + + chain_address += 4; + } + + // base operation count + if (reload & CC_BOC) + { + boc = s.read_word(chain_address); + + LOGMASKED(LOG_REGW, "base operation count 0x%04x\n", boc); + + chain_address += 2; + } + + // pattern and mask + if (reload & CC_PM) + { + pattern = s.read_word(chain_address + 0); + mask = s.read_word(chain_address + 2); + + LOGMASKED(LOG_REGW, "pattern 0x%04x mask %04x\n", pattern, mask); + + chain_address += 4; + } + + // interrupt vector + if (reload & CC_IV) + { + iv = s.read_word(chain_address); + + LOGMASKED(LOG_REGW, "interrupt vector 0x%04x\n", iv); + + chain_address += 2; + } + + // channel mode + if (reload & CC_CM) + { + cmh = s.read_word(chain_address + 0) & CMH_WM; + cml = s.read_word(chain_address + 2); + + LOGMASKED(LOG_REGW, "channel mode 0x%04x %04x\n", cmh, cml); + log_mode(LOG_DMA, true); + + chain_address += 4; + } + + // chain address + if (reload & CC_CA) + { + cau = s.read_word(chain_address + 0) & (ARU_UA | ARU_WC); + cal = s.read_word(chain_address + 2); + + LOGMASKED(LOG_REGW, "chain address 0x%04x %04x\n", cau, cal); + + chain_address += 4; + } + else + { + // update chain address register + cau = ((chain_address >> 8) & ARU_UA) | u8(cau); + cal = u16(chain_address); + } + + status &= ~(S_CA | S_NAC); + + if (cmh & CMH_SR) + run->adjust(attotime::zero); +} + +void am9516_device::channel::log_mode(unsigned mask, bool high) const +{ + if (VERBOSE & mask) + { + static const char *const match[] = + { + "no match", "no match", "word match", "byte match" + }; + static const char *const operation[] = + { + "transfer, word/word flowthru", + "transfer, byte/byte flowthru", + "transfer, word/word flyby", + "transfer, byte/byte flyby", + "transfer/search, word/word flowthru", + "transfer/search, byte/byte flowthru", + "transfer/search, word/word flyby", + "transfer/search, byte/byte flyby", + "transfer, byte/word flowthru", + "transfer, byte/word flowthru", + "illegal", + "illegal", + "transfer/search, byte/word flowthru", + "transfer/search, byte/word flowthru", + "search, word/word", + "search, byte/byte", + }; + static const char *const tt[] = + { + "single transfer", "demand dedicated/bus hold", "demand dedicated/bus release", "demand interleave" + }; + static const char *const flags[] = + { + "-", "eop", "mc", "mc|eop", "tc", "tc|eop", "tc|mc", "tc|mc|eop" + }; + + LOGMASKED(mask, "channel mode %s, %s, complete(int:%s rld:%s chn:%s)\n", + operation[cml & CML_OPER], tt[BIT(cml, 5, 2)], flags[BIT(cml, 7, 3)], flags[BIT(cml, 10, 3)], flags[BIT(cml, 13, 3)]); + + if (high) + LOGMASKED(mask, "channel mode stop:%s /dack:%d hm:%d sr:%d\n", + match[BIT(cmh, 0, 2)], BIT(cmh, 2), BIT(cmh, 3), BIT(cmh, 4)); + } +} + +void am9516_device::channel::log_addr(unsigned mask, const char *const name, u16 aru, u16 arl) const +{ + if (VERBOSE & mask) + { + static const char *const ar[] = + { + "system i/o", "system mem", "normal i/o", "normal mem" + }; + static const char *const ac[] = + { + "inc", "dec", "hld", "hld" + }; + + LOGMASKED(mask, "%s %s 0x%06x %s wait:%d\n", + name, ar[BIT(aru, 6, 2)], u32(aru & ARU_UA) << 8 | arl, + ac[BIT(aru, 3, 2)], wait_states[BIT(aru, 1, 2)]); + } +} diff --git a/src/devices/machine/am9516.h b/src/devices/machine/am9516.h index b171cf89abf..67ec7263187 100644 --- a/src/devices/machine/am9516.h +++ b/src/devices/machine/am9516.h @@ -52,8 +52,7 @@ protected: private: void command(u8 data); - void chain(unsigned const c); - void operate(s32 param); + template void operate(s32 param); void complete(unsigned const c, u16 status); void interrupt(); @@ -68,8 +67,7 @@ private: bool m_eop_in_state; // chip-level registers - u8 m_master_mode; - u16 m_chain_control; + u8 m_mode; u8 m_pointer; u16 m_temporary; @@ -86,12 +84,17 @@ private: u32 address(u16 &aru, u16 &arl, int delta = 0); - u8 read_byte(bool flip = false); - void write_byte(u8 data, bool flip = false); - u16 read_word(bool flip = false); - void write_word(u16 data, bool flip = false); + u8 read_byte(unsigned &cycles, bool flip = false); + void write_byte(u8 data, unsigned &cycles, bool flip = false); + u16 read_word(unsigned &cycles, bool flip = false); + void write_word(u16 data, unsigned &cycles, bool flip = false); void interrupt(bool assert); + void chain(); + void reload(); + + void log_mode(unsigned mask, bool high = false) const; + void log_addr(unsigned mask, const char *const name, u16 aru, u16 arl) const; am9516_device &udc; @@ -121,6 +124,8 @@ private: u16 cml = 0; // channel mode low u16 cmh = 0; // channel mode high u8 iv = 0; // interrupt vector + + unsigned const wait_states[4] = { 0, 1, 2, 4 }; } m_channel[2]; };