41static constexpr uint8_t MT_UNKNOWN = 0x00;
42static constexpr uint8_t MT_2DD_UN = 0x10;
43static constexpr uint8_t MT_2DD = 0x11;
44static constexpr uint8_t MT_2HD_UN = 0x20;
45static constexpr uint8_t MT_2HD_12_98 = 0x22;
46static constexpr uint8_t MT_2HD_12 = 0x23;
47static constexpr uint8_t MT_2HD_144 = 0x24;
48static constexpr uint8_t MT_LS120 = 0x31;
49static constexpr uint8_t MT_NO_DISK = 0x70;
50static constexpr uint8_t MT_DOOR_OPEN = 0x71;
51static constexpr uint8_t MT_FMT_ERROR = 0x72;
53static constexpr std::array<uint8_t, 36> inqData = {
64 'o',
'p',
'e',
'n',
'M',
'S',
'X',
' ',
65 'S',
'C',
'S',
'I',
'2',
' ',
'H',
'a',
66 'r',
'd',
'd',
'i',
's',
'k',
' ',
' ',
78 , scsiId(
narrow_cast<uint8_t>(targetConfig.getAttributeValueAsInt(
"id", 0)))
92void SCSIHD::busReset()
98void SCSIHD::disconnect()
104bool SCSIHD::isSelected()
110unsigned SCSIHD::inquiry()
112 unsigned length = currentLength;
114 if (length == 0)
return 0;
132 length = std::min(length, 96u);
135 memset(buffer + 56, 0, 40);
141 length = std::min(length, 56u);
147 imageName.resize(20,
' ');
153unsigned SCSIHD::modeSense()
155 uint8_t* pBuffer = buffer;
156 if ((currentLength > 0) && (cdb[2] == 3)) {
159 uint8_t media = MT_UNKNOWN;
160 uint8_t sectors = 64;
163 uint8_t
size = 4 + 24;
164 uint8_t removable = 0x80;
166 memset(pBuffer + 2, 0, 34);
178 if (!(cdb[1] & 0x08)) {
180 pBuffer[1] = (total >> 16) & 0xff;
181 pBuffer[2] = (total >> 8) & 0xff;
182 pBuffer[3] = (total >> 0) & 0xff;
183 pBuffer[6] = blockLength & 0xff;
191 pBuffer[ 3] = tracks;
192 pBuffer[11] = sectors;
193 pBuffer[12] = blockLength;
194 pBuffer[20] = removable;
196 buffer[0] =
size - 1;
198 return std::min<unsigned>(currentLength, size);
204unsigned SCSIHD::requestSense()
206 unsigned length = currentLength;
208 unitAttention =
false;
212 memset(buffer + 1, 0, 17);
217 buffer[ 0] = (tmpKeycode >> 8) & 0xff;
221 buffer[ 2] = (tmpKeycode >> 16) & 0xff;
223 buffer[12] = (tmpKeycode >> 8) & 0xff;
224 buffer[13] = (tmpKeycode >> 0) & 0xff;
225 length = std::min(length, 18u);
230bool SCSIHD::checkReadOnly()
239unsigned SCSIHD::readCapacity()
256bool SCSIHD::checkAddress()
265 if ((currentLength > 0) && (currentSector + currentLength <= total)) {
273unsigned SCSIHD::readSectors(
unsigned& blocks)
277 unsigned numSectors = std::min(currentLength, BUFFER_BLOCK_SIZE);
281 for (
auto i :
xrange(numSectors)) {
282 auto* sbuf = aligned_cast<SectorBuffer*>(buffer);
287 blocks = currentLength;
289 }
catch (MSXException&) {
296unsigned SCSIHD::dataIn(
unsigned& blocks)
299 unsigned counter = readSectors(blocks);
300 if (counter)
return counter;
308unsigned SCSIHD::writeSectors(
unsigned& blocks)
312 unsigned numSectors = std::min(currentLength, BUFFER_BLOCK_SIZE);
315 for (
auto i :
xrange(numSectors)) {
316 const auto* sbuf = aligned_cast<const SectorBuffer*>(buffer);
322 unsigned tmp = std::min(currentLength, BUFFER_BLOCK_SIZE);
323 blocks = currentLength - tmp;
324 unsigned counter = tmp * SECTOR_SIZE;
326 }
catch (MSXException&) {
333unsigned SCSIHD::dataOut(
unsigned& blocks)
336 return writeSectors(blocks);
344void SCSIHD::formatUnit()
346 if (!checkReadOnly()) {
347 auto& sbuf = *aligned_cast<SectorBuffer*>(buffer);
348 memset(&sbuf, 0,
sizeof(sbuf));
351 unitAttention =
true;
352 }
catch (MSXException&) {
358uint8_t SCSIHD::getStatusCode()
363unsigned SCSIHD::executeCmd(std::span<const uint8_t, 12> cdb_,
SCSI::Phase& phase,
unsigned& blocks)
375 unitAttention =
false;
397 currentSector = ((cdb[1] & 0x1f) << 16) | (cdb[2] << 8) | cdb[3];
398 currentLength = cdb[4];
405 unsigned counter = inquiry();
412 unsigned counter = requestSense();
419 if (currentLength == 0) {
420 currentLength = SECTOR_SIZE / 2;
422 if (checkAddress()) {
423 unsigned counter = readSectors(blocks);
433 if (currentLength == 0) {
434 currentLength = SECTOR_SIZE / 2;
436 if (checkAddress() && !checkReadOnly()) {
438 unsigned tmp = std::min(currentLength, BUFFER_BLOCK_SIZE);
439 blocks = currentLength - tmp;
440 unsigned counter = tmp * SECTOR_SIZE;
450 (void)checkAddress();
454 unsigned counter = modeSense();
482 if (checkAddress()) {
483 unsigned counter = readSectors(blocks);
492 if (checkAddress() && !checkReadOnly()) {
493 unsigned tmp = std::min(currentLength, BUFFER_BLOCK_SIZE);
494 blocks = currentLength - tmp;
495 unsigned counter = tmp * SECTOR_SIZE;
502 unsigned counter = readCapacity();
511 (void)checkAddress();
521unsigned SCSIHD::executingCmd(
SCSI::Phase& phase,
unsigned& blocks)
528uint8_t SCSIHD::msgIn()
530 uint8_t result = message;
544int SCSIHD::msgOut(uint8_t value)
568 return ((value >= 0x04) && (value <= 0x11)) ? 3 : 1;
572template<
typename Archive>
577 ar.template serializeBase<HD>(*
this);
578 ar.serialize(
"keycode", keycode,
579 "currentSector", currentSector,
580 "currentLength", currentLength,
581 "unitAttention", unitAttention,
584 ar.serialize_blob(
"cdb", cdb);
const Filename & getImageName() const
MSXMotherBoard & getMotherBoard() const
void setLed(Led led, bool status)
LedStatus & getLedStatus()
static constexpr unsigned BIT_SCSI3
static constexpr unsigned BUFFER_SIZE
static constexpr unsigned MODE_NOVAXIS
static constexpr unsigned BIT_SCSI2
static constexpr unsigned MODE_UNITATTENTION
void serialize(Archive &ar, unsigned version)
SCSIHD(const DeviceConfig &targetConfig, AlignedBuffer &buf, unsigned mode)
bool isWriteProtected() const
static constexpr size_t SECTOR_SIZE
size_t getNbSectors() const
void readSector(size_t sector, SectorBuffer &buf) const
void writeSector(size_t sector, const SectorBuffer &buf)
ALWAYS_INLINE uint16_t read_UA_B16(const void *p)
ALWAYS_INLINE uint32_t read_UA_B32(const void *p)
void writeB32(void *p, uint32_t x)
T length(const vecN< N, T > &x)
string_view getFilename(string_view path)
Returns the file portion of a path name.
constexpr uint8_t MSG_NO_OPERATION
constexpr uint32_t SENSE_POWER_ON
constexpr uint8_t OP_RESERVE_UNIT
constexpr uint8_t ST_GOOD
constexpr uint32_t SENSE_WRITE_PROTECT
constexpr uint32_t SENSE_INVALID_COMMAND_CODE
constexpr uint8_t OP_MODE_SENSE
constexpr uint8_t OP_READ_CAPACITY
constexpr uint8_t ST_CHECK_CONDITION
constexpr uint32_t SENSE_UNRECOVERED_READ_ERROR
constexpr uint32_t SENSE_NO_SENSE
constexpr uint8_t OP_TEST_UNIT_READY
constexpr uint8_t OP_SEEK6
constexpr uint8_t OP_READ6
constexpr uint32_t SENSE_MEDIUM_NOT_PRESENT
constexpr uint8_t MSG_ABORT
constexpr uint8_t OP_REZERO_UNIT
constexpr uint32_t SENSE_WRITE_FAULT
constexpr uint32_t SENSE_ILLEGAL_BLOCK_ADDRESS
constexpr uint8_t OP_WRITE10
constexpr uint8_t MSG_BUS_DEVICE_RESET
constexpr uint8_t OP_WRITE6
constexpr uint8_t OP_INQUIRY
constexpr uint8_t OP_REASSIGN_BLOCKS
constexpr uint8_t OP_SEND_DIAGNOSTIC
constexpr uint8_t MSG_INITIATOR_DETECT_ERROR
constexpr uint32_t SENSE_INVALID_LUN
constexpr uint32_t SENSE_INITIATOR_DETECTED_ERR
constexpr uint8_t OP_FORMAT_UNIT
constexpr uint8_t OP_START_STOP_UNIT
constexpr uint8_t MSG_PARITY_ERROR
constexpr uint8_t OP_READ10
constexpr uint8_t OP_GROUP1
constexpr uint8_t OP_SEEK10
constexpr uint8_t OP_REQUEST_SENSE
constexpr uint8_t MSG_REJECT
constexpr uint8_t DT_DirectAccess
constexpr uint8_t OP_RELEASE_UNIT
This file implemented 3 utility functions:
constexpr auto copy(InputRange &&range, OutputIter out)
size_t size(std::string_view utf8)
constexpr To narrow_cast(From &&from) noexcept
constexpr auto subspan(Range &&range, size_t offset, size_t count=std::dynamic_extent)
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
constexpr auto xrange(T e)