scsi_bus: packet data transfers.

This commit is contained in:
Maxim Poliakovski 2022-10-31 23:17:08 +01:00
parent c7ceb9d6b9
commit fbfae98d6d
5 changed files with 63 additions and 15 deletions

View File

@ -144,6 +144,7 @@ public:
// ScsiDevice methods // ScsiDevice methods
void notify(ScsiBus* bus_obj, ScsiMsg msg_type, int param); void notify(ScsiBus* bus_obj, ScsiMsg msg_type, int param);
bool has_data() { return this->data_fifo_pos != 0; };
bool send_bytes(uint8_t* dst_ptr, int count); bool send_bytes(uint8_t* dst_ptr, int count);
void process_command() {}; void process_command() {};

View File

@ -46,7 +46,7 @@ enum {
}; };
namespace ScsiPhase { namespace ScsiPhase {
enum : int { enum : int {
BUS_FREE = 0, BUS_FREE = 0,
ARBITRATION, ARBITRATION,
SELECTION, SELECTION,
@ -58,7 +58,7 @@ enum : int {
MESSAGE_IN, MESSAGE_IN,
MESSAGE_OUT, MESSAGE_OUT,
RESET, RESET,
}; };
}; };
enum ScsiMsg : int { enum ScsiMsg : int {
@ -140,6 +140,7 @@ public:
virtual void notify(ScsiBus* bus_obj, ScsiMsg msg_type, int param); virtual void notify(ScsiBus* bus_obj, ScsiMsg msg_type, int param);
virtual bool has_data() = 0;
virtual bool send_bytes(uint8_t* dst_ptr, int count) = 0; virtual bool send_bytes(uint8_t* dst_ptr, int count) = 0;
virtual void process_command() = 0; virtual void process_command() = 0;
@ -179,6 +180,8 @@ public:
bool end_selection(int initiator_id, int target_id); bool end_selection(int initiator_id, int target_id);
bool transfer_command(uint8_t* dst_ptr); bool transfer_command(uint8_t* dst_ptr);
void disconnect(int dev_id); void disconnect(int dev_id);
bool target_request_data();
bool target_pull_data(uint8_t* dst_ptr, int size);
protected: protected:
void change_bus_phase(int initiator_id); void change_bus_phase(int initiator_id);

View File

@ -246,6 +246,31 @@ bool ScsiBus::transfer_command(uint8_t* dst_ptr)
return true; return true;
} }
bool ScsiBus::target_request_data()
{
if (this->devices[this->target_id]->has_data()) {
this->assert_ctrl_line(target_id, SCSI_CTRL_REQ);
return true;
} else {
return false;
}
}
bool ScsiBus::target_pull_data(uint8_t* dst_ptr, int size)
{
if (dst_ptr == nullptr || !size) {
return false;
}
// transfer the requested number of bytes from target to initiator
if (!this->devices[this->target_id]->send_bytes(dst_ptr, size)) {
LOG_F(ERROR, "ScsiBus: error while transferring data from target!");
return false;
}
return true;
}
void ScsiBus::disconnect(int dev_id) void ScsiBus::disconnect(int dev_id)
{ {
this->release_ctrl_lines(dev_id); this->release_ctrl_lines(dev_id);

View File

@ -123,6 +123,18 @@ void ScsiHardDisk::process_command() {
} }
} }
bool ScsiHardDisk::send_bytes(uint8_t* dst_ptr, int count) {
if (dst_ptr == nullptr || !count || count > this->cur_buf_cnt) {
return false;
}
std::memcpy(dst_ptr, &this->img_buffer[this->cur_buf_pos], count);
this->cur_buf_pos += count;
this->cur_buf_cnt -= count;
return true;
}
int ScsiHardDisk::test_unit_ready() { int ScsiHardDisk::test_unit_ready() {
if (img_path.empty() || img_path == " ") { if (img_path.empty() || img_path == " ") {
return ScsiError::DEV_NOT_READY; return ScsiError::DEV_NOT_READY;
@ -204,6 +216,8 @@ void ScsiHardDisk::read(uint32_t lba, uint16_t transfer_len, uint8_t cmd_len) {
this->hdd_img.seekg(device_offset, this->hdd_img.beg); this->hdd_img.seekg(device_offset, this->hdd_img.beg);
this->hdd_img.read(img_buffer, transfer_size); this->hdd_img.read(img_buffer, transfer_size);
this->cur_buf_cnt = transfer_size;
} }
void ScsiHardDisk::write(uint32_t lba, uint16_t transfer_len, uint8_t cmd_len) { void ScsiHardDisk::write(uint32_t lba, uint16_t transfer_len, uint8_t cmd_len) {

View File

@ -41,7 +41,8 @@ public:
void insert_image(std::string filename); void insert_image(std::string filename);
void process_command(); void process_command();
bool send_bytes(uint8_t* dst_ptr, int count) { return true; }; bool has_data() { return this->cur_buf_cnt != 0; };
bool send_bytes(uint8_t* dst_ptr, int count);
int test_unit_ready(); int test_unit_ready();
int req_sense(uint16_t alloc_len); int req_sense(uint16_t alloc_len);
@ -57,7 +58,7 @@ public:
void seek(uint32_t lba); void seek(uint32_t lba);
void rewind(); void rewind();
protected: private:
std::string img_path; std::string img_path;
std::fstream hdd_img; std::fstream hdd_img;
uint64_t img_size; uint64_t img_size;
@ -65,6 +66,10 @@ protected:
uint64_t file_offset = 0; uint64_t file_offset = 0;
uint8_t status = ScsiError::NO_ERROR; uint8_t status = ScsiError::NO_ERROR;
// SCSI transfer pointers
uint32_t cur_buf_pos = 0;
uint32_t cur_buf_cnt = 0;
//inquiry info //inquiry info
char vendor_info[8] = {'D', 'i', 'n', 'g', 'u', 's', 'D', '\0'}; char vendor_info[8] = {'D', 'i', 'n', 'g', 'u', 's', 'D', '\0'};
char prod_info[16] = {'E', 'm', 'u', 'l', 'a', 't', 'e', 'd', ' ', 'D', 'i', 's', 'k', '\0'}; char prod_info[16] = {'E', 'm', 'u', 'l', 'a', 't', 'e', 'd', ' ', 'D', 'i', 's', 'k', '\0'};