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
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);
void process_command() {};

View File

@ -46,19 +46,19 @@ enum {
};
namespace ScsiPhase {
enum : int {
BUS_FREE = 0,
ARBITRATION,
SELECTION,
RESELECTION,
COMMAND,
DATA_IN,
DATA_OUT,
STATUS,
MESSAGE_IN,
MESSAGE_OUT,
RESET,
};
enum : int {
BUS_FREE = 0,
ARBITRATION,
SELECTION,
RESELECTION,
COMMAND,
DATA_IN,
DATA_OUT,
STATUS,
MESSAGE_IN,
MESSAGE_OUT,
RESET,
};
};
enum ScsiMsg : int {
@ -140,6 +140,7 @@ public:
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 void process_command() = 0;
@ -179,6 +180,8 @@ public:
bool end_selection(int initiator_id, int target_id);
bool transfer_command(uint8_t* dst_ptr);
void disconnect(int dev_id);
bool target_request_data();
bool target_pull_data(uint8_t* dst_ptr, int size);
protected:
void change_bus_phase(int initiator_id);

View File

@ -246,6 +246,31 @@ bool ScsiBus::transfer_command(uint8_t* dst_ptr)
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)
{
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() {
if (img_path.empty() || img_path == " ") {
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.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) {

View File

@ -41,7 +41,8 @@ public:
void insert_image(std::string filename);
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 req_sense(uint16_t alloc_len);
@ -57,7 +58,7 @@ public:
void seek(uint32_t lba);
void rewind();
protected:
private:
std::string img_path;
std::fstream hdd_img;
uint64_t img_size;
@ -65,6 +66,10 @@ protected:
uint64_t file_offset = 0;
uint8_t status = ScsiError::NO_ERROR;
// SCSI transfer pointers
uint32_t cur_buf_pos = 0;
uint32_t cur_buf_cnt = 0;
//inquiry info
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'};