mirror of
https://github.com/dingusdev/dingusppc.git
synced 2025-01-12 11:31:16 +00:00
sc53c94: fix sending commands to SCSI devices.
This commit is contained in:
parent
2065f3588b
commit
f3cd5b8b36
@ -75,13 +75,14 @@ void Sc53C94::reset_device()
|
||||
|
||||
uint8_t Sc53C94::read(uint8_t reg_offset)
|
||||
{
|
||||
uint8_t int_status;
|
||||
uint8_t status, int_status;
|
||||
|
||||
switch (reg_offset) {
|
||||
case Read::Reg53C94::Command:
|
||||
return this->cmd_fifo[0];
|
||||
case Read::Reg53C94::Status:
|
||||
return this->status;
|
||||
status = bus_obj->test_ctrl_lines(SCSI_CTRL_MSG | SCSI_CTRL_CD | SCSI_CTRL_IO);
|
||||
return (this->status & 0xF8) | status;
|
||||
case Read::Reg53C94::Int_Status:
|
||||
int_status = this->int_status;
|
||||
this->seq_step = 0;
|
||||
@ -92,6 +93,8 @@ uint8_t Sc53C94::read(uint8_t reg_offset)
|
||||
return this->seq_step;
|
||||
case Read::Reg53C94::FIFO_Flags:
|
||||
return (this->seq_step << 5) | (this->data_fifo_pos & 0x1F);
|
||||
case Read::Reg53C94::Config_1:
|
||||
return this->config1;
|
||||
case Read::Reg53C94::Config_3:
|
||||
return this->config3;
|
||||
case Read::Reg53C94::Xfer_Cnt_Hi:
|
||||
@ -332,6 +335,12 @@ void Sc53C94::sequencer()
|
||||
case SeqState::CMD_BEGIN:
|
||||
LOG_F(INFO, "CMD_BEGIN reached");
|
||||
break;
|
||||
case SeqState::CMD_COMPLETE:
|
||||
this->cmd_steps++;
|
||||
this->int_status |= this->cmd_steps->status;
|
||||
this->update_irq();
|
||||
exec_next_command();
|
||||
break;
|
||||
default:
|
||||
ABORT_F("SC53C94: unimplemented sequencer state %d", this->cur_state);
|
||||
}
|
||||
@ -350,16 +359,6 @@ 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
|
||||
@ -370,6 +369,14 @@ void Sc53C94::notify(ScsiBus* bus_obj, ScsiMsg msg_type, int param)
|
||||
LOG_F(WARNING, "SC53C94: ignore invalid selection confirmation message");
|
||||
}
|
||||
break;
|
||||
case ScsiMsg::SEND_CMD_BEGIN:
|
||||
this->cur_state = SeqState::CMD_BEGIN;
|
||||
this->sequencer();
|
||||
break;
|
||||
case ScsiMsg::SEND_CMD_END:
|
||||
this->cur_state = SeqState::CMD_COMPLETE;
|
||||
this->sequencer();
|
||||
break;
|
||||
default:
|
||||
LOG_F(WARNING, "SC53C94: ignore notification message, type: %d", msg_type);
|
||||
}
|
||||
|
@ -52,9 +52,11 @@ enum : int {
|
||||
SELECTION,
|
||||
RESELECTION,
|
||||
COMMAND,
|
||||
DATA,
|
||||
DATA_IN,
|
||||
DATA_OUT,
|
||||
STATUS,
|
||||
MESSAGE,
|
||||
MESSAGE_IN,
|
||||
MESSAGE_OUT,
|
||||
RESET,
|
||||
};
|
||||
};
|
||||
@ -62,6 +64,8 @@ enum : int {
|
||||
enum ScsiMsg : int {
|
||||
CONFIRM_SEL = 1,
|
||||
BUS_PHASE_CHANGE,
|
||||
SEND_CMD_BEGIN,
|
||||
SEND_CMD_END,
|
||||
};
|
||||
|
||||
enum ScsiCommand : int {
|
||||
@ -165,6 +169,7 @@ public:
|
||||
uint8_t get_data_lines() { return this->data_lines; };
|
||||
|
||||
// high-level control/status
|
||||
int switch_phase(int id, int new_phase);
|
||||
bool begin_arbitration(int id);
|
||||
bool end_arbitration(int id);
|
||||
bool begin_selection(int initiator_id, int target_id, bool atn);
|
||||
|
@ -120,6 +120,37 @@ uint16_t ScsiBus::test_ctrl_lines(uint16_t mask)
|
||||
return new_state & mask;
|
||||
}
|
||||
|
||||
int ScsiBus::switch_phase(int id, int new_phase)
|
||||
{
|
||||
int old_phase = this->cur_phase;
|
||||
|
||||
// leave the current phase (low-level)
|
||||
switch (old_phase) {
|
||||
case ScsiPhase::COMMAND:
|
||||
this->release_ctrl_line(id, SCSI_CTRL_CD);
|
||||
break;
|
||||
case ScsiPhase::DATA_IN:
|
||||
this->release_ctrl_line(id, SCSI_CTRL_IO);
|
||||
break;
|
||||
}
|
||||
|
||||
// enter new phase (low-level)
|
||||
switch (new_phase) {
|
||||
case ScsiPhase::COMMAND:
|
||||
this->assert_ctrl_line(id, SCSI_CTRL_CD);
|
||||
break;
|
||||
case ScsiPhase::DATA_IN:
|
||||
this->assert_ctrl_line(id, SCSI_CTRL_IO);
|
||||
break;
|
||||
}
|
||||
|
||||
// switch the bus to the new phase (high-level)
|
||||
this->cur_phase = new_phase;
|
||||
change_bus_phase(id);
|
||||
|
||||
return old_phase;
|
||||
}
|
||||
|
||||
bool ScsiBus::begin_arbitration(int initiator_id)
|
||||
{
|
||||
if (this->cur_phase == ScsiPhase::BUS_FREE) {
|
||||
@ -191,8 +222,9 @@ bool ScsiBus::transfer_command(uint8_t* dst_ptr)
|
||||
{
|
||||
static uint8_t cmd_to_cdb_length[8] = {6, 10, 10, 6, 6, 12, 6, 6};
|
||||
|
||||
this->cur_phase = ScsiPhase::COMMAND;
|
||||
change_bus_phase(target_id);
|
||||
this->switch_phase(target_id, ScsiPhase::COMMAND);
|
||||
|
||||
this->devices[this->initiator_id]->notify(this, ScsiMsg::SEND_CMD_BEGIN, 0);
|
||||
|
||||
// attempt to transfer the shortest Command Description Block (CDB)
|
||||
if (!this->devices[this->initiator_id]->send_bytes(dst_ptr, 6)) {
|
||||
@ -200,7 +232,7 @@ bool ScsiBus::transfer_command(uint8_t* dst_ptr)
|
||||
return false;
|
||||
}
|
||||
|
||||
// transfer the remaining CDB
|
||||
// transfer the remaining CDB bytes if any
|
||||
int cdb_length = cmd_to_cdb_length[dst_ptr[0] >> 5];
|
||||
if (cdb_length > 6) {
|
||||
if (!this->devices[this->initiator_id]->send_bytes(dst_ptr + 6, cdb_length - 6)) {
|
||||
@ -209,6 +241,8 @@ bool ScsiBus::transfer_command(uint8_t* dst_ptr)
|
||||
}
|
||||
}
|
||||
|
||||
this->devices[this->initiator_id]->notify(this, ScsiMsg::SEND_CMD_END, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -49,6 +49,7 @@ void ScsiDevice::notify(ScsiBus* bus_obj, ScsiMsg msg_type, int param)
|
||||
}
|
||||
bus_obj->transfer_command(this->cmd_buf);
|
||||
//this->process_command();
|
||||
bus_obj->switch_phase(this->scsi_id, ScsiPhase::DATA_IN);
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user