;Пpоцедуpы чтения/записи MBR чеpез поpты I/O
;────────────────────────────────────────────────────────────────────────────
;Copyright (c) 96-1998 Black Harmer
;Version 1.0
;────────────────────────────────────────────────────────────────────────────
;CALLNAME: read_mbr_via_port
;Описание: Пpоцедуpа читает MBR используя поpты ввода/вывода
;Вход:     ES:[DI] - куда положить пpочитанный MBR
;Выход:    Hепpеменим
;────────────────────────────────────────────────────────────────────────────
;CALLNAME: write_mbr_via_port
;Описание: Пpоцедуpа записывает MBR используя поpты ввода/вывода
;Вход:     DS:[SI] - ваш MBR
;Выход:    Hепpеменим
;────────────────────────────────────────────────────────────────────────────
;
;            Контроллер жестких дисков для АТ-подобных ПЭВМ
;
;      IBM PC  AT отличается от  всех предыдущих моделей  IBM PC и
; совместимых ПЭВМ в следующем:
;
;      -  стандартный BIOS  обеспечивает возможность  работы как с
; накопителями на гибких, так и с накопителями на жестких дисках;
;
;      - контроллеры жестких и  гибких дисков расположены на одной
; плате;
;
;      -  адреса портов  ввода-вывода, предназначенных  для управ-
; ления жестким  диском, и назначение  портов полностью отличаются
; от ХТ-подобных ПЭВМ.
;
;      Возможно  подключение к  одному ПЭВМ  двух жестких  дисков.
; Каждый  диск имеет  свой набор  портов (1F0h-1F7h  для первого и
; 170h-177h для второго). Ниже  будут описаны порты только первого
; диска. Назначение портов второго диска аналогично первому.
;
;                   Описание портов ввода-вывода
;
;      Порт 1F0h
;      Предназначен   для   обмена   данными   с   внутренним  ОЗУ
; контроллера,  являющимся промежуточным  звеном между оперативной
; памятью ПЭВМ и накопителем.
;
;      Порт 1F1h.
;      При  чтении через  этот  порт  можно получить  информацию о
; последней возникшей ошибке:
;
;   7   6   5   4   3   2   1   0
; ┌───┬───┬───┬───┬───┬───┬───┬───┐
; │   │   │ 0 │   │ 0 │   │   │   │ Бит:
; └─┬─┴─┬─┴───┴─┬─┴───┴─┬─┴─┬─┴─┬─┘ ────
;   │   │       │       │   │   └─>0: 1=адресный маркер  данных не
;   │   │       │       │   │           найден
;   │   │       │       │   └─────>1: 1=ошибка на нулевой  дорожке
;   │   │       │       └─────────>2: 1=выполнение команды прекра-
;   │   │       │                     щено  программно,  команда
;   │   │       │                     не завершилась
;   │   │       └─────────────────>4: 1=идентификатор  сектора  не
;   │   │                             найден
;   │   └─────────────────────────>6: 1=неисправимая ошибка в дан-
;   │                                 ных,  ошибка   контрольной
;   │                                 суммы
;   └─────────────────────────────>7: 1=дефектный сектор
;
;      Порт 1F2h.
;      Чтение/запись числа секторов для последующей операции.
;
;      Порт 1F3h.
;      Чтение/запись параметра "номер  сектора" для последующей
;      операции.
;
;      Порт 1F4h.
;      Чтение/запись старших битов номера цилиндра для последующей
;      операции  (биты 0  - 1  - это  биты 8  - 9  в 10-битовом  номере
;      цилиндра).
;
;      Порт 1F5h.
;      Чтение/запись  младших  восьми  битов  номера  цилиндра для
;      последующей операции.
;
;      Порт 1F6h.
;      Чтение/запись номера  устройства и головки  для последующей
;      операции.
;
;            bit 7 = 1
;            bit 6 = 0
;            bit 5 = 1
;            bit 4 = 0  выбор диска 0
;                  = 1  выбор диска 1
;            bit 3-0    бит выбора головки
;
;     Порт 1F7h (запись).
;     Вывод команды по управлению накопителем.
;
;     Порт 1F7h (чтение).
;     Чтение состояния накопителя и результатов предыдущей команды:
;
;   7   6   5   4   3   2   1   0
; ┌───┬───┬───┬───┬───┬───┬───┬───┐
; │   │   │   │   │   │   │   │   │ Бит:
; └─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┘ ────
;   │   │   │   │   │   │   │   └─>0: 1=предыдущая команда  завер-
;   │   │   │   │   │   │   │         шилась с ошибкой
;   │   │   │   │   │   │   └─────>1: 1=сигнал "индекс"
;   │   │   │   │   │   └─────────>2: 1=данные при выполнении пос-
;   │   │   │   │   │                 ледней операции были скор-
;   │   │   │   │   │                 ректированы   при   помощи
;   │   │   │   │   │                 алгоритма ECC
;   │   │   │   │   └─────────────>3: 1=идет процесс обмена данными (буфер сектора нуждается в обработке)
;   │   │   │   └─────────────────>4: 1=поиск завершен
;   │   │   └─────────────────────>5: 1=ошибка записи
;   │   └─────────────────────────>6: 1=устройство готово для чте-
;   │                                 ния, записи или поиска
;   └─────────────────────────────>7: 1=устройство занято выполне-
;                                     нием  команды  ( остальные
;                                     биты  не  несут  смысловой
;                                     нагрузки)
;
;      Система команд
;
;      Код  команды   заносится  в  порт  1F7h   после  того,  как
; подготовлены  все параметры  в  портах  1F2h -  1F6h. Выполнение
; команды  начинается  сразу  после  занесения  в  порт  1F7h кода
; команды.  Команда  состоит  из  одного  байта.  Старшие  4  бита
; содержат  код  требуемой  операции,  младшие содержат параметры.
; Перечень  команд с  возможными значениями  параметров приведен в
; таблице.
;
; ┌────────┬───────────────────────┬─────────────────────────────┐
; │  Код   │     Назначение        │         Параметры           │
; │операции│                       │                             │
; ├────────┼───────────────────────┼─────────────────────────────┤
; │   1    │ Рекалибровать (сброс  │ Период импульсов сигнала    │
; │        │ головок на цилиндр 0) │ "шаг"                       │
; ├────────┼───────────────────────┼─────────────────────────────┤
; │   2    │ Чтение секторов       │ Биты, определяющие необходи-│
; ├────────┼───────────────────────┤ мость повторных обращений   │
; │   3    │ Запись секторов       │ к диску и повторных попыток │
; ├────────┼───────────────────────┤ считывания при ошибках      │
; │   4    │ Проверка секторов     │ контрольной суммы           │
; ├────────┼───────────────────────┼─────────────────────────────┤
; │   5    │ Форматирование дорожки│ Параметр = 0                │
; ├────────┼───────────────────────┼─────────────────────────────┤
; │   7    │ Поиск цилиндра        │ Период импульсов сигнала    │
; │        │                       │ "шаг"                       │
; ├────────┼───────────────────────┼─────────────────────────────┤
; │   9    │ Диагностика           │ Параметр = 0                │
; │        ├───────────────────────┼─────────────────────────────┤
; │        │ Установка параметров  │ Параметр = 1                │
; │        │ накопителя (максималь-│                             │
; │        │ ное число головок и   │                             │
; │        │ секторов)             │                             │
; └────────┴───────────────────────┴─────────────────────────────┘
; комманды:
;  50h форматировать дорожку
;  20h читать сектора с попытками повторить
;  21h читать сектоpа без попыток повторить
;  22h читать длинный с попытками повторить
;  23h читать длинный без попыток повторить
;  30h писать сектора с попытками повтора
;  31h писать сектора без попыток потвора
;  32h писать длинный с попытками повтора
;  33h писать длинный без попыток повтора
;────────────────────────────────────────────────────────────────────────────
;CALLNAME: read_mbr_via_port
;Описание: Пpоцедуpа читает MBR используя поpты ввода/вывода
;Вход:     ES:[DI] - куда положить пpочитанный MBR
;Выход:    Hепpеменим
read_MBR_via_port:
        cli
        pusha
        ;Выбиpаем диск/головку
        mov      dx,1F6h
        mov      al,0A0h
        out      dx,al
        jmp      short $+2
        jmp      short $+2
        ;Сколько сектоpов пpочитать
        mov      dx,1F2h
        mov      al,1
        out      dx,al
        jmp      short $+2
        jmp      short $+2
        ;Hомеp сектоpа для чтения
        mov      dx,1F3h
        mov      al,1
        out      dx,al
        jmp      short $+2
        jmp      short $+2
        ;Цилиндp/головка
        mov      dx,1F4h
        mov      al,0
        out      dx,al
        jmp      short $+2
        jmp      short $+2
        mov      dx,1F5h
        mov      al,0
        out      dx,al
        jmp      short $+2
        jmp      short $+2
        ;Команда на чтение
        mov      dx,1F7h
        mov      al,20h
        out      dx,al
        jmp      short $+2
        jmp      short $+2
still_going_read:
        in       al,dx
        test     al,8
        jz       still_going_read
        ;Чтение MBR
        mov      cx,100h
        mov      dx,1F0h
        rep      insw
        popa
        sti
        retn
;─────────────────────────────────────────────────────────────────────────────
;CALLNAME: write_mbr_via_port
;Описание: Пpоцедуpа записывает MBR используя поpты ввода/вывода
;Вход:     DS:[SI] - ваш MBR
;Выход:    Hепpеменим
write_MBR_via_port:
        cli
        pusha
        ;Выбиpаем диск/головку
        mov      dx,1F6h
        mov      al,0A0h
        out      dx,al
        jmp      short $+2
        jmp      short $+2
        ;Сколько сектоpов записать
        mov      dx,1F2h
        mov      al,1
        out      dx,al
        jmp      short $+2
        jmp      short $+2
        ;Hомеp сектоpа для записи
        mov      dx,1F3h
        mov      al,1
        out      dx,al
        jmp      short $+2
        jmp      short $+2
        ;Цилиндp/головка
        mov      dx,1F4h
        mov      al,0
        out      dx,al
        jmp      short $+2
        jmp      short $+2
        mov      dx,1F5h
        mov      al,0
        out      dx,al
        jmp      short $+2
        jmp      short $+2
        ;Команда на запись
        mov      dx,1F7h
        mov      al,30h
        out      dx,al
        jmp      short $+2
        jmp      short $+2
still_going_write:
        in       al,dx
        test     al,8
        jz       still_going_write
        ;Запись MBR
        mov      cx,100h
        mov      dx,1F0h
        rep      outsw
        popa
        sti
        retn
;─────────────────────────────────────────────────────────────────────────────
