Перевод статьи по восстановлению одной старой интересной машинки. Много тяжелых картинок. Курсивом мои комментарии.
Этот PDP 11/04 изначально принадлежал Ericsson. Мы получили его в конце восьмидесятых от EDKX — компьютерного клуба Ericsson. Компьютер был передан по частям, но всё было на месте за исключением пары винтиков. Вместе с самим PDP-11 шла ленточная станция TU60.
Панель операторской консоли
PDP-11/04 появился в середине семидесятых как удешевленный преемник PDP-11/05. В этой новой версии DEC смогла уместить всю процессорную логику на одной шестиконтактной плате (в PDP применялось несколько видов плат с различными форм-факторами — шестиконтактные, четырёхконтактные, двухконтактные. На фото чуть-чуть ниже видно 6 групп пинов. Кроме того платы разделялись по тому, на какую шину они рассчитаны.) вместо двух в предшественнике. Модули подключались к общей кросс-плате (backplate) с девятью слотами, выполненной монтажем накруткой. Обычно с PDP 11 шла программерская консоль (отдельная панель. PDP собиралась из нескольких блоков. что-то типа стойки с набором оборудования), через которую оператор мог вводить несложные загрузочные программы и проводить техобслуживание системы. Однако, именно этот экземпляр имел только обычную ограниченную операторскую консоль.
Кросс-плата
В книге Computer Engineering: A DEC view of hardware design семейство машин PDP-11 описывается очень подробно. Книга отсканирована и находится в публичном доступе. Очень увлекательное чтиво!
Плата CPU
Процессорный модуль состоит из 138 микросхем. Небольшое упрощение операционного автомата (datapath, часть процессора, которая выполняет операции над любыми данными. К примеру, это АЛУ, мультиплексоры, регистровые файлы, декодеры. В общем, практически это самая главная часть процессора.) и использование программируемой памяти позволило уменьшить число используемых чипов. На плате есть пять 256x8 биполярных программируемых микросхем ПЗУ, выделенных под хранение микрокода, который упакован в 40-битные структуры. Первые восемь бит отведены под адрес следующей микроинструкции. Интересной особенностью является то, что линия, по которой передаются эти адреса, реализована по схеме с открытым коллектором, что позволяет делать условные ветвления микрокода просто используя проводные OR-соединения прямо на шине. В качестве главного АЛУ, DEC взяли широко известные 74181, а микросхемы Intel 3101 16x4 RAM использовались в качестве сверхоперативной памяти (scratchpad memory) под основные регистры. Для тактирования нет отдельного кристалла, но вместо него присутствует линия задержки в цепи обратной связи.
Плата памяти
Нам достался PDP-11/04 с модулем памяти на 16 килобайт. Он содержит 32 MK4096, MOS-чипов динамической памяти, произведенных MOSTEK. Занятная ремарка — это была первая память с мультплесированной адресацией по колонке/строке, похожая схема используется и в современном DDR. Благодаря этому новшеству, инженеры MOSTEK'a смогли уместить 4 килобита памяти в 16-пиновый корпус.
Это карта M7800, модуль асинхронных коммуникаций DL11. (В PDP-11 применялась своя классификация модулей. К примеру, в схеме указано MS11-JP, что значит модуль памяти, но конкретные платы могли различаться — M7867-XJ, M7847-DJ или какая еще карта, соответствующая стандарту модуля. В данном случае DL11 это классификатор, а M7800 — конкретная плата.)
Последняя плата, M9312, используется для начальной загрузки системы, и, кроме того, выполняет роль терминатора шины. Вообще, в системе должно быть два терминатора, поскольку процессорный модуль сам по себе не выполняет данную функцию. Поэтому другой терминатор должен быть установлен на противоположном краю шины, в данном случае как можно ближе к процессорному модулю. На M9312 есть четыре разъема под биполярные программируемые ПЗУ, позволяющие обеспечить поддержку загрузки с разных устройств. Кроме этого на плате есть ППЗУ, которое содержит код эмулятора консоли для коммуникации с оператором через последовательный порт.
Компьютер разобран по винтикам в этом документе.
Проверяем блок питания H777
Первое, с чего нужно начать, это проверить, что с блоком питания всё в порядке. В частности, важно убедиться в том, что конденсаторы в хорошем состоянии. H777 является импульсным блоком питания с ключевым элементом во вторичной цепи, из чего следует, что он содержит огромный трансформатор (по сравнению со схемой с ключем в первичной цепи, он действительно большой), который понижает амплитуду входного переменного напряжения до куда более приятных в работе 38 VAC. Не очень здорово возиться с блоками питания, в которых почти на всех участках цепи напряжение в районе 400 VDC. H777 состоит из двух регуляторов: 5 вольтового, генерирующего 25 ампер, и MOS-регулятора, отдающего +15V, -15V, +5V (в других версиях H777 есть еще и третий регулятор на +20V, -5V).
Какая-то добрая душа отсканировала необходимый мануал, в котором в деталях описана вся внутренняя кухня этого БП.
Большие конденсаторы 50В x 22000мФ, фильтрующие нерегулируемый постоянный ток, смогли полностью зарядиться через 10кОм сопротивление, а ток утечки был крайне мал. Выходной конденсатор на 5В был в куда худшей форме. Конденсатор 6В x 3900мФ от Sprague, на впечатляющих ножках, ни разу не достигал номинального напряжения, даже при долгом использовании с 560 Ом резистором.
Слева — подпорченный временем элемент, справа — его замена
В настоящее время таких конденсаторов 6В x 3900мФ с креплением болтами не найти, поэтому я заменил его на 40В x 6800мФ от RIFA.
С новым конденсатором БП смог выдать 3 ампера на мою тестовую плату, от которой вскорости потянулся приятный аромат разогретого гетинакса (макетки часто из этого материала делают).
Процесс проверки БП. Кстати, виден здоровый трансформатор первичной цепи
Но заработает ли всё это, если подключить БП к кросс-плате? К сожалению, не заработало. Выяснилось, что два сигнальных контакта БП находятся в перманентно низком состоянии: BUS DC LO L и BUS AC LO L. Эти сигналы с активным низким уровнем, и в активном состоянии подавляют тактовый генератор главного процессора.
Схема выше описывает 5-вольтовый регулятор. Выделенная голубым область это цепь источника тока, которая на вход получает нерегулируемый постоянный ток, заряжая 50мФ конденсатор, который затем выдаёт красивый пилообразный сигнал. Резисторная матрица и набор компараторов (операционные усилители, которые выступают здесь в роли компараторов напряжения) генерируют BUS DC LO L, BUS AC LO L и внутренний сигнал, на котором основывается тактирование главного ШИМ-ключа. Напряжение на конденсаторе не превосходило 20.4 вольта, что недостаточно для смены полярности двух компараторов. Это выглядело так, как будто слишком много тока поглощается с этого источника. Замена конденсатора ничего не изменила. Но, кроме источника тока, к конденсатору подключена красная область схемы — цепь защиты от перегрузок. Если какой-нибудь из транзисторных ключей сбойнёт, то на выход пойдёт 38 вольт нерегулируемого постоянного тока. Что, само-собой, не очень хорошо. Поэтому здесь используется стабилитрон и пара тиристоров, которые срабатывают при выходном напряжении больше 5.4 VDC, что приводит к короткому замыканию в источнике тока, и, в свою очередь, крайне эффективно останавливает любую активность в блоке питания. Проблема, видимо, была в том, что даже при нормальных условиях защитной цепью поглощалось 1.5 мА из-за утечки тиристора, причём в зактрытом состоянии. Конечно же, любой тиристор течёт, но не настолько сильно как этот.
сломанный тиристор, возможно C32AX135
После замены тиристора на современный BT145, блок питания заработал как надо.
Проверка процессора
Подключаем все кабели и включаем питание. Дыма не видно, что является хорошим знаком. Но лампочка «RUN» часто мерцает, а, после переключения соответствующего тумблера на консоли в значение «INIT», и, вовсе, только раз коротко мигнула. Ситуация не обнадеживающая.
Подключенный к главному тактовому сигналу процессорного модуля осциллограф показывает, что в начале идут 8 тактов, затем пауза на пару микросекунд, 3 такта, еще одна пауза и опять 3 такта, но за ними уже ничего не следует.
На этом фото можно заметить, что период синхросигнала ближе к 250нс чем к 260нс, про которые написано в «Computer Engineering». Однако, использование линии задержки в цепи обратной связи и не сможет дать такую точность. Тем не менее, 4 МГц очень впечатляющий результат для середины семидесятых.
Скорее всего, в дальнейшем выяснении причин неполадки осциллограф помочь не смог бы. Для такого рода задач я держу этот маленький USB-анализатор.
Но для того чтобы охватить весь компьютер с его шинами адреса и данных, мне нужно четыре таких. К счастью, мне в тот момент предложили купить логический анализатор HP1664A по доступной цене.
Поиск ошибок с использованием логического анализатора
После некоторых проблем в начале, когда я перепутал некоторые сигналы и забыл про то, что плата использует активно-низкие уровни, я получил несколько занимательных логов трассировки:
Здесь отображены значение шины, по которой передаются адреса микро-инструкций на выполнение. На самом деле, здесь показывается адрес следующей микро-инструкции, во время выполнения текущей. Однако, судя по мануалу, это вполне корректная последовательность микро-операций (если действительно интересно, то глава 6.3.3 Restarts from power failure).
Интересно в логе сверху то, что, при выставлении на шине адреса значения 026, мы получаем 0165020, являющееся значением счетчика команд, содержащего адрес, с которого мы должны начать исполнение после сбоя питания. Данный адрес принадлежит M9312 и указывает на программу диагностики. Но следующий адрес инструкции, выставленный на шине, — 0167020. По какой-то причине 10-ый бит оказался единицей! Исследуя более подробно чип-приёмник шины DS8641, заметил, что даже при входном токе в 3.31В, на выходе получаем 3.78В! Выглядит странновато.
Оно живое!
Вот, эта маленькая злостная штуковина:
К сожалению, DS8641 не особо распространенная микросхема. К тому же, она была специально адаптирована к шинам с открытым коллектором для DEC'a. Я заказал несколько на Ebay у продавца из Китая, но, так как идёт посылка довольно долго, я решил выпаять такой же чип с другой платы, и заменить им сбоящую микросхему в процессорном модуле.
На этот раз результат был лучше:
Тем не менее, всё заканчивается зацикленным ожиданием бита готовности TX консольного последовательного порта. Странно. Может дело в ошибке M7800?
Еще одна плата M7800
Другой модуль M7800 был подключен к кросс-плате. Последовательный порт подключил к ноутбуку.
Отлично. Теперь система проходит все диагностические шаги с первого по четвёртый. Но ввод «DL» в консоли для того, чтобы попытаться загрузиться с несуществующего RL-устройства (RL01/RL02 — что-то типа жестких дисков, но со сменными картриджами с данными.), приводит к остановке машины.
Похоже на то, что при попытке протестировать оперативную память, происходит сбой, и затем, сразу же, получаем двойную ошибку во время обработки первой. Такое поведение характерно для обработки исключения (точнее ловушки, trap) процессором.
Корявый DIP-переключатель!
Во время исследования модуля памяти и проверки джамперов и позиций переключателей, я обнаружил, что при щелкании туда и обратно DIP-переключателем, игнорируется положение 6-ого ключа из 8ми, и цепь остаётся замкнутой. Проблемка.
Слева — новый переключатель, справа — старый.
Наконец-то, компьютер запустился!
Понять, что он работает, можно по тому, что автор вводит консольные команды в терминале: @L — загрузить адрес, @E — проверить данные по адресу, @D — записать данные по загруженному адресу.
PDP11GUI
PDP11GUI — отличная утилита под Windows для управления вашим PDP-11. Она умеет загружать файлы в память PDP-11, просматривать слепок памяти и запускать процессор.
Перфоленты с BASIC'ом могут быть найдены на просторах интернета. Но, к сожалению, они в формате Absolute Binary Loader, который PDP11GUI не понимает. Однако, можно написать простенькую программу на Си для конвертирования. Полученный файл можно уже скармливать мини-ЭВМ, но это всё очень медленно на линии 9600bps.
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char ** argv) {
FILE * input, * output;
int ch, state = 0, count, size, sum = 0, address, data=0, start=0;
if (argc==3) {
input = fopen (argv[1], "rb");
if (input == NULL) {
fprintf(stderr, "cannot open file %s for readingn", argv[1]);
exit(1);
}
output = fopen (argv[2], "w+");
if (output == NULL) {
fprintf(stderr, "cannot open file %s for readingn", argv[2]);
exit(1);
}
}
else {
fprintf(stderr, "Usage conver <input> <output>");
exit(1);
}
while(!feof(input)) {
ch = fgetc (input);
//fprintf (stderr, "state=%d ch=%02x sum=%02x count=%d start=%dn", state, ch, sum, count, start);
switch (state) {
case 0:
if (ch != 1) state = 0;
else {
state = 1;
count = 1;
sum += ch;
sum &= 0xff;
}
break;
case 1:
if (ch != 0) state = 0;
else {
state = 2;
count ++;
sum += ch;
sum &= 0xff;
}
break;
case 2:
// read low count byte
size = ch;
state = 3;
sum += ch;
sum &= 0xff;
count ++;
break;
case 3:
// read count
size = size | (ch << 8);
state = 4;
sum += ch;
sum &= 0xff;
if (size==6) {
start = 1;
}
count ++;
break;
case 4:
// read address low
address = ch;
sum += ch;
sum &= 0xff;
state = 5;
count ++;
break;
case 5:
address = address | (ch << 8);
state = 6;
sum += ch;
sum &= 0xff;
count ++;
if (count == size) {
state =0;
}
if (start==1) {
fprintf (stderr, "Start at %06on", address);
fclose (input);
fclose (output);
exit(0);
}
break;
case 6:
data = ch;
sum += ch;
sum &= 0xff;
count ++;
if (count == size) {
state = 7;
} else {
state = 8;
}
break;
case 8:
sum += ch;
sum &= 0xff;
data = data | (ch <<8);
fprintf (output, "%06o %06on",address, data);
address +=2;
count++;
if (count == size) {
state = 7;
}
else {
state = 6;
}
break;
case 7:
// checksum
sum += ch;
sum &= 0xff;
if (sum!=0) {
fprintf (stderr, "Checksum error chsum = %02Xn", sum);
exit(1);
}
sum = 0;
state = 0;
}
}
}
UPDATE: В версии 1.38 PDP11GUI уже не нуждается во внешней программе, так как код конвертации был включен в PDP11GUI. (Да-да, в оригинале 5 одинаковых ссылок на PDP11GUI).
Запустив PDP с начальным адресом 016104, получим приглашение BASIC'a (очевидно, что запуск проходил через ту тулзу, в коей есть соответствующая настройка «initial PC»).
Заметно, что я уже очень давно не писал ничего на BASIC'e.
Запуск диагностик
Для настоящей проверки того, что процессор работает так как надо, существует две диагностических программы — GKAA и GKAB. Есть два способа запустить их: загрузить в PDP11GUI образ перфоленты или использовать XXDP. Я испробовал оба метода.
Точно известно, что эти программы хранились на перфоленте, но, увы, я не смог найти образы этих перфолент. Но я нашёл образ для XXDP, который содержал GKAAA0.BIC и GKABC0.BIC. Оказывается, что бинарники имеют тот же формат что и перфоленты. Я использовал PUTR для извлечения их из образа. Не забудьте, что файлы нужно копировать как бинарные, а не то, так же как и я, будете ломать голову несколько часов (PUTR предоставляет некий DOS-подобный интерфейс, и нужно делать «copy /b» вместо просто «copy»).
После извлечения, я просто загрузил образы в PDP11GUI и запустил с адреса 0200.
Загрузка XXDP
XXDP должен запускаться с какого-нибудь запоминающего устройства. Мне подходит только одна опция, которая была бы достаточно простой для использования на моём PDP-11 в тот момент, — TU58 (ленточная система), так как она использует последовательный порт для подключения, и поэтому может быть сэмулирована на ПК. Я скачал tu58em и скомпилировал на своём Маке. Нужно было сделать всего несколько правок в коде работы с последовательным портом для того, чтобы программа успешно скомпилировалась.
После этого я начал работать над созданием загрузочного образа с XXDP. Такого рода работа может быть выполнена значительно быстрее с использованием эмулятора PDP-11. Я использовал E11. Сначала я попробовал XXDP 2.6, найденный в виде образа на bitsavers:
Ersatz-11 V7.0 Demo version, COMMERCIAL USE LIMITED TO 30-DAY EVALUATION
Copyright (C) 1993-2013 by Digby's Bitpile, Inc. All rights reserved.
See www.dbit.com for more information.
E11>assign tt1: dda:
E11>mount dda0: dddp.dsk
E11>set cpu 04
E11>set mem 16
E11>boot tt1:
%HALT
?Bad kernel stack
R0/000000 R1/176506 R2/000000 R3/000066 CM=K PM=K PRIO=0
R4/100020 R5/000000 SP/057774 PC/000006 N=0 Z=0 V=0 C=0
000006 halt
E11>set mem 24
E11>boot tt1:
CPU NOT SUPPORTED BY XXDP-XM
BOOTING UP XXDP-SM SMALL MONITOR
XXDP-SM SMALL MONITOR - XXDP V2.6
REVISION: E0
BOOTED FROM DD0
12KW OF MEMORY
UNIBUS SYSTEM
RESTART ADDRESS: 052010
TYPE "H" FOR HELP
.R GKABC0
GKABC0.BIC
%HALT
R0/000357 R1/000000 R2/000300 R3/054426 CM=K PM=K PRIO=0
R4/000001 R5/000776 SP/000500 PC/012006 N=0 Z=0 V=0 C=0
012006 cmp 177776,#000000
E11>
Но он требовал больше памяти, чем было на моей машине, поэтому использовать эту версию никак не получилось бы. Кроме того, GKAB совсем не хотел запускаться на эмулируемом PDP-11/04 по неизвестной причине.
После этого я потратил время на то, чтобы сделать TU58-образ для XXDP+, более ранней версии пакета XXDP. Вот как это у меня получилось в E11:
.R UPD2
CHUP2A2 XXDP+ UPD2 UTILITY
RESTART: 002432
*ZERO DD0:
*DRIVER DD0:
*LOAD DY0:HMDDA1.SYS
XFR:005034 CORE:000000,017774
*SAVM DD0:
*PIP DD0:HMDDA1.SYS=DY0:HMDDA1.SYS
*PIP DD0:HDDDA1.SYS=DY0:HDDDA1.SYS
*PIP DD0:GKA???.BIC=DY0:GKA???.BIC
GKAAA0.BIC
GKABC0.BIC
*PIP DD0:HELP.TXT=DY0:HELP.TXT
*PIP DD0:HUDIA0.SYS=DY0:HUDIA0.SYS
*PIP DD0:HSAAA0.SYS=DY0:HSAAA0.SYS
*PIP DD0:UPD?.BIN=DY0:UPD?.BIN
UPD1 .BIN
UPD2 .BIN
*PIP DD0:SETUP.BIN=DY0:SETUP.BIN
E11>set cpu 04
E11>set mem 16
E11>boot tt1:
CLEARING MEMORY
CHMDDA0 XXDP+ DD MONITOR 8K
BOOTED VIA UNIT 0
ENTER DATE (DD-MMM-YY):
RESTART ADDR:033726
50 HZ? N Y
LSI? N
THIS IS XXDP+. TYPE "H" OR "H/L" FOR DETAILS
.DIR
ENTRY# FILNAM.EXT DATE LENGTH START
000001 HMDDA1.SYS 22-MAR-80 17 000050
000002 HDDDA1.SYS 22-MAR-80 3 000071
000003 GKAAA0.BIC 11-AUG-76 15 000074
000004 GKABC0.BIC 29-JAN-77 16 000113
000005 HELP .TXT 22-MAR-80 26 000133
000006 HUDIA0.SYS 22-MAR-80 6 000165
000007 HSAAA0.SYS 22-MAR-80 24 000173
000010 UPD1 .BIN 22-MAR-80 12 000223
000011 UPD2 .BIN 22-MAR-80 16 000237
000012 SETUP .BIN 22-MAR-80 26 000257
.R GKABC0
%HALT
R0/000357 R1/000000 R2/000300 R3/032240 CM=K PM=K PRIO=0
R4/000001 R5/000776 SP/000500 PC/012006 N=0 Z=0 V=0 C=0
012006 cmp 177776,#000000
GKAAA0.BIC под XXDP+ на настоящей машине запустился успешно. Большая часть системы в отличном состоянии! Вот ссылка на образ, который я сделал.
Но запуск GKABC0 закончился остановкой системы. Невозможно найти исходники для конкретной версии утилиты, но версия под PDP-11/34 должна подойти. Просматривая код, можно заметить, что участок, в котором происходит остановка системы, это проверка логики обработки переполнения стека. Устанавливается указатель стека в значение 0400, а затем дергается консольное TX-прерывание (видимо имеется в виду инструкция IOT, вызывающее прерывание 020, на которое OS обычно вешает I/O обработчик). При этом указатель стека становится меньше 0400, что ведёт к генерации исключения, номер вектора обработки которого 4 или 6. На моей машине поведение было иное — генерировались всё новые и новые консольные прерывания до тех пор, пока стек не достигал 0177774 (физической памяти по этому адресу нет), а затем останавливался с двойной ошибкой шины.
Глючный DL11-W!
Меняя платы, я заметил, что использование другой DL11-W, устраняет проблему. Похоже, что в DL11-W логика обработки прерываний сломана. Прерывание должно быть очищено, как только процессор отвечает SSYN (сигнал шины Unibus, своего рода handshake). Этого не происходило на сломанной карте. Только процессор начинал обработку прерывания, как получал его снова и снова. Процесс работы с прерываниями на шине Unibus не очень сложен. Устройство устанавливает сигнал BRn, а процессор отвечает установкой BGn, когда он готов к обслуживанию прерывания. После этого устройство, в свою очередь, отвечает SACK, устанавливает номер вектора прерывания и подтягивает INTR. Трассировка ниже взята с работающей карты:
Не забываем, что в PDP-11 активный уровень сигнала — низкий
Схема показывает триггер прерывания и вентиль, который должен очищать сигнал прерывания, когда оно уже обслужено.
Данная нечеткая фотография ясно показывает сбоящий 7408 AND-вентиль на сломанной плате.
7408 здесь обозначен как E4, 12 и 13 — входные сигналы, 11 — выходной, который должен, по идее, очищать прерывание, когда находится в низком состоянии. Этого не происходит, и прерывания всё идут и идут.
На этом починка основного блока плат окончена, во второй части статьи чиним ленточную станцию TU60, а в третьей — терминал LA30 Decwriter.
Автор: mark_ablov