diff options
Diffstat (limited to 'src/devices/machine/applefdc.cpp')
-rw-r--r-- | src/devices/machine/applefdc.cpp | 586 |
1 files changed, 0 insertions, 586 deletions
diff --git a/src/devices/machine/applefdc.cpp b/src/devices/machine/applefdc.cpp deleted file mode 100644 index 681dcc525ed..00000000000 --- a/src/devices/machine/applefdc.cpp +++ /dev/null @@ -1,586 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Nathan Woods, Raphael Nabet, R. Belmont -/********************************************************************* - - applefdc.c - - Implementation of various Apple Floppy Disk Controllers, including - the classic Apple controller and the IWM (Integrated Woz Machine) - chip - - The IWM chip was used as the floppy disk controller for early Macs and the - Apple IIgs, and was eventually superseded by the SWIM chp. - - Nate Woods - Raphael Nabet - - Writing this code would not be possible if it weren't for the work of the - XGS and KEGS emulators which also contain IWM emulations. - - TODO - - Implement the unimplemented IWM modes - - IWM_MODE_CLOCKSPEED - - IWM_MODE_BITCELLTIME - - IWM_MODE_HANDSHAKEPROTOCOL - - IWM_MODE_LATCHMODE - - Investigate the differences between the IWM and the classic Apple II - controller more fully. It is currently unclear what are genuine - differences and what are effectively hacks that "just seem" to work. - - Figure out iwm_readenable2handshake() and iwm_enable2(); they are - hackish at best - - Support the SWIM chip - - Proper timing - - This code was originally IWM specific; we need to clean up IWMisms in - the code - - Make it faster? - - Add sound? - -*********************************************************************/ - -#include "emu.h" -#include "applefdc.h" - - -/*************************************************************************** - CONSTANTS -***************************************************************************/ - -// logging -#define LOG_APPLEFDC 0 -#define LOG_APPLEFDC_EXTRA 0 - -// mask for FDC lines -#define IWM_MOTOR 0x10 -#define IWM_DRIVE 0x20 -#define IWM_Q6 0x40 -#define IWM_Q7 0x80 - -const device_timer_id TIMER_MOTOR_ONOFF = 1; - - - - - -/*************************************************************************** - IWM MODE - - The IWM mode has the following values: - - Bit 7 Reserved - Bit 6 Reserved - Bit 5 Reserved - Bit 4 ! Clock speed - 0=7MHz; used by Apple IIgs - 1=8MHz; used by Mac (I believe) - Bit 3 ! Bit cell time - 0=4usec/bit (used for 5.25" drives) - 1=2usec/bit (used for 3.5" drives) - Bit 2 Motor-off delay - 0=leave on for 1 sec after system turns it off - 1=turn off immediately - Bit 1 ! Handshake protocol - 0=synchronous (software supplies timing for writing data; used for 5.25" drives) - 1=asynchronous (IWM supplies timing; used for 3.5" drives) - Bit 0 ! Latch mode - 0=read data stays valid for 7usec (used for 5.25" drives) - 1=read data stays valid for full byte time (used for 3.5" drives) - - ***************************************************************************/ - -enum -{ - IWM_MODE_CLOCKSPEED = 0x10, - IWM_MODE_BITCELLTIME = 0x08, - IWM_MODE_MOTOROFFDELAY = 0x04, - IWM_MODE_HANDSHAKEPROTOCOL = 0x02, - IWM_MODE_LATCHMODE = 0x01 -}; - - - -/*************************************************************************** - BASE DEVICE -***************************************************************************/ - -//------------------------------------------------- -// ctor -//------------------------------------------------- - -applefdc_base_device::applefdc_base_device(applefdc_base_device::applefdc_t fdc_type, const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, type, tag, owner, clock), - m_type(fdc_type), - m_interface(nullptr) -{ -} - - - -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void applefdc_base_device::device_start() -{ - // timer - m_motor_timer = timer_alloc(TIMER_MOTOR_ONOFF); - - // state - m_write_byte = 0x00; - m_lines = 0x00; - m_mode = 0x1F; // default value needed by Lisa 2 - no, I don't know if it is true - m_handshake_hack = 0x00; - - // register save states - save_item(NAME(m_write_byte)); - save_item(NAME(m_lines)); - save_item(NAME(m_mode)); - save_item(NAME(m_handshake_hack)); -} - - - -//------------------------------------------------- -// device_reset - device-specific reset -//------------------------------------------------- - -void applefdc_base_device::device_reset(void) -{ - m_handshake_hack = 0x00; - m_write_byte = 0x00; - m_lines = 0x00; - m_mode = 0x1F; /* default value needed by Lisa 2 - no, I don't know if it is true */ - m_motor_timer->reset(); -} - - - -//------------------------------------------------- -// device_timer - device-specific timer callbacks -//------------------------------------------------- - -void applefdc_base_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) -{ - switch(id) - { - case TIMER_MOTOR_ONOFF: - turn_motor_onoff(param != 0); - break; - } -} - - - -//------------------------------------------------- -// get_interface - gets the interface -//------------------------------------------------- - -const applefdc_interface *applefdc_base_device::get_interface() -{ - static const applefdc_interface dummy_interface = {nullptr, }; - - return (m_interface != nullptr) ? m_interface : &dummy_interface; -} - - - -//------------------------------------------------- -// iwm_enable2 - hackish function -//------------------------------------------------- - -int applefdc_base_device::iwm_enable2() -{ - /* R. Nabet : This function looks more like a hack than a real feature of the IWM; */ - /* it is not called from the Mac Plus driver */ - return (m_lines & APPLEFDC_PH1) && (m_lines & APPLEFDC_PH3); -} - - - -//------------------------------------------------- -// iwm_readenable2handshake - hackish function -//------------------------------------------------- - -uint8_t applefdc_base_device::iwm_readenable2handshake() -{ - /* R. Nabet : This function looks more like a hack than a real feature of the IWM; */ - /* it is not called from the Mac Plus driver */ - m_handshake_hack++; - m_handshake_hack %= 4; - return (m_handshake_hack != 0) ? 0xc0 : 0x80; -} - - - -//------------------------------------------------- -// statusreg_r - reads the status register -//------------------------------------------------- - -uint8_t applefdc_base_device::statusreg_r() -{ - uint8_t result; - int status; - const applefdc_interface *intf = get_interface(); - - /* IWM status: - * - * Bit 7 Sense input (write protect for 5.25" drive and general status line for 3.5") - * Bit 6 Reserved - * Bit 5 Drive enable (is 1 if drive is on) - * Bits 4-0 Same as IWM mode bits 4-0 - */ - - status = iwm_enable2() ? 1 : (intf->read_status ? intf->read_status(this) : 0); - - result = (status ? 0x80 : 0x00); - - if (m_type != APPLEFDC_APPLE2) - result |= (((m_lines & IWM_MOTOR) ? 1 : 0) << 5) | m_mode; - return result; -} - - - -//------------------------------------------------- -// iwm_modereg_w - changes the mode register -//------------------------------------------------- - -void applefdc_base_device::iwm_modereg_w(uint8_t data) -{ - m_mode = data & 0x1f; /* write mode register */ - - if (LOG_APPLEFDC_EXTRA) - logerror("iwm_modereg_w: iwm_mode=0x%02x\n", (unsigned) m_mode); -} - - - -//------------------------------------------------- -// read_reg - reads a register -//------------------------------------------------- - -uint8_t applefdc_base_device::read_reg(int lines) -{ - const applefdc_interface *intf = get_interface(); - uint8_t result = 0; - - switch(lines) - { - case 0: - // read data register - if ((m_type != APPLEFDC_APPLE2) && (iwm_enable2() || !(m_lines & IWM_MOTOR))) - { - result = 0xFF; - } - else - { - // Right now, this function assumes latch mode; which is always used for - // 3.5 inch drives. Eventually we should check to see if latch mode is - // off - if (LOG_APPLEFDC) - { - if ((m_mode & IWM_MODE_LATCHMODE) == 0x00) - logerror("applefdc_read_reg(): latch mode off not implemented\n"); - } - - result = (intf->read_data ? intf->read_data(this) : 0x00); - } - break; - - case IWM_Q6: - // read status register - result = statusreg_r(); - break; - - case IWM_Q7: - // Classic Apple II: Read status register - // IWM: Read handshake register - if (m_type == APPLEFDC_APPLE2) - result = statusreg_r(); - else - result = iwm_enable2() ? iwm_readenable2handshake() : 0x80; - break; - } - return result; -} - - - -//------------------------------------------------- -// write_reg - writes a register -//------------------------------------------------- - -void applefdc_base_device::write_reg(uint8_t data) -{ - const applefdc_interface *intf = get_interface(); - - switch(m_lines & (IWM_Q6 | IWM_Q7)) - { - case IWM_Q6 | IWM_Q7: - if (!(m_lines & IWM_MOTOR)) - { - iwm_modereg_w(data); - } - else if (!iwm_enable2()) - { - // Right now, this function assumes latch mode; which is always used for - // 3.5 inch drives. Eventually we should check to see if latch mode is - // off - if (LOG_APPLEFDC) - { - if ((m_mode & IWM_MODE_LATCHMODE) == 0) - logerror("applefdc_write_reg(): latch mode off not implemented\n"); - } - - if (intf->write_data != nullptr) - intf->write_data(this, data); - } - break; - } -} - - - -//------------------------------------------------- -// turn_motor_onoff - timer callback for turning -// motor on or off -//------------------------------------------------- - -void applefdc_base_device::turn_motor_onoff(bool status) -{ - const applefdc_interface *intf = get_interface(); - int enable_lines; - - if (status) - { - m_lines |= IWM_MOTOR; - enable_lines = (m_lines & IWM_DRIVE) ? 2 : 1; - } - else - { - m_lines &= ~IWM_MOTOR; - - if (m_type == APPLEFDC_APPLE2) - enable_lines = (m_lines & IWM_DRIVE) ? 2 : 1; - else - enable_lines = 0; - } - - /* invoke callback, if present */ - if (intf->set_enable_lines != nullptr) - intf->set_enable_lines(this, enable_lines); - - if (LOG_APPLEFDC_EXTRA) - logerror("iwm_turnmotor_onoff(): Turning motor %s\n", status ? "on" : "off"); -} - - - -//------------------------------------------------- -// iwm_access -//------------------------------------------------- - -void applefdc_base_device::iwm_access(int offset) -{ - static const char *const lines[] = - { - "PH0", - "PH1", - "PH2", - "PH3", - "MOTOR", - "DRIVE", - "Q6", - "Q7" - }; - - const applefdc_interface *intf = get_interface(); - - if (offset & 1) - m_lines |= (1 << (offset >> 1)); - else - m_lines &= ~(1 << (offset >> 1)); - - if (LOG_APPLEFDC_EXTRA) - { - logerror("iwm_access(): %s line %s => %02x\n", - (offset & 1) ? "setting" : "clearing", lines[offset >> 1], m_lines); - } - - if ((offset < 0x08) && (intf->set_lines != nullptr)) - intf->set_lines(this, m_lines & 0x0f); - - switch(offset) - { - case 0x08: - /* turn off motor */ - m_motor_timer->adjust( - (m_mode & IWM_MODE_MOTOROFFDELAY) ? attotime::zero : attotime::from_seconds(1), 0); - break; - - case 0x09: - /* turn on motor */ - m_motor_timer->adjust(attotime::zero, 1); - break; - - case 0x0A: - /* turn off IWM_DRIVE */ - if ((m_lines & IWM_MOTOR) && (intf->set_enable_lines != nullptr)) - intf->set_enable_lines(this, 1); - break; - - case 0x0B: - /* turn on IWM_DRIVE */ - if ((m_lines & IWM_MOTOR) && (intf->set_enable_lines != nullptr)) - intf->set_enable_lines(this, 2); - break; - } -} - - - -//------------------------------------------------- -// read - reads a byte from the FDC -//------------------------------------------------- - -uint8_t applefdc_base_device::read(uint8_t offset) -{ - const applefdc_interface *intf = get_interface(); - uint8_t result = 0; - - // normalize offset - offset &= 0xf; - - if (LOG_APPLEFDC_EXTRA) - logerror("applefdc_r: offset=%i\n", offset); - - iwm_access(offset); - - switch(m_type) - { - case APPLEFDC_APPLE2: - switch(offset) - { - case 0x0C: - if (m_lines & IWM_Q7) - { - if (intf->write_data != nullptr) - intf->write_data(this, m_write_byte); - result = 0; - } - else - result = read_reg(0); - break; - - case 0x0D: - result = read_reg(IWM_Q6); - break; - - case 0x0E: - result = read_reg(IWM_Q7); - break; - - case 0x0F: - result = read_reg(IWM_Q7 | IWM_Q6); - break; - } - break; - - case APPLEFDC_IWM: - if ((offset & 1) == 0) - result = read_reg(m_lines & (IWM_Q6 | IWM_Q7)); - break; - - case APPLEFDC_SWIM: - if ((offset & 1) == 0) - result = read_reg(m_lines & (IWM_Q6 | IWM_Q7)); - break; - } - - return result; -} - - - -//------------------------------------------------- -// write - writes a byte to the FDC -//------------------------------------------------- - -void applefdc_base_device::write(uint8_t offset, uint8_t data) -{ - const applefdc_interface *intf = get_interface(); - - /* normalize offset */ - offset &= 15; - - if (LOG_APPLEFDC_EXTRA) - logerror("applefdc_w: offset=%i data=0x%02x\n", offset, data); - - iwm_access(offset); - - switch(m_type) - { - case APPLEFDC_APPLE2: - switch(offset) - { - case 0x0C: - if (m_lines & IWM_Q7) - { - if (intf->write_data != nullptr) - intf->write_data(this, m_write_byte); - } - break; - - case 0x0D: - m_write_byte = data; - break; - } - break; - - case APPLEFDC_IWM: - if (offset & 1) - write_reg(data); - break; - - case APPLEFDC_SWIM: - if (offset & 1) - write_reg(data); - break; - } -} - - - -//------------------------------------------------- -// get_lines - accessor -//------------------------------------------------- - -uint8_t applefdc_base_device::get_lines() -{ - return m_lines & 0x0f; -} - - - -/*************************************************************************** - APPLE FDC - Used on Apple II -***************************************************************************/ - -DEFINE_DEVICE_TYPE(APPLEFDC, applefdc_device, "apple_fdc", "Apple FDC") - -applefdc_device::applefdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : applefdc_base_device(APPLEFDC_APPLE2, mconfig, APPLEFDC, tag, owner, clock) -{ -} - - - -/*************************************************************************** - IWM - Used on early Macs -***************************************************************************/ - -DEFINE_DEVICE_TYPE(IWM, iwm_device, "iwm", "Apple IWM (Integrated Woz Machine)") - -iwm_device::iwm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : applefdc_base_device(APPLEFDC_IWM, mconfig, IWM, tag, owner, clock) -{ -} |