// license:BSD-3-Clause // copyright-holders:R. Belmont /********************************************************************* swim.c Implementation of the Apple SWIM FDC controller; used on (less) early Macs *********************************************************************/ #include "emu.h" #include "machine/swim.h" /*************************************************************************** CONSTANTS ***************************************************************************/ #define LOG_SWIM 0 enum { SWIM_MODE_IWM, SWIM_MODE_SWIM, SWIM_MODE_SWIM2, SWIM_MODE_SWIM3 }; /*************************************************************************** DEVICE ***************************************************************************/ DEFINE_DEVICE_TYPE(LEGACY_SWIM, swim_device, "swiml", "Apple SWIM (Sander/Woz Integrated Machine) (legacy)") //------------------------------------------------- // ctor //------------------------------------------------- swim_device::swim_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : applefdc_base_device(APPLEFDC_SWIM, mconfig, LEGACY_SWIM, tag, owner, clock) { } //------------------------------------------------- // device_start - device-specific start //------------------------------------------------- void swim_device::device_start() { // call inherited version applefdc_base_device::device_start(); m_swim_mode = SWIM_MODE_IWM; m_swim_magic_state = 0x00; m_parm_offset = 0x00; memset(m_ism_regs, 0, sizeof(m_ism_regs)); memset(m_parms, 0, sizeof(m_parms)); } //------------------------------------------------- // device_reset - device-specific reset //------------------------------------------------- void swim_device::device_reset() { // call inherited version applefdc_base_device::device_reset(); static uint8_t swim_default_parms[16] = { 0x38, 0x18, 0x41, 0x2e, 0x2e, 0x18, 0x18, 0x1b, 0x1b, 0x2f, 0x2f, 0x19, 0x19, 0x97, 0x1b, 0x57 }; for (int i = 0; i < 16; i++) { m_parms[i] = swim_default_parms[i]; } m_swim_magic_state = 0; m_swim_mode = SWIM_MODE_IWM; m_parm_offset = 0; } //------------------------------------------------- // read - reads a byte from the FDC //------------------------------------------------- uint8_t swim_device::read(offs_t offset) { uint8_t result = 0; if (m_swim_mode == SWIM_MODE_IWM) { // IWM mode result = applefdc_base_device::read(offset); } else if (m_swim_mode >= SWIM_MODE_SWIM) { // reading parameter RAM? if ((offset & 7) == 3) { result = m_parms[m_parm_offset++]; m_parm_offset &= 0xf; } else { result = m_ism_regs[offset&7]; } if (LOG_SWIM) logerror("SWIM: read %02x from offset %x\n", result, offset & 7); } return result; } //------------------------------------------------- // write - write a byte to the FDC //------------------------------------------------- void swim_device::write(offs_t offset, uint8_t data) { if (m_swim_mode == SWIM_MODE_IWM) { // IWM mode applefdc_base_device::write(offset, data); } else if (m_swim_mode >= SWIM_MODE_SWIM) { if (LOG_SWIM) logerror("SWIM: write %02x to offset %x\n", data, offset & 7); switch (offset & 7) { case 2: // write CRC break; case 3: // write parameter m_parms[m_parm_offset++] = data; m_parm_offset &= 0xf; break; case 6: // write zeros to status (also zeroes parameter RAM pointer) m_ism_regs[6] &= ~data; m_parm_offset = 0; if (data == 0xf8) // magic "revert to IWM" value { if (LOG_SWIM) logerror("SWIM: reverting to IWM\n"); m_swim_mode = SWIM_MODE_IWM; } break; case 7: // write ones to status m_ism_regs[6] |= data; break; default: m_ism_regs[offset & 7] = data; break; } } } //------------------------------------------------- // iwm_modereg_w - changes the mode register //------------------------------------------------- void swim_device::iwm_modereg_w(uint8_t data) { // SWIM mode is unlocked by writing 1/0/1/1 in a row to bit 6 (which is unused on IWM) // when SWIM mode engages, the IWM is disconnected from both the 68k and the drives, // and the ISM is substituted. switch (m_swim_magic_state) { case 0: case 2: case 3: if (data & 0x40) { m_swim_magic_state++; } else { m_swim_magic_state = 0; } break; case 1: if (!(data & 0x40)) { m_swim_magic_state++; } else { m_swim_magic_state = 0; } break; } if (m_swim_magic_state == 4) { m_swim_magic_state = 0; m_swim_mode = SWIM_MODE_SWIM; } // call inherited version applefdc_base_device::iwm_modereg_w(data); }