openMSX
AbstractIDEDevice.hh
Go to the documentation of this file.
1#ifndef ABSTRACTIDEDEVICE_HH
2#define ABSTRACTIDEDEVICE_HH
3
4#include "IDEDevice.hh"
5#include "AlignedBuffer.hh"
6#include "serialize_meta.hh"
7#include <string>
8
9namespace openmsx {
10
11class MSXMotherBoard;
12
14{
15public:
16 void reset(EmuTime::param time) override;
17
18 [[nodiscard]] word readData(EmuTime::param time) override;
19 [[nodiscard]] byte readReg(nibble reg, EmuTime::param time) override;
20
21 void writeData(word value, EmuTime::param time) override;
22 void writeReg(nibble reg, byte value, EmuTime::param time) override;
23
24 template<typename Archive>
25 void serialize(Archive& ar, unsigned version);
26
27protected:
28 // Bit flags for the status register:
29 static constexpr byte DRDY = 0x40;
30 static constexpr byte DSC = 0x10;
31 static constexpr byte DRQ = 0x08;
32 static constexpr byte ERR = 0x01;
33
34 // Bit flags for the error register:
35 static constexpr byte UNC = 0x40;
36 static constexpr byte IDNF = 0x10;
37 static constexpr byte ABORT = 0x04;
38
39 explicit AbstractIDEDevice(MSXMotherBoard& motherBoard);
40 ~AbstractIDEDevice() override = default;
41
45 [[nodiscard]] virtual bool isPacketDevice() = 0;
46
51 [[nodiscard]] virtual std::string_view getDeviceName() = 0;
52
58 virtual void fillIdentifyBlock(AlignedBuffer& buffer) = 0;
59
69 [[nodiscard]] virtual unsigned readBlockStart(AlignedBuffer& buffer, unsigned count) = 0;
70
74 virtual void readEnd();
75
81 virtual void writeBlockComplete(AlignedBuffer& buffer, unsigned count) = 0;
82
87 virtual void executeCommand(byte cmd);
88
92 void setError(byte error);
93
97 [[nodiscard]] unsigned getSectorNumber() const;
98
101 [[nodiscard]] unsigned getNumSectors() const;
102
107 void setInterruptReason(byte value);
108
112 [[nodiscard]] unsigned getByteCount() const;
113
117 void setByteCount(unsigned count);
118
122 void setSectorNumber(unsigned lba);
123
130 void startLongReadTransfer(unsigned count);
131
139 [[nodiscard]] AlignedBuffer& startShortReadTransfer(unsigned count);
140
143 void abortReadTransfer(byte error);
144
148 void startWriteTransfer(unsigned count);
149
152 void abortWriteTransfer(byte error);
153
154 [[nodiscard]] byte getFeatureReg() const { return featureReg; }
155 void setLBALow (byte value) { sectorNumReg = value; }
156 void setLBAMid (byte value) { cylinderLowReg = value; }
157 void setLBAHigh(byte value) { cylinderHighReg = value; }
158
159 [[nodiscard]] MSXMotherBoard& getMotherBoard() const { return motherBoard; }
160
161private:
165 [[nodiscard]] byte diagnostic();
166
172 void createSignature(bool preserveDevice = false);
173
178 void createIdentifyBlock(AlignedBuffer& buffer);
179
182 void startReadTransfer();
183
187 void readNextBlock();
188
191 void setTransferRead(bool status);
192
196 void writeNextBlock();
197
200 void setTransferWrite(bool status);
201
202private:
203 MSXMotherBoard& motherBoard;
204
211
214 unsigned transferIdx = 0; // avoid UMR on serialize
215
218 unsigned bufferLeft = 0;
219
223 unsigned transferCount = 0;
224
225 // ATA registers:
226 byte errorReg;
227 byte sectorCountReg;
228 byte sectorNumReg;
229 byte cylinderLowReg;
230 byte cylinderHighReg;
231 byte devHeadReg;
232 byte statusReg;
233 byte featureReg;
234
235 bool transferRead = false;
236 bool transferWrite = false;
237};
238
240
241} // namespace openmsx
242
243#endif // ABSTRACTIDEDEVICE_HH
void writeData(word value, EmuTime::param time) override
void startWriteTransfer(unsigned count)
Indicates the start of a write data transfer.
AlignedBuffer & startShortReadTransfer(unsigned count)
Indicates the start of a read data transfer where all data fits into the buffer at once.
~AbstractIDEDevice() override=default
virtual bool isPacketDevice()=0
Is this device a packet (ATAPI) device?
static constexpr byte DRDY
static constexpr byte UNC
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.
MSXMotherBoard & getMotherBoard() const
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.
void reset(EmuTime::param time) override
static constexpr byte IDNF
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
This file implemented 3 utility functions:
Definition Autofire.cc:9
uint8_t nibble
4 bit integer
Definition openmsx.hh:23
uint16_t word
16 bit unsigned integer
Definition openmsx.hh:29
#define REGISTER_BASE_NAME_HELPER(B, N)