Добрый день, уважаемые хабровчане.
В сегодняшней статье мы предаемся ностальгии, поработаем со старым добрым железом и попробуем приделать к нему не менее хорошее новое железо.
Заодно вспомним, как работает шина ISA и как процессор x86 вообще общается с периферией.
Введение
Пару дней назад я наткнулся на свой самый первый компьютер - старенький 386, на процессоре AMD (Am386-DX), с 4 мегабайтами ОЗУ, видеокартой VGA и мультиплатой, берущей на себя функции диска.контроллер накопителя, жесткий диск, параллельный и последовательный порты.
Разумеется, он уже давно избавился от корпуса и древнего вышедшего из строя жесткого диска — теперь это была просто материнская плата с парой плат расширения.
Несколько лет назад я подключил к нему более новый жесткий диск на 10 ГБ (изначально у него был диск всего на 200 мегабайт), на который установил FreeDOS.
Однако на этот раз он отказался загружаться дальше биоса — судя по звукам, винчестер на 10 ГБ после нескольких лет лежания в шкафу умудрился последовать за 200-метровым винчестером.
И тогда у меня появилось сильное желание что-то сделать с этим компьютером, прикоснуться к этой древности, с которой я начал свое знакомство с ИТ, теперь уже как разработчик, а не как пользователь.
В идеале, конечно, хотелось бы сделать эмулятор жесткого диска, работающий с SD-картой, но к этой цели мы будем идти постепенно.
Начнем с задачи попроще — соберем устройство, которое висит параллельно с реальным контроллером жесткого диска и логирует обмен данными, чтобы выяснить, как именно старый биос определяет жесткие диски.
Изначально я собирался сделать то же самое, но для контроллера дискет, однако после того, как умер мой последний жесткий диск, у меня остался работать только биос, который никак не проверяет наличие дискеты.
Но в нем есть пара моментов, связанных с жесткими дисками — обнаружение жестких дисков и инструменты для их форматирования.
Конечно, на ПЛИС это можно сделать очень легко благодаря их архитектуре, но мы остановимся на бюджетном варианте и попробуем сделать это на контроллере STM32F103 и нескольких микросхемах дискретной логики.
Итак, начнем.
Железо
Традиционно начнём с аппаратного дна.Давайте вспомним, что такое шина ISA, лежащая в основе старых компьютеров, и как к ней можно подключиться.
Для тех, кто не очень разбирается в схеме внутри x86-машин, это поможет пролить свет на архитектуру таких систем.
На самом деле все очень просто — в «чистой» ISA нет инструментов Plug&Play — они появились только в следующем стандарте — и, следовательно, нет средств выдачи адресов устройствам.
Таким образом, карты ISA представляют собой устройства с аппаратно определяемым адресом (жестко схемотехнически определенным, в лучшем случае с возможностью выбора базового адреса с помощью перемычек).
Сама шина содержит 20 адресных линий, 16 линий данных, несколько сигналов питания, несколько линий IRQ и набор сигналов управления.
Как все это работает? Допустим, нам нужна возможность включать/выключать на нашем устройстве несколько светодиодов.
Для этого разместим на нашей плате ISA микросхему регистра, например, такую как 74HC273 .
Это самая обычная 8-битная «защелка», запоминающая то, что было дано ей на вход сигналом.
Подключим выходы регистров к светодиодам и забудем о них.
С программной точки зрения взаимодействие с устройством на шине ISA может быть реализовано двумя способами.
- Использование отображения памяти - тогда мы будем декодировать сигналы чтения/записи памяти и выводить результаты на шину вместо контроллера DRAM - это то, что делает видеокарта, ее видеопамять отображается в адресное пространство памяти компьютера.
Таким образом, запись в память видеокарты для компьютера ничем не отличается от записи в ее оперативную память и выполняется обычной командой МОВ .
- Для тех устройств, которым не требуется передавать большие блоки данных, используется так называемое «пространство ввода/вывода» — отдельное адресное пространство, выделенное для периферийных устройств и ограниченное 16 адресными битами.
Доступ к нему можно получить с помощью команд В И ВНЕ (чтение и запись в порты ввода-вывода)
При выполнении команды чтения/записи памяти ( МОВ ) или чтение/запись в 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 и мы войдем в прерывание на спаде.
Как видите, вся логика укладывается ровно в три здания.
К этим условиям добавляется наличие активного уровня на ИОР или МОВ (не забывайте, что по стандарту активный уровень на них низкий, то есть мы получаем уже инвертированные сигналы, ~ИОР И ~IOW ): CS = CS2 & (IOR | IOW)
(IOR|IOW) = ~(~(IOR & IOW) ) = ~(~IOR & ~ IOW) = (IOR NAND IOW)
CS = CS2 & (IOR NAND IOW)
Итоговая диаграмма выглядит так:
Теперь начинаем собирать его аппаратно, используя макетную плату.
Для начала разберем первые три микросхемы, которые принимают больше всего входных сигналов, и позаботимся о подключении их к шинам питания и заземлению.
Аккуратно добавим выходные цепи, а затем добавим входные цепи в виде достаточно длинных щупов, которые впоследствии подключим к материнской плате компьютера:
Для удобства я временно назначил старшие адресные входы слева ( А3-А9 ), младший правый ( А0-А2 ), а посередине выведите сигнал CS2 .
Давайте на время отдохнем от сборки и попробуем посмотреть осциллографом, что произошло.
Итак, подключаем адресные входы к шине — поскольку ISA это всего лишь шина, то не нужно пытаться воткнуть щупы в тот же разъем, куда вставлена плата АТА-контроллера, выбираем любой, который нам удобен.
Щупы, к сожалению, оказались слишком малы для таких отверстий, поэтому я еще сверху приклеил гребешок из прямых штифтов - по отдельности и щупы, и штифты выпадают, но вместе они держатся вполне хорошо.
Также не забудьте подключить к ISA землю и питание схемы, а заодно – землю щупов осциллографа.
Включаем осциллограф и компьютер (я сразу зашел в меню настройки биоса) и тыкаем на сигнал КЛК .
Мы должны увидеть что-то вроде этого:
Это, конечно же, тактовый сигнал шины, частота которого обычно составляет 8 МГц.
На моей материнке его частота составляет 7,19 МГц, что отражено в настройках биоса.
Видимо, это особенность железа - биос не позволил мне понизить эту частоту или хотя бы выставить ровно 8 МГц, упорно устанавливая ее на 7,19 МГц.
В любом случае.
Проверяем входные контакты нашей схемы — если ткнуть в любой из них, то на экране осциллографа получим хаотичный сигнал, так как система постоянно обращается к разным адресам и портам.
Так что если на входе тишина, это значит, что у вас разболтался контакт и его необходимо перепроверить.
Теперь давайте подключимся к нашему сигналу CS2 и видим следующую картину:
Вполне ожидаемо - сигналы ИОР И МОВ не участвовать в формировании CS2 , чтобы он стал активным, когда адрес на шине совпадет с указанным нами ( 0x1F0-0x1F7 И 0x3F6 ).
Система выполняет регулярную регенерацию DRAM, поэтому мы получаем хороший периодический сигнал.
Теперь пришло время настроить развертку и уровни осциллографа, чтобы увидеть сигналы во всей их красе.
Убедившись, что все работает, обесточиваем схему и собираем ее полностью, получая адский беспорядок из проводов вот так:
Снова включите компьютер, зайдите в меню настройки BIOS, включите осциллограф.
Никаких сигналов! Что ж, пришло время проверить правильность наших расчетов – выбираем пункт «Автоопределение жесткого диска».
Первый диск определяется быстро, и, скорее всего, мы не успеем ничего заметить на экране осциллографа, если только не включили одиночный режим.
А вот второй диск (из-за его отсутствия) будет определяться достаточно долго, чтобы мы могли увидеть это на экране компьютера:
А на экране осциллографа — это:
Чтобы окончательно убедиться в своей правоте, выходим из режима обнаружения диска, включаем одиночный режим осциллографа и внимательно смотрим на его экран – ничего! Сколько бы мы ни ждали, К.
С.
не становится активным! Но как только мы переходим к обнаружению дисков, мы снова ловим знакомую картину, вполне соответствующую стандартам — цикл ввода-вывода длится четыре такта шины.
Что ж, пришло время взять плату 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
-
Кин Наблюдатель
19 Oct, 24 -
Новый Процессор Для Iphone 2.0
19 Oct, 24 -
Раскрыты Секретные Разработки Apple И Bmw
19 Oct, 24