diff options
Diffstat (limited to 'src/mame/machine/fm_scsi.cpp')
-rw-r--r-- | src/mame/machine/fm_scsi.cpp | 447 |
1 files changed, 0 insertions, 447 deletions
diff --git a/src/mame/machine/fm_scsi.cpp b/src/mame/machine/fm_scsi.cpp deleted file mode 100644 index f84738e3ec0..00000000000 --- a/src/mame/machine/fm_scsi.cpp +++ /dev/null @@ -1,447 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Barry Rodewald -/* - * - * Implementation of Fujitsu FMR-50, FMR-60 and FM-Towns SCSI hardware - * - * - - info from Toshiya Takeda's e-FMR50 source (the Towns uses the same controller?) - 0xc30 = Data register - 0xc32 = Status register (read) - bit 7 = REQ - bit 6 = I/O - bit 5 = MSG - bit 4 = C/D - bit 3 = BUSY - bit 1 = INT - bit 0 = PERR - 0xc32 = Control register (write) - bit 7 = WEN - bit 6 = IMSK - bit 4 = ATN - bit 2 = SEL - bit 1 = DMAE - bit 0 = RST -*/ -#include "emu.h" -#include "fm_scsi.h" -#include "debugger.h" - -// SCSI input lines (from target) -#define FMSCSI_LINE_REQ 0x80 -#define FMSCSI_LINE_IO 0x40 -#define FMSCSI_LINE_MSG 0x20 -#define FMSCSI_LINE_CD 0x10 -#define FMSCSI_LINE_BSY 0x08 -#define FMSCSI_LINE_EX 0x04 -#define FMSCSI_LINE_INT 0x02 -#define FMSCSI_LINE_PERR 0x01 - -// SCSI output lines (to target) -#define FMSCSI_LINE_WEN 0x80 -#define FMSCSI_LINE_IMSK 0x40 -#define FMSCSI_LINE_RMSK 0x20 -#define FMSCSI_LINE_ATN 0x10 -#define FMSCSI_LINE_WRD 0x08 -#define FMSCSI_LINE_SEL 0x04 -#define FMSCSI_LINE_DMAE 0x02 -#define FMSCSI_LINE_RST 0x01 - -/* - * Device config - */ - -DEFINE_DEVICE_TYPE(FMSCSI, fmscsi_device, "fmscsi", "FM-SCSI") - -/* - * Device - */ - -fmscsi_device::fmscsi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : legacy_scsi_host_adapter(mconfig, FMSCSI, tag, owner, clock), - m_irq_handler(*this), - m_drq_handler(*this) -{ -} - -void fmscsi_device::device_start() -{ - m_input_lines = 0; - m_output_lines = 0; - m_data = 0; - m_command_index = 0; - m_last_id = 0; - m_target = 0; - m_phase = SCSI_PHASE_BUS_FREE; - - m_irq_handler.resolve_safe(); - m_drq_handler.resolve_safe(); - - // allocate read timer - m_transfer_timer = timer_alloc(TIMER_TRANSFER); - m_phase_timer = timer_alloc(TIMER_PHASE); -} - -void fmscsi_device::device_reset() -{ - m_input_lines = 0; - m_output_lines = 0; - m_data = 0; - m_command_index = 0; - m_last_id = 0; - m_target = 0; - m_result_length = 0; - m_result_index = 0; - stop_transfer(); - set_input_line(FMSCSI_LINE_INT,0); - m_irq_handler(0); - - m_phase = SCSI_PHASE_BUS_FREE; -} - -// get the length of a SCSI command based on it's command byte type -int fmscsi_device::get_scsi_cmd_len(uint8_t cbyte) -{ - int group; - - group = (cbyte>>5) & 7; - - if (group == 0) return 6; - if (group == 1 || group == 2) return 10; - if (group == 5) return 12; - - fatalerror("fmscsi: Unknown SCSI command group %d\n", group); - - // never executed - //return 6; -} - -void fmscsi_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) -{ - switch(id) - { - case TIMER_TRANSFER: - set_input_line(FMSCSI_LINE_REQ,1); - //logerror("FMSCSI: timer triggered: %i/%i\n",m_result_index,m_result_length); - if(m_output_lines & FMSCSI_LINE_DMAE) - { - m_drq_handler(1); - } - break; - case TIMER_PHASE: - set_phase(param); - break; - } -} - -void fmscsi_device::stop_transfer() -{ - m_transfer_timer->adjust(attotime::never); // stop timer - m_phase_timer->adjust(attotime::from_usec(800),SCSI_PHASE_STATUS); - if(m_output_lines & FMSCSI_LINE_DMAE) - { - m_drq_handler(0); - } - logerror("FMSCSI: Stopping transfer : (%i/%i)\n",m_result_index,m_result_length); -} - -uint8_t fmscsi_device::fmscsi_data_r(void) -{ - // read from data bus - // ACK is automatic on accessing the data bus, so REQ will go low. - set_input_line(FMSCSI_LINE_REQ,0); - - if(m_phase == SCSI_PHASE_DATAIN) - { - m_data = m_buffer[m_result_index % 512]; - //logerror("FMSCSI: DATAIN phase read data %02x\n",m_data); - m_result_index++; - if(m_result_index % 512 == 0) - read_data(m_buffer,512); // read next sector - - if(m_result_index >= m_result_length) - { - // end of data transfer - stop_transfer(); - } - return m_data; - } - - if(m_phase == SCSI_PHASE_MESSAGE_IN) - { - m_data = 0; // command complete message - m_phase_timer->adjust(attotime::from_usec(800),SCSI_PHASE_BUS_FREE); - m_command_index = 0; - return m_data; - } - - if(m_phase == SCSI_PHASE_STATUS) - { - m_data = get_status(); - // no command complete message? - m_phase_timer->adjust(attotime::from_usec(800),SCSI_PHASE_MESSAGE_IN); - m_command_index = 0; - //set_input_line(FMSCSI_LINE_REQ,1); // raise REQ yet again - return m_data; - } - - return m_data; -} - -void fmscsi_device::fmscsi_data_w(uint8_t data) -{ - int phase; - - // write to data bus - m_data = data; - //logerror("FMSCSI: data write %02x\n",data); - - // ACK is automatic on accessing the data bus, so REQ will go low. - set_input_line(FMSCSI_LINE_REQ,0); - - if(m_phase == SCSI_PHASE_BUS_FREE) - { - // select target - switch(data & 0x7f) - { - case 0x01: m_target = 0; break; - case 0x02: m_target = 1; break; - case 0x04: m_target = 2; break; - case 0x08: m_target = 3; break; - case 0x10: m_target = 4; break; - } - } - if(m_phase == SCSI_PHASE_DATAOUT) - { - m_buffer[m_result_index % 512] = m_data; - m_result_index++; - if(m_result_index % 512 == 0) - write_data(m_buffer,512); // write buffer to disc - if(m_result_index >= m_result_length) - { - // end of data transfer - m_transfer_timer->adjust(attotime::never); // stop timer - m_phase_timer->adjust(attotime::from_usec(800),SCSI_PHASE_STATUS); - if(m_output_lines & FMSCSI_LINE_DMAE) - { - m_drq_handler(0); - } - logerror("FMSCSI: Stopping transfer : (%i/%i)\n",m_result_index,m_result_length); - } - } - if(m_phase == SCSI_PHASE_COMMAND) - { - m_command[m_command_index] = data; - logerror("FMSCSI: writing command byte %02x [%i]\n",data,m_command_index); - m_command_index++; - if(m_command_index >= get_scsi_cmd_len(m_command[0])) - { - // command complete - send_command(m_command,m_command_index); - m_result_length = get_length(); - phase = legacy_scsi_host_adapter::get_phase(); - m_phase_timer->adjust(attotime::from_usec(800),phase); - - logerror("FMSCSI: Command %02x sent, result length = %i\n",m_command[0],m_result_length); - } - else - { - m_phase_timer->adjust(attotime::from_usec(800),SCSI_PHASE_COMMAND); - } - } - if(m_phase == SCSI_PHASE_MESSAGE_OUT) - { - m_phase_timer->adjust(attotime::from_usec(800),SCSI_PHASE_STATUS); - } -} - -void fmscsi_device::set_phase(int phase) -{ - m_phase = phase; - logerror("FMSCSI: phase set to %i\n",m_phase); - // set input lines accordingly - switch(phase) - { - case SCSI_PHASE_BUS_FREE: - set_input_line(FMSCSI_LINE_BSY,0); - set_input_line(FMSCSI_LINE_CD,0); - set_input_line(FMSCSI_LINE_MSG,0); - set_input_line(FMSCSI_LINE_IO,0); - //set_input_line(FMSCSI_LINE_REQ,0); - break; - case SCSI_PHASE_COMMAND: - set_input_line(FMSCSI_LINE_BSY,1); - set_input_line(FMSCSI_LINE_CD,1); - set_input_line(FMSCSI_LINE_MSG,0); - set_input_line(FMSCSI_LINE_IO,0); - set_input_line(FMSCSI_LINE_REQ,1); - break; - case SCSI_PHASE_STATUS: - set_input_line(FMSCSI_LINE_CD,1); - set_input_line(FMSCSI_LINE_MSG,0); - set_input_line(FMSCSI_LINE_IO,1); - set_input_line(FMSCSI_LINE_REQ,1); - break; - case SCSI_PHASE_DATAIN: - set_input_line(FMSCSI_LINE_CD,0); - set_input_line(FMSCSI_LINE_MSG,0); - set_input_line(FMSCSI_LINE_IO,1); - set_input_line(FMSCSI_LINE_REQ,1); - // start transfer timer - m_transfer_timer->adjust(attotime::zero,0,attotime::from_hz(3000000)); // arbitrary value for now - read_data(m_buffer,512); - m_result_index = 0; - logerror("FMSCSI: Starting transfer in (%i)\n",m_result_length); - break; - case SCSI_PHASE_DATAOUT: - set_input_line(FMSCSI_LINE_CD,0); - set_input_line(FMSCSI_LINE_MSG,0); - set_input_line(FMSCSI_LINE_IO,0); - set_input_line(FMSCSI_LINE_REQ,1); - // start transfer timer - m_transfer_timer->adjust(attotime::zero,0,attotime::from_hz(3000000)); // arbitrary value for now - m_result_index = 0; - logerror("FMSCSI: Starting transfer out (%i)\n",m_result_length); - break; - case SCSI_PHASE_MESSAGE_IN: - set_input_line(FMSCSI_LINE_CD,1); - set_input_line(FMSCSI_LINE_MSG,1); - set_input_line(FMSCSI_LINE_IO,1); - set_input_line(FMSCSI_LINE_REQ,1); - break; - case SCSI_PHASE_MESSAGE_OUT: - set_input_line(FMSCSI_LINE_CD,1); - set_input_line(FMSCSI_LINE_MSG,1); - set_input_line(FMSCSI_LINE_IO,0); - set_input_line(FMSCSI_LINE_REQ,1); - break; - } -} - -int fmscsi_device::get_phase(void) -{ - return m_phase; -} - -void fmscsi_device::set_input_line(uint8_t line, uint8_t state) -{ - if(line == FMSCSI_LINE_REQ) - { - if(state != 0 && !(m_input_lines & FMSCSI_LINE_REQ)) // low to high - { - if(m_output_lines & FMSCSI_LINE_IMSK && m_phase != SCSI_PHASE_DATAIN && m_phase != SCSI_PHASE_DATAOUT) - { - set_input_line(FMSCSI_LINE_INT,1); - m_irq_handler(1); - logerror("FMSCSI: IRQ high\n"); - } - } - if(state == 0 && (m_input_lines & FMSCSI_LINE_REQ)) // high to low - { - if(m_output_lines & FMSCSI_LINE_IMSK && m_phase != SCSI_PHASE_DATAIN && m_phase != SCSI_PHASE_DATAOUT) - { - set_input_line(FMSCSI_LINE_INT,0); - m_irq_handler(0); - logerror("FMSCSI: IRQ low\n"); - } - } - } - if(state != 0) - m_input_lines |= line; - else - m_input_lines &= ~line; -// logerror("FMSCSI: input line %02x set to %i\n",line,state); -} - -uint8_t fmscsi_device::get_input_line(uint8_t line) -{ - return m_input_lines & line; -} - -void fmscsi_device::set_output_line(uint8_t line, uint8_t state) -{ - if(line == FMSCSI_LINE_RST && state != 0) - { - device_reset(); - logerror("FMSCSI: reset\n"); - } - - if(line == FMSCSI_LINE_SEL) - { - if(state != 0 && !(m_output_lines & FMSCSI_LINE_SEL)) // low to high transition - { - if (select(m_target)) - { - m_phase_timer->adjust(attotime::from_usec(800),SCSI_PHASE_COMMAND); - m_data = 0x08; - } - } - } - - if(line == FMSCSI_LINE_ATN) - { - if(state != 0) - m_phase_timer->adjust(attotime::from_usec(800),SCSI_PHASE_MESSAGE_OUT); - } - - if(state != 0) - m_output_lines |= line; - else - m_output_lines &= ~line; -// logerror("FMSCSI: output line %02x set to %i\n",line,state); -} - -uint8_t fmscsi_device::get_output_line(uint8_t line) -{ - return m_output_lines & line; -} - -uint8_t fmscsi_device::fmscsi_status_r(void) -{ - // status inputs - return m_input_lines; -} - -void fmscsi_device::fmscsi_control_w(uint8_t data) -{ - // control outputs - set_output_line(FMSCSI_LINE_RST,data & FMSCSI_LINE_RST); - set_output_line(FMSCSI_LINE_DMAE,data & FMSCSI_LINE_DMAE); - set_output_line(FMSCSI_LINE_IMSK,data & FMSCSI_LINE_IMSK); - set_output_line(FMSCSI_LINE_ATN,data & FMSCSI_LINE_ATN); - set_output_line(FMSCSI_LINE_WEN,data & FMSCSI_LINE_WEN); - set_output_line(FMSCSI_LINE_SEL,data & FMSCSI_LINE_SEL); - logerror("FMSCSI: control write %02x\n",data); -} - -uint8_t fmscsi_device::fmscsi_r(offs_t offset) -{ - switch(offset & 0x03) - { - case 0x00: - return fmscsi_data_r(); - case 0x01: - return fmscsi_status_r(); - case 0x02: - return 0x80; // Linux uses this port to detect the ability to do word transfers. We'll tell it that it doesn't for now. - default: - logerror("FMSCSI: Unknown read at offset %i\n",offset); - } - return 0; -} - -void fmscsi_device::fmscsi_w(offs_t offset, uint8_t data) -{ - switch(offset & 0x03) - { - case 0x00: - fmscsi_data_w(data); - break; - case 0x01: - fmscsi_control_w(data); - break; - default: - logerror("FMSCSI: Unknown write 0x%02x at offset %i\n",data,offset); - } -} |