2019-08-18 03:43:42 +00:00
|
|
|
//
|
2019-08-22 03:22:58 +00:00
|
|
|
// Target.cpp
|
2019-08-18 03:43:42 +00:00
|
|
|
// Clock Signal
|
|
|
|
//
|
|
|
|
// Created by Thomas Harte on 17/08/2019.
|
|
|
|
// Copyright © 2019 Thomas Harte. All rights reserved.
|
|
|
|
//
|
|
|
|
|
2019-08-22 03:22:58 +00:00
|
|
|
#include "Target.hpp"
|
2019-08-18 03:43:42 +00:00
|
|
|
|
2019-08-20 02:47:01 +00:00
|
|
|
using namespace SCSI::Target;
|
|
|
|
|
2019-09-13 01:58:09 +00:00
|
|
|
CommandState::CommandState(const std::vector<uint8_t> &data, const std::vector<uint8_t> &received) : data_(data), received_(received) {}
|
2019-08-20 02:47:01 +00:00
|
|
|
|
2019-08-25 21:03:41 +00:00
|
|
|
uint32_t CommandState::address() const {
|
2019-08-20 02:47:01 +00:00
|
|
|
switch(data_.size()) {
|
|
|
|
default: return 0;
|
|
|
|
case 6:
|
|
|
|
return
|
|
|
|
(uint32_t(data_[1]) << 16) |
|
|
|
|
(uint32_t(data_[2]) << 8) |
|
|
|
|
uint32_t(data_[3]);
|
|
|
|
case 10:
|
|
|
|
case 12:
|
|
|
|
return
|
|
|
|
(uint32_t(data_[1]) << 24) |
|
|
|
|
(uint32_t(data_[2]) << 16) |
|
|
|
|
(uint32_t(data_[3]) << 8) |
|
|
|
|
uint32_t(data_[4]);
|
2019-08-19 02:39:27 +00:00
|
|
|
}
|
2019-08-20 02:47:01 +00:00
|
|
|
}
|
2019-08-19 02:39:27 +00:00
|
|
|
|
2019-08-25 21:03:41 +00:00
|
|
|
uint16_t CommandState::number_of_blocks() const {
|
2019-08-20 02:47:01 +00:00
|
|
|
switch(data_.size()) {
|
|
|
|
default: return 0;
|
|
|
|
case 6:
|
|
|
|
return uint16_t(data_[4]);
|
|
|
|
case 10:
|
|
|
|
return uint16_t((data_[7] << 8) | data_[8]);
|
2019-08-18 03:43:42 +00:00
|
|
|
}
|
|
|
|
}
|
2019-09-08 02:04:44 +00:00
|
|
|
|
2019-09-17 02:20:42 +00:00
|
|
|
CommandState::ReadWrite CommandState::read_write_specs() const {
|
|
|
|
ReadWrite specs;
|
|
|
|
|
|
|
|
specs.address = address();
|
|
|
|
specs.number_of_blocks = number_of_blocks();
|
2019-09-18 01:59:32 +00:00
|
|
|
if(!specs.number_of_blocks && (data_.size() == 6)) {
|
|
|
|
specs.number_of_blocks = 256;
|
|
|
|
}
|
2019-09-17 02:20:42 +00:00
|
|
|
|
|
|
|
return specs;
|
|
|
|
}
|
|
|
|
|
2019-09-08 02:04:44 +00:00
|
|
|
size_t CommandState::allocated_inquiry_bytes() const {
|
2019-09-09 01:59:56 +00:00
|
|
|
// 0 means 256 bytes allocated for inquiry.
|
2019-09-08 02:04:44 +00:00
|
|
|
return size_t(((data_[4] - 1) & 0xff) + 1);
|
|
|
|
}
|
2019-09-09 01:59:56 +00:00
|
|
|
|
|
|
|
CommandState::ModeSense CommandState::mode_sense_specs() const {
|
2019-09-12 01:52:02 +00:00
|
|
|
ModeSense specs;
|
2019-09-09 01:59:56 +00:00
|
|
|
|
|
|
|
specs.exclude_block_descriptors = (data_[1] & 0x08);
|
|
|
|
specs.page_control_values = ModeSense::PageControlValues(data_[2] >> 5);
|
|
|
|
specs.page_code = data_[2] & 0x3f;
|
|
|
|
specs.subpage_code = data_[3];
|
|
|
|
specs.allocated_bytes = number_of_blocks();
|
|
|
|
|
|
|
|
return specs;
|
|
|
|
}
|
2019-09-12 01:52:02 +00:00
|
|
|
|
|
|
|
CommandState::ReadBuffer CommandState::read_buffer_specs() const {
|
|
|
|
ReadBuffer specs;
|
|
|
|
|
|
|
|
specs.mode = ReadBuffer::Mode(data_[1]&7);
|
|
|
|
if(specs.mode > ReadBuffer::Mode::Reserved) specs.mode = ReadBuffer::Mode::Reserved;
|
|
|
|
specs.buffer_id = data_[2];
|
|
|
|
specs.buffer_offset = uint32_t((data_[3] << 16) | (data_[4] << 8) | data_[5]);
|
|
|
|
specs.buffer_length = uint32_t((data_[6] << 16) | (data_[7] << 8) | data_[8]);
|
|
|
|
|
|
|
|
return specs;
|
|
|
|
}
|
2019-09-13 01:58:09 +00:00
|
|
|
|
|
|
|
CommandState::ModeSelect CommandState::mode_select_specs() const {
|
|
|
|
ModeSelect specs;
|
|
|
|
|
|
|
|
specs.parameter_list_length = number_of_blocks();
|
|
|
|
specs.content_is_vendor_specific = !(data_[1] & 0x10);
|
|
|
|
specs.revert_to_default = (data_[1] & 0x02);
|
|
|
|
specs.save_pages = (data_[1] & 0x01);
|
|
|
|
|
|
|
|
return specs;
|
|
|
|
}
|