47 constexpr
byte MT_2DD = 0x11;
68 'o',
'p',
'e',
'n',
'M',
'S',
'X',
' ',
69 'S',
'C',
'S',
'I',
'2',
' ',
'L',
'S',
70 '-',
'1',
'2',
'0',
'd',
'i',
's',
'k',
75 constexpr
char fds120[28 + 1] =
"IODATA LS-120 COSM 0001";
82 : motherBoard(targetconfig.getMotherBoard())
86 , scsiId(targetconfig.getAttributeValueAsInt(
"id", 0))
91 while ((*lsInUse)[
id]) {
97 name[2] = char(
'a' +
id);
98 (*lsInUse)[
id] =
true;
115 unsigned id = name[2] -
'a';
116 assert((*lsInUse)[
id]);
117 (*lsInUse)[
id] =
false;
120 void SCSILS120::reset()
122 mediaChanged =
false;
128 void SCSILS120::busReset()
134 void SCSILS120::disconnect()
140 bool SCSILS120::isSelected()
146 bool SCSILS120::getReady()
148 if (file.
is_open())
return true;
153 void SCSILS120::testUnitReady()
161 mediaChanged =
false;
164 void SCSILS120::startStopUnit()
180 unsigned SCSILS120::inquiry()
183 unsigned length = currentLength;
185 bool fdsmode = (total > 0) && (total <= 2880);
187 if (
length == 0)
return 0;
190 memcpy(buffer + 2,
inqData + 2, 6);
191 memcpy(buffer + 8,
fds120, 28);
193 memcpy(buffer + 2,
inqData + 2, 34);
202 if (!fdsmode) buffer[20] =
'1';
206 if (!fdsmode) buffer[20] =
'3';
214 memset(buffer + 56, 0, 40);
226 memcpy(buffer + 36,
filename.data(), 20);
231 unsigned SCSILS120::modeSense()
233 byte* pBuffer = buffer;
235 if ((currentLength > 0) && (cdb[2] == 3)) {
242 byte removable = 0xa0;
244 memset(pBuffer + 2, 0, 34);
252 blockLength = 2048 >> 8;
258 blockLength = 2048 >> 8;
270 if (!(cdb[1] & 0x08)) {
272 pBuffer[1] = (total >> 16) & 0xff;
273 pBuffer[2] = (total >> 8) & 0xff;
274 pBuffer[3] = (total >> 0) & 0xff;
275 pBuffer[6] = blockLength & 0xff;
283 pBuffer[ 3] = tracks;
284 pBuffer[11] = sectors;
285 pBuffer[12] = blockLength;
286 pBuffer[20] = removable;
288 buffer[0] =
size - 1;
290 return std::min<unsigned>(currentLength,
size);
296 unsigned SCSILS120::requestSense()
298 unsigned length = currentLength;
300 unitAttention =
false;
304 memset(buffer + 1, 0, 17);
309 buffer[ 0] = (tmpKeycode >> 8) & 0xff;
313 buffer[ 2] = (tmpKeycode >> 16) & 0xff;
315 buffer[12] = (tmpKeycode >> 8) & 0xff;
316 buffer[13] = (tmpKeycode >> 0) & 0xff;
322 bool SCSILS120::checkReadOnly()
331 unsigned SCSILS120::readCapacity()
348 bool SCSILS120::checkAddress()
357 if ((currentLength > 0) && (currentSector + currentLength <= total)) {
365 unsigned SCSILS120::readSector(
unsigned& blocks)
376 currentSector += numSectors;
377 currentLength -= numSectors;
378 blocks = currentLength;
380 }
catch (FileException&) {
387 unsigned SCSILS120::dataIn(
unsigned& blocks)
390 unsigned counter = readSector(blocks);
401 unsigned SCSILS120::writeSector(
unsigned& blocks)
411 currentSector += numSectors;
412 currentLength -= numSectors;
415 blocks = currentLength - tmp;
418 }
catch (FileException&) {
425 unsigned SCSILS120::dataOut(
unsigned& blocks)
428 return writeSector(blocks);
436 void SCSILS120::formatUnit()
438 if (getReady() && !checkReadOnly()) {
443 unitAttention =
true;
445 }
catch (FileException&) {
451 byte SCSILS120::getStatusCode()
456 void SCSILS120::eject()
461 unitAttention =
true;
466 void SCSILS120::insert(
const std::string&
filename)
471 unitAttention =
true;
476 unsigned SCSILS120::executeCmd(
const byte* cdb_,
SCSI::Phase& phase,
unsigned& blocks)
478 memcpy(cdb, cdb_,
sizeof(cdb));
486 unitAttention =
false;
489 mediaChanged =
false;
508 currentSector = ((cdb[1] & 0x1f) << 16) | (cdb[2] << 8) | cdb[3];
509 currentLength = cdb[4];
517 unsigned counter = inquiry();
524 unsigned counter = requestSense();
531 if (currentLength == 0) {
534 if (checkAddress()) {
535 unsigned counter = readSector(blocks);
545 if (currentLength == 0) {
548 if (checkAddress() && !checkReadOnly()) {
551 blocks = currentLength - tmp;
562 (void)checkAddress();
566 unsigned counter = modeSense();
594 if (checkAddress()) {
595 unsigned counter = readSector(blocks);
604 if (checkAddress() && !checkReadOnly()) {
606 blocks = currentLength - tmp;
614 unsigned counter = readCapacity();
623 (void)checkAddress();
633 unsigned SCSILS120::executingCmd(
SCSI::Phase& phase,
unsigned& blocks)
640 byte SCSILS120::msgIn()
642 byte result = message;
656 int SCSILS120::msgOut(
byte value)
680 return ((value >= 0x04) && (value <= 0x11)) ? 3 : 1;
683 size_t SCSILS120::getNbSectorsImpl()
const
688 bool SCSILS120::isWriteProtectedImpl()
const
693 Sha1Sum SCSILS120::getSha1SumImpl(FilePool& filePool)
698 return filePool.getSha1Sum(file);
701 void SCSILS120::readSectorsImpl(
702 SectorBuffer* buffers,
size_t startSector,
size_t num)
704 file.
seek(startSector *
sizeof(SectorBuffer));
705 file.
read(buffers, num *
sizeof(SectorBuffer));
708 void SCSILS120::writeSectorImpl(
size_t sector,
const SectorBuffer& buf)
710 file.
seek(
sizeof(buf) * sector);
711 file.
write(&buf,
sizeof(buf));
714 SectorAccessibleDisk* SCSILS120::getSectorAccessibleDisk()
719 std::string_view SCSILS120::getContainerName()
const
724 bool SCSILS120::diskChanged()
729 int SCSILS120::insertDisk(
const std::string&
filename)
734 }
catch (MSXException&) {
746 scheduler_, ls_.name)
754 if (tokens.size() == 1) {
755 auto& file = ls.file;
757 file.is_open() ? file.getURL() : std::string{});
759 }
else if ((tokens.size() == 2) && (tokens[1] ==
one_of(
"eject",
"-eject"))) {
762 if (tokens[1] ==
"-eject") {
763 result =
"Warning: use of '-eject' is deprecated, "
764 "instead use the 'eject' subcommand";
766 }
else if ((tokens.size() == 2) ||
767 ((tokens.size() == 3) && (tokens[1] ==
"insert"))) {
769 if (tokens[1] ==
"insert") {
770 if (tokens.size() > 2) {
774 "Missing argument to insert subcommand");
791 ls.name,
" : display the disk image for this LS-120 drive\n",
792 ls.name,
" eject : eject the disk image from this LS-120 drive\n",
793 ls.name,
" insert <filename> : change the disk image for this LS-120 drive\n",
794 ls.name,
" <filename> : change the disk image for this LS-120 drive\n");
799 using namespace std::literals;
800 static constexpr std::array extra = {
"eject"sv,
"insert"sv};
805 template<
typename Archive>
808 std::string
filename = file.is_open() ? file.getURL() : std::string{};
810 if constexpr (Archive::IS_LOADER) {
819 ar.serialize(
"keycode", keycode,
820 "currentSector", currentSector,
821 "currentLength", currentLength,
822 "unitAttention", unitAttention,
823 "mediaChanged", mediaChanged,
826 ar.serialize_blob(
"cdb", cdb,
sizeof(cdb));
virtual void update(UpdateType type, std::string_view name, std::string_view value)=0
static void completeFileName(std::vector< std::string > &tokens, const FileContext &context, const RANGE &extra)
void close()
Close the current file.
void seek(size_t pos)
Move read/write pointer to the specified position.
bool isReadOnly() const
Check if this file is readonly.
void read(void *buffer, size_t num)
Read from file.
bool is_open() const
Return true iff this file handle refers to an open file.
void write(const void *buffer, size_t num)
Write to file.
const std::string & getURL() const
Returns the URL of this file object.
void execute(std::span< const TclObject > tokens, TclObject &result, EmuTime::param time) override
This is like the execute() method of the Command class, it only has an extra time parameter.
void tabCompletion(std::vector< std::string > &tokens) const override
Attempt tab completion for this command.
LSXCommand(CommandController &commandController, StateChangeDistributor &stateChangeDistributor, Scheduler &scheduler, SCSILS120 &ls)
std::string help(std::span< const TclObject > tokens) const override
Print help for this command.
void setLed(Led led, bool status)
StateChangeDistributor & getStateChangeDistributor()
Scheduler & getScheduler()
CliComm & getMSXCliComm()
CommandController & getCommandController()
LedStatus & getLedStatus()
std::shared_ptr< T > getSharedStuff(std::string_view name, Args &&...args)
Some MSX device parts are shared between several MSX devices (e.g.
Commands that directly influence the MSX state should send and events so that they can be recorded by...
static constexpr unsigned BIT_SCSI3
static constexpr unsigned BUFFER_SIZE
static constexpr unsigned MODE_MEGASCSI
static constexpr unsigned MODE_NOVAXIS
static constexpr unsigned BIT_SCSI2
static constexpr unsigned MODE_UNITATTENTION
SCSILS120(const SCSILS120 &)=delete
void serialize(Archive &ar, unsigned version)
static constexpr size_t SECTOR_SIZE
size_t getNbSectors() const
virtual Sha1Sum getSha1SumImpl(FilePool &filepool)
void addListElement(const T &t)
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)
constexpr vecN< N, T > min(const vecN< N, T > &x, const vecN< N, T > &y)
T length(const vecN< N, T > &x)
string_view getFilename(string_view path)
Returns the file portion of a path name.
constexpr unsigned SENSE_INVALID_COMMAND_CODE
constexpr byte OP_READ_CAPACITY
constexpr byte MSG_PARITY_ERROR
constexpr unsigned SENSE_UNRECOVERED_READ_ERROR
constexpr byte MSG_INITIATOR_DETECT_ERROR
constexpr unsigned SENSE_NO_SENSE
constexpr byte MSG_BUS_DEVICE_RESET
constexpr unsigned SENSE_POWER_ON
constexpr unsigned SENSE_INITIATOR_DETECTED_ERR
constexpr byte OP_INQUIRY
constexpr byte OP_WRITE10
constexpr byte OP_RESERVE_UNIT
constexpr byte OP_MODE_SENSE
constexpr byte OP_REASSIGN_BLOCKS
constexpr unsigned SENSE_INVALID_LUN
constexpr unsigned SENSE_ILLEGAL_BLOCK_ADDRESS
constexpr unsigned SENSE_MEDIUM_NOT_PRESENT
constexpr unsigned SENSE_WRITE_FAULT
constexpr byte OP_TEST_UNIT_READY
constexpr byte OP_REQUEST_SENSE
constexpr byte MSG_REJECT
constexpr byte DT_DirectAccess
constexpr byte MSG_NO_OPERATION
constexpr byte OP_RELEASE_UNIT
constexpr byte OP_START_STOP_UNIT
constexpr byte OP_SEND_DIAGNOSTIC
constexpr byte ST_CHECK_CONDITION
constexpr byte OP_FORMAT_UNIT
constexpr unsigned SENSE_WRITE_PROTECT
constexpr byte OP_REZERO_UNIT
This file implemented 3 utility functions:
constexpr byte MT_FMT_ERROR
constexpr byte MT_2HD_12_98
REGISTER_POLYMORPHIC_INITIALIZER(Pluggable, CassettePlayer, "CassettePlayer")
constexpr unsigned BUFFER_BLOCK_SIZE
constexpr byte inqData[36]
constexpr byte MT_2HD_144
constexpr byte MT_DOOR_OPEN
constexpr const char *const filename
constexpr byte MT_UNKNOWN
FileContext userFileContext(string_view savePath)
constexpr byte MT_NO_DISK
constexpr char fds120[28+1]
size_t size(std::string_view utf8)
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
TemporaryString tmpStrCat(Ts &&... ts)
std::string strCat(Ts &&...ts)