From f95883ac29b0fc592f5ae0698511a83b1050c7ed Mon Sep 17 00:00:00 2001 From: tedgreen99 Date: Thu, 14 Apr 2022 15:02:53 -0600 Subject: [PATCH] Fix MT07568: hyprdriv (seattle) randomly freezes. (#9559) * Fix MT07568: hyprdriv (seattle) randomly freezes. gt64xxx: Change interrupt handler to not send new interrupts if an interrupt has already been asserted and improve dma timing. seattle: Add some harddrive dma delay to make harddrive performance more realistic. * Adjust comment to clarify word size * vegas: Move hdd set_dma_transfer into machine config seattle: Move hdd set_dma_transfer into machine config --- src/devices/machine/gt64xxx.cpp | 290 +++++++++++++++++++------------- src/devices/machine/gt64xxx.h | 2 + src/mame/drivers/seattle.cpp | 15 +- src/mame/drivers/vegas.cpp | 19 ++- 4 files changed, 203 insertions(+), 123 deletions(-) diff --git a/src/devices/machine/gt64xxx.cpp b/src/devices/machine/gt64xxx.cpp index 15e20e56ebf..4c698e12809 100644 --- a/src/devices/machine/gt64xxx.cpp +++ b/src/devices/machine/gt64xxx.cpp @@ -8,6 +8,7 @@ #define LOG_TIMERS (1U << 2) #define LOG_DMA (1U << 3) #define LOG_PCI (1U << 4) +#define LOG_IRQ (1U << 5) //#define VERBOSE (LOG_GENERAL | LOG_GALILEO | LOG_TIMERS | LOG_DMA | LOG_PCI) #include "logmacro.h" @@ -16,26 +17,28 @@ #define LOGTIMERS(...) LOGMASKED(LOG_TIMERS, __VA_ARGS__) #define LOGDMA(...) LOGMASKED(LOG_DMA, __VA_ARGS__) #define LOGPCI(...) LOGMASKED(LOG_PCI, __VA_ARGS__) +#define LOGIRQ(...) LOGMASKED(LOG_IRQ, __VA_ARGS__) -/************************************* - * - * Galileo constants - * - *************************************/ +//************************************ +// +// Galileo constants +// +//************************************ #define TIMER_PERIOD attotime::from_hz(clock()) #define PCI_BUS_CLOCK 33000000 -// Number of dma words to transfer at a time, real hardware configurable between 8-32 +// Number of dma words (32 bits) to transfer at a time, real hardware configurable between 8-32 #define DMA_BURST_SIZE 32 -#define DMA_TIMER_PERIOD attotime::from_hz(PCI_BUS_CLOCK / 48) +// DMA will transfer up to DMA_BURST_SIZE*4 bytes every DMA_TIMER_PERIOD seconds +#define DMA_TIMER_PERIOD attotime::from_hz(PCI_BUS_CLOCK / 64) -/* Galileo registers - 0x000-0x3ff */ +// Galileo registers - 0x000-0x3ff #define GREG_CPU_CONFIG (0x000/4) -#define GREG_R1_0_LO (0x008/4) -#define GREG_R1_0_HI (0x010/4) -#define GREG_R3_2_LO (0x018/4) -#define GREG_R3_2_HI (0x020/4) +#define GREG_R1_0_LO (0x008/4) +#define GREG_R1_0_HI (0x010/4) +#define GREG_R3_2_LO (0x018/4) +#define GREG_R3_2_HI (0x020/4) #define GREG_CS_2_0_LO (0x028/4) #define GREG_CS_2_0_HI (0x030/4) #define GREG_CS_3_BOOT_LO (0x038/4) @@ -51,7 +54,7 @@ #define GREG_PCI_MEM1_LO (0x080/4) #define GREG_PCI_MEM1_HI (0x088/4) -/* Galileo registers - 0x400-0x7ff */ +// Galileo registers - 0x400-0x7ff #define GREG_RAS0_LO (0x400/4) #define GREG_RAS0_HI (0x404/4) #define GREG_RAS1_LO (0x408/4) @@ -82,7 +85,7 @@ #define GREG_DEVICE_BOOT (0x46c/4) #define GREG_ADDRESS_ERROR (0x470/4) -/* Galileo registers - 0x800-0xbff */ +// Galileo registers - 0x800-0xbff #define GREG_DMA0_COUNT (0x800/4) #define GREG_DMA1_COUNT (0x804/4) #define GREG_DMA2_COUNT (0x808/4) @@ -110,20 +113,20 @@ #define GREG_DMA_ARBITER (0x860/4) #define GREG_TIMER_CONTROL (0x864/4) -/* Galileo registers - 0xc00-0xfff */ +// Galileo registers - 0xc00-0xfff #define GREG_PCI_COMMAND (0xc00/4) #define GREG_PCI_TIMEOUT (0xc04/4) -#define GREG_PCI_R1_0 (0xc08/4) -#define GREG_PCI_R3_2 (0xc0c/4) +#define GREG_PCI_R1_0 (0xc08/4) +#define GREG_PCI_R3_2 (0xc0c/4) #define GREG_PCI_CS_2_0 (0xc10/4) #define GREG_PCI_CS_3_BOOT (0xc14/4) -#define GREG_INT_STATE (0xc18/4) -#define GREG_INT_MASK (0xc1c/4) -#define GREG_PCI_INT_MASK (0xc24/4) +#define GREG_INTR_CAUSE (0xc18/4) +#define GREG_CPU_MASK (0xc1c/4) +#define GREG_PCI_MASK (0xc24/4) #define GREG_CONFIG_ADDRESS (0xcf8/4) #define GREG_CONFIG_DATA (0xcfc/4) -/* Galileo interrupts */ +// Galileo interrupts #define GINT_SUMMARY_SHIFT (0) #define GINT_MEMOUT_SHIFT (1) #define GINT_DMAOUT_SHIFT (2) @@ -227,13 +230,15 @@ void gt64xxx_device::device_start() LOGGALILEO("gt64xxx_device::device_start UPDATE Mapped size: 0x%08X start: 0x1fd00000 end: %08X\n", romSize, 0x1fd00000 + romSize - 1); } - /* allocate timers for the galileo */ + // allocate timers for the galileo m_timer[0].timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gt64xxx_device::timer_callback), this)); m_timer[1].timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gt64xxx_device::timer_callback), this)); m_timer[2].timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gt64xxx_device::timer_callback), this)); m_timer[3].timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gt64xxx_device::timer_callback), this)); // Save states + save_item(NAME(m_irq_pending)); + save_item(NAME(m_irq_state)); save_item(NAME(m_pci_stall_state)); save_item(NAME(m_retry_count)); save_item(NAME(m_pci_cpu_stalled)); @@ -306,6 +311,8 @@ void gt64xxx_device::device_reset() map_cpu_space(); regenerate_config_mapping(); + m_irq_pending = 0; + m_irq_state = CLEAR_LINE; m_pci_stall_state = 0; m_retry_count = 0; m_pci_cpu_stalled = 0; @@ -479,13 +486,13 @@ WRITE_LINE_MEMBER(gt64xxx_device::pci_stall) m_stall_windex--; index++; } - /* resume CPU execution */ + // resume CPU execution machine().scheduler().trigger(45678); - LOGGALILEO("Resuming CPU on PCI Stall\n"); + LOGMASKED(LOG_GALILEO | LOG_PCI | LOG_DMA, "Resuming CPU on PCI Stall\n"); } } - /* set the new state */ + // set the new state m_pci_stall_state = state; } @@ -520,7 +527,7 @@ void gt64xxx_device::master_mem0_w(offs_t offset, uint32_t data, uint32_t mem_ma m_stall_windex++; // Stall cpu until trigger m_cpu_space->device().execute().spin_until_trigger(45678); - LOGMASKED(LOG_GALILEO | LOG_PCI, "%s Stalling CPU on PCI Stall\n", machine().describe_context()); + LOGMASKED(LOG_GALILEO | LOG_PCI | LOG_DMA, "%s Stalling CPU on PCI Stall\n", machine().describe_context()); } else { fatalerror("master_mem0_w: m_stall_windex full\n"); @@ -621,7 +628,7 @@ uint32_t gt64xxx_device::cpu_if_r(offs_t offset) { uint32_t result = m_reg[offset]; - /* switch off the offset for special cases */ + // switch off the offset for special cases switch (offset) { case GREG_TIMER0_COUNT: @@ -660,10 +667,16 @@ uint32_t gt64xxx_device::cpu_if_r(offs_t offset) result = config_address_r(); break; - case GREG_INT_STATE: - case GREG_INT_MASK: + case GREG_INTR_CAUSE: + LOGIRQ("%s Galileo GREG_INTR_CAUSE read from offset %03X = %08X\n", machine().describe_context(), offset * 4, result); + break; + + case GREG_CPU_MASK: + LOGGALILEO("%s Galileo GREG_CPU_MASK read from offset %03X = %08X\n", machine().describe_context(), offset*4, result); + break; + case GREG_TIMER_CONTROL: -// LOGGALILEO("%s Galileo read from offset %03X = %08X\n", machine().describe_context(), offset*4, result); + LOGTIMERS("%s Galileo read from offset %03X = %08X\n", machine().describe_context(), offset*4, result); break; default: @@ -686,7 +699,7 @@ void gt64xxx_device::cpu_if_w(address_space &space, offs_t offset, uint32_t data uint32_t oldata = m_reg[offset]; COMBINE_DATA(&m_reg[offset]); - /* switch off the offset for special cases */ + // switch off the offset for special cases switch (offset) { case GREG_R1_0_LO: @@ -717,25 +730,33 @@ void gt64xxx_device::cpu_if_w(address_space &space, offs_t offset, uint32_t data { int which = offset % 4; - /* keep the read only activity bit */ + // keep the read only activity bit m_reg[offset] &= ~0x4000; m_reg[offset] |= (oldata & 0x4000); - /* fetch next record */ + // fetch next record if (data & 0x2000) dma_fetch_next(space, which); m_reg[offset] &= ~0x2000; - /* if enabling, start the DMA */ + // if enabling, start the DMA if (!(oldata & 0x1000) && (data & 0x1000) && !(m_dma_active & (1<adjust(attotime::zero, 0, DMA_TIMER_PERIOD); + m_dma_timer->adjust(DMA_TIMER_PERIOD, 0, DMA_TIMER_PERIOD); m_dma_active |= (1<< which); //perform_dma(space, which); LOGDMA("%s Galileo starting DMA Chan %i\n", machine().describe_context(), which); } + if ((oldata & 0x1000) && !(data & 0x1000) && (m_dma_active & (1 << which))) + { + m_dma_active &= ~(1 << which); + // Turn off the timer + m_dma_timer->adjust(attotime::never); + LOGDMA("%s Galileo stopping DMA Chan %i\n", machine().describe_context(), which); + } + LOGGALILEO("%s Galileo write to offset %03X = %08X & %08X\n", machine().describe_context(), offset * 4, data, mem_mask); break; } @@ -774,7 +795,7 @@ void gt64xxx_device::cpu_if_w(address_space &space, offs_t offset, uint32_t data timer->count &= 0xffffff; } timer->timer->adjust(TIMER_PERIOD * timer->count, which); - LOGTIMERS("Adjusted timer to fire in %f secs\n", (TIMER_PERIOD * timer->count).as_double()); + LOGTIMERS("Adjusted timer%d to fire in %f secs\n", which, (TIMER_PERIOD * timer->count).as_double()); } else if (timer->active && !(data & mask)) { @@ -782,18 +803,25 @@ void gt64xxx_device::cpu_if_w(address_space &space, offs_t offset, uint32_t data timer->active = 0; timer->count = (timer->count > elapsed) ? (timer->count - elapsed) : 0; timer->timer->adjust(attotime::never, which); - LOGTIMERS("Disabled timer\n"); + LOGTIMERS("Disabled timer%d\n", which); } } break; } - case GREG_INT_STATE: - LOGGALILEO("%s Galileo write to IRQ clear = %08X & %08X\n", offset*4, data, mem_mask); + case GREG_INTR_CAUSE: + LOGIRQ("%s Galileo GREG_INTR_CAUSE write to offset %03X = %08X & %08X\n", machine().describe_context(), offset * 4, data, mem_mask); m_reg[offset] = oldata & data; update_irqs(); break; + case GREG_CPU_MASK: + LOGGALILEO("%s Galileo GREG_CPU_MASK write to offset %03X = %08X & %08X\n", machine().describe_context(), offset * 4, data, mem_mask); + // Bits 0, 25:21, 31:30 are read only '0' + m_reg[offset] &= 0x3c1ffffe; + update_irqs(); + break; + case GREG_CONFIG_DATA: pci_host_device::config_data_w(offset, data); LOGGALILEO("%s Galileo PCI config data write to offset %03X = %08X & %08X\n", machine().describe_context(), offset*4, data, mem_mask); @@ -829,7 +857,6 @@ void gt64xxx_device::cpu_if_w(address_space &space, offs_t offset, uint32_t data case GREG_DMA0_SOURCE: case GREG_DMA1_SOURCE: case GREG_DMA2_SOURCE: case GREG_DMA3_SOURCE: case GREG_DMA0_DEST: case GREG_DMA1_DEST: case GREG_DMA2_DEST: case GREG_DMA3_DEST: case GREG_DMA0_NEXT: case GREG_DMA1_NEXT: case GREG_DMA2_NEXT: case GREG_DMA3_NEXT: - case GREG_INT_MASK: LOGGALILEO("%s Galileo write to offset %03X = %08X & %08X\n", machine().describe_context(), offset*4, data, mem_mask); break; @@ -839,39 +866,65 @@ void gt64xxx_device::cpu_if_w(address_space &space, offs_t offset, uint32_t data } } -/************************************* - * - * Galileo timers & interrupts - * - *************************************/ +//************************************ +// +// Galileo timers & interrupts +// +//************************************ void gt64xxx_device::update_irqs() { + // Set cause from pending only if current irq state is clear + // seattle hyprdriv freezes (MT07568) if a DMA0 interrupt is sent while the processor is already in the exception handler + if (!m_irq_state) + { + m_reg[GREG_INTR_CAUSE] = m_irq_pending; + m_irq_pending = 0; + // Set interrupt summary bit + if (m_reg[GREG_INTR_CAUSE] & 0xfffffffe) + m_reg[GREG_INTR_CAUSE] |= (1 << 0); + else + m_reg[GREG_INTR_CAUSE] &= ~(1 << 0); + + // set CPU interrupt summary of bits 29:26, 20:1 + if (m_reg[GREG_INTR_CAUSE] & m_reg[GREG_CPU_MASK] & 0x3c1ffffe) + m_reg[GREG_INTR_CAUSE] |= (1 << 30); + else + m_reg[GREG_INTR_CAUSE] &= ~(1 << 30); + } + // if any unmasked interrupts are active, we generate int state = CLEAR_LINE; - - /* if any unmasked interrupts are live, we generate */ - if (m_reg[GREG_INT_STATE] & m_reg[GREG_INT_MASK]) + if (m_reg[GREG_INTR_CAUSE] & m_reg[GREG_CPU_MASK]) state = ASSERT_LINE; - if (m_irq_num != -1) + + if (m_irq_num != -1 && state != m_irq_state) + { m_cpu->set_input_line(m_irq_num, state); + m_irq_state = state; + LOGIRQ("gt64xxx_device IRQ %s irqNum: %i cause = %08X mask = %08X time: %s\n", (state == ASSERT_LINE) ? "asserted" : "cleared", m_irq_num, m_reg[GREG_INTR_CAUSE], m_reg[GREG_CPU_MASK], machine().time().as_string()); + } - LOGGALILEO("Galileo IRQ %s irqNum: %i state = %08X mask = %08X\n", (state == ASSERT_LINE) ? "asserted" : "cleared", m_irq_num, m_reg[GREG_INT_STATE], m_reg[GREG_INT_MASK]); + // Run again if we cleared and there are new interrupts pending + if (!state && m_irq_pending) + { + LOGIRQ("gt64xxx_device new irq pending %08x time: %s\n", m_irq_pending, machine().time().as_string()); + update_irqs(); + } } - TIMER_CALLBACK_MEMBER(gt64xxx_device::timer_callback) { int which = param; galileo_timer *timer = &m_timer[which]; - LOGTIMERS("timer %d fired\n", which); + LOGTIMERS("timer%d fired at time %s\n", which, machine().time().as_string()); - /* copy the start value from the registers */ + // copy the start value from the registers timer->count = m_reg[GREG_TIMER0_COUNT + which]; if (which != 0) timer->count &= 0xffffff; - /* if we're a timer, adjust the timer to fire again */ + // if we're a timer, adjust the timer to fire again if (m_reg[GREG_TIMER_CONTROL] & (2 << (2 * which))) { // unsure what a 0-length timer should do, but it produces an infinite loop so guard against it @@ -883,8 +936,9 @@ TIMER_CALLBACK_MEMBER(gt64xxx_device::timer_callback) else timer->active = timer->count = 0; - /* trigger the interrupt */ - m_reg[GREG_INT_STATE] |= 1 << (GINT_T0EXP_SHIFT + which); + // trigger the interrupt + //m_reg[GREG_INTR_CAUSE] |= 1 << (GINT_T0EXP_SHIFT + which); + m_irq_pending |= 1 << (GINT_T0EXP_SHIFT + which); update_irqs(); } @@ -908,35 +962,30 @@ int gt64xxx_device::dma_fetch_next(address_space &space, int which) offs_t address = 0; uint32_t data; - /* no-op for unchained mode */ + // no-op for unchained mode if (!(m_reg[GREG_DMA0_CONTROL + which] & 0x200)) address = m_reg[GREG_DMA0_NEXT + which]; - /* if we hit the end address, signal an interrupt */ + // exit if we hit the end address if (address == 0) { - if (m_reg[GREG_DMA0_CONTROL + which] & 0x400) - { - m_reg[GREG_INT_STATE] |= 1 << (GINT_DMA0COMP_SHIFT + which); - update_irqs(); - } m_reg[GREG_DMA0_CONTROL + which] &= ~0x5000; return 0; } - /* fetch the byte count */ + // fetch the byte count data = space.read_dword(address); address += 4; m_reg[GREG_DMA0_COUNT + which] = data; - /* fetch the source address */ + // fetch the source address data = space.read_dword(address); address += 4; m_reg[GREG_DMA0_SOURCE + which] = data; - /* fetch the dest address */ + // fetch the dest address data = space.read_dword(address); address += 4; m_reg[GREG_DMA0_DEST + which] = data; - /* fetch the next record address */ + // fetch the next record address data = space.read_dword(address); address += 4; m_reg[GREG_DMA0_NEXT + which] = data; return 1; @@ -960,7 +1009,8 @@ TIMER_CALLBACK_MEMBER (gt64xxx_device::perform_dma) if (which==-1) { logerror("gt64xxx_device::perform_dma Warning! DMA Timer called with no pending DMA. m_dma_active = %08X\n", m_dma_active); - } else + } + else { offs_t srcaddr = m_reg[GREG_DMA0_SOURCE + which]; offs_t dstaddr = m_reg[GREG_DMA0_DEST + which]; @@ -972,7 +1022,7 @@ TIMER_CALLBACK_MEMBER (gt64xxx_device::perform_dma) m_reg[GREG_DMA0_CONTROL + which] |= 0x5000; - /* determine src/dst inc */ + // determine src/dst inc switch ((m_reg[GREG_DMA0_CONTROL + which] >> 2) & 3) { default: @@ -988,36 +1038,39 @@ TIMER_CALLBACK_MEMBER (gt64xxx_device::perform_dma) case 2: dstinc = 0; break; } - LOGDMA("Performing DMA%d: src=%08X dst=%08X bytes=%04X sinc=%d dinc=%d\n", which, srcaddr, dstaddr, bytesleft, srcinc, dstinc); - - int burstCount = 0; - /* standard transfer */ - while (bytesleft > 0 && burstCount < DMA_BURST_SIZE) + // check for pci stall + if (m_pci_stall_state) { - if (m_pci_stall_state) + uint32_t configRetryCount = (m_reg[GREG_PCI_TIMEOUT] >> 16) & 0xff; + m_retry_count++; + if (m_retry_count < 4) + LOGDMA("%s Stalling DMA on voodoo retry_count: %i max: %i time: %s\n", machine().describe_context(), m_retry_count, configRetryCount, machine().time().as_string()); + if (configRetryCount == 0) { - if (m_retry_count<4) LOGDMA("%s Stalling DMA on voodoo retry_count: %i\n", machine().describe_context(), m_retry_count); - // Save info - m_reg[GREG_DMA0_SOURCE + which] = srcaddr; - m_reg[GREG_DMA0_DEST + which] = dstaddr; - m_reg[GREG_DMA0_COUNT + which] = (m_reg[GREG_DMA0_COUNT + which] & ~0xffff) | bytesleft; - - m_retry_count++; - uint32_t configRetryCount = (m_reg[GREG_PCI_TIMEOUT] >> 16) & 0xff; - if (m_retry_count >= configRetryCount && configRetryCount > 0) - { - logerror("gt64xxx_device::perform_dma Error! Too many PCI retries. DMA%d: src=%08X dst=%08X bytes=%04X sinc=%d dinc=%d\n", which, srcaddr, dstaddr, bytesleft, srcinc, dstinc); - // Signal error and abort DMA - m_dma_active &= ~(1 << which); - m_retry_count = 0; - return; - } - else - { - // Come back later - return; - } + // Almost infinite retries, but avoid hanging the machine + if (configRetryCount == ~0x0) + fatalerror("gt64xxx_device::perform_dma Error! PCI is hung. DMA%d: src=%08X dst=%08X bytes=%04X sinc=%d dinc=%d\n", which, srcaddr, dstaddr, bytesleft, srcinc, dstinc); } + else if (m_retry_count >= configRetryCount) + { + logerror("gt64xxx_device::perform_dma Error! Too many PCI retries. DMA%d: src=%08X dst=%08X bytes=%04X sinc=%d dinc=%d\n", which, srcaddr, dstaddr, bytesleft, srcinc, dstinc); + // Signal error and abort DMA + m_dma_active &= ~(1 << which); + m_retry_count = 0; + // Turn off the timer + m_dma_timer->adjust(attotime::never); + // Set the RetryCtr interrupt + m_irq_pending |= 1 << (GINT_DMA0COMP_SHIFT + which); + update_irqs(); + } + return; + } + + // do the transfer + LOGDMA("gt64xxx_device: Starting DMA%d: src=%08X dst=%08X bytes=%04X sinc=%d dinc=%d time=%s\n", which, srcaddr, dstaddr, bytesleft, srcinc, dstinc, machine().time().as_string()); + int burstCount = 0; + while (bytesleft > 0 && burstCount < DMA_BURST_SIZE && !m_pci_stall_state) + { if (bytesleft < 4) { dstSpace->write_byte(dstaddr, srcSpace->read_byte(srcaddr)); @@ -1025,7 +1078,8 @@ TIMER_CALLBACK_MEMBER (gt64xxx_device::perform_dma) dstaddr += dstinc; bytesleft--; } - else { + else + { dstSpace->write_dword(dstaddr, srcSpace->read_dword(srcaddr)); srcaddr += srcinc * 4; dstaddr += dstinc * 4; @@ -1033,29 +1087,37 @@ TIMER_CALLBACK_MEMBER (gt64xxx_device::perform_dma) } burstCount++; } - /* not verified, but seems logical these should be updated byte the end */ + // not verified, but seems logical these should be updated at the end m_reg[GREG_DMA0_SOURCE + which] = srcaddr; m_reg[GREG_DMA0_DEST + which] = dstaddr; m_reg[GREG_DMA0_COUNT + which] = (m_reg[GREG_DMA0_COUNT + which] & ~0xffff) | bytesleft; - /* if we did not hit zero, punt and return later */ - if (bytesleft != 0) + // Check if we are done this descriptor + if (bytesleft == 0) { - return; - } - /* interrupt? */ - if (!(m_reg[GREG_DMA0_CONTROL + which] & 0x400)) - { - m_reg[GREG_INT_STATE] |= 1 << (GINT_DMA0COMP_SHIFT + which); - update_irqs(); - } + // byte count zero interrupt + if (!(m_reg[GREG_DMA0_CONTROL + which] & (1 << 10))) + { + m_irq_pending |= 1 << (GINT_DMA0COMP_SHIFT + which); + update_irqs(); + } - // Fetch the next dma for this channel (to be performed next scheduled burst) - if (dma_fetch_next(*m_cpu_space, which) == 0) - { - m_dma_active &= ~(1 << which); - // Turn off the timer - m_dma_timer->adjust(attotime::never); + // Fetch the next dma for this channel (to be performed next scheduled burst) + if ((m_reg[GREG_DMA0_CONTROL + which] & (1 << 9)) || dma_fetch_next(*m_cpu_space, which) == 0) + { + LOGDMA("gt64xxx_device: Done DMA descriptors time: %s\n", machine().time().as_string()); + m_dma_active &= ~(1 << which); + + // Turn off the timer + m_dma_timer->adjust(attotime::never); + + // no more descriptors interrupt (bit 10) in chained mode (not bit 9) + if ((m_reg[GREG_DMA0_CONTROL + which] & (1 << 10)) && !(m_reg[GREG_DMA0_CONTROL + which] & (1 << 9))) + { + m_irq_pending |= 1 << (GINT_DMA0COMP_SHIFT + which); + update_irqs(); + } + } } } } diff --git a/src/devices/machine/gt64xxx.h b/src/devices/machine/gt64xxx.h index 0126dac306f..644d101c72e 100644 --- a/src/devices/machine/gt64xxx.h +++ b/src/devices/machine/gt64xxx.h @@ -104,6 +104,8 @@ private: int m_irq_num; int m_simm_size[4]; + int m_irq_state; + uint32_t m_irq_pending; int m_pci_stall_state; int m_retry_count; int m_pci_cpu_stalled; diff --git a/src/mame/drivers/seattle.cpp b/src/mame/drivers/seattle.cpp index f800767931f..13d1b93a582 100644 --- a/src/mame/drivers/seattle.cpp +++ b/src/mame/drivers/seattle.cpp @@ -197,6 +197,7 @@ #include "machine/pci.h" #include "machine/gt64xxx.h" #include "machine/pci-ide.h" +#include "bus/ata/idehd.h" #include "video/voodoo_pci.h" #include "screen.h" @@ -443,6 +444,8 @@ private: void widget_cs3_map(address_map &map); void carnevil_cs3_map(address_map &map); void flagstaff_cs3_map(address_map &map); + + static void hdd_config(device_t* device); }; /************************************* @@ -454,7 +457,7 @@ private: void seattle_state::machine_start() { // set the fastest DRC options, but strict verification - m_maincpu->mips3drc_set_options(MIPS3DRC_FASTEST_OPTIONS + MIPS3DRC_STRICT_VERIFY); + m_maincpu->mips3drc_set_options(MIPS3DRC_FASTEST_OPTIONS | MIPS3DRC_STRICT_VERIFY); // configure fast RAM regions // m_maincpu->add_fastram(0x00000000, 0x007fffff, FALSE, m_rambase); @@ -905,7 +908,7 @@ uint32_t seattle_state::carnevil_gun_r(offs_t offset) void seattle_state::carnevil_gun_w(offs_t offset, uint32_t data) { - logerror("carnevil_gun_w(%d) = %02X\n", offset, data); + //logerror("carnevil_gun_w(%d) = %02X\n", offset, data); } /************************************* @@ -1013,7 +1016,7 @@ void seattle_state::output_w(uint32_t data) } else if (!BIT(data, 9) || !BIT(data, 8)) { - logerror("%08X:output_w = %04X\n", m_maincpu->pc(), data); + //logerror("%08X:output_w = %04X\n", m_maincpu->pc(), data); } } @@ -2024,6 +2027,7 @@ void seattle_state::seattle_common(machine_config &config) ide_pci_device &ide(IDE_PCI(config, PCI_ID_IDE, 0, 0x100b0002, 0x01, 0x0)); ide.irq_handler().set_inputline(m_maincpu, IDE_IRQ_NUM); ide.set_legacy_top(0x0a0); + ide.subdevice("ide")->slot(0).set_option_machine_config("hdd", hdd_config); // video hardware VOODOO_1_PCI(config, m_voodoo, 0, m_maincpu, m_screen); @@ -2045,6 +2049,11 @@ void seattle_state::seattle_common(machine_config &config) m_screen->set_screen_update(PCI_ID_VIDEO, FUNC(voodoo_1_pci_device::screen_update)); } +void seattle_state::hdd_config(device_t* device) +{ + // Set the disk dma transfer speed + static_cast(device)->set_dma_transfer_time(attotime::from_usec(15)); +} void seattle_state::phoenix(machine_config &config) { diff --git a/src/mame/drivers/vegas.cpp b/src/mame/drivers/vegas.cpp index c8fe99f630d..5b8c9dace09 100644 --- a/src/mame/drivers/vegas.cpp +++ b/src/mame/drivers/vegas.cpp @@ -472,6 +472,8 @@ private: void vegas_cs6_map(address_map &map); void vegas_cs7_map(address_map &map); void vegas_cs8_map(address_map &map); + + static void hdd_config(device_t* device); }; /************************************* @@ -542,12 +544,6 @@ void vegas_state::machine_reset() m_wheel_offset = 0; m_wheel_calibrated = false; - // Set the disk dma transfer speed - auto *hdd = subdevice(PCI_ID_IDE":ide:0:hdd"); - hdd->set_dma_transfer_time(attotime::from_usec(15)); - // Allow ultra dma - //uint16_t *identify_device = hdd->identify_device_buffer(); - //identify_device[88] = 0x7f; } /************************************* @@ -1926,6 +1922,7 @@ void vegas_state::vegascore(machine_config &config) ide_pci_device &ide(IDE_PCI(config, PCI_ID_IDE, 0, 0x10950646, 0x05, 0x0)); ide.irq_handler().set(PCI_ID_NILE, FUNC(vrc5074_device::pci_intr_d)); //ide.set_pif(0x8f); + ide.subdevice("ide")->slot(0).set_option_machine_config("hdd", hdd_config); // video hardware voodoo_2_pci_device &voodoo(VOODOO_2_PCI(config, PCI_ID_VIDEO, 0, m_maincpu, "screen")); @@ -1950,6 +1947,16 @@ void vegas_state::vegascore(machine_config &config) screen.set_screen_update(PCI_ID_VIDEO, FUNC(voodoo_pci_device::screen_update)); } +void vegas_state::hdd_config(device_t* device) +{ + // Set the disk dma transfer speed + static_cast(device)->set_dma_transfer_time(attotime::from_usec(15)); + // Allow ultra dma + //uint16_t *identify_device = static_cast(device)->identify_device_buffer(); + //identify_device[88] = 0x7f; + +} + void vegas_state::vegas(machine_config &config) {