text: ///                MentOS, The Mentoring Operating system project
  /// @file ata.h
  /// @brief ATA values and data structures.
  /// @details
  /// IDE is a keyword which refers to the electrical specification of the cables
  ///  which connect ATA drives (like hard drives) to another device. The drives
  ///  use the ATA (Advanced Technology Attachment) interface. An IDE cable also
  ///  can terminate at an IDE card connected to PCI.
  /// ATAPI is an extension to ATA (recently renamed to PATA) which adds support
  ///  for the SCSI command set.
  /// @copyright (c) 2014-2021 This file is distributed under the MIT License.
  /// See LICENSE.md for details.
  ///! @cond Doxygen_Suppress
  
  #pragma once
  
  #include "stdint.h"
  
  /// @defgroup ata_defines The ATA configuration registers.
  /// @{
  
  /// @defgroup status_register Status register bits.
  /// @{
  
  #define ATA_STAT_BUSY  0x80 /// Device Busy
  #define ATA_STAT_READY 0x40 ///< Device Ready
  #define ATA_STAT_FAULT 0x20 ///< Device Fault
  #define ATA_STAT_SEEK  0x10 ///< Device Seek Complete
  #define ATA_STAT_DRQ   0x08 ///< Data Request (ready)
  #define ATA_STAT_CORR  0x04 ///< Corrected Data Error
  #define ATA_STAT_INDEX 0x02 ///< Vendor specific
  #define ATA_STAT_ERR   0x01 ///< Error
  
  ///< @}
  
  /// @defgroup ata_commands ATA Commands
  /// @{
  
  #define ATA_CMD_READ    0x20 ///< Read Sectors (with retries)
  #define ATA_CMD_READN   0x21 ///< Read Sectors (no  retries)
  #define ATA_CMD_WRITE   0x30 ///< Write Sectores (with retries)
  #define ATA_CMD_WRITEN  0x31 ///< Write Sectors  (no  retries)
  #define ATA_CMD_VRFY    0x40 ///< Read Verify  (with retries)
  #define ATA_CMD_VRFYN   0x41 ///< Read verify  (no  retries)
  #define ATA_CMD_SEEK    0x70 ///< Seek
  #define ATA_CMD_DIAG    0x90 ///< Execute Device Diagnostic
  #define ATA_CMD_INIT    0x91 ///< Initialize Device Parameters
  #define ATA_CMD_RD_MULT 0xC4 ///< Read Multiple
  #define ATA_CMD_WR_MULT 0xC5 ///< Write Multiple
  #define ATA_CMD_SETMULT 0xC6 ///< Set Multiple Mode
  #define ATA_CMD_RD_DMA  0xC8 ///< Read DMA (with retries)
  #define ATA_CMD_RD_DMAN 0xC9 ///< Read DMS (no  retries)
  #define ATA_CMD_WR_DMA  0xCA ///< Write DMA (with retries)
  #define ATA_CMD_WR_DMAN 0xCB ///< Write DMA (no  retires)
  #define ATA_CMD_IDENT   0xEC ///< Identify Device
  #define ATA_CMD_CH_FLSH 0xE7 ///< Cache flush.
  #define ATA_CMD_SETF    0xEF ///< Set Features
  #define ATA_CMD_CHK_PWR 0xE5 ///< Check Power Mode
  
  ///< @}
  
  /// @defgroup atapi_commands ATAPI Commands
  /// @{
  
  #define ATAPI_CMD_PACKET  0xA0
  #define ATAPI_CMD_ID_PCKT 0xA1
  
  /// @}
  
  /// @defgroup ata_ident_brits Identification Space Bits
  /// @brief Definitions used to read information from the identification space.
  /// @{
  
  #define ATA_IDENT_DEVICETYPE   0
  #define ATA_IDENT_CYLINDERS    2
  #define ATA_IDENT_HEADS        6
  #define ATA_IDENT_SECTORS      12
  #define ATA_IDENT_SERIAL       20
  #define ATA_IDENT_MODEL        54
  #define ATA_IDENT_CAPABILITIES 98
  #define ATA_IDENT_FIELDVALID   106
  #define ATA_IDENT_MAX_LBA      120
  #define ATA_IDENT_COMMANDSETS  164
  #define ATA_IDENT_MAX_LBA_EXT  200
  
  /// @}
  
  /// @defgroup ata_interface Interface Type
  /// @{
  
  #define IDE_ATA   0x00 ///< ATA (Advanced Technology Attachment) interface.
  #define IDE_ATAPI 0x01 ///< Extended ATA with support for SCSI command set.
  
  /// @}
  
  /// @defgroup ata_priority Interface Priority
  /// @{
  
  #define ATA_DEVICE_0 0x00
  #define ATA_DEVICE_1 0x01
  
  /// @}
  
  /// @defgroup ata_command_block_registers Command block registers
  /// @{
  
  #define ATA_REG_DATA       0x00 ///< Read/Write PIO data bytes.
  #define ATA_REG_ERROR      0x01 ///< Error generated by the last ATA command.
  #define ATA_REG_FEATURES   0x01 ///< Control command specific interface features.
  #define ATA_REG_SECCOUNT0  0x02 ///< Number of sectors to read/write (0 is a special value).
  #define ATA_REG_LBA0       0x03 ///< Sector Number Register.
  #define ATA_REG_LBA1       0x04 ///< Cylinder Low Register.
  #define ATA_REG_LBA2       0x05 ///< Cylinder High Register.
  #define ATA_REG_HDDEVSEL   0x06 ///< Used to select a drive and/or head.
  #define ATA_REG_COMMAND    0x07 ///< Used to send ATA commands to the device.
  #define ATA_REG_STATUS     0x07 ///< Used to read the current status.
  #define ATA_REG_SECCOUNT1  0x08 ///<
  #define ATA_REG_LBA3       0x09 ///<
  #define ATA_REG_LBA4       0x0A ///<
  #define ATA_REG_LBA5       0x0B ///<
  #define ATA_REG_CONTROL    0x0C ///<
  #define ATA_REG_ALTSTATUS  0x0C ///<
  #define ATA_REG_DEVADDRESS 0x0D ///<
  
  /// @}
  
  /// @defgroup ata_channels Channels
  /// @{
  
  #define ATA_PRIMARY   0x00 ///< Primary channel.
  #define ATA_SECONDARY 0x01 ///< Secondary channel.
  /// @}
  
  /// @defgroup ata_directions Directions
  /// @{
  
  #define ATA_READ  0x00 ///< Read direction.
  #define ATA_WRITE 0x01 ///< Write direction.
  
  /// @}
  /// @}
  
  /// @brief Stores information of a channel.
  typedef struct ide_channel_regs_t{
      uint16_t base;  ///< I/O Base.
      uint16_t ctrl;  ///< Control Base
      uint16_t bmide; ///< Bus Master IDE
      uint16_t nien;  ///< nIEN (No Interrupt);
  } ide_channel_regs_t;
  
  /// @brief Stores information of a device.
  typedef struct ide_device_t{
      uint8_t reserved;      ///< 0 (Empty) or 1 (This Drive really exists).
      uint8_t channel;       ///< 0 (Primary Channel) or 1 (Secondary Channel).
      uint8_t drive;         ///< 0 (Drive 0) or 1 (Drive 1).
      uint16_t type;         ///< 0: ATA, 1:ATAPI.
      uint16_t signature;    ///< Drive Signature.
      uint16_t capabilities; ///< Features.
      uint32_t command_sets; ///< Command Sets Supported.
      uint32_t size;         ///< Size in Sectors.
      uint8_t model[41];     ///< Model in string.
  } ide_device_t;
  
  /// @brief
  typedef struct partition_t{
      uint8_t status;              ///<
      uint8_t chs_first_sector[3]; ///<
      uint8_t type;                ///<
      uint8_t chs_last_sector[3];  ///<
      uint32_t lba_first_sector;   ///<
      uint32_t sector_count;       ///<
  } partition_t;
  
  typedef struct ata_identify_t{
      uint16_t flags;
      uint16_t unused1[9];
      char serial[20];
      uint16_t unused2[3];
      char firmware[8];
      char model[40];
      uint16_t sectors_per_int;
      uint16_t unused3;
      uint16_t capabilities[2];
      uint16_t unused4[2];
      uint16_t valid_ext_data;
      uint16_t unused5[5];
      uint16_t size_of_rw_mult;
      uint32_t sectors_28;
      uint16_t unused6[38];
      uint64_t sectors_48;
      uint16_t unused7[152];
  } __attribute__((packed)) ata_identify_t;
  
  /// @brief Master Boot Record.
  typedef struct mbr_t{
      uint8_t boostrap[446];
      partition_t partitions[4];
      uint8_t signature[2];
  } __attribute__((packed)) mbr_t;
  
  int ata_initialize();
  
  int ata_finalize();
  
  ///! @endcond