Давайте Встряхнемся: Перехват Потока Данных Между I386 И Ata-Контроллером С Помощью Stm32

Добрый день, уважаемые хабровчане.

В сегодняшней статье мы предаемся ностальгии, поработаем со старым добрым железом и попробуем приделать к нему не менее хорошее новое железо.

Заодно вспомним, как работает шина ISA и как процессор x86 вообще общается с периферией.



Введение

Пару дней назад я наткнулся на свой самый первый компьютер - старенький 386, на процессоре AMD (Am386-DX), с 4 мегабайтами ОЗУ, видеокартой VGA и мультиплатой, берущей на себя функции диска.

контроллер накопителя, жесткий диск, параллельный и последовательный порты.

Разумеется, он уже давно избавился от корпуса и древнего вышедшего из строя жесткого диска — теперь это была просто материнская плата с парой плат расширения.

Несколько лет назад я подключил к нему более новый жесткий диск на 10 ГБ (изначально у него был диск всего на 200 мегабайт), на который установил FreeDOS.

Давайте встряхнемся: перехват потока данных между i386 и ATA-контроллером с помощью STM32

Однако на этот раз он отказался загружаться дальше биоса — судя по звукам, винчестер на 10 ГБ после нескольких лет лежания в шкафу умудрился последовать за 200-метровым винчестером.

И тогда у меня появилось сильное желание что-то сделать с этим компьютером, прикоснуться к этой древности, с которой я начал свое знакомство с ИТ, теперь уже как разработчик, а не как пользователь.

В идеале, конечно, хотелось бы сделать эмулятор жесткого диска, работающий с SD-картой, но к этой цели мы будем идти постепенно.

Начнем с задачи попроще — соберем устройство, которое висит параллельно с реальным контроллером жесткого диска и логирует обмен данными, чтобы выяснить, как именно старый биос определяет жесткие диски.

Изначально я собирался сделать то же самое, но для контроллера дискет, однако после того, как умер мой последний жесткий диск, у меня остался работать только биос, который никак не проверяет наличие дискеты.

Но в нем есть пара моментов, связанных с жесткими дисками — обнаружение жестких дисков и инструменты для их форматирования.

Конечно, на ПЛИС это можно сделать очень легко благодаря их архитектуре, но мы остановимся на бюджетном варианте и попробуем сделать это на контроллере STM32F103 и нескольких микросхемах дискретной логики.

Итак, начнем.



Железо

Традиционно начнём с аппаратного дна.

Давайте вспомним, что такое шина ISA, лежащая в основе старых компьютеров, и как к ней можно подключиться.

Для тех, кто не очень разбирается в схеме внутри x86-машин, это поможет пролить свет на архитектуру таких систем.

На самом деле все очень просто — в «чистой» ISA нет инструментов Plug&Play — они появились только в следующем стандарте — и, следовательно, нет средств выдачи адресов устройствам.

Таким образом, карты ISA представляют собой устройства с аппаратно определяемым адресом (жестко схемотехнически определенным, в лучшем случае с возможностью выбора базового адреса с помощью перемычек).

Сама шина содержит 20 адресных линий, 16 линий данных, несколько сигналов питания, несколько линий IRQ и набор сигналов управления.



Давайте встряхнемся: перехват потока данных между i386 и ATA-контроллером с помощью STM32

Как все это работает? Допустим, нам нужна возможность включать/выключать на нашем устройстве несколько светодиодов.

Для этого разместим на нашей плате ISA микросхему регистра, например, такую как 74HC273 .

Это самая обычная 8-битная «защелка», запоминающая то, что было дано ей на вход сигналом.

Подключим выходы регистров к светодиодам и забудем о них.

С программной точки зрения взаимодействие с устройством на шине ISA может быть реализовано двумя способами.

  1. Использование отображения памяти - тогда мы будем декодировать сигналы чтения/записи памяти и выводить результаты на шину вместо контроллера DRAM - это то, что делает видеокарта, ее видеопамять отображается в адресное пространство памяти компьютера.

    Таким образом, запись в память видеокарты для компьютера ничем не отличается от записи в ее оперативную память и выполняется обычной командой МОВ .

  2. Для тех устройств, которым не требуется передавать большие блоки данных, используется так называемое «пространство ввода/вывода» — отдельное адресное пространство, выделенное для периферийных устройств и ограниченное 16 адресными битами.

    Доступ к нему можно получить с помощью команд В И ВНЕ (чтение и запись в порты ввода-вывода)

На самом деле за словами «отдельное адресное пространство» скрывается физически простая суть: на шине ISA имеется 4 сигнала — МЕМВ, МЭМР, ИОР, IOW .

При выполнении команды чтения/записи памяти ( МОВ ) или чтение/запись в IO ( В , ВНЕ ), требуемый адрес устанавливается на той же шине, линии А0-А19 ЭТО.

Данные также текут по тем же линиям - Д0-Д15 .

Разница лишь в том, что при чтении из памяти активный уровень устанавливается на строке МЭМР , при записи в память – МЕМВ , при чтении из порта ввода-вывода – ИОР , при записи на него – МОВ .

Таким образом, чтобы сделать простое устройство с одним регистром и светодиодами, нам нужно определить, когда на шине установлен нужный нам адрес (мы помним, адреса нам никто не дает, мы должны сами выбрать адрес, который не будет конфликтовать с существующие периферийные устройства) и по сигналу МОВ разрешить запись данных со строк Д0-Д8 в наш реестр.

В более сложных устройствах, содержащих несколько регистров, старшие адресные строки идут в декодер, генерируя активный выходной сигнал при совпадении с некоторым «базовым» адресом устройства, а младшие формируют номер регистра, к которому осуществляется доступ.

Перейдем к более конкретному примеру — нашему ATA-контроллеру.

Для лучшего понимания принципов его работы рекомендую ознакомиться с статья из вики OSDev. Он управляется девятью регистрами ввода-вывода, восемь из которых расположены подряд, начиная с базового адреса.

0x1F0 .

Девятый, к сожалению, находится по адресу: 0x3F6 , что несколько усложняет схему декодирования.

Конечно, мы не будем подключать все адресные линии к контроллеру и делать на нем декодер, иначе ничего не успеем сделать - тактовая частота шины 8 МГц, такт ввода-вывода по спецификации, длится 4 такта, что при частоте контроллера 72 МГц дает нам всего 36 тактов на размышление.

Поэтому мы будем использовать дешевые микросхемы дискретной логики.

Если бы не этот девятый регистр, который торчит в 0x3F6 , то нам нужно будет построить схему, которая выдает активный сигнал, когда линии А9 И А3 установить на ноль и А4-А8 – единица измерения (то есть для адресов 0x1F(.

) ).

Биты старше А9 Карты ISA обычно не декодируются, независимо от возможности доступа к тому же устройству по более высоким адресам.

Обработку трех младших битов уже можно было поручить контроллеру.

Увы, у нас еще есть непокрытый реестр 0х3F6 .

Начальные условия (линии активны А4-А8 и неактивен А3 ) выполняются всегда, так как эти биты находятся в заданных состояниях и для 0x1F(.

) и для 0x3F6 .

К ним добавляется условие, которое можно сформулировать следующим образом: при активном А9 – должны быть активные уровни на А1 И А2 (адрес 0x3F6 ) То есть,

  
  
  
  
   

CS0 = A8 & A7 & A6 & A5 & A4 & ~A3 CS1 = A1 & A2 & A9 CS2 = CS0 & (~A9 | CS1)

Использование онлайн-симулятора логических схем Логика.

Ly , эту схему я построил на основе имеющихся у меня микросхем - 74HC04, счетверенный элемент НЕТ , 74HC30 - восьмивходовой NAND и 74HC10, тройной, трехвходовой NAND .

Поскольку элемент ИЛИ у нас нет, помним правила Де Моргана - отрицание союза есть дизъюнкция отрицаний, а отрицание дизъюнкции - это конъюнкция отрицаний, или, в виде логических равенств

~(A&B) = ~A | ~B ~(A|B) = ~A & ~B

Давайте использовать это:

~( ~ (~A9 | CS1))) = ~(A9&~CS1) - = (A9 NAND ~CS1) CS2 = CS0 & (A9 NAND ~CS1)

Чистый И У нас его тоже нет, поэтому подадим его компоненты на трехвходовой блок NAND и мы войдем в прерывание на спаде.

Как видите, вся логика укладывается ровно в три здания.



Давайте встряхнемся: перехват потока данных между i386 и ATA-контроллером с помощью STM32

К этим условиям добавляется наличие активного уровня на ИОР или МОВ (не забывайте, что по стандарту активный уровень на них низкий, то есть мы получаем уже инвертированные сигналы, ~ИОР И ~IOW ):

CS = CS2 & (IOR | IOW) (IOR|IOW) = ~(~(IOR & IOW) ) = ~(~IOR & ~ IOW) = (IOR NAND IOW) CS = CS2 & (IOR NAND IOW)

Итоговая диаграмма выглядит так:

Давайте встряхнемся: перехват потока данных между i386 и ATA-контроллером с помощью STM32

Теперь начинаем собирать его аппаратно, используя макетную плату.

Для начала разберем первые три микросхемы, которые принимают больше всего входных сигналов, и позаботимся о подключении их к шинам питания и заземлению.



Давайте встряхнемся: перехват потока данных между i386 и ATA-контроллером с помощью STM32

Аккуратно добавим выходные цепи, а затем добавим входные цепи в виде достаточно длинных щупов, которые впоследствии подключим к материнской плате компьютера:

Давайте встряхнемся: перехват потока данных между i386 и ATA-контроллером с помощью STM32

Для удобства я временно назначил старшие адресные входы слева ( А3-А9 ), младший правый ( А0-А2 ), а посередине выведите сигнал CS2 .

Давайте на время отдохнем от сборки и попробуем посмотреть осциллографом, что произошло.

Итак, подключаем адресные входы к шине — поскольку ISA это всего лишь шина, то не нужно пытаться воткнуть щупы в тот же разъем, куда вставлена плата АТА-контроллера, выбираем любой, который нам удобен.

Щупы, к сожалению, оказались слишком малы для таких отверстий, поэтому я еще сверху приклеил гребешок из прямых штифтов - по отдельности и щупы, и штифты выпадают, но вместе они держатся вполне хорошо.

Также не забудьте подключить к ISA землю и питание схемы, а заодно – землю щупов осциллографа.

Включаем осциллограф и компьютер (я сразу зашел в меню настройки биоса) и тыкаем на сигнал КЛК .

Мы должны увидеть что-то вроде этого:

Давайте встряхнемся: перехват потока данных между i386 и ATA-контроллером с помощью STM32

Это, конечно же, тактовый сигнал шины, частота которого обычно составляет 8 МГц.

На моей материнке его частота составляет 7,19 МГц, что отражено в настройках биоса.

Видимо, это особенность железа - биос не позволил мне понизить эту частоту или хотя бы выставить ровно 8 МГц, упорно устанавливая ее на 7,19 МГц.

В любом случае.

Проверяем входные контакты нашей схемы — если ткнуть в любой из них, то на экране осциллографа получим хаотичный сигнал, так как система постоянно обращается к разным адресам и портам.

Так что если на входе тишина, это значит, что у вас разболтался контакт и его необходимо перепроверить.

Теперь давайте подключимся к нашему сигналу CS2 и видим следующую картину:

Давайте встряхнемся: перехват потока данных между i386 и ATA-контроллером с помощью STM32

Вполне ожидаемо - сигналы ИОР И МОВ не участвовать в формировании CS2 , чтобы он стал активным, когда адрес на шине совпадет с указанным нами ( 0x1F0-0x1F7 И 0x3F6 ).

Система выполняет регулярную регенерацию DRAM, поэтому мы получаем хороший периодический сигнал.

Теперь пришло время настроить развертку и уровни осциллографа, чтобы увидеть сигналы во всей их красе.

Убедившись, что все работает, обесточиваем схему и собираем ее полностью, получая адский беспорядок из проводов вот так:

Давайте встряхнемся: перехват потока данных между i386 и ATA-контроллером с помощью STM32

Снова включите компьютер, зайдите в меню настройки BIOS, включите осциллограф.

Никаких сигналов! Что ж, пришло время проверить правильность наших расчетов – выбираем пункт «Автоопределение жесткого диска».

Первый диск определяется быстро, и, скорее всего, мы не успеем ничего заметить на экране осциллографа, если только не включили одиночный режим.

А вот второй диск (из-за его отсутствия) будет определяться достаточно долго, чтобы мы могли увидеть это на экране компьютера:

Давайте встряхнемся: перехват потока данных между i386 и ATA-контроллером с помощью STM32

А на экране осциллографа — это:

Давайте встряхнемся: перехват потока данных между i386 и ATA-контроллером с помощью STM32

Чтобы окончательно убедиться в своей правоте, выходим из режима обнаружения диска, включаем одиночный режим осциллографа и внимательно смотрим на его экран – ничего! Сколько бы мы ни ждали, К.

С.

не становится активным! Но как только мы переходим к обнаружению дисков, мы снова ловим знакомую картину, вполне соответствующую стандартам — цикл ввода-вывода длится четыре такта шины.

Что ж, пришло время взять плату STM32 и подключить ее к системе! Я подключил так: Шина данных ISA ( Д0–Д7 ) подключен к GPIOD.0 – GPIOD.7 , Три младшие адресные строки ( А0–А2 ) - К GPIOD.8 – GPIOD.10 , Адресная строка А9 - К ГПИОД.

11 (ведь этот бит нам понадобится, чтобы понять, что вызов не собирается 0x1F6 , и чтобы 0x3F6 !) Линии МОВ И ИОР К ГПИОД.

12 И ГПИОД.

13 .

Сигнал К.

С.

- К ГПИОБ.

0 Теперь, когда его прерывают на ГПИОБ.

0 нам просто нужно будет прочитать GPIOD-> ИРД (регистр входных данных), в котором младшие 8 бит будут искомыми данными, следующие четыре – адресом (причем возможные комбинации будут 0000 – 0111 И 1011 , соответствующий портам 0x1F0 – 0x1F7 И 0x3F6 ), следующие два – режим (чтение по 01 или записи на 10 ).

Здесь важно отметить следующее — если вдруг мы получим результат с битами режима, находящимися в недопустимом состоянии — 00 или 11 , это будет сигнализировать нам об ошибке в работе — этот факт очень скоро нам пригодится.

Итак, перейдем к программному обеспечению.



Программное обеспечение

С ПО все предельно просто – настраиваем ГПИОД у входа, а также ГПИОБ.

0 , после чего ставим прерывание при падении линии ЭКСТИ , подключен к ГПИОБ.

0 .

В обработчике прерывания мы будем читать только значение из ГПИОД и увеличить указатель на буфер.

Этот буфер можно потом отправить на компьютер на анализ через любой интерфейс, а можно вообще не заморачиваться с ним и посмотреть его прямо в отладке.

Код установки показан ниже:

GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE); GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|

Теги: #stm32 #arm #DIY или Сделай сам #diy #HDD #Старое железо #isa #x86 #i386 #i386 #логические схемы #ata

Вместе с данным постом часто просматривают: