AbstractIDEDevice.hh 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. #ifndef ABSTRACTIDEDEVICE_HH
  2. #define ABSTRACTIDEDEVICE_HH
  3. #include "IDEDevice.hh"
  4. #include "AlignedBuffer.hh"
  5. #include "serialize_meta.hh"
  6. #include <string>
  7. namespace openmsx {
  8. class MSXMotherBoard;
  9. class AbstractIDEDevice : public IDEDevice
  10. {
  11. public:
  12. void reset(EmuTime::param time) override;
  13. word readData(EmuTime::param time) override;
  14. byte readReg(nibble reg, EmuTime::param time) override;
  15. void writeData(word value, EmuTime::param time) override;
  16. void writeReg(nibble reg, byte value, EmuTime::param time) override;
  17. template<typename Archive>
  18. void serialize(Archive& ar, unsigned version);
  19. protected:
  20. // Bit flags for the status register:
  21. static constexpr byte DRDY = 0x40;
  22. static constexpr byte DSC = 0x10;
  23. static constexpr byte DRQ = 0x08;
  24. static constexpr byte ERR = 0x01;
  25. // Bit flags for the error register:
  26. static constexpr byte UNC = 0x40;
  27. static constexpr byte IDNF = 0x10;
  28. static constexpr byte ABORT = 0x04;
  29. explicit AbstractIDEDevice(MSXMotherBoard& motherBoard);
  30. ~AbstractIDEDevice() override = default;
  31. /** Is this device a packet (ATAPI) device?
  32. * @return True iff this device supports the packet commands.
  33. */
  34. virtual bool isPacketDevice() = 0;
  35. /** Gets the device name to insert as "model number" into the identify
  36. * block.
  37. * @return An ASCII string, up to 40 characters long.
  38. */
  39. virtual const std::string& getDeviceName() = 0;
  40. /** Tells a subclass to fill the device specific parts of the identify
  41. * block located in the buffer.
  42. * The generic part is already written there.
  43. * @param buffer Array of 512 bytes.
  44. */
  45. virtual void fillIdentifyBlock(AlignedBuffer& buffer) = 0;
  46. /** Called when a block of read data should be buffered by the controller:
  47. * when the buffer is empty or at the start of the transfer.
  48. * @param buffer Pointer to the start of a byte array.
  49. * @param count Number of bytes to be filled by this method.
  50. * This number will not exceed the array size nor the transfer length.
  51. * @return The number of bytes that was added to the array,
  52. * or 0 if the transfer was aborted (the implementation of this method
  53. * must set the relevant error flags as well).
  54. */
  55. virtual unsigned readBlockStart(AlignedBuffer& buffer, unsigned count) = 0;
  56. /** Called when a read transfer completes.
  57. * The default implementation does nothing.
  58. */
  59. virtual void readEnd();
  60. /** Called when a block of written data has been buffered by the controller:
  61. * when the buffer is full or at the end of the transfer.
  62. * @param buffer Pointer to the start of a byte array.
  63. * @param count Number of data bytes in the array.
  64. */
  65. virtual void writeBlockComplete(AlignedBuffer& buffer, unsigned count) = 0;
  66. /** Starts execution of an IDE command.
  67. * Override this to implement additional commands and make sure you call
  68. * the superclass implementation for all commands that you don't handle.
  69. */
  70. virtual void executeCommand(byte cmd);
  71. /** Indicates an error: sets error register, error flag, aborts transfers.
  72. * @param error Value to be written to the error register.
  73. */
  74. void setError(byte error);
  75. /** Creates an LBA sector address from the contents of the sectorNumReg,
  76. * cylinderLowReg, cylinderHighReg and devHeadReg registers.
  77. */
  78. unsigned getSectorNumber() const;
  79. /** Gets the number of sectors indicated by the sector count register.
  80. */
  81. unsigned getNumSectors() const;
  82. /** Writes the interrupt reason register.
  83. * This is the same as register as sector count, but serves a different
  84. * purpose.
  85. */
  86. void setInterruptReason(byte value);
  87. /** Reads the byte count limit of a packet transfer in the registers.
  88. * The cylinder low/high registers are used for this.
  89. */
  90. unsigned getByteCount() const;
  91. /** Writes the byte count of a packet transfer in the registers.
  92. * The cylinder low/high registers are used for this.
  93. */
  94. void setByteCount(unsigned count);
  95. /** Writes a 28-bit LBA sector number in the registers.
  96. * The cylinder low/high registers are used for this.
  97. */
  98. void setSectorNumber(unsigned lba);
  99. /** Indicates the start of a read data transfer which uses blocks.
  100. * The readBlockStart() method is called at the start of each block.
  101. * The first block will be read immediately, so make sure you initialise
  102. * all variables needed by readBlockStart() before calling this method.
  103. * @param count Total number of bytes to transfer.
  104. */
  105. void startLongReadTransfer(unsigned count);
  106. /** Indicates the start of a read data transfer where all data fits
  107. * into the buffer at once.
  108. * @param count Total number of bytes to transfer.
  109. * @return Pointer to the start of the buffer.
  110. * The caller should write the data there.
  111. * The relevant part of the buffer contains zeroes.
  112. */
  113. AlignedBuffer& startShortReadTransfer(unsigned count);
  114. /** Aborts the read transfer in progress.
  115. */
  116. void abortReadTransfer(byte error);
  117. /** Indicates the start of a write data transfer.
  118. * @param count Total number of bytes to transfer.
  119. */
  120. void startWriteTransfer(unsigned count);
  121. /** Aborts the write transfer in progress.
  122. */
  123. void abortWriteTransfer(byte error);
  124. byte getFeatureReg() const { return featureReg; }
  125. void setLBALow (byte value) { sectorNumReg = value; }
  126. void setLBAMid (byte value) { cylinderLowReg = value; }
  127. void setLBAHigh(byte value) { cylinderHighReg = value; }
  128. MSXMotherBoard& getMotherBoard() const { return motherBoard; }
  129. private:
  130. /** Perform diagnostic and return result.
  131. * Actually, just return success, because we don't emulate faulty hardware.
  132. */
  133. byte diagnostic();
  134. /** Puts special values in the sector address, sector count and device
  135. * registers to identify the type of device.
  136. * @param preserveDevice If true, preserve the value of the DEV bit;
  137. * if false, set the DEV bit to 0.
  138. */
  139. void createSignature(bool preserveDevice = false);
  140. /** Puts the output for the IDENTIFY DEVICE command in the buffer.
  141. * @param buffer Pointer to the start of the buffer.
  142. * The buffer must be at least 512 bytes in size.
  143. */
  144. void createIdentifyBlock(AlignedBuffer& buffer);
  145. /** Initialises registers for a data transfer.
  146. */
  147. void startReadTransfer();
  148. /** Initialises buffer related variables for the next data block.
  149. * Calls readBlockStart() to deliver the actual data.
  150. */
  151. void readNextBlock();
  152. /** Indicates that a read transfer starts.
  153. */
  154. void setTransferRead(bool status);
  155. /** Initialises buffer related variables for the next data block.
  156. * Make sure transferCount is initialised before calling this method.
  157. */
  158. void writeNextBlock();
  159. /** Indicates that a write transfer starts.
  160. */
  161. void setTransferWrite(bool status);
  162. MSXMotherBoard& motherBoard;
  163. /** Data buffer shared by all transfers.
  164. * The size must be a multiple of 512.
  165. * Right now I don't see any reason to make it larger than the minimum
  166. * size of 1 * 512.
  167. */
  168. AlignedByteArray<512> buffer;
  169. /** Index of current read/write position in the buffer.
  170. */
  171. unsigned transferIdx;
  172. /** Number of bytes remaining in the buffer.
  173. */
  174. unsigned bufferLeft;
  175. /** Number of bytes remaining in the transfer after this buffer.
  176. * (total bytes remaining == transferCount + bufferLeft)
  177. */
  178. unsigned transferCount;
  179. // ATA registers:
  180. byte errorReg;
  181. byte sectorCountReg;
  182. byte sectorNumReg;
  183. byte cylinderLowReg;
  184. byte cylinderHighReg;
  185. byte devHeadReg;
  186. byte statusReg;
  187. byte featureReg;
  188. bool transferRead;
  189. bool transferWrite;
  190. };
  191. REGISTER_BASE_NAME_HELPER(AbstractIDEDevice, "IDEDevice");
  192. } // namespace openmsx
  193. #endif // ABSTRACTIDEDEVICE_HH