diff options
author | 2014-03-18 11:46:44 +0000 | |
---|---|---|
committer | 2014-03-18 11:46:44 +0000 | |
commit | f65e037141714318cfd32ecf988a7993f6cd9b3f (patch) | |
tree | 4c9a58e4b763733d3e2e80a409da026626978cc7 /src/mess/machine/i8271.c | |
parent | 15b2c80c62e9eddad3a6322fdef9c22039ce1eaa (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.c | 1543 |
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(); -} |