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 
9 namespace openmsx {
10 
11 class MSXMotherBoard;
12 
14 {
15 public:
16  void reset(EmuTime::param time) override;
17 
18  word readData(EmuTime::param time) override;
19  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 
27 protected:
28  // Bit flags for the status register:
29  static const byte DRDY = 0x40;
30  static const byte DSC = 0x10;
31  static const byte DRQ = 0x08;
32  static const byte ERR = 0x01;
33 
34  // Bit flags for the error register:
35  static const byte UNC = 0x40;
36  static const byte IDNF = 0x10;
37  static const byte ABORT = 0x04;
38 
39  explicit AbstractIDEDevice(MSXMotherBoard& motherBoard);
40  ~AbstractIDEDevice() override = default;
41 
45  virtual bool isPacketDevice() = 0;
46 
51  virtual const std::string& getDeviceName() = 0;
52 
58  virtual void fillIdentifyBlock(AlignedBuffer& buffer) = 0;
59 
69  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  unsigned getSectorNumber() const;
98 
101  unsigned getNumSectors() const;
102 
107  void setInterruptReason(byte value);
108 
112  unsigned getByteCount();
113 
117  void setByteCount(unsigned count);
118 
122  void setSectorNumber(unsigned lba);
123 
130  void startLongReadTransfer(unsigned count);
131 
140 
143  void abortReadTransfer(byte error);
144 
148  void startWriteTransfer(unsigned count);
149 
152  void abortWriteTransfer(byte error);
153 
154  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  MSXMotherBoard& getMotherBoard() const { return motherBoard; }
160 
161 private:
165  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 
202  MSXMotherBoard& motherBoard;
203 
209  AlignedByteArray<512> buffer;
210 
213  unsigned transferIdx;
214 
217  unsigned bufferLeft;
218 
222  unsigned transferCount;
223 
224  // ATA registers:
225  byte errorReg;
226  byte sectorCountReg;
227  byte sectorNumReg;
228  byte cylinderLowReg;
229  byte cylinderHighReg;
230  byte devHeadReg;
231  byte statusReg;
232  byte featureReg;
233 
234  bool transferRead;
235  bool transferWrite;
236 };
237 
239 
240 } // namespace openmsx
241 
242 #endif // ABSTRACTIDEDEVICE_HH
void reset(EmuTime::param time) override
void startLongReadTransfer(unsigned count)
Indicates the start of a read data transfer which uses blocks.
unsigned getSectorNumber() const
Creates an LBA sector address from the contents of the sectorNumReg, cylinderLowReg, cylinderHighReg and devHeadReg registers.
unsigned getNumSectors() const
Gets the number of sectors indicated by the sector count register.
REGISTER_BASE_NAME_HELPER(MSXFDC, "FDC")
uint8_t byte
8 bit unsigned integer
Definition: openmsx.hh:26
void writeReg(nibble reg, byte value, EmuTime::param time) override
AbstractIDEDevice(MSXMotherBoard &motherBoard)
void abortWriteTransfer(byte error)
Aborts the write transfer in progress.
AlignedBuffer & startShortReadTransfer(unsigned count)
Indicates the start of a read data transfer where all data fits into the buffer at once...
MSXMotherBoard & getMotherBoard() const
byte readReg(nibble reg, EmuTime::param time) override
void serialize(Archive &ar, unsigned version)
void writeData(word value, EmuTime::param time) override
~AbstractIDEDevice() override=default
unsigned getByteCount()
Reads the byte count limit of a packet transfer in the registers.
virtual bool isPacketDevice()=0
Is this device a packet (ATAPI) device?
void setSectorNumber(unsigned lba)
Writes a 28-bit LBA sector number in the registers.
void abortReadTransfer(byte error)
Aborts the read transfer in progress.
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...
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
void startWriteTransfer(unsigned count)
Indicates the start of a write data transfer.
void setError(byte error)
Indicates an error: sets error register, error flag, aborts transfers.
auto count(InputRange &&range, const T &value)
Definition: ranges.hh:209
uint8_t nibble
4 bit integer
Definition: openmsx.hh:23
uint16_t word
16 bit unsigned integer
Definition: openmsx.hh:29
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 fillIdentifyBlock(AlignedBuffer &buffer)=0
Tells a subclass to fill the device specific parts of the identify block located in the buffer...
virtual void readEnd()
Called when a read transfer completes.
virtual const std::string & getDeviceName()=0
Gets the device name to insert as "model number" into the identify block.
virtual void executeCommand(byte cmd)
Starts execution of an IDE command.
void setInterruptReason(byte value)
Writes the interrupt reason register.
void setByteCount(unsigned count)
Writes the byte count of a packet transfer in the registers.