summaryrefslogtreecommitdiffstatshomepage
path: root/src/mess/machine/i8271.c
diff options
context:
space:
mode:
author Curt Coder <curtcoder@mail.com>2014-03-18 11:46:44 +0000
committer Curt Coder <curtcoder@mail.com>2014-03-18 11:46:44 +0000
commitf65e037141714318cfd32ecf988a7993f6cd9b3f (patch)
tree4c9a58e4b763733d3e2e80a409da026626978cc7 /src/mess/machine/i8271.c
parent15b2c80c62e9eddad3a6322fdef9c22039ce1eaa (diff)
(MESS) Moved common machine and video chips to emu. (nw)
Diffstat (limited to 'src/mess/machine/i8271.c')
-rw-r--r--src/mess/machine/i8271.c1543
1 files changed, 0 insertions, 1543 deletions
diff --git a/src/mess/machine/i8271.c b/src/mess/machine/i8271.c
deleted file mode 100644
index e24b2a591a3..00000000000
--- a/src/mess/machine/i8271.c
+++ /dev/null
@@ -1,1543 +0,0 @@
-/* Intel 8271 Floppy Disc Controller */
-/* used in BBC Micro B,Acorn Atom */
-/* Jun 2000. Kev Thacker */
-
-/* TODO:
-
- - Scan commands
- - Check the commands work properly using a BBC disc copier program
- - check if 0 is specified as number of sectors, how many sectors
- is actually transfered
- - deleted data functions (error if data finds deleted data?)
-*/
-
-
-#include "emu.h"
-#include "i8271.h"
-#include "imagedev/flopdrv.h"
-
-/* data request */
-#define I8271_FLAGS_DATA_REQUEST 0x01
-/* data direction. If 0x02, then it is from fdc to cpu, else
-it is from cpu to fdc */
-#define I8271_FLAGS_DATA_DIRECTION 0x02
-
-enum I8271_STATE_t
-{
- I8271_STATE_EXECUTION_READ = 0,
- I8271_STATE_EXECUTION_WRITE
-};
-
-/* commands accepted */
-#define I8271_COMMAND_SPECIFY 0x035
-#define I8271_COMMAND_SEEK 0x029
-#define I8271_COMMAND_READ_DRIVE_STATUS 0x02c
-#define I8271_COMMAND_READ_SPECIAL_REGISTER 0x03d
-#define I8271_COMMAND_WRITE_SPECIAL_REGISTER 0x03a
-#define I8271_COMMAND_FORMAT 0x023
-#define I8271_COMMAND_READ_ID 0x01b
-#define I8271_COMMAND_READ_DATA_SINGLE_RECORD 0x012
-#define I8271_COMMAND_READ_DATA_AND_DELETED_DATA_SINGLE_RECORD 0x016
-#define I8271_COMMAND_WRITE_DATA_SINGLE_RECORD 0x00a
-#define I8271_COMMAND_WRITE_DELETED_DATA_SINGLE_RECORD 0x00e
-#define I8271_COMMAND_VERIFY_DATA_AND_DELETED_DATA_SINGLE_RECORD 0x01e
-#define I8271_COMMAND_READ_DATA_MULTI_RECORD 0x013
-#define I8271_COMMAND_READ_DATA_AND_DELETED_DATA_MULTI_RECORD 0x017
-#define I8271_COMMAND_WRITE_DATA_MULTI_RECORD 0x00b
-#define I8271_COMMAND_WRITE_DELETED_DATA_MULTI_RECORD 0x00f
-#define I8271_COMMAND_VERIFY_DATA_AND_DELETED_DATA_MULTI_RECORD 0x01f
-#define I8271_COMMAND_SCAN_DATA 0x000
-#define I8271_COMMAND_SCAN_DATA_AND_DELETED_DATA 0x004
-
-/*
-#define I8271_COMMAND_READ_OPERATION (1<<4)
-#define I8271_COMMAND_DELETED_DATA (1<<2)
-#define I8271_COMMAND_MULTI_RECORD (1<<0)
-*/
-
-
-
-/* first parameter for specify command */
-#define I8271_SPECIFY_INITIALIZATION 0x0d
-#define I8271_SPECIFY_LOAD_BAD_TRACKS_SURFACE_0 0x010
-#define I8271_SPECIFY_LOAD_BAD_TRACKS_SURFACE_1 0x018
-
-/* first parameter for read/write special register */
-#define I8271_SPECIAL_REGISTER_SCAN_SECTOR_NUMBER 0x06
-#define I8271_SPECIAL_REGISTER_SCAN_MSB_OF_COUNT 0x014
-#define I8271_SPECIAL_REGISTER_SCAN_LSB_OF_COUNT 0x013
-#define I8271_SPECIAL_REGISTER_SURFACE_0_CURRENT_TRACK 0x012
-#define I8271_SPECIAL_REGISTER_SURFACE_1_CURRENT_TRACK 0x01a
-#define I8271_SPECIAL_REGISTER_MODE_REGISTER 0x017
-#define I8271_SPECIAL_REGISTER_DRIVE_CONTROL_OUTPUT_PORT 0x023
-#define I8271_SPECIAL_REGISTER_DRIVE_CONTROL_INPUT_PORT 0x022
-#define I8271_SPECIAL_REGISTER_SURFACE_0_BAD_TRACK_1 0x010
-#define I8271_SPECIAL_REGISTER_SURFACE_0_BAD_TRACK_2 0x011
-#define I8271_SPECIAL_REGISTER_SURFACE_1_BAD_TRACK_1 0x018
-#define I8271_SPECIAL_REGISTER_SURFACE_1_BAD_TRACK_2 0x019
-
-
-/* status register bits */
-#define I8271_STATUS_COMMAND_BUSY 0x080
-#define I8271_STATUS_COMMAND_FULL 0x040
-#define I8271_STATUS_PARAMETER_FULL 0x020
-#define I8271_STATUS_RESULT_FULL 0x010
-#define I8271_STATUS_INT_REQUEST 0x008
-#define I8271_STATUS_NON_DMA_REQUEST 0x004
-
-#define VERBOSE 0
-
-#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
-#define FDC_LOG(x) do { if (VERBOSE) logerror("I8271: %s\n",x); } while (0)
-#define FDC_LOG_COMMAND(x) do { if (VERBOSE) logerror("I8271: COMMAND %s\n",x); } while (0)
-
-
-/* Device Interface */
-
-const device_type I8271 = &device_creator<i8271_device>;
-
-i8271_device::i8271_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
- : device_t(mconfig, I8271, "Intel 8271", tag, owner, clock, "i8271", __FILE__),
- m_flags(0),
- m_state(0),
- m_Command(0),
- m_StatusRegister(0),
- m_CommandRegister(0),
- m_ResultRegister(0),
- m_ParameterRegister(0),
- m_ResetRegister(0),
- m_data(0),
- m_ParameterCount(0),
- m_ParameterCountWritten(0),
- m_Mode(0),
- m_drive(0),
- m_side(0),
- m_drive_control_output(0),
- m_drive_control_input(0),
- m_StepRate(0),
- m_HeadSettlingTime(0),
- m_IndexCountBeforeHeadUnload(0),
- m_HeadLoadTime(0),
- //m_ID_C(0),
- //m_ID_H(0),
- m_ID_R(0),
- m_ID_N(0),
- m_data_id(0),
- m_ExecutionPhaseTransferCount(0),
- m_ExecutionPhaseCount(0),
- m_Counter(0)
- //m_data_direction(0)
-{
- for (int i = 0; i < 8; i++ )
- {
- m_CommandParameters[i] = 0;
- }
-
- for (int i = 0; i < 2; i++ )
- {
- m_CurrentTrack[i] = 0;
- }
-
- for (int i = 0; i < 4; i++ )
- {
- m_BadTracks[i] = 0;
- }
-}
-
-//-------------------------------------------------
-// device_config_complete - perform any
-// operations now that the configuration is
-// complete
-//-------------------------------------------------
-
-void i8271_device::device_config_complete()
-{
- // inherit a copy of the static data
- const i8271_interface *intf = reinterpret_cast<const i8271_interface *>(static_config());
- if (intf != NULL)
- *static_cast<i8271_interface *>(this) = *intf;
-
- // or initialize to defaults if none provided
- else
- {
- memset(&m_interrupt_cb, 0, sizeof(m_interrupt_cb));
- m_dma_request = NULL;
- m_floppy_drive_tags[0] = "";
- m_floppy_drive_tags[1] = "";
- }
-}
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void i8271_device::device_start()
-{
- m_data_timer = timer_alloc(TIMER_DATA_CALLBACK);
- m_command_complete_timer = timer_alloc(TIMER_TIMED_COMMAND_COMPLETE);
- m_drive = 0;
- m_pExecutionPhaseData = auto_alloc_array(machine(), char, 0x4000);
- m_interrupt_func.resolve(m_interrupt_cb, *this);
-
- // register for state saving
- /*save_item(NAME(m_flags));
- save_item(NAME(m_state));
- save_item(NAME(m_Command));
- save_item(NAME(m_StatusRegister));
- save_item(NAME(m_CommandRegister));
- save_item(NAME(m_ResultRegister));
- save_item(NAME(m_ParameterRegister));
- save_item(NAME(m_ResetRegister));
- save_item(NAME(m_data));
- //save_item(NAME(m_ParameterCount));
- //save_item(NAME(m_ParameterCountWritten));
- save_item(NAME(m_CommandParameters));
- //save_item(NAME(m_CurrentTrack));
- //save_item(NAME(m_BadTracks));
- //save_item(NAME(m_Mode));
- save_item(NAME(m_drive));
- save_item(NAME(m_side));
- save_item(NAME(m_drive_control_output));
- save_item(NAME(m_drive_control_input));
- //save_item(NAME(m_StepRate));
- //save_item(NAME(m_HeadSettlingTime));
- //save_item(NAME(m_IndexCountBeforeHeadUnload));
- //save_item(NAME(m_HeadLoadTime));
- save_item(NAME(m_ID_C));
- save_item(NAME(m_ID_H));
- save_item(NAME(m_ID_R));
- save_item(NAME(m_ID_N));
- save_item(NAME(m_data_id));
- save_item(NAME(m_ExecutionPhaseTransferCount));
- save_item(NAME(m_ExecutionPhaseCount));
- save_item(NAME(m_Counter));
- save_item(NAME(m_data_direction));
- save_pointer(NAME(m_pExecutionPhaseData), 0x4000);*/
-}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void i8271_device::device_reset()
-{
- m_StatusRegister = 0; //I8271_STATUS_INT_REQUEST | I8271_STATUS_NON_DMA_REQUEST;
- m_Mode = 0x0c0; /* bits 0, 1 are initialized to zero */
- m_ParameterCountWritten = 0;
- m_ParameterCount = 0;
-
- /* if timer is active remove */
- m_command_complete_timer->reset();
- m_data_timer->reset();
-
- /* clear irq */
- set_irq_state(0);
- /* clear dma */
- set_dma_drq();
-}
-
-device_t *i8271_device::current_image()
-{
- if (m_floppy_drive_tags[m_drive]!=NULL) {
- return machine().device(m_floppy_drive_tags[m_drive]);
- } else {
- return NULL;
- }
-}
-
-
-void i8271_device::seek_to_track(int track)
-{
- device_t *img = current_image();
- if (track==0)
- {
- /* seek to track 0 */
- unsigned char StepCount = 0x0ff;
-
- /*logerror("step\n"); */
-
- /* track 0 not set, not seeked more than 255 tracks */
- while (floppy_tk00_r(img) && (StepCount != 0))
- {
-/* logerror("step\n"); */
- StepCount--;
- floppy_drive_seek(img, -1);
- }
-
- m_CurrentTrack[m_drive] = 0;
-
- /* failed to find track 0? */
- if (StepCount==0)
- {
- /* Completion Type: operator intervation probably required for recovery */
- /* Completion code: track 0 not found */
- m_ResultRegister |= (2<<3) | 2<<1;
- }
-
- /* step out - towards track 0 */
- m_drive_control_output &=~(1<<2);
- }
- else
- {
- signed int SignedTracks;
-
- /* calculate number of tracks to seek */
- SignedTracks = track - m_CurrentTrack[m_drive];
-
- /* step towards 0 */
- m_drive_control_output &= ~(1<<2);
-
- if (SignedTracks>0)
- {
- /* step away from 0 */
- m_drive_control_output |= (1<<2);
- }
-
-
- /* seek to track 0 */
- floppy_drive_seek(img, SignedTracks);
-
- m_CurrentTrack[m_drive] = track;
- }
-}
-
-void i8271_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
-{
- switch (id)
- {
- case TIMER_DATA_CALLBACK:
- /* ok, trigger data request now */
- data_request();
-
- /* stop it */
- m_data_timer->reset();
- break;
-
- case TIMER_TIMED_COMMAND_COMPLETE:
- command_complete(1,1);
-
- /* stop it, but don't allow it to be free'd */
- m_command_complete_timer->reset();
- break;
-
- default:
- break;
- }
-}
-
-/* setup a timed data request - data request will be triggered in a few usecs time */
-void i8271_device::timed_data_request()
-{
- int usecs;
- /* 64 for single density */
- usecs = 64;
-
- /* set timers */
- m_command_complete_timer->reset();
- m_data_timer->adjust(attotime::from_usec(usecs));
-}
-
-
-/* setup a irq to occur 128us later - in reality this would be much later, because the int would
-come after reading the two CRC bytes at least! This function is used when a irq is required at
-command completion. Required for read data and write data, where last byte could be missed! */
-void i8271_device::timed_command_complete()
-{
- int usecs;
-
- /* 64 for single density - 2 crc bytes later*/
- usecs = 64*2;
-
- /* set timers */
- m_data_timer->reset();
- m_command_complete_timer->adjust(attotime::from_usec(usecs));
-}
-
-void i8271_device::set_irq_state(int state)
-{
- m_StatusRegister &= ~I8271_STATUS_INT_REQUEST;
- if (state)
- {
- m_StatusRegister |= I8271_STATUS_INT_REQUEST;
- }
-
- if (!m_interrupt_func.isnull())
- m_interrupt_func(m_StatusRegister & I8271_STATUS_INT_REQUEST);
-}
-
-void i8271_device::set_dma_drq()
-{
- if (m_dma_request)
- {
- m_dma_request(*this, (m_flags & I8271_FLAGS_DATA_REQUEST), (m_flags & I8271_FLAGS_DATA_DIRECTION));
- }
-}
-
-void i8271_device::load_bad_tracks(int surface)
-{
- m_BadTracks[(surface<<1) + 0] = m_CommandParameters[1];
- m_BadTracks[(surface<<1) + 1] = m_CommandParameters[2];
- m_CurrentTrack[surface] = m_CommandParameters[3];
-}
-
-void i8271_device::write_bad_track(int surface, int track, int data)
-{
- m_BadTracks[(surface<<1) + (track-1)] = data;
-}
-
-void i8271_device::write_current_track(int surface, int track)
-{
- m_CurrentTrack[surface] = track;
-}
-
-int i8271_device::read_current_track(int surface)
-{
- return m_CurrentTrack[surface];
-}
-
-int i8271_device::read_bad_track(int surface, int track)
-{
- return m_BadTracks[(surface<<1) + (track-1)];
-}
-
-void i8271_device::get_drive()
-{
- /* &40 = drive 0 side 0 */
- /* &80 = drive 1 side 0 */
-
-
-
- if (m_CommandRegister & (1<<6))
- {
- m_drive = 0;
- }
-
- if (m_CommandRegister & (1<<7))
- {
- m_drive = 1;
- }
-
-}
-
-void i8271_device::check_all_parameters_written()
-{
- if (m_ParameterCount == m_ParameterCountWritten)
- {
- m_StatusRegister &= ~I8271_STATUS_COMMAND_FULL;
-
- command_execute();
- }
-}
-
-
-void i8271_device::update_state()
-{
- switch (m_state)
- {
- /* fdc reading data and passing it to cpu which must read it */
- case I8271_STATE_EXECUTION_READ:
- {
- // /* if data request has been cleared, i.e. caused by a read of the register */
- // if ((m_flags & I8271_FLAGS_DATA_REQUEST)==0)
- {
- /* setup data with byte */
- m_data = m_pExecutionPhaseData[m_ExecutionPhaseCount];
-
-/* logerror("read data %02x\n", m_data); */
-
- /* update counters */
- m_ExecutionPhaseCount++;
- m_ExecutionPhaseTransferCount--;
-
- // logerror("Count: %04x\n", m_ExecutionPhaseCount);
- // logerror("Remaining: %04x\n", m_ExecutionPhaseTransferCount);
-
- /* completed? */
- if (m_ExecutionPhaseTransferCount==0)
- {
- /* yes */
-
- // logerror("sector read complete!\n");
- /* continue command */
- command_continue();
- }
- else
- {
- /* no */
-
- /* issue data request */
- timed_data_request();
- }
- }
- }
- break;
-
- /* fdc reading data and passing it to cpu which must read it */
- case I8271_STATE_EXECUTION_WRITE:
- {
- /* setup data with byte */
- m_pExecutionPhaseData[m_ExecutionPhaseCount] = m_data;
- /* update counters */
- m_ExecutionPhaseCount++;
- m_ExecutionPhaseTransferCount--;
-
- /* completed? */
- if (m_ExecutionPhaseTransferCount==0)
- {
- /* yes */
-
- /* continue command */
- command_continue();
- }
- else
- {
- /* no */
-
- /* issue data request */
- timed_data_request();
- }
- }
- break;
-
- default:
- break;
- }
-}
-
-void i8271_device::initialise_execution_phase_read(int transfer_size)
-{
- /* read */
- m_flags |= I8271_FLAGS_DATA_DIRECTION;
- m_ExecutionPhaseCount = 0;
- m_ExecutionPhaseTransferCount = transfer_size;
- m_state = I8271_STATE_EXECUTION_READ;
-}
-
-
-void i8271_device::initialise_execution_phase_write(int transfer_size)
-{
- /* write */
- m_flags &= ~I8271_FLAGS_DATA_DIRECTION;
- m_ExecutionPhaseCount = 0;
- m_ExecutionPhaseTransferCount = transfer_size;
- m_state = I8271_STATE_EXECUTION_WRITE;
-}
-
-/* for data transfers */
-void i8271_device::data_request()
-{
- m_flags |= I8271_FLAGS_DATA_REQUEST;
-
- if ((m_Mode & 0x01)!=0)
- {
- /* non-dma */
- m_StatusRegister |= I8271_STATUS_NON_DMA_REQUEST;
- /* set int */
- set_irq_state(1);
- }
- else
- {
- /* dma */
- m_StatusRegister &= ~I8271_STATUS_NON_DMA_REQUEST;
-
- set_dma_drq();
- }
-}
-
-void i8271_device::command_complete(int result, int int_rq)
-{
- /* not busy, and not a execution phase data request in non-dma mode */
- m_StatusRegister &= ~(I8271_STATUS_COMMAND_BUSY | I8271_STATUS_NON_DMA_REQUEST);
-
- if (result)
- {
- m_StatusRegister |= I8271_STATUS_RESULT_FULL;
- }
-
- if (int_rq)
- {
- /* trigger an int */
- set_irq_state(1);
- }
-
- /* correct?? */
- m_drive_control_output &=~1;
-}
-
-
-/* for data transfers */
-void i8271_device::clear_data_request()
-{
- m_flags &= ~I8271_FLAGS_DATA_REQUEST;
-
- if ((m_Mode & 0x01)!=0)
- {
- /* non-dma */
- m_StatusRegister &= ~I8271_STATUS_NON_DMA_REQUEST;
- /* set int */
- set_irq_state(0);
- }
- else
- {
- /* dma */
- set_dma_drq();
- }
-}
-
-
-void i8271_device::command_continue()
-{
- switch (m_Command)
- {
- case I8271_COMMAND_READ_DATA_MULTI_RECORD:
- case I8271_COMMAND_READ_DATA_SINGLE_RECORD:
- {
- /* completed all sectors? */
- m_Counter--;
- /* increment sector id */
- m_ID_R++;
-
- /* end command? */
- if (m_Counter==0)
- {
- timed_command_complete();
- return;
- }
-
- do_read();
- }
- break;
-
- case I8271_COMMAND_WRITE_DATA_MULTI_RECORD:
- case I8271_COMMAND_WRITE_DATA_SINGLE_RECORD:
- {
- /* put the buffer to the sector */
- floppy_drive_write_sector_data(current_image(), m_side, m_data_id, m_pExecutionPhaseData, 1<<(m_ID_N+7),0);
-
- /* completed all sectors? */
- m_Counter--;
- /* increment sector id */
- m_ID_R++;
-
- /* end command? */
- if (m_Counter==0)
- {
- timed_command_complete();
- return;
- }
-
- do_write();
- }
- break;
-
- case I8271_COMMAND_READ_ID:
- {
- m_Counter--;
-
- if (m_Counter==0)
- {
- timed_command_complete();
- return;
- }
-
- do_read_id();
- }
- break;
-
- default:
- break;
- }
-}
-
-void i8271_device::do_read()
-{
- /* find the sector */
- if (find_sector())
- {
- /* get the sector into the buffer */
- floppy_drive_read_sector_data(current_image(), m_side, m_data_id, m_pExecutionPhaseData, 1<<(m_ID_N+7));
-
- /* initialise for reading */
- initialise_execution_phase_read(1<<(m_ID_N+7));
-
- /* update state - gets first byte and triggers a data request */
- timed_data_request();
- return;
- }
- LOG(("error getting sector data\n"));
-
- timed_command_complete();
-}
-
-void i8271_device::do_read_id()
-{
- chrn_id id;
-
- /* get next id from disc */
- floppy_drive_get_next_id(current_image(), m_side,&id);
-
- m_pExecutionPhaseData[0] = id.C;
- m_pExecutionPhaseData[1] = id.H;
- m_pExecutionPhaseData[2] = id.R;
- m_pExecutionPhaseData[3] = id.N;
-
- initialise_execution_phase_read(4);
-}
-
-
-void i8271_device::do_write()
-{
- /* find the sector */
- if (find_sector())
- {
- /* initialise for reading */
- initialise_execution_phase_write(1<<(m_ID_N+7));
-
- /* update state - gets first byte and triggers a data request */
- timed_data_request();
- return;
- }
- LOG(("error getting sector data\n"));
-
- timed_command_complete();
-}
-
-
-
-int i8271_device::find_sector()
-{
- device_t *img = current_image();
-// int track_count_attempt;
-
-// track_count_attempt
- /* find sector within one revolution of the disc - 2 index pulses */
-
- /* number of times we have seen index hole */
- int index_count = 0;
-
- /* get sector id's */
- do
- {
- chrn_id id;
-
- /* get next id from disc */
- if (floppy_drive_get_next_id(img, m_side,&id))
- {
- /* tested on Amstrad CPC - All bytes must match, otherwise
- a NO DATA error is reported */
- if (id.R == m_ID_R)
- {
- /* TODO: Is this correct? What about bad tracks? */
- if (id.C == m_CurrentTrack[m_drive])
- {
- m_data_id = id.data_id;
- return 1;
- }
- else
- {
- /* TODO: if track doesn't match, the real 8271 does a step */
-
-
- return 0;
- }
- }
- }
-
- /* index set? */
- if (floppy_drive_get_flag_state(img, FLOPPY_DRIVE_INDEX))
- {
- index_count++;
- }
-
- }
- while (index_count!=2);
-
- /* completion type: command/drive error */
- /* completion code: sector not found */
- m_ResultRegister |= (3<<3);
-
- return 0;
-}
-
-void i8271_device::command_execute()
-{
- device_t *img = current_image();
-
- /* clear it = good completion status */
- /* this will be changed if anything bad happens! */
- m_ResultRegister = 0;
-
- switch (m_Command)
- {
- case I8271_COMMAND_SPECIFY:
- {
- switch (m_CommandParameters[0])
- {
- case 0x0d:
- {
- LOG(("Initialization\n"));
- m_StepRate = m_CommandParameters[1];
- m_HeadSettlingTime = m_CommandParameters[2];
- m_IndexCountBeforeHeadUnload = (m_CommandParameters[3]>>4) & 0x0f;
- m_HeadLoadTime = (m_CommandParameters[3] & 0x0f);
- }
- break;
-
- case 0x010:
- {
- LOG(("Load bad Tracks Surface 0\n"));
- load_bad_tracks(0);
-
- }
- break;
-
- case 0x018:
- {
- LOG(("Load bad Tracks Surface 1\n"));
- load_bad_tracks(1);
-
- }
- break;
- }
-
- /* no result */
- command_complete(0,0);
- }
- break;
-
- case I8271_COMMAND_READ_SPECIAL_REGISTER:
- {
- /* unknown - what is read when a special register that isn't allowed is specified? */
- int data = 0x0ff;
-
- switch (m_CommandParameters[0])
- {
- case I8271_SPECIAL_REGISTER_MODE_REGISTER:
- {
- data = m_Mode;
- }
- break;
-
- case I8271_SPECIAL_REGISTER_SURFACE_0_CURRENT_TRACK:
- {
- data = read_current_track(0);
-
- }
- break;
-
- case I8271_SPECIAL_REGISTER_SURFACE_1_CURRENT_TRACK:
- {
- data = read_current_track(1);
- }
- break;
-
- case I8271_SPECIAL_REGISTER_SURFACE_0_BAD_TRACK_1:
- {
- data = read_bad_track(0,1);
- }
- break;
-
- case I8271_SPECIAL_REGISTER_SURFACE_0_BAD_TRACK_2:
- {
- data = read_bad_track(0,2);
- }
- break;
-
- case I8271_SPECIAL_REGISTER_SURFACE_1_BAD_TRACK_1:
- {
- data = read_bad_track(1,1);
- }
- break;
-
- case I8271_SPECIAL_REGISTER_SURFACE_1_BAD_TRACK_2:
- {
- data = read_bad_track(1,2);
- }
- break;
-
- case I8271_SPECIAL_REGISTER_DRIVE_CONTROL_OUTPUT_PORT:
- {
- FDC_LOG_COMMAND("Read Drive Control Output port\n");
-
- get_drive();
-
- /* assumption: select bits reflect the select bits from the previous
- command. i.e. read drive status */
- data = (m_drive_control_output & ~0x0c0)
- | (m_CommandRegister & 0x0c0);
-
-
- }
- break;
-
- case I8271_SPECIAL_REGISTER_DRIVE_CONTROL_INPUT_PORT:
- {
- /* bit 7: not used */
- /* bit 6: ready 1 */
- /* bit 5: write fault */
- /* bit 4: index */
- /* bit 3: wr prot */
- /* bit 2: rdy 0 */
- /* bit 1: track 0 */
- /* bit 0: cnt/opi */
-
- FDC_LOG_COMMAND("Read Drive Control Input port\n");
-
-
- m_drive_control_input = (1<<6) | (1<<2);
-
- /* bit 3 = 0 if write protected */
- m_drive_control_input |= floppy_wpt_r(img) << 3;
-
- /* bit 1 = 0 if head at track 0 */
- m_drive_control_input |= floppy_tk00_r(img) << 1;
-
- /* need to setup this register based on drive selected */
- data = m_drive_control_input;
- }
- break;
-
- }
-
- m_ResultRegister = data;
-
- command_complete(1,0);
- }
- break;
-
-
- case I8271_COMMAND_WRITE_SPECIAL_REGISTER:
- {
- switch (m_CommandParameters[0])
- {
- case I8271_SPECIAL_REGISTER_MODE_REGISTER:
- {
- /* TODO: Check bits 6-7 and 5-2 are valid */
- m_Mode = m_CommandParameters[1];
-
- if (m_Mode & 0x01)
- {
- LOG(("Mode: Non-DMA\n"));
- }
- else
- {
- LOG(("Mode: DMA\n"));
- }
-
- if (m_Mode & 0x02)
- {
- LOG(("Single actuator\n"));
- }
- else
- {
- LOG(("Double actuator\n"));
- }
- }
- break;
-
- case I8271_SPECIAL_REGISTER_SURFACE_0_CURRENT_TRACK:
- {
- LOG(("Surface 0 Current Track\n"));
- write_current_track(0, m_CommandParameters[1]);
- }
- break;
-
- case I8271_SPECIAL_REGISTER_SURFACE_1_CURRENT_TRACK:
- {
- LOG(("Surface 1 Current Track\n"));
- write_current_track(1, m_CommandParameters[1]);
- }
- break;
-
- case I8271_SPECIAL_REGISTER_SURFACE_0_BAD_TRACK_1:
- {
- LOG(("Surface 0 Bad Track 1\n"));
- write_bad_track(0, 1, m_CommandParameters[1]);
- }
- break;
-
- case I8271_SPECIAL_REGISTER_SURFACE_0_BAD_TRACK_2:
- {
- LOG(("Surface 0 Bad Track 2\n"));
- write_bad_track(0, 2,m_CommandParameters[1]);
- }
- break;
-
- case I8271_SPECIAL_REGISTER_SURFACE_1_BAD_TRACK_1:
- {
- LOG(("Surface 1 Bad Track 1\n"));
-
-
- write_bad_track(1, 1, m_CommandParameters[1]);
- }
- break;
-
- case I8271_SPECIAL_REGISTER_SURFACE_1_BAD_TRACK_2:
- {
- LOG(("Surface 1 Bad Track 2\n"));
-
- write_bad_track(1, 2, m_CommandParameters[1]);
- }
- break;
-
- case I8271_SPECIAL_REGISTER_DRIVE_CONTROL_OUTPUT_PORT:
- {
-// /* get drive selected */
-// m_drive = (m_CommandParameters[1]>>6) & 0x03;
-
- FDC_LOG_COMMAND("Write Drive Control Output port\n");
-
-
- if (m_CommandParameters[1] & 0x01)
- {
- LOG(("Write Enable\n"));
- }
- if (m_CommandParameters[1] & 0x02)
- {
- LOG(("Seek/Step\n"));
- }
- if (m_CommandParameters[1] & 0x04)
- {
- LOG(("Direction\n"));
- }
- if (m_CommandParameters[1] & 0x08)
- {
- LOG(("Load Head\n"));
- }
- if (m_CommandParameters[1] & 0x010)
- {
- LOG(("Low head current\n"));
- }
- if (m_CommandParameters[1] & 0x020)
- {
- LOG(("Write Fault Reset\n"));
- }
-
- LOG(("Select %02x\n", (m_CommandParameters[1] & 0x0c0)>>6));
-
- /* get drive */
- get_drive();
-
- /* on bbc dfs 09 this is the side select output */
- m_side = (m_CommandParameters[1]>>5) & 0x01;
-
- /* load head - on mini-sized drives this turns on the disc motor,
- on standard-sized drives this loads the head and turns the motor on */
- floppy_mon_w(img, !BIT(m_CommandParameters[1], 3));
- floppy_drive_set_ready_state(img, 1, 1);
-
- /* step pin changed? if so perform a step in the direction indicated */
- if (((m_drive_control_output^m_CommandParameters[1]) & (1<<1))!=0)
- {
- /* step pin changed state? */
-
- if ((m_CommandParameters[1] & (1<<1))!=0)
- {
- signed int signed_tracks;
-
- if ((m_CommandParameters[1] & (1<<2))!=0)
- {
- signed_tracks = 1;
- }
- else
- {
- signed_tracks = -1;
- }
-
- floppy_drive_seek(img, signed_tracks);
- }
- }
-
- m_drive_control_output = m_CommandParameters[1];
-
-
- }
- break;
-
- case I8271_SPECIAL_REGISTER_DRIVE_CONTROL_INPUT_PORT:
- {
- FDC_LOG_COMMAND("Write Drive Control Input port\n");
-
- // m_drive_control_input = m_CommandParameters[1];
- }
- break;
-
- }
-
- /* write doesn't supply a result */
- command_complete(0,0);
- }
- break;
-
- case I8271_COMMAND_READ_DRIVE_STATUS:
- {
- unsigned char status;
-
- get_drive();
-
- /* no write fault */
- status = 0;
-
- status |= (1<<2) | (1<<6);
-
- /* these two do not appear to be set at all! ?? */
-
- if (m_floppy_drive_tags[0]!=NULL) {
- if (floppy_drive_get_flag_state(machine().device(m_floppy_drive_tags[0]), FLOPPY_DRIVE_READY))
- {
- status |= (1<<2);
- }
- }
-
- if (m_floppy_drive_tags[1]!=NULL) {
- if (floppy_drive_get_flag_state(machine().device(m_floppy_drive_tags[1]), FLOPPY_DRIVE_READY))
- {
- status |= (1<<6);
- }
- }
-
- /* bit 3 = 1 if write protected */
- status |= !floppy_wpt_r(img) << 3;
-
- /* bit 1 = 1 if head at track 0 */
- status |= !floppy_tk00_r(img) << 1;
-
- m_ResultRegister = status;
- command_complete(1,0);
-
- }
- break;
-
- case I8271_COMMAND_SEEK:
- {
- get_drive();
-
-
- seek_to_track(m_CommandParameters[0]);
-
- /* check for bad seek */
- timed_command_complete();
-
- }
- break;
-
- case I8271_COMMAND_READ_DATA_MULTI_RECORD:
- {
- /* N value as stored in ID field */
- m_ID_N = (m_CommandParameters[2]>>5) & 0x07;
-
- /* starting sector id */
- m_ID_R = m_CommandParameters[1];
-
- /* number of sectors to transfer */
- m_Counter = m_CommandParameters[2] & 0x01f;
-
-
- FDC_LOG_COMMAND("READ DATA MULTI RECORD");
-
- LOG(("Sector Count: %02x\n", m_Counter));
- LOG(("Track: %02x\n",m_CommandParameters[0]));
- LOG(("Sector: %02x\n", m_CommandParameters[1]));
- LOG(("Sector Length: %02x bytes\n", 1<<(m_ID_N+7)));
-
- get_drive();
-
- if (!floppy_drive_get_flag_state(img, FLOPPY_DRIVE_READY))
- {
- /* Completion type: operation intervention probably required for recovery */
- /* Completion code: Drive not ready */
- m_ResultRegister = (2<<3);
- timed_command_complete();
- }
- else
- {
- seek_to_track(m_CommandParameters[0]);
-
-
- do_read();
- }
-
- }
- break;
-
- case I8271_COMMAND_READ_DATA_SINGLE_RECORD:
- {
- FDC_LOG_COMMAND("READ DATA SINGLE RECORD");
-
- m_ID_N = 0;
- m_Counter = 1;
- m_ID_R = m_CommandParameters[1];
-
- LOG(("Sector Count: %02x\n", m_Counter));
- LOG(("Track: %02x\n",m_CommandParameters[0]));
- LOG(("Sector: %02x\n", m_CommandParameters[1]));
- LOG(("Sector Length: %02x bytes\n", 1<<(m_ID_N+7)));
-
- get_drive();
-
- if (!floppy_drive_get_flag_state(img, FLOPPY_DRIVE_READY))
- {
- /* Completion type: operation intervention probably required for recovery */
- /* Completion code: Drive not ready */
- m_ResultRegister = (2<<3);
- timed_command_complete();
- }
- else
- {
- seek_to_track(m_CommandParameters[0]);
-
- do_read();
- }
-
- }
- break;
-
- case I8271_COMMAND_WRITE_DATA_MULTI_RECORD:
- {
- /* N value as stored in ID field */
- m_ID_N = (m_CommandParameters[2]>>5) & 0x07;
-
- /* starting sector id */
- m_ID_R = m_CommandParameters[1];
-
- /* number of sectors to transfer */
- m_Counter = m_CommandParameters[2] & 0x01f;
-
- FDC_LOG_COMMAND("READ DATA MULTI RECORD");
-
- LOG(("Sector Count: %02x\n", m_Counter));
- LOG(("Track: %02x\n",m_CommandParameters[0]));
- LOG(("Sector: %02x\n", m_CommandParameters[1]));
- LOG(("Sector Length: %02x bytes\n", 1<<(m_ID_N+7)));
-
- get_drive();
-
- m_drive_control_output &=~1;
-
- if (!floppy_drive_get_flag_state(img, FLOPPY_DRIVE_READY))
- {
- /* Completion type: operation intervention probably required for recovery */
- /* Completion code: Drive not ready */
- m_ResultRegister = (2<<3);
- timed_command_complete();
- }
- else
- {
- if (floppy_wpt_r(img) == CLEAR_LINE)
- {
- /* Completion type: operation intervention probably required for recovery */
- /* Completion code: Drive write protected */
- m_ResultRegister = (2<<3) | (1<<1);
- timed_command_complete();
- }
- else
- {
- m_drive_control_output |=1;
-
- seek_to_track(m_CommandParameters[0]);
-
- do_write();
- }
- }
- }
- break;
-
- case I8271_COMMAND_WRITE_DATA_SINGLE_RECORD:
- {
- FDC_LOG_COMMAND("WRITE DATA SINGLE RECORD");
-
- m_ID_N = 0;
- m_Counter = 1;
- m_ID_R = m_CommandParameters[1];
-
-
- LOG(("Sector Count: %02x\n", m_Counter));
- LOG(("Track: %02x\n",m_CommandParameters[0]));
- LOG(("Sector: %02x\n", m_CommandParameters[1]));
- LOG(("Sector Length: %02x bytes\n", 1<<(m_ID_N+7)));
- get_drive();
-
- m_drive_control_output &=~1;
-
- if (!floppy_drive_get_flag_state(img, FLOPPY_DRIVE_READY))
- {
- /* Completion type: operation intervention probably required for recovery */
- /* Completion code: Drive not ready */
- m_ResultRegister = (2<<3);
- timed_command_complete();
- }
- else
- {
- if (floppy_wpt_r(img) == CLEAR_LINE)
- {
- /* Completion type: operation intervention probably required for recovery */
- /* Completion code: Drive write protected */
- m_ResultRegister = (2<<3) | (1<<1);
- timed_command_complete();
- }
- else
- {
- m_drive_control_output |=1;
-
- seek_to_track(m_CommandParameters[0]);
-
- do_write();
- }
- }
-
- }
- break;
-
-
- case I8271_COMMAND_READ_ID:
- {
- FDC_LOG_COMMAND("READ ID");
-
- LOG(("Track: %02x\n",m_CommandParameters[0]));
- LOG(("ID Field Count: %02x\n", m_CommandParameters[2]));
-
- get_drive();
-
- if (!floppy_drive_get_flag_state(img, FLOPPY_DRIVE_READY))
- {
- /* Completion type: operation intervention probably required for recovery */
- /* Completion code: Drive not ready */
- m_ResultRegister = (2<<3);
- timed_command_complete();
- }
- else
- {
- m_Counter = m_CommandParameters[2];
-
- seek_to_track(m_CommandParameters[0]);
-
- do_read_id();
- }
- }
- break;
-
- default:
- LOG(("ERROR Unrecognised Command\n"));
- break;
- }
-}
-
-
-
-WRITE8_MEMBER(i8271_device::write)
-{
- switch (offset & 3)
- {
- case 0:
- {
- LOG(("I8271 W Command Register: %02x\n", data));
-
- m_CommandRegister = data;
- m_Command = m_CommandRegister & 0x03f;
-
- m_StatusRegister |= I8271_STATUS_COMMAND_BUSY | I8271_STATUS_COMMAND_FULL;
- m_StatusRegister &= ~I8271_STATUS_PARAMETER_FULL | I8271_STATUS_RESULT_FULL;
- m_ParameterCountWritten = 0;
-
- switch (m_Command)
- {
- case I8271_COMMAND_SPECIFY:
- {
- FDC_LOG_COMMAND("SPECIFY");
-
- m_ParameterCount = 4;
- }
- break;
-
- case I8271_COMMAND_SEEK:
- {
- FDC_LOG_COMMAND("SEEK");
-
- m_ParameterCount = 1;
- }
- break;
-
- case I8271_COMMAND_READ_DRIVE_STATUS:
- {
- FDC_LOG_COMMAND("READ DRIVE STATUS");
-
- m_ParameterCount = 0;
- }
- break;
-
- case I8271_COMMAND_READ_SPECIAL_REGISTER:
- {
- FDC_LOG_COMMAND("READ SPECIAL REGISTER");
-
- m_ParameterCount = 1;
- }
- break;
-
- case I8271_COMMAND_WRITE_SPECIAL_REGISTER:
- {
- FDC_LOG_COMMAND("WRITE SPECIAL REGISTER");
-
- m_ParameterCount = 2;
- }
- break;
-
- case I8271_COMMAND_FORMAT:
- {
- m_ParameterCount = 5;
- }
- break;
-
- case I8271_COMMAND_READ_ID:
- {
- m_ParameterCount = 3;
-
- }
- break;
-
-
- case I8271_COMMAND_READ_DATA_SINGLE_RECORD:
- case I8271_COMMAND_READ_DATA_AND_DELETED_DATA_SINGLE_RECORD:
- case I8271_COMMAND_WRITE_DATA_SINGLE_RECORD:
- case I8271_COMMAND_WRITE_DELETED_DATA_SINGLE_RECORD:
- case I8271_COMMAND_VERIFY_DATA_AND_DELETED_DATA_SINGLE_RECORD:
- {
- m_ParameterCount = 2;
- }
- break;
-
- case I8271_COMMAND_READ_DATA_MULTI_RECORD:
- case I8271_COMMAND_READ_DATA_AND_DELETED_DATA_MULTI_RECORD:
- case I8271_COMMAND_WRITE_DATA_MULTI_RECORD:
- case I8271_COMMAND_WRITE_DELETED_DATA_MULTI_RECORD:
- case I8271_COMMAND_VERIFY_DATA_AND_DELETED_DATA_MULTI_RECORD:
- {
- m_ParameterCount = 3;
- }
- break;
-
- case I8271_COMMAND_SCAN_DATA:
- case I8271_COMMAND_SCAN_DATA_AND_DELETED_DATA:
- {
- m_ParameterCount = 5;
- }
- break;
-
-
-
-
-
-
- }
-
- check_all_parameters_written();
- }
- break;
-
- case 1:
- {
- LOG(("I8271 W Parameter Register: %02x\n",data));
- m_ParameterRegister = data;
-
- if (m_ParameterCount!=0)
- {
- m_CommandParameters[m_ParameterCountWritten] = data;
- m_ParameterCountWritten++;
- }
-
- check_all_parameters_written();
- }
- break;
-
- case 2:
- {
- LOG(("I8271 W Reset Register: %02x\n", data));
- if (((data ^ m_ResetRegister) & 0x01)!=0)
- {
- if ((data & 0x01)==0)
- {
- reset();
- }
- }
-
- m_ResetRegister = data;
-
-
- }
- break;
-
- default:
- break;
- }
-}
-
-READ8_MEMBER(i8271_device::read)
-{
- switch (offset & 3)
- {
- case 0:
- {
- /* bit 1,0 are zero other bits contain status data */
- m_StatusRegister &= ~0x03;
- LOG(("I8271 R Status Register: %02x\n",m_StatusRegister));
- return m_StatusRegister;
- }
-
- case 1:
- {
- if ((m_StatusRegister & I8271_STATUS_COMMAND_BUSY)==0)
- {
- /* clear IRQ */
- set_irq_state(0);
-
- m_StatusRegister &= ~I8271_STATUS_RESULT_FULL;
- LOG(("I8271 R Result Register %02x\n",m_ResultRegister));
- return m_ResultRegister;
- }
-
- /* not useful information when command busy */
- return 0x0ff;
- }
-
-
- default:
- break;
- }
-
- return 0x0ff;
-}
-
-
-/* to be completed! */
-READ8_MEMBER(i8271_device::dack_r)
-{
- return data_r(space, offset);
-}
-
-/* to be completed! */
-WRITE8_MEMBER(i8271_device::dack_w)
-{
- data_w(space, offset, data);
-}
-
-READ8_MEMBER(i8271_device::data_r)
-{
- clear_data_request();
-
- update_state();
-
- // logerror("I8271 R data: %02x\n",m_data);
-
-
- return m_data;
-}
-
-WRITE8_MEMBER(i8271_device::data_w)
-{
- m_data = data;
-
-// logerror("I8271 W data: %02x\n",m_data);
-
- clear_data_request();
-
- update_state();
-}