diff options
Diffstat (limited to 'src/devices/machine/gt64xxx.cpp')
-rw-r--r-- | src/devices/machine/gt64xxx.cpp | 392 |
1 files changed, 228 insertions, 164 deletions
diff --git a/src/devices/machine/gt64xxx.cpp b/src/devices/machine/gt64xxx.cpp index fdde2d52c66..3f3ea408022 100644 --- a/src/devices/machine/gt64xxx.cpp +++ b/src/devices/machine/gt64xxx.cpp @@ -3,11 +3,11 @@ #include "emu.h" #include "gt64xxx.h" -#define LOG_GENERAL (1U << 0) #define LOG_GALILEO (1U << 1) #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 +16,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 +53,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 +84,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 +112,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) @@ -193,8 +195,7 @@ void gt64xxx_device::device_start() { pci_host_device::device_start(); m_cpu_space = &m_cpu->space(AS_PCI_CONFIG); - memory_space = &space(AS_PCI_MEM); - io_space = &space(AS_PCI_IO); + set_spaces(&space(AS_PCI_MEM), &space(AS_PCI_IO)); memory_window_start = 0; memory_window_end = 0xffffffff; @@ -205,7 +206,7 @@ void gt64xxx_device::device_start() status = 0x0; // DMA timer - m_dma_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gt64xxx_device::perform_dma), this)); + m_dma_timer = timer_alloc(FUNC(gt64xxx_device::perform_dma), this); // Leave the timer disabled. m_dma_timer->adjust(attotime::never, 0, DMA_TIMER_PERIOD); @@ -227,13 +228,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 */ - 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)); + // allocate timers for the galileo + m_timer[0].timer = timer_alloc(FUNC(gt64xxx_device::timer_callback), this); + m_timer[1].timer = timer_alloc(FUNC(gt64xxx_device::timer_callback), this); + m_timer[2].timer = timer_alloc(FUNC(gt64xxx_device::timer_callback), this); + m_timer[3].timer = timer_alloc(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)); @@ -243,10 +246,8 @@ void gt64xxx_device::device_start() save_item(NAME(m_cpu_stalled_mem_mask)); save_item(NAME(m_prev_addr)); save_item(NAME(m_reg)); - for (int i = 0; i < ARRAY_LENGTH(m_timer); i++) { - save_item(NAME(m_timer[i].active), i); - save_item(NAME(m_timer[i].count), i); - } + save_item(STRUCT_MEMBER(m_timer, active)); + save_item(STRUCT_MEMBER(m_timer, count)); save_item(NAME(m_dma_active)); // m_ram[4] save_pointer(NAME(m_ram[0].data()), m_simm_size[0] / 4); @@ -308,6 +309,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; @@ -367,22 +370,22 @@ void gt64xxx_device::map_cpu_space() // PCI IO Window winStart = m_reg[GREG_PCI_IO_LO]<<21; winEnd = (m_reg[GREG_PCI_IO_LO]<<21) | (m_reg[GREG_PCI_IO_HI]<<21) | 0x1fffff; - m_cpu_space->install_read_handler(winStart, winEnd, read32_delegate(FUNC(gt64xxx_device::master_io_r), this)); - m_cpu_space->install_write_handler(winStart, winEnd, write32_delegate(FUNC(gt64xxx_device::master_io_w), this)); + m_cpu_space->install_read_handler(winStart, winEnd, read32s_delegate(*this, FUNC(gt64xxx_device::master_io_r))); + m_cpu_space->install_write_handler(winStart, winEnd, write32s_delegate(*this, FUNC(gt64xxx_device::master_io_w))); logerror("map_cpu_space pci_io start: %08X end: %08X\n", winStart, winEnd); // PCI MEM0 Window winStart = m_reg[GREG_PCI_MEM0_LO]<<21; winEnd = (m_reg[GREG_PCI_MEM0_LO]<<21) | (m_reg[GREG_PCI_MEM0_HI]<<21) | 0x1fffff; - m_cpu_space->install_read_handler(winStart, winEnd, read32_delegate(FUNC(gt64xxx_device::master_mem0_r), this)); - m_cpu_space->install_write_handler(winStart, winEnd, write32_delegate(FUNC(gt64xxx_device::master_mem0_w), this)); + m_cpu_space->install_read_handler(winStart, winEnd, read32s_delegate(*this, FUNC(gt64xxx_device::master_mem0_r))); + m_cpu_space->install_write_handler(winStart, winEnd, write32s_delegate(*this, FUNC(gt64xxx_device::master_mem0_w))); logerror("map_cpu_space pci_mem0 start: %08X end: %08X\n", winStart, winEnd); // PCI MEM1 Window winStart = m_reg[GREG_PCI_MEM1_LO]<<21; winEnd = (m_reg[GREG_PCI_MEM1_LO]<<21) | (m_reg[GREG_PCI_MEM1_HI]<<21) | 0x1fffff; - m_cpu_space->install_read_handler(winStart, winEnd, read32_delegate(FUNC(gt64xxx_device::master_mem1_r), this)); - m_cpu_space->install_write_handler(winStart, winEnd, write32_delegate(FUNC(gt64xxx_device::master_mem1_w), this)); + m_cpu_space->install_read_handler(winStart, winEnd, read32s_delegate(*this, FUNC(gt64xxx_device::master_mem1_r))); + m_cpu_space->install_write_handler(winStart, winEnd, write32s_delegate(*this, FUNC(gt64xxx_device::master_mem1_w))); logerror("map_cpu_space pci_mem1 start: %08X end: %08X\n", winStart, winEnd); // Setup the address mapping table for DMA lookups @@ -424,8 +427,8 @@ void gt64xxx_device::map_extra(uint64_t memory_window_start, uint64_t memory_win winStart = (m_reg[GREG_R1_0_LO + 0x10 / 4 * (ramIndex / 2)] << 21) | (m_reg[GREG_RAS0_LO + 0x8 / 4 * ramIndex] << 20); winEnd = (m_reg[GREG_R1_0_LO + 0x10 / 4 * (ramIndex / 2)] << 21) | (m_reg[GREG_RAS0_HI + 0x8 / 4 * ramIndex] << 20) | 0xfffff; winSize = winEnd - winStart + 1; - memory_space->install_read_handler(winStart, winEnd, read32_delegate(FUNC(gt64xxx_device::ras_0_r), this)); - memory_space->install_write_handler(winStart, winEnd, write32_delegate(FUNC(gt64xxx_device::ras_0_w), this)); + memory_space->install_read_handler(winStart, winEnd, read32s_delegate(*this, FUNC(gt64xxx_device::ras_0_r))); + memory_space->install_write_handler(winStart, winEnd, write32s_delegate(*this, FUNC(gt64xxx_device::ras_0_w))); LOGGALILEO("map_extra RAS0 start=%08X end=%08X size=%08X\n", winStart, winEnd, winSize); // RAS1 @@ -433,8 +436,8 @@ void gt64xxx_device::map_extra(uint64_t memory_window_start, uint64_t memory_win winStart = (m_reg[GREG_R1_0_LO + 0x10 / 4 * (ramIndex / 2)] << 21) | (m_reg[GREG_RAS0_LO + 0x8 / 4 * ramIndex] << 20); winEnd = (m_reg[GREG_R1_0_LO + 0x10 / 4 * (ramIndex / 2)] << 21) | (m_reg[GREG_RAS0_HI + 0x8 / 4 * ramIndex] << 20) | 0xfffff; winSize = winEnd - winStart + 1; - memory_space->install_read_handler(winStart, winEnd, read32_delegate(FUNC(gt64xxx_device::ras_1_r), this)); - memory_space->install_write_handler(winStart, winEnd, write32_delegate(FUNC(gt64xxx_device::ras_1_w), this)); + memory_space->install_read_handler(winStart, winEnd, read32s_delegate(*this, FUNC(gt64xxx_device::ras_1_r))); + memory_space->install_write_handler(winStart, winEnd, write32s_delegate(*this, FUNC(gt64xxx_device::ras_1_w))); LOGGALILEO("map_extra RAS1 start=%08X end=%08X size=%08X\n", winStart, winEnd, winSize); // RAS2 @@ -442,8 +445,8 @@ void gt64xxx_device::map_extra(uint64_t memory_window_start, uint64_t memory_win winStart = (m_reg[GREG_R1_0_LO + 0x10 / 4 * (ramIndex / 2)] << 21) | (m_reg[GREG_RAS0_LO + 0x8 / 4 * ramIndex] << 20); winEnd = (m_reg[GREG_R1_0_LO + 0x10 / 4 * (ramIndex / 2)] << 21) | (m_reg[GREG_RAS0_HI + 0x8 / 4 * ramIndex] << 20) | 0xfffff; winSize = winEnd - winStart + 1; - memory_space->install_read_handler(winStart, winEnd, read32_delegate(FUNC(gt64xxx_device::ras_2_r), this)); - memory_space->install_write_handler(winStart, winEnd, write32_delegate(FUNC(gt64xxx_device::ras_2_w), this)); + memory_space->install_read_handler(winStart, winEnd, read32s_delegate(*this, FUNC(gt64xxx_device::ras_2_r))); + memory_space->install_write_handler(winStart, winEnd, write32s_delegate(*this, FUNC(gt64xxx_device::ras_2_w))); LOGGALILEO("map_extra RAS2 start=%08X end=%08X size=%08X\n", winStart, winEnd, winSize); // RAS3 @@ -451,8 +454,8 @@ void gt64xxx_device::map_extra(uint64_t memory_window_start, uint64_t memory_win winStart = (m_reg[GREG_R1_0_LO + 0x10 / 4 * (ramIndex / 2)] << 21) | (m_reg[GREG_RAS0_LO + 0x8 / 4 * ramIndex] << 20); winEnd = (m_reg[GREG_R1_0_LO + 0x10 / 4 * (ramIndex / 2)] << 21) | (m_reg[GREG_RAS0_HI + 0x8 / 4 * ramIndex] << 20) | 0xfffff; winSize = winEnd - winStart + 1; - memory_space->install_read_handler(winStart, winEnd, read32_delegate(FUNC(gt64xxx_device::ras_3_r), this)); - memory_space->install_write_handler(winStart, winEnd, write32_delegate(FUNC(gt64xxx_device::ras_3_w), this)); + memory_space->install_read_handler(winStart, winEnd, read32s_delegate(*this, FUNC(gt64xxx_device::ras_3_r))); + memory_space->install_write_handler(winStart, winEnd, write32s_delegate(*this, FUNC(gt64xxx_device::ras_3_w))); LOGGALILEO("map_extra RAS3 start=%08X end=%08X size=%08X\n", winStart, winEnd, winSize); } @@ -462,7 +465,7 @@ void gt64xxx_device::reset_all_mappings() } // PCI Stalling -WRITE_LINE_MEMBER(gt64xxx_device::pci_stall) +void gt64xxx_device::pci_stall(int state) { // Reset the retry count once unstalled if (state==0 && m_pci_stall_state==1) { @@ -481,35 +484,35 @@ 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; } // PCI bus control -READ32_MEMBER (gt64xxx_device::pci_config_r) +uint32_t gt64xxx_device::pci_config_r(offs_t offset, uint32_t mem_mask) { uint32_t result = 0; LOGGALILEO("%s galileo pci_config_r from offset %02X = %08X & %08X\n", machine().describe_context(), offset*4, result, mem_mask); return result; } -WRITE32_MEMBER (gt64xxx_device::pci_config_w) +void gt64xxx_device::pci_config_w(offs_t offset, uint32_t data, uint32_t mem_mask) { LOGGALILEO("%s galileo pci_config_w to offset %02X = %08X & %08X\n", machine().describe_context(), offset*4, data, mem_mask); } // PCI Master Window 0 -READ32_MEMBER (gt64xxx_device::master_mem0_r) +uint32_t gt64xxx_device::master_mem0_r(offs_t offset, uint32_t mem_mask) { uint32_t result = this->space(AS_PCI_MEM).read_dword((m_reg[GREG_PCI_MEM0_LO]<<21) | (offset*4), mem_mask); LOGPCI("%s galileo pci mem0 read from offset %08X = %08X & %08X\n", machine().describe_context(), (m_reg[GREG_PCI_MEM0_LO]<<21) | (offset*4), result, mem_mask); return result; } -WRITE32_MEMBER (gt64xxx_device::master_mem0_w) +void gt64xxx_device::master_mem0_w(offs_t offset, uint32_t data, uint32_t mem_mask) { if (m_pci_stall_state) { if (m_stall_windex < 2) { @@ -522,7 +525,7 @@ WRITE32_MEMBER (gt64xxx_device::master_mem0_w) 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"); @@ -534,20 +537,20 @@ WRITE32_MEMBER (gt64xxx_device::master_mem0_w) } // PCI Master Window 1 -READ32_MEMBER (gt64xxx_device::master_mem1_r) +uint32_t gt64xxx_device::master_mem1_r(offs_t offset, uint32_t mem_mask) { uint32_t result = this->space(AS_PCI_MEM).read_dword((m_reg[GREG_PCI_MEM1_LO]<<21) | (offset*4), mem_mask); LOGPCI("%s galileo pci mem1 read from offset %08X = %08X & %08X\n", machine().describe_context(), (m_reg[GREG_PCI_MEM1_LO]<<21) | (offset*4), result, mem_mask); return result; } -WRITE32_MEMBER (gt64xxx_device::master_mem1_w) +void gt64xxx_device::master_mem1_w(offs_t offset, uint32_t data, uint32_t mem_mask) { this->space(AS_PCI_MEM).write_dword((m_reg[GREG_PCI_MEM1_LO]<<21) | (offset*4), data, mem_mask); LOGPCI("%s galileo pci mem1 write to offset %08X = %08X & %08X\n", machine().describe_context(), (m_reg[GREG_PCI_MEM1_LO]<<21) | (offset*4), data, mem_mask); } // PCI Master IO -READ32_MEMBER (gt64xxx_device::master_io_r) +uint32_t gt64xxx_device::master_io_r(offs_t offset, uint32_t mem_mask) { uint32_t result = this->space(AS_PCI_IO).read_dword((m_reg[GREG_PCI_IO_LO] << 21) | (offset * 4), mem_mask); if (m_prev_addr != offset) { @@ -556,7 +559,7 @@ READ32_MEMBER (gt64xxx_device::master_io_r) } return result; } -WRITE32_MEMBER (gt64xxx_device::master_io_w) +void gt64xxx_device::master_io_w(offs_t offset, uint32_t data, uint32_t mem_mask) { this->space(AS_PCI_IO).write_dword((m_reg[GREG_PCI_IO_LO] << 21) | (offset * 4), data, mem_mask); if (m_prev_addr != offset) { @@ -565,53 +568,53 @@ WRITE32_MEMBER (gt64xxx_device::master_io_w) } } -READ32_MEMBER(gt64xxx_device::ras_0_r) +uint32_t gt64xxx_device::ras_0_r(offs_t offset, uint32_t mem_mask) { uint32_t result = m_ram[0][offset]; LOGPCI("%s galileo ras_0 read from offset %08X = %08X & %08X\n", machine().describe_context(), offset * 4, result, mem_mask); return result; } -WRITE32_MEMBER(gt64xxx_device::ras_0_w) +void gt64xxx_device::ras_0_w(offs_t offset, uint32_t data, uint32_t mem_mask) { COMBINE_DATA(&m_ram[0][offset]); LOGPCI("%s galileo ras_0 write to offset %08X = %08X & %08X\n", machine().describe_context(), offset * 4, data, mem_mask); } -READ32_MEMBER(gt64xxx_device::ras_1_r) +uint32_t gt64xxx_device::ras_1_r(offs_t offset, uint32_t mem_mask) { uint32_t result = m_ram[1][offset]; LOGPCI("%s galileo ras_0 read from offset %08X = %08X & %08X\n", machine().describe_context(), offset * 4, result, mem_mask); return result; } -WRITE32_MEMBER(gt64xxx_device::ras_1_w) +void gt64xxx_device::ras_1_w(offs_t offset, uint32_t data, uint32_t mem_mask) { COMBINE_DATA(&m_ram[1][offset]); LOGPCI("%s galileo ras_0 write to offset %08X = %08X & %08X\n", machine().describe_context(), offset * 4, data, mem_mask); } -READ32_MEMBER(gt64xxx_device::ras_2_r) +uint32_t gt64xxx_device::ras_2_r(offs_t offset, uint32_t mem_mask) { uint32_t result = m_ram[2][offset]; LOGPCI("%s galileo ras_0 read from offset %08X = %08X & %08X\n", machine().describe_context(), offset * 4, result, mem_mask); return result; } -WRITE32_MEMBER(gt64xxx_device::ras_2_w) +void gt64xxx_device::ras_2_w(offs_t offset, uint32_t data, uint32_t mem_mask) { COMBINE_DATA(&m_ram[2][offset]); LOGPCI("%s galileo ras_0 write to offset %08X = %08X & %08X\n", machine().describe_context(), offset * 4, data, mem_mask); } -READ32_MEMBER(gt64xxx_device::ras_3_r) +uint32_t gt64xxx_device::ras_3_r(offs_t offset, uint32_t mem_mask) { uint32_t result = m_ram[3][offset]; LOGPCI("%s galileo ras_0 read from offset %08X = %08X & %08X\n", machine().describe_context(), offset * 4, result, mem_mask); return result; } -WRITE32_MEMBER(gt64xxx_device::ras_3_w) +void gt64xxx_device::ras_3_w(offs_t offset, uint32_t data, uint32_t mem_mask) { COMBINE_DATA(&m_ram[3][offset]); LOGPCI("%s galileo ras_0 write to offset %08X = %08X & %08X\n", machine().describe_context(), offset * 4, data, mem_mask); @@ -619,11 +622,11 @@ WRITE32_MEMBER(gt64xxx_device::ras_3_w) // CPU I/F -READ32_MEMBER (gt64xxx_device::cpu_if_r) +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: @@ -654,18 +657,24 @@ READ32_MEMBER (gt64xxx_device::cpu_if_r) break; case GREG_CONFIG_DATA: - result = config_data_r(space, offset); + result = config_data_r(offset); LOGGALILEO("%s Galileo GREG_CONFIG_DATA read from offset %03X = %08X\n", machine().describe_context(), offset*4, result); break; case GREG_CONFIG_ADDRESS: - result = config_address_r(space, offset); + result = config_address_r(); + break; + + 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_INT_STATE: - case GREG_INT_MASK: 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: @@ -678,7 +687,7 @@ READ32_MEMBER (gt64xxx_device::cpu_if_r) return result; } -WRITE32_MEMBER(gt64xxx_device::cpu_if_w) +void gt64xxx_device::cpu_if_w(address_space &space, offs_t offset, uint32_t data, uint32_t mem_mask) { if (m_be) { data = swapendian_int32(data); @@ -688,7 +697,7 @@ WRITE32_MEMBER(gt64xxx_device::cpu_if_w) 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: @@ -719,25 +728,33 @@ WRITE32_MEMBER(gt64xxx_device::cpu_if_w) { 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<<which))) { // Trigger the timer if there are no dma's active if (m_dma_active==0) - m_dma_timer->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; } @@ -776,7 +793,7 @@ WRITE32_MEMBER(gt64xxx_device::cpu_if_w) 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)) { @@ -784,20 +801,27 @@ WRITE32_MEMBER(gt64xxx_device::cpu_if_w) 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(space, offset, 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); break; @@ -823,7 +847,7 @@ WRITE32_MEMBER(gt64xxx_device::cpu_if_w) // Type 1 transaction, no modification needed modData = data; } - pci_host_device::config_address_w(space, offset, modData); + pci_host_device::config_address_w(offset, modData); LOGGALILEO("%s Galileo PCI config address write to offset %03X = %08X & %08X origData = %08X\n", machine().describe_context(), offset*4, modData, mem_mask, data); break; @@ -831,7 +855,6 @@ WRITE32_MEMBER(gt64xxx_device::cpu_if_w) 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; @@ -841,46 +864,79 @@ WRITE32_MEMBER(gt64xxx_device::cpu_if_w) } } -/************************************* - * - * 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))) - timer->timer->adjust(TIMER_PERIOD * timer->count, which); + { + // unsure what a 0-length timer should do, but it produces an infinite loop so guard against it + u32 effcount = timer->count; + if (effcount == 0) + effcount = (which != 0) ? 0xffffff : 0xffffffff; + timer->timer->adjust(TIMER_PERIOD * effcount, which); + } 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(); } @@ -904,35 +960,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; @@ -956,7 +1007,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]; @@ -968,7 +1020,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: @@ -984,36 +1036,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)); @@ -1021,7 +1076,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; @@ -1029,29 +1085,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) - { - return; - } - /* interrupt? */ - if (!(m_reg[GREG_DMA0_CONTROL + which] & 0x400)) + // Check if we are done this descriptor + if (bytesleft == 0) { - 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(); + } + } } } } |