15 : motherBoard(motherBoard_)
20byte AbstractIDEDevice::diagnostic()
const
29void AbstractIDEDevice::createSignature(
bool preserveDevice)
31 sectorCountReg = 0x01;
34 cylinderLowReg = 0x14;
35 cylinderHighReg = 0xEB;
45 cylinderLowReg = 0x00;
46 cylinderHighReg = 0x00;
53 errorReg = diagnostic();
57 setTransferRead(
false);
58 setTransferWrite(
false);
68 return sectorCountReg;
74 return cylinderLowReg;
77 return cylinderHighReg;
104 nibble reg,
byte value, EmuTime::param
113 sectorCountReg = value;
117 sectorNumReg = value;
121 cylinderLowReg = value;
125 cylinderHighReg = value;
134 statusReg &= ~(
DRQ |
ERR);
135 setTransferRead(
false);
136 setTransferWrite(
false);
163 assert((transferIdx + 1) <
sizeof(buffer));
164 auto result =
word((buffer[transferIdx + 0] << 0) +
165 (buffer[transferIdx + 1] << 8));
168 if (bufferLeft == 0) {
169 if (transferCount == 0) {
171 setTransferRead(
false);
182void AbstractIDEDevice::readNextBlock()
185 buffer, std::min<unsigned>(
sizeof(buffer), transferCount));
186 assert((bufferLeft & 1) == 0);
188 transferCount -= bufferLeft;
193 if (!transferWrite) {
197 assert((transferIdx + 1) <
sizeof(buffer));
198 buffer[transferIdx + 0] = narrow_cast<byte>(value & 0xFF);
199 buffer[transferIdx + 1] = narrow_cast<byte>(value >> 8);
202 if (bufferLeft == 0) {
203 unsigned bytesInBuffer = transferIdx;
204 if (transferCount == 0) {
206 setTransferWrite(
false);
218void AbstractIDEDevice::writeNextBlock()
221 bufferLeft = std::min<unsigned>(
sizeof(buffer), transferCount);
222 transferCount -= bufferLeft;
234 setTransferWrite(
false);
235 setTransferRead(
false);
240 return sectorNumReg | (cylinderLowReg << 8) |
241 (cylinderHighReg << 16) | ((devHeadReg & 0x0F) << 24);
246 return (sectorCountReg == 0) ? 256 : sectorCountReg;
251 sectorCountReg = value;
256 return cylinderLowReg | (cylinderHighReg << 8);
261 cylinderLowReg = narrow_cast<byte>(count & 0xFF);
262 cylinderHighReg = narrow_cast<byte>(count >> 8);
267 sectorNumReg = (lba & 0x000000FF) >> 0;
268 cylinderLowReg = (lba & 0x0000FF00) >> 8;
269 cylinderHighReg = (lba & 0x00FF0000) >> 16;
270 devHeadReg = (lba & 0x0F000000) >> 24;
282 errorReg = diagnostic();
283 createSignature(
true);
294 errorReg = diagnostic();
323 fprintf(stderr,
"Unhandled set feature subcommand: %02X\n",
330 fprintf(stderr,
"unsupported IDE command %02X\n", cmd);
337 assert(count <=
sizeof(buffer));
338 assert((count & 1) == 0);
350 assert((count & 1) == 0);
352 transferCount = count;
356void AbstractIDEDevice::startReadTransfer()
359 setTransferRead(
true);
365 setTransferRead(
false);
371 setTransferWrite(
true);
372 transferCount = count;
379 setTransferWrite(
false);
382void AbstractIDEDevice::setTransferRead(
bool status)
384 if (status != transferRead) {
385 transferRead = status;
386 if (!transferWrite) {
393void AbstractIDEDevice::setTransferWrite(
bool status)
395 if (status != transferWrite) {
396 transferWrite = status;
411static void writeIdentifyString(std::span<byte> dst, std::string s)
413 assert((dst.size() % 2) == 0);
414 s.resize(dst.size(),
' ');
415 for (
size_t i = 0; i < dst.size(); i += 2) {
417 dst[i + 0] = s[i + 1];
418 dst[i + 1] = s[i + 0];
422void AbstractIDEDevice::createIdentifyBlock(AlignedBuffer& buf)
426 writeIdentifyString(std::span{&buf[10 * 2], 2 * 10},
"s00000001");
427 writeIdentifyString(std::span{&buf[23 * 2], 2 * 4},
431 :
strCat(
'd', Version::REVISION));
432 writeIdentifyString(std::span{&buf[27 * 2], 2 * 20}, std::string(
getDeviceName()));
438template<
typename Archive>
442 ar.serialize_blob(
"buffer", buffer);
443 ar.serialize(
"transferIdx", transferIdx,
444 "bufferLeft", bufferLeft,
445 "transferCount", transferCount,
446 "errorReg", errorReg,
447 "sectorCountReg", sectorCountReg,
448 "sectorNumReg", sectorNumReg,
449 "cylinderLowReg", cylinderLowReg,
450 "cylinderHighReg", cylinderHighReg,
451 "devHeadReg", devHeadReg,
452 "statusReg", statusReg,
453 "featureReg", featureReg);
454 bool transferIdentifyBlock =
false;
456 ar.serialize(
"transferIdentifyBlock", transferIdentifyBlock,
457 "transferRead", transferRead,
458 "transferWrite", transferWrite);
void writeData(word value, EmuTime::param time) override
void startWriteTransfer(unsigned count)
Indicates the start of a write data transfer.
byte getFeatureReg() const
AlignedBuffer & startShortReadTransfer(unsigned count)
Indicates the start of a read data transfer where all data fits into the buffer at once.
virtual bool isPacketDevice()=0
Is this device a packet (ATAPI) device?
static constexpr byte DRDY
void startLongReadTransfer(unsigned count)
Indicates the start of a read data transfer which uses blocks.
void serialize(Archive &ar, unsigned version)
virtual void executeCommand(byte cmd)
Starts execution of an IDE command.
void writeReg(nibble reg, byte value, EmuTime::param time) override
static constexpr byte DRQ
static constexpr byte ERR
virtual void fillIdentifyBlock(AlignedBuffer &buffer)=0
Tells a subclass to fill the device specific parts of the identify block located in the buffer.
void setSectorNumber(unsigned lba)
Writes a 28-bit LBA sector number in the registers.
void setByteCount(unsigned count)
Writes the byte count of a packet transfer in the registers.
virtual std::string_view getDeviceName()=0
Gets the device name to insert as "model number" into the identify block.
static constexpr byte DSC
virtual unsigned readBlockStart(AlignedBuffer &buffer, unsigned count)=0
Called when a block of read data should be buffered by the controller: when the buffer is empty or at...
unsigned getNumSectors() const
Gets the number of sectors indicated by the sector count register.
void abortReadTransfer(byte error)
Aborts the read transfer in progress.
unsigned getByteCount() const
Reads the byte count limit of a packet transfer in the registers.
void setError(byte error)
Indicates an error: sets error register, error flag, aborts transfers.
byte readReg(nibble reg, EmuTime::param time) override
void abortWriteTransfer(byte error)
Aborts the write transfer in progress.
AbstractIDEDevice(MSXMotherBoard &motherBoard)
void reset(EmuTime::param time) override
unsigned getSectorNumber() const
Creates an LBA sector address from the contents of the sectorNumReg, cylinderLowReg,...
void setInterruptReason(byte value)
Writes the interrupt reason register.
virtual void writeBlockComplete(AlignedBuffer &buffer, unsigned count)=0
Called when a block of written data has been buffered by the controller: when the buffer is full or a...
word readData(EmuTime::param time) override
virtual void readEnd()
Called when a read transfer completes.
static constexpr byte ABORT
void setLed(Led led, bool status)
LedStatus & getLedStatus()
static const char *const VERSION
static const bool RELEASE
This file implemented 3 utility functions:
uint8_t nibble
4 bit integer
uint16_t word
16 bit unsigned integer
constexpr void fill(ForwardRange &&range, const T &value)
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)