#pragma once

/*
TODO:
ещё нужен класс, в котором будут диалоги создания нового образа винчестера,
выбора монтируемого образа винчестера.
*/

// флаг реализации модели с выполнением в потоке
#define THREADED_MODEL 0

#if (THREADED_MODEL)
#include <thread>
#include <mutex>
#include <condition_variable>
#endif // THREADED_MODEL

#include "Config.h"

enum class HDD_REGISTER : int
{
	H1F0 = 0,
	H1F1,
	H1F2,
	H1F3,
	H1F4,
	H1F5,
	H1F6,
	H1F7,
	H3F6,
	H3F7
};

struct HDDREG
{
	//  Регистр данных (1F0 чтение/запись)
	uint16_t data;
	//  Регистр ошибок (1F1 чтение) определяет состояние НЖМД после выполнения операции. Состояние
	//  этого регистра действительно:
	//  - после выполнения команды, если установлен бит «Error» в регистре состояния;
	//  - после выполнения команды «Диагностика» или после выполнения внутренней диагностики НЖМД по
	//      системному сбросу.
	//      В диагностическом режиме коды регистра ошибок определяют следующее:
	//      01H - нет ошибки;
	//      02H - ошибка микроконтроллера;
	//      03H - ошибка буферного ОЗУ;
	//      04H - ошибка аппаратуры ECC;
	//      05H - ошибка микропроцессора
	//      8XH - НЖМД неисправен.
	//      Значения битов регистра ошибок после выполнения команды:
	//      7   6   5 4    3 2    1    0
	//      BBK UNC 0 IDNF 0 ABRT TONF AMNF
	//      Бит 0 - Data Adres Mark Not Found - устанавливаются во время выполнения команды «Чтение сектора»,
	//      если адресный маркер данных соответствующего сектора не найден после правильного нахождения
	//      идентификатора этого сектора.
	//      Бит 1 - Track 0 Not Found - устанавливается только в команде
	//      «Рекалибровка», если после 2048-и шагов не обнаружена дорожка 0.
	//      Бит 2 - Aborted Command - устанавливается при получении из НЖМД состояния «Write fault», «Not seek
	//      complete», «Drive not ready» или когда была загружена недействительная команда. Причина ошибки может
	//      быть определена при помощи регистров состояния и ошибки.
	//      Бит 3 - не используется (равен 0).
	//      Бит 4 - ID Not Found - требуемый цилиндр, головка, сектор не могут быть обнаружены или же произошла
	//      ошибка ECC в поле идентификатора.
	//      Бит 5 - не используется (равен 0).
	//      Бит 6 - Uncorrect Data - ошибка ECC в поле данных. Устанавливается в случае некорректируемой ошибки.
	//      Бит 7 - Bad Mark Block - в идентификаторе обнаружена метка дефектного сектора.
	uint16_t error; // по чтению
	uint16_t features; // по записи
	//  Регистр счётчик секторов (1F2 чтение/запись)
	uint16_t count;
	//  Регистр номер сектора (1F3 чтение/запись)
	uint16_t sector; // LBA 7..0
	//  Регистр номер цилиндра мл. (1F4 чтение/запись)
	uint16_t cyl_lo; // LBA 15..8
	//  Регистр номер цилиндра ст. (1F5 чтение/запись)
	uint16_t cyl_hi; // LBA 23..16

	// формат регистра 1f6
	//  Регистр выбора НЖМД / номера головки (1F6 чтение/запись) имеет следующий вид:
	//  7   6   5 4   3   2   1   0
	//      LBA 1 DRV HS3 HS2 HS1 HS0
	//      Биты 0 - 3 - двоичный код выбранной головки,
	//      Бит 4 - выбор НЖМД, DRV = 0 выбран НЖМД 0,
	//      DRV = 1 выбран НЖМД 1.
	//  бит 7 Extended data field for ECC
	//  биты 5-6: Used to be sector size.  00=256,01=512,10=1024,11=128
	//   Since 512 was always used, bit 6 was taken to mean LBA mode:
	//     b6 1=LBA mode, 0=CHS mode
	//     b5 1
	uint16_t head; // LBA 27..24 - вместо номера головки

	//  Регистр состояния (1F7 чтение) отображает текущее состояние НЖМД IDE AT. Значение этого регистра
	//      обновляется после выполнения каждой команды. Если установлен бит BSY этого регистра, то любые обращения
	//      к НЖМД запрещены и значения остальных битов регистра состояния недействительны. Чтение этого регистра
	//      сбрасывает аппаратное прерывание IRQ14. Значения битов регистра состояния:
	//      7   6    5   4   3   2    1   0
	//      BSY DRDY WFT DSC DRQ CORR INX ERR
	//      Бит 0 - Error - индицирует, что предыдущая команда закончилась с ошибкой и что один или несколько
	//      битов установлены в регистре ошибок. Используется для быстрой проверки успешного завершения команды.
	//      Сбрасывается, когда в регистр команд засылается новая команда.
	//      Бит 1 - Index - этот бит устанавливается в 1 при каждом обороте магнитного диска. В современных
	//      моделях НЖМД не используется.
	//      Бит 2 - Corrected Data - индицирует, что при считывании с диска данных произошла ошибка, которая
	//      была успешно скорректирована аппаратурой КЦК. Корректируемые ошибки не прекращают мультисекторную
	//      передачу.
	//      Бит 3 - Data Request - этот бит показывает , что имеется запрос на обмен данными с буфером сектора при
	//      выполнении команд чтения/записи. По этому запросу необходимо прочитать буфер или переслать данные в
	//      буфер, в зависимости от выполняемой команды.
	//      Бит 4 - Drive Seek Complete - индицирует, что головки чтения/записи завершили операцию поиска.
	//      Бит 5 - Write Fault - индицирует неисправность в накопителе или попытку выполнить команду запись
	//      с некорректными параметрами.
	//      Бит 6 - Drive Ready - установленный в 1 означает готовность НЖМД к выполнению команды.
	//      Бит 7 - Busy - определяет состояние НЖМД IDE AT. Устанавливается в 1 во время выполнения команды
	//      или диагностики НЖМД после системного сброса. Когда этот бит установлен, никакие другие биты регистра
	//      состояния не являются действительными. Бит Busy должен быть проверен перед чтением любого регистра
	//      состояния.
	uint16_t status; // по чтению
	uint16_t command; // по записи

	//  Регистр состояния устройства (3F6 запись) содержит три управляющих бита.
	//      7 6 5 4 3     2    1    0
	//              HS3EN SRST /IEN
	//      Бит 1 - Interrupt Enable - бит разрешения прерывания для НЖМД к HOST. Когда этот бит активен и
	//      накопитель выбран, HOST прерывается. Сигнал HOST IRQ14 должен быть разрешён через 3 - стабильный
	//      буфер. Когда этот бит не активен или НЖМД не выбран, сигнал HOST IRQ14 будет иметь высокий уровень.
	//      Бит 2 - Soft Reset - программный бит сброса. Накопитель выполняет сброс, когда этот бит в состоянии
	//      высокого уровня.
	//      Бит 3 - Heads 3 Enable - используется для разрешения выбора головок с 8 по 15.
	uint16_t control; // по записи

	//  Регистр адреса накопителя (3F7 чтение) содержит номер головки и НЖМД, выбранные в предыдущей
	//      операции.
	//      7 6  5    4    3    2    1    0
	//        WG /HS3 /HS2 /HS1 /HS0 /DS1 /DS0
	//      Биты 0, 1 - /DS0, /DS1 - биты выбора соответствующего накопителя 0 или 1.
	//      Биты 2...5 - /HS0.../HS3 - содержат двоичный код выбранной головки.
	//      Бит 6 - Write Gate - бит выполнения записи, активен во время операции записи
	uint16_t addr;

	void clear()
	{
		memset(this, 0, sizeof(HDDREG));
	}
	void unset()
	{
		memset(this, 0xff, sizeof(HDDREG));
	}
};



class CHDD
{
		CFile m_fHDDImageFile;      // файл образа
		CString m_strImageFileName; // имя файла образа
		uint16_t m_nDeviceID;       // статус - master/slave ( ==0 - master ==0x10 - slave)
		bool m_bReadOnly;           // если у файла образа атрибут RO, то образ будет доступен только по чтению.

		bool m_bChangeBuffer;       // флаг, что данные в буфере изменены, и его надо записать на диск
		USector m_pSectorBuffer;    // указатель на буфер куда читается текущий сектор

		/* геометрия винта*/
		int m_nCylinders;
		int m_nHeads;
		int m_nSectors;
		int m_nHDDSize;             // == m_nCylinders * m_nHeads * m_nSectors
		int m_nSectorPosition;      // позиция в файле сектора, который надо прочитать/записать в/из буфер(а)
		int m_nSectIdx_Word;        // позиция в секторе в словах

#if (THREADED_MODEL)
		void                StopExecuteThread();
		bool                StartExecuteThread();
		void                ExecuteThreadFunc();    // собственно функция
		std::thread         m_ExecuteThread;
		bool                m_bThreadTerminate;   // флаг завершения потока
		bool                m_bNotify;  // флаг от ложных пробуждений потока
		std::mutex          m_mutThr;   // мутекс потока. залочен пока поток живой
		std::mutex          m_mutex;    // мутекс для синхронизации
		std::condition_variable m_cv;   // условная переменная, чтоб будить поток, когда надо
#endif // THREADED_MODEL

		int                 m_nSectorCounter;  // т.к. 0 в регистре 1f2 означает 256 секторов, то чтобы такое работало
		// добавим рабочую переменную. в которой будут значения 1..256, а 0 - означает что секторы закончились

		HDDREG m_reg;

		enum class HDD_IDE_PHASE : int
		{
			FAILURE = - 1,
			READY = 0,
			PIO_OUT,
			PIO_IN
		};

		HDD_IDE_PHASE m_nPhase;

		// биты регистра 1f1 по чтению

		enum HDD_ERROR : uint16_t
		{
			ERR_BBK = 0x80,
			ERR_UNC = 0x40,
			ERR_MC = 0x20,
			ERR_IDNF = 0x10,
			ERR_MCR = 0x08,
			ERR_ABRT = 0x04,
			ERR_TK0NF = 0x02,
			ERR_AMNF = 0x01
		};

		// биты регистра 1f7 по чтению и 3f6 по чтению

		enum HDD_STATUS : uint16_t
		{
			BSY = 0x80,  // Busy - определяет состояние НЖМД IDE AT
			DRDY = 0x40, // Drive Ready - установленный в 1 означает готовность НЖМД к выполнению команды.
			DWF = 0x20,  // Write Fault - индицирует неисправность в накопителе или попытку выполнить команду запись с некорректными параметрами.
			DSC = 0x10,  // Drive Seek Complete - индицирует, что головки чтения/записи завершили операцию поиска.
			DRQ = 0x08,  // Data Request - этот бит показывает , что имеется запрос на обмен данными с буфером сектора
			CORR = 0x04, // Corrected Data - индицирует, что при считывании с диска данных произошла ошибка которая была скорректирована
			IDX = 0x02,  // Index - этот бит устанавливается в 1 при каждом обороте магнитного диска. В современных моделях не используется
			ERR = 0x01   // Error - индицирует, что предыдущая команда закончилась с ошибкой
		};

		// биты регистра 3f6 по записи

		enum HDD_CONTROL : uint16_t
		{
			CONTROL_SRST = 0x04,
			CONTROL_nIEN = 0x02
		};
		// биты регистра 3f7 по чтению

		enum HDD_DRIVEADDR : uint16_t
		{
			HDD_DRVADDR_DS0 = 0x01,
			HDD_DRVADDR_DS1 = 0x02,
			HDD_DRVADDR_HS = 0x3c,
			HDD_DRVADDR_WG = 0x40
		};

		// биты регистра 1f6 по записи

		enum HDD_IDE_HEADREG : uint16_t
		{
			HEAD = 0x0f,
			DEV = 0x10,
			LBA = 0x40
		};

		enum class IDE_CMD : uint16_t
		{
			// команды которые будут выдавать command_ok
			NOP = 0x00,
			IDLE = 0xe3,
			IDLE_IMMEDIATE = 0xe1,
			RECALIBRATE = 0x10,
			FORMAT_TRACK = 0x50,
			SEEK = 0x70,
			SLEEP = 0xe6,
			STANDBY = 0xe2,
			STANBY_IMMEDIATE = 0xe0,
			// команды, которые должны обрабатываться обработчиком
			READ_SECTOR_RETRY = 0x20,
			READ_SECTOR_NORETRY = 0x21,
			READ_LONG_SECTOR_RETRY = 0x22,
			READ_LONG_SECTOR_NORETRY = 0x23,
			WRITE_SECTOR_RETRY = 0x30,
			WRITE_SECTOR_NORETRY = 0x31,
			WRITE_LONG_SECTOR_RETRY = 0x32,
			WRITE_LONG_SECTOR_NORETRY = 0x33,
			READ_VERIFY_SECTOR_RETRY = 0x40,
			READ_VERIFY_SECTOR_NORETRY = 0x41,
			WRITE_VERIFY_SECTOR = 0x3c,
			WRITE_SAME = 0xe9,
			READ_BUFFER = 0xe4,
			WRITE_BUFFER = 0xe8,
			IDENTIFY_DEVICE = 0xec,
			EXECUTE_DEVICE_DIAGNOSTICS = 0x90,
			DEVICE_RESET = 0x08,
			INITIALIZE_DEVICE_PARAMETERS = 0x91
		};

		// bool  m_bDiagsCmd;    // команда, после которой регистр ошибок пригоден
		bool read_file();
		bool write_file();
		bool seek();
		void readsector(bool bVerify);
		void writesector();
		void command_ok();
		void execute_command(IDE_CMD cmd);
		void int_init();
		void reset_signature(bool reset_hard);
		bool identifydevice();
	public:
		CHDD(const CString &name, HDD_MODE mode);
		CHDD();
		virtual ~CHDD();
		bool attach_hdd(const CString &name, HDD_MODE mode);
		void detach_hdd();
		bool is_attached() const;
		void reset(bool reset_hard);
		bool configure();
		void write_regs(HDD_REGISTER reg, uint16_t data);
		uint16_t read_regs(HDD_REGISTER reg);
		void write_data(uint16_t data);
		uint16_t read_data();

		void read_verify_sector();

		uint16_t get_debug_regs(HDD_REGISTER reg, bool bReadMode) const;
};

class CATA_IDE
{
		// на один канал вешается 2 винта
		CHDD m_mDrive[2];
	public:
		bool attach(const CString &name, HDD_MODE mode = HDD_MODE::MASTER);
		void detach(HDD_MODE mode = HDD_MODE::MASTER);
		void reset();
		void write_regs(HDD_REGISTER reg, uint16_t data);
		uint16_t read_regs(HDD_REGISTER reg);
		uint16_t read_regs_internal(HDD_REGISTER reg) const;

		uint16_t get_debug_regs(int nDrive, HDD_REGISTER reg, bool bReadMode) const;
};

/*
HDD_IDE_COMMAND_READ_SECTOR_RETRY = 0x20
HDD_IDE_COMMAND_READ_SECTOR_NORETRY = 0x21
Эта команда читает от 1 до 256 секторов, как задано в регистре Sector Count.
Значение 0 означает читать 256 секторов. Передача начинается с сектора, заданного
в регистре Sector Number. See 10.1 for the DRQ, IRQ, and BSY protocol on data transfers.

HDD_IDE_COMMAND_READ_LONG_SECTOR_RETRY = 0x22,
HDD_IDE_COMMAND_READ_LONG_SECTOR_NORETRY = 0x23
То же самое что и READ_SECTOR, но ещё возвращает ECC, заданные в полях данных читаемых секторов

HDD_IDE_COMMAND_READ_VERIFY_SECTOR_RETRY = 0x40,
HDD_IDE_COMMAND_READ_VERIFY_SECTOR_NORETRY = 0x41
То же самое что и READ_SECTOR, но DRQ никогда не устанавливается и данные не передаются
хосту. Пока выполняется команда, устанавливается бит BSY.

HDD_IDE_COMMAND_WRITE_SECTOR_RETRY = 0x30,
HDD_IDE_COMMAND_WRITE_SECTOR_NORETRY = 0x31
Эта команда записывает от 1 до 256 секторов, как задано в регистре Sector Count.
Значение 0 означает читать 256 секторов. Передача начинается с сектора, заданного
в регистре Sector Number. See 10.1 for the DRQ, IRQ, and BSY protocol on data transfers.

HDD_IDE_COMMAND_WRITE_LONG_SECTOR_RETRY = 0x32,
HDD_IDE_COMMAND_WRITE_LONG_SECTOR_NORETRY = 0x33
То же самое, что и WRITE_SECTOR, но кроме данных ещё записываются ECC байты непосредственно
из буфера сектора. Винт сам не умеет генерировать ECC. Операция поддерживает запись только
одного сектора.

HDD_IDE_COMMAND_WRITE_VERIFY_SECTOR = 0x3c
То же самое, что и WRITE_SECTOR, но каждый записанный сектор проверяется сразу же после записи.
Все возникающие ошибки отображаются в регистрах.

HDD_IDE_COMMAND_WRITE_SAME = 0xe9
Подобна команде WRITE_SECTOR за исключением того, что передаётся только один сектор, содержимое
сектора записывается один или более раз.
если в регистре FeaturesReg 1f1 (по зап.) содержится 22h, то пишется столько раз, сколько указано
в регистрах кол-ва секторов, в то место, как указано в регистрах c/h/s
если в регистре FeaturesReg 1f1 (по зап.) содержится ddh, то привод запишет буфером всё доступное
пространство
если в регистре FeaturesReg 1f1 (по зап.) содержится любое другое значение команда отбрасывается
и устанавливается флаг ошибки

HDD_IDE_COMMAND_READ_BUFFER = 0xe4
Предпосылки
Бит DRDY, установленный в единицу. Командой, приоритетной перед командой READ BUFFER,
является команда WRITE BUFFER.
Команда READ BUFFER подготавливает хост к чтению текущего содержимого буфера сектора
устройства. Команды READ BUFFER и WRITE BUFFER будут синхронизированы так что
последующие команды WRITE BUFFER и READ BUFFER получают доступ к тем же 512 байтам в
рамках буфера.

HDD_IDE_COMMAND_WRITE_BUFFER = 0xe8
Эта команда позволяет хосту перезаписать содержимое буфера сектора винта любыми
желаемыми данными.

HDD_IDE_COMMAND_IDENTIFY_DEVICE = 0xec
Надо прочитать первый сектор с параметрами в буфер. и выставить DRQ

HDD_IDE_COMMAND_INITIALIZE_DEVICE_PARAMETERS = 0x91
This command enables the host to set the number of sectors per track and the
number of heads minus 1, per cylinder. Upon receipt of the command, the drive
sets BSY, saves the parameters, clears BSY, and generates an interrupt.
The only two register values used by this command are the Sector Count
Register which specifies the number of sectors per track, and the Drive/Head
Register which specifies the number of heads minus 1. The DRV bit designates
these values to Drive 0 or Drive 1, as appropriate.
The sector count and head values are not checked for validity by this command.
If they are invalid, no error will be posted until an illegal access is made
by some other command.


-------------------------------------------------------------
что должно выдать IDENTIFY DEVICE (ECh)
массив 256 слов, это полная спецификация, для БК тут нужна
от силы треть.
смещение    размер      значение
-------------------------------------------------------------
0           1           Основная конфигурация   (0x045A)
1           1           кол-во цилиндров
2           1           зарезервировано         (0xC837h)
3           1           кол-во головок
4           1           кол-во байт на дорожке (неформатированных)
5           1           кол-во байт в секторе  (неформатированных)
6           1           кол-во секторов на дорожке
7-8         2           Зарезервировано для использования ассоциацией компакт-флеш
9           1           Зарезервировано
10          10          Серийный номер (20 символов ASCII) (0 - не задано)
20          1           Тип буфера
21          1           Размер буфера делённый на 512 (0 - не определено)
22          1           Кол-во ECC байтов доступное при команда длинного чтения/записи
23          4           Версия прошивки (8 символов ASCII)
27          20          Имя модели (40 символов ASCII)
47          1           15-8 80h
                        7-0 00h = Зарезервировано
                        01h-FFh = Максимальное число секторов, которые могут
                        быть переданы за одно прерывание командами READ/WRITE MULTIPLE
48          1           0 - не может обмениваться DWORDами, 1 - может
49          1           Способности
                        15-14 Зарезервировано для команды IDENTIFY PACKET DEVICE.
                        13  1 = Значения таймера останова как описано в текущем Стандарте
                            0 = Значения таймера останова, управляемые устройством
                        12  Зарезервировано для команды IDENTIFY PACKET DEVICE.
                        11  1 = Поддерживается IORDY
                            0 = Может поддерживаться IORDY
                        10  1 = IORDY может быть отключено
                        9   1 = Поддерживается LBA
                        8   1 = Поддерживается DMA.
                        7-0 Отложены для вендоров
50          1           Способности
                        15 Будет очищен в нуль.
                        14 Будет выставлен в единицу.
                        13-2 Зарезервированы.
                        1 Устарел
                        0 Будет установлен в единицу для отображения характерного для устройства
                        минимального значения таймера останова.
51          1           15-8 PIO data transfer cycle timing mode
                        7-0 Vendor unique
52          1           15-8 DMA data transfer cycle timing mode
                        7-0 Vendor unique
53          1           15-3 Зарезервировано
                        2   1 = поля, сообщённые в слове 88, пригодны
                            0 = поля, сообщённые в слове 88, непригодны
                        1   1 = поля, сообщённые в словах 64-70, пригодны
                            0 = поля, сообщённые в словах 64-70, непригодны
                        0   1 = поля, сообщённые в словах 54-58, пригодны
                            0 = поля, сообщённые в словах 54-58, непригодны
54          1           Number of current cylinders
55          1           Number of current heads
56          1           Number of current sectors per track
57-58       2           Current capacity in sectors
59          1           15–9 Зарезервировано
                        8   1 = Свойства блочного сектора пригодны
                        7-0 XXh = Текущие настройки количества секторов которое может быть передано за
                        прерывание командой блочного чтения или записи
60-61       2           Общее число секторов, доступных для пользователя
62          1           15-8 Single word DMA transfer mode active
                        7-0 Single word DMA transfer modes supported (устарело)
63          1           15-11 Reserved
                        10  1 = Multiword DMA mode 2 is selected
                            0 = Multiword DMA mode 2 is not selected
                        9   1 = Multiword DMA mode 1 is selected
                            0 = Multiword DMA mode 1 is not selected
                        8   1 = Multiword DMA mode 0 is selected
                            0 = Multiword DMA mode 0 is not selected
                        7-3 Reserved
                        2   1 = Multiword DMA mode 2 and below are supported
                        1   1 = Multiword DMA mode 1 and below are supported
                        0   1 = Multiword DMA mode 0 is supported
64          1           15-8 Зарезервировано
                        7-0 Поддерживаемые режимы PIO
65          1           Минимальное время цикла передачи Multiword DMA на слово
                        15-0 Время цикла в наносекундах
66          1           Рекомендованное производителем минимальное время цикла передачи Multiword DMA
                        15-0 Время цикла в наносекундах
67          1           Минимальное время цикла передачи РIO без контроля потока
                        15-0 Время цикла в наносекундах
68          1           Минимальное время цикла передачи PIO с контролем потока IORDY
                        15-0 Время цикла в наносекундах
69-70       2           Зарезервировано (для будущих команд наложения и очереди)
71-74       4           Зарезервировано для команды IDENTIFY PACKET DEVICE
75          1           Величина очереди
                        15-5 Зарезервировано
                        4-0 Максимальная величина очереди – 1
76-79       4           Зарезервировано
80          1           Старший номер [поддерживаемой] версии Стандарта
                        0000h или FFFFh = устройство не сообщило версии
                        15  Зарезервировано
                        14  Зарезервировано для ATA/ATAPI-14
                        13  Зарезервировано для ATA/ATAPI-13
                        12  Зарезервировано для ATA/ATAPI-12
                        11  Зарезервировано для ATA/ATAPI-11
                        10  Зарезервировано для ATA/ATAPI-10
                        9   Зарезервировано для ATA/ATAPI-9
                        8   Зарезервировано для ATA/ATAPI-8
                        7   1 = Поддерживается Стандарт ATA/ATAPI-7
                        6   1 = Поддерживается Стандарт ATA/ATAPI-6
                        5   1 = Поддерживается Стандарт ATA/ATAPI-5
                        4   1 = Поддерживается Стандарт ATA/ATAPI-4
                        3   1 = Поддерживается Стандарт ATA-3
                        2   1 = Поддерживается Стандарт ATA-2
                        1   Устарел
                        0   Зарезервирован
81          1           Младший номер [поддерживаемой] версии Стандарта
                        0000h или FFFFh = устройство не сообщило о версии
                        0001h-FFFEh = см. п. 8.16.41 (там много всякого)
82          1           Поддерживаемые наборы команд
                        15  Устарел
                        14  1 = Поддерживается команда NOP
                        13  1 = Команда READ BUFFER поддерживается
                        12  1 = Поддерживается команда WRITE BUFFER
                        11  Устарел
                        10  1 = Поддерживается набор функций Область, защищённая хостом
                        9   1 = Поддерживается команда DEVICE RESET
                        8   1 = Поддерживается прерывание SERVICE
                        7   1 = Поддерживается прерывание выпуска
                        6   1 = Поддерживается предвыборка
                        5   1 = Поддерживается кэш записи
                        4   Будет очищен в нуль для отображения того, что пакетные команда не
                        поддерживаются
                        3   1 = Поддерживается управление питанием
                        2   1 = Поддерживается набор функций Сменные носители
                        1   1 = Поддерживается защищённый режим
                        0   1 = Поддерживается ТСОУ
83          1           Поддерживаемые наборы команд
                        15  Будет очищен в нуль
                        14  Будет установлен в единицу
                        13  1 = Поддерживается команда FLUSH CACHE EXT
                        12  1 = Поддерживается команда FLUSH CACHE
                        11  1 = Поддерживается набор функций Оверлей конфигурации устройства
                        10  1 = Поддерживается 48-битная адресация
                        9   1 = Поддерживается автоматическое управление звуком
                        8   1 = Поддерживается расширение защиты SET MAX
                        7   Зарезервировано для проекта 407DT Загрузка по смещению адреса
                            зарезервированной области.
                        6   1 = Для запуска двигателя после подачи питания требуется подкоманда SET
                                FEATURES
                        5   1 = Поддерживается включение в режиме останова
                        4   1 = Поддерживается Оповещение о статусе сменных носителей
                        3   1 = Поддерживается Расширенное управление питанием
                        2   1 = Поддерживается набор функций Контакт-флеш
                        1   1 = Поддерживается READ/WRITE DMA QUEUED
                        0   1 = Поддерживается команда DOWNLOAD MICROCODE
84          1           Поддерживаемые расширения команд/наборов функций
                        15  Будет очищено в нуль
                        14  Будет установлено в единицу
                        13-6 Зарезервировано
                        5   1 = Поддерживается Протоколирование основных событий
                        4   1 = Поддерживается набор функций потоков
                        3   1 = Поддерживается набор функций Команды карт Media Card Pass Through
                        2   1 = Поддерживается серийный номер пластин
                        1   1 = Поддерживается самотест ТСОУ
                        0   1 = Поддерживается протоколирование ошибок ТСОУ
85          1           Задействованные наборы функций/команды
                        15  Устарел
                        14  1 = Команда NOP включена
                        13  1 = Задействована команда READ BUFFER
                        12  1 = Задействована команда WRITE BUFFER
                        11  Устарел
                        10  1 = Задействован набор функций Область, защищённая хостом.
                        9   1 = Задействована команда DEVICE RESET
                        8   1 = Задействовано прерывание SERVICE
                        7   1 = Задействовано отложенное прерывание
                        6   1 = Задействована предвыборка
                        5   1 = Задействован кэш записи
                        4   Будет очищено в нуль для показа того, что пакетные команды не
                            поддерживаются.
                        3   1 = Задействован набор функций автоматического управления питанием
                        2   1 = Задействован набор функций сменных носителей.
                        1   1 = Задействован набор функций защиты
                        0   1 = Задействован набор функций ТСОУ
86          1           Задействованные наборы команд/функции
                        15-14 Зарезервировано
                        13  1 = Команда FLUSH CACHE EXT поддерживается
                        12  1 = Поддерживается команда FLUSH CACHE
                        11  1 = Поддерживается Оверлей конфигурации устройства
                        10  1 = Поддерживается 48-битная адресация
                        9   1 = Включено автоматическое управление акустикой
                        8   1 = Расширение защиты SET MAX включено командой SET MAX SET
                                PASSWORD
                        7   Зарезервировано для проекта 1407DT Загрузка по смещению адреса
                            зарезервированной области.
                        6   1 = Для раскручивания шпинделя после подачи питания требуется
                                подкоманда SET FEATURES
                        5   1 = Задействовано включение в режиме останова.
                        4   1 = Задействован режим Оповещение о состоянии сменных носителей.
                        3   1 = Задействованы функции расширенного управления питанием.
                        2   1 = Задействован набор функций Компакт-флеш
                        1   1 = Поддерживаются команды READ/WRITE DMA QUEUED
                        0   1 = Поддерживается команда DOWNLOAD MICROCODE
87          1           Набор команд/функций по умолчанию
                        15  Будет очищен в нуль
                        14  Будет установлен в единицу
                        13-6 Зарезервировано
                        5   Поддерживается Основная функция протоколирования
                        4   1 = Была выполнена пригодная команда CONFIGURE STREAM
                        3   1 = Задействованы функции Команд карт Media Card Pass Through
                        2   1 = Серийный номер пластины пригоден
                        1   1 = SMART self-test supported
                        0   1 = SMART error logging supported
88          1           5-14 Зарезервировано
                        13  1 = Выбран режим Ultra DMA 5
                            0 = Не выбран режим Ultra DMA 5
                        12  1 = Выбран режим Ultra DMA 4
                            0 = Не выбран режим Ultra DMA 4
                        11  1 = Выбран режим Ultra DMA 3
                            0 = Не выбран режим Ultra DMA 3
                        10  1 = Выбран режим Ultra DMA 2
                            0 = Не выбран режим Ultra DMA 2
                        9   1 = Выбран режим Ultra DMA 1
                            0 = Не выбран режим Ultra DMA 1
                        8   1 = Выбран режим Ultra DMA 0
                            0 = Не выбран режим Ultra DMA 0
                        7-6 Зарезервировано
                        5   1 = Поддерживается режим Ultra DMA 5 и ниже
                        4   1 = Поддерживается режим Ultra DMA 4 и ниже
                        3   1 = Поддерживается режим Ultra DMA 3 и ниже
                        2   1 = Поддерживается режим Ultra DMA 2 и ниже
                        1   1 = Поддерживается режим Ultra DMA 1 и ниже
                        0   1 = Поддерживается режим Ultra DMA 0
89          1           Время, необходимое для завершения очистки устройства в режиме защиты.
90          1           Время, необходимое для завершения расширенной очистки в режиме защиты.
91          1           Текущее расширенное значение управления электропитанием
92          1           Код версии супер-пароля
93          1           Результат аппаратного сброса. Содержимое битов 12 – 0 этого слова будет меняться
                        только в процессе исполнения аппаратного сброса.
                        15  Будет очищено в нуль.
                        14  Будет установлено в единицу.
                        13  1 = Устройством обнаружен сигнал CBLID- над ViH
                            0 = Устройством обнаружен сигнал CBLID- под ViL
                        12-8 Результат аппаратного сброса устройства 1. Устройство 0 очистит эти биты в нуль.
                            Устройство 1 установит эти биты как показано ниже:
                        12  Зарезервировано.
                        11  0 = Устройство 1 не выставило сигнал PDIAG-.
                            1 = Устройством 1 выставлен сигнал PDIAG-.
                        10-9 Эти биты указывают, как устройство 1 определяет номер устройства.
                            00 = Зарезервировано.
                            01 = Использована перемычка.
                            10 = Использован сигнал CSEL.
                            11 = Использован любой другой метод, или метод не известен.
                        8   Будет установлено в единицу.
                        7-0 Результат аппаратного сброса устройства 0. Устройство 1 очистит эти биты в ноль.
                            Устройство 0 установит эти биты как указано ниже:
                        7   Зарезервировано.
                        6   0 = Устройство 0 не будет отвечать если выбрано устройство 1
                            1 = Устройство 0 будет отвечать если выбрано устройство 1.
                        5   0 = Устройство 0 не определяет выставление сигнала DASP-.
                            1 = Устройство 0 определяет выставление сигнала DASP-.
                        4   0 = Устройство 0 не определяет выставление сигнала PDIAG-.
                            1 = Устройство 0 определяет выставление сигнала PDIAG-.
                        3   0 = Устройство 0 не прошло диагностику.
                            1 = Устройство 0 прошло диагностику.
                        2-1 Эти биты указывают, как устройством 0 определяется его номер.
                            00 = Зарезервировано.
                            01 = Использована перемычка.
                            10 = Использован сигнал CSEL.
                            11 = Использован какой-то другой метод, или метод неизвестен.
                        0   Будет установлен в единицу.
94          1           15-8 Рекомендованное производителем значение управления шумом
                        7-0 Текущее значение управления шумом.
95          1           Минимальный размер запроса потока
96          1           Время передачи потока
97          1           Латентность доступа потока
98-99       2           Степень детализации выполнения потока
100-103     4           Максимальный адрес LBA пользовательской зоны для 48-битной LBA.
104-126     23          Зарезервировано
127         1           Поддержка набора функций Оповещение о статусе сменных носителей
                        15-2 Зарезервировано
                        1-0 00 = Набор функций не поддерживается
                            01 = Набор функций поддерживается
                            10 = Зарезервировано
                            11 = Зарезервировано
128         1           Статус защиты
                        15-9 Зарезервировано
                        8   Уровень защиты 0 = высокий, 1 = максимальный
                        7-6 Зарезервировано
                        5   1 = Расширенное стирание устройства в режиме защиты поддерживается
                        4   1 = Счётчик защиты заполнен
                        3   1 = Защита заморожена
                        2   1 = Защита заблокирована
                        1   1 = Защита включена
                        0   1 = Защита поддерживается
129-159     31          Зависит от производителя
160         1           Режим питания компакт-флеш 1
                        15  Слово 160 поддерживается
                        14  Зарезервировано
                        13  Режим питания компакт-флеш 1 требуется для выполнения одной или больше
                            команд устройства.
                        12  Режим питания компакт-флеш 1 отключён
                        11-0 Текущий максимум, в миллиамперах
161-175     15          Зарезервировано для использования ассоциацией компакт-флеш
176-205     30          Серийный номер текущей пластины
206-254     49          Зарезервировано
255         1           Слово целостности
                        15-8 Контрольная сумма
                        7-0 Сигнатура

--------------------------------------------------------------------
Работа регистров

1f0 чт./зап.
Этот регистр будет доступен для передачи данных с использованием протокола
PIO хостом только если бит DRQ установлен в единицу и сигнал DMACK- не выставлен.

1f1 чт.
Содержимое этого регистра будет пригодным, если биты BSY и DRQ равны нулю и бит ERR равен
единице. Содержимое этого регистра будет пригодно на момент выполнения включения, или после
программного или аппаратного сброса, или после выполнения команд EXECUTE DEVICE
DIAGNOSTICS (90h) или DEVICE RESET (08h).
1f1 зап.
Этот регистр может быть записан, только если биты BSY и DRQ равны нулю и не выставлен сигнал
DMACK-.

1f2 чт./зап.
Этот регистр может быть записан только если оба бита BSY и DRQ очищены в нуль и не выставлен
сигнал DMACK-. Содержимое этого регистра пригодно только когда бит BSY очищен в нуль.

1f3 чт./зап. (LBA low)
Этот регистр может быть записан только если оба бита BSY и DRQ очищены в нуль и не выставлен
сигнал DMACK-. Содержимое этого регистра пригодно только когда бит BSY очищен в нуль.

1f4 чт./зап. (LBA mid)
Этот регистр может быть записан только если оба бита BSY и DRQ очищены в нуль и не выставлен
сигнал DMACK-. Содержимое этого регистра пригодно только когда бит BSY очищен в нуль.

1f5 чт./зап. (LBA high)
Этот регистр может быть записан только если оба бита BSY и DRQ очищены в нуль и не выставлен
сигнал DMACK-. Содержимое этого регистра пригодно только когда бит BSY очищен в нуль.

1f6 чт./зап.
Запись возможна только если BSY & DRQ == 0, и не выставлен сигнал DMACK-
Содержимое этого регистра пригодно только если бит BSY очищен в нуль.
Если этот регистр записывается, когда биты BSY или DRQ установлены в
единицу, результат не определяется.
Бит DEV становится эффективен, если этот регистр записывается хостом или устройством
устанавливается сигнатура для хоста. Все другие биты этого регистра становятся параметрами
команды, если записывается регистр команды.

1f7 чт.
Содержимое этого регистра, за исключением бита BSY, будет игнорироваться, если BSY установлен
в единицу. BSY пригоден в любое время.
1f7 зап.
Запись возможна только если BSY & DRQ == 0, и не выставлен сигнал DMACK-
кроме команды DEVICE RESET
Если записывается, когда BSY или DRQ установлены в единицу, результаты
записи регистра команд не определяются, за исключением команды DEVICE RESET.

3f6 чт.
Если выставлен BSY, то другие биты не используются
3f6 зап.
Этот регистр может быть записан только если не выставлен сигнал DMACK-.


*/
