diff --git a/devices/common/scsi/sc53c94.cpp b/devices/common/scsi/sc53c94.cpp index b175725..28dd5b4 100644 --- a/devices/common/scsi/sc53c94.cpp +++ b/devices/common/scsi/sc53c94.cpp @@ -30,6 +30,7 @@ along with this program. If not, see . #include #include +#include Sc53C94::Sc53C94(uint8_t chip_id, uint8_t my_id) : ScsiDevice(my_id) { @@ -172,7 +173,7 @@ void Sc53C94::update_command_reg(uint8_t cmd) void Sc53C94::exec_command() { - uint8_t cmd = this->cmd_fifo[0] & 0x7F; + uint8_t cmd = this->cur_cmd = this->cmd_fifo[0] & 0x7F; bool is_dma_cmd = !!(this->cmd_fifo[0] & 0x80); if (is_dma_cmd) { @@ -192,7 +193,7 @@ void Sc53C94::exec_command() exec_next_command(); break; case CMD_CLEAR_FIFO: - this->data_fifo_pos = 0; // set the bottom of the FIFO to zero + this->data_fifo_pos = 0; // set the bottom of the data FIFO to zero this->data_fifo[0] = 0; exec_next_command(); break; @@ -225,7 +226,7 @@ void Sc53C94::exec_command() this->seq_step = 0; this->cmd_steps = sel_no_atn_desc; this->cur_state = SeqState::BUS_FREE; - sequencer(); + this->sequencer(); LOG_F(INFO, "SC53C94: SELECT W/O ATN command started"); break; case CMD_ENA_SEL_RESEL: @@ -316,6 +317,7 @@ void Sc53C94::sequencer() break; case SeqState::SEL_END: if (this->bus_obj->end_selection(this->my_bus_id, this->target_id)) { + this->bus_obj->release_ctrl_line(this->my_bus_id, SCSI_CTRL_SEL); LOG_F(INFO, "SC53C94: selection completed"); this->cmd_steps++; } else { // selection timeout @@ -327,6 +329,9 @@ void Sc53C94::sequencer() exec_next_command(); } break; + case SeqState::CMD_BEGIN: + LOG_F(INFO, "CMD_BEGIN reached"); + break; default: ABORT_F("SC53C94: unimplemented sequencer state %d", this->cur_state); } @@ -345,12 +350,22 @@ void Sc53C94::update_irq() void Sc53C94::notify(ScsiBus* bus_obj, ScsiMsg msg_type, int param) { switch (msg_type) { + case ScsiMsg::BUS_PHASE_CHANGE: + switch (param) { + case ScsiPhase::COMMAND: + this->cur_state = SeqState::CMD_BEGIN; + this->sequencer(); + break; + default: + LOG_F(WARNING, "SC53C94: ignore bus phase change %d message", param); + } + break; case ScsiMsg::CONFIRM_SEL: if (this->target_id == param) { // cancel selection timeout timer TimerManager::get_instance()->cancel_timer(this->seq_timer_id); this->cur_state = SeqState::SEL_END; - sequencer(); + this->sequencer(); } else { LOG_F(WARNING, "SC53C94: ignore invalid selection confirmation message"); } @@ -362,11 +377,18 @@ void Sc53C94::notify(ScsiBus* bus_obj, ScsiMsg msg_type, int param) bool Sc53C94::send_bytes(uint8_t* dst_ptr, int count) { - if ((this->data_fifo_pos - this->data_fifo_read_pos) < count) { + if (this->data_fifo_pos < count) { return false; } - std::memcpy(dst_ptr, &this->data_fifo[this->data_fifo_read_pos], count); + // move data out of the data FIFO + std::memcpy(dst_ptr, this->data_fifo, count); + + // remove the just readed data from the data FIFO + this->data_fifo_pos -= count; + if (this->data_fifo_pos > 0) { + std::memcpy(this->data_fifo, &this->data_fifo[count], this->data_fifo_pos); + } return true; }