summaryrefslogblamecommitdiffstatshomepage
path: root/src/mess/machine/swim.c
blob: 9e1506ad9ab006b36089f7ca6fa66385744f454e (plain) (tree)
1
2
3
4
5
6
7
8

                               




                                                                      
              









                                                                            
                     




















                                                                                                       
                                                                                                                                              













                                                   


                                            
































































































                                                                                            
                                                                                  

































































                                                                                              
// license:BSD-3-Clause
// copyright-holders:R. Belmont
/*********************************************************************

    swim.c

    Implementation of the Apple SWIM FDC controller; used on (less)
    early Macs

*********************************************************************/

#include "machine/swim.h"


/***************************************************************************
    CONSTANTS
***************************************************************************/

#define LOG_SWIM    0

enum
{
	SWIM_MODE_IWM,
	SWIM_MODE_SWIM,
	SWIM_MODE_SWIM2,
	SWIM_MODE_SWIM3
};


/***************************************************************************
    DEVICE
***************************************************************************/

const device_type SWIM = &device_creator<swim_device>;

//-------------------------------------------------
//  ctor
//-------------------------------------------------

swim_device::swim_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
	: applefdc_base_device(APPLEFDC_SWIM, mconfig, SWIM, "Apple SWIM (Steve Woz Integrated Machine)", tag, owner, clock, "swim", __FILE__)
{
}



//-------------------------------------------------
//  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 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 swim_device::read(UINT8 offset)
{
	UINT8 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(UINT8 offset, UINT8 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 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);
}