// license:GPL-2.0+ // copyright-holders:Dirk Best /*************************************************************************** GAYLE Gate array used in the Amiga 600 and Amiga 1200 computers. ***************************************************************************/ #include "emu.h" #include "gayle.h" //************************************************************************** // CONSTANTS //************************************************************************** #define VERBOSE 0 //************************************************************************** // DEVICE DEFINITIONS //************************************************************************** DEFINE_DEVICE_TYPE(GAYLE, gayle_device, "gayle", "Amiga GAYLE") //************************************************************************** // LIVE DEVICE //************************************************************************** //------------------------------------------------- // gayle_device - constructor //------------------------------------------------- gayle_device::gayle_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, GAYLE, tag, owner, clock), m_int2_w(*this), m_cs0_read(*this), m_cs0_write(*this), m_cs1_read(*this), m_cs1_write(*this), m_gayle_id(0xff), m_gayle_id_count(0) { } //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- void gayle_device::device_start() { // resolve callbacks m_int2_w.resolve_safe(); m_cs0_read.resolve_safe(0xffff); m_cs0_write.resolve_safe(); m_cs1_read.resolve_safe(0xffff); m_cs1_write.resolve_safe(); } //------------------------------------------------- // device_reset - device-specific reset //------------------------------------------------- void gayle_device::device_reset() { m_gayle_reg[0] = 0; m_gayle_reg[1] = 0; m_gayle_reg[2] = 0; m_gayle_reg[3] = 0; } //************************************************************************** // IMPLEMENTATION //************************************************************************** READ16_MEMBER( gayle_device::gayle_r ) { uint16_t data = 0xffff; offset <<= 1; // swap mem_mask = (mem_mask << 8) | (mem_mask >> 8); if (BIT(offset, 15)) { switch (offset & 0x7fff) { case 0x0000: data = m_gayle_reg[0]; break; case 0x1000: data = m_gayle_reg[1]; break; case 0x2000: data = m_gayle_reg[2]; break; case 0x3000: data = m_gayle_reg[3]; break; } } else { if (!BIT(offset, 14)) { if (BIT(offset, 13)) data = m_cs0_read(space, (offset >> 2) & 0x07, mem_mask); else data = m_cs1_read(space, (offset >> 2) & 0x07, mem_mask); } } if (VERBOSE) logerror("gayle_r(%06x): %04x & %04x\n", offset, data, mem_mask); // swap data data = (data << 8) | (data >> 8); return data; } WRITE16_MEMBER( gayle_device::gayle_w ) { offset <<= 1; // swap mem_mask = (mem_mask << 8) | (mem_mask >> 8); data = ((data << 8) | (data >> 8)) & mem_mask; if (VERBOSE) logerror("gayle_w(%06x): %04x & %04x\n", offset, data, mem_mask); if (BIT(offset, 15)) { switch (offset & 0x7fff) { case 0x0000: m_gayle_reg[0] = data; break; case 0x1000: m_gayle_reg[1] &= data; m_gayle_reg[1] |= data & 0x03; break; case 0x2000: m_gayle_reg[2] = data; break; case 0x3000: m_gayle_reg[3] = data; break; } } else { if (!BIT(offset, 14)) { if (BIT(offset, 13)) m_cs0_write(space, (offset >> 2) & 0x07, data, mem_mask); else m_cs1_write(space, (offset >> 2) & 0x07, data, mem_mask); } } } WRITE_LINE_MEMBER( gayle_device::ide_interrupt_w ) { if (VERBOSE) logerror("ide_interrupt_w: %d\n", state); // did we change state? if (BIT(m_gayle_reg[GAYLE_CS], 7) != state) m_gayle_reg[GAYLE_IRQ] |= 1 << 7; // set line state if (state) m_gayle_reg[GAYLE_CS] |= 1 << 7; else m_gayle_reg[GAYLE_CS] &= ~(1 << 7); // update interrupts if (BIT(m_gayle_reg[GAYLE_INTEN], 7)) m_int2_w(BIT(m_gayle_reg[GAYLE_CS], 7)); } READ16_MEMBER( gayle_device::gayle_id_r ) { uint16_t data; if (ACCESSING_BITS_8_15) data = ((m_gayle_id << m_gayle_id_count++) & 0x80) << 8; else data = 0xffff; if (VERBOSE) logerror("gayle_id_r(%06x): %04x & %04x (id=%02x)\n", offset, data, mem_mask, m_gayle_id); return data; } WRITE16_MEMBER( gayle_device::gayle_id_w ) { if (VERBOSE) logerror("gayle_id_w(%06x): %04x & %04x (id=%02x)\n", offset, data, mem_mask, m_gayle_id); m_gayle_id_count = 0; }