- PVSM.RU - https://www.pvsm.ru -

Изготовление контроллера терминала IBM 3270

IBM 3270 – это терминал компьютерного мейнфрейма. Я давно восхищаюсь мейнфреймами от IBM, и особенно этими терминалами. У ранних моделей, 3278 и 3279, была уникальная эстетика, а их блочная система работы заметно отличается от той, которой пользовались вездесущие терминалы серии VT.

Изготовление контроллера терминала IBM 3270 - 1
Терминал IBM 3278-2 и его пра-пра-правнук, ThinkPad X1, на котором запущен оес. Терминал подсоединён к современному z14 при помощи TN3270.

Не один я хотел попробовать подсоединить настоящий терминал от IBM к эмулятору Hercules [1] [программный эмулятор мейнфреймов IBM (System/370, System/390, zSeries/System z) и совместимых (Amdahl)]. К сожалению, довольно трудно найти контроллер терминала IBM 3174 с интерфейсом Ethernet или Token Ring, версией софта с поддержкой TCP/IP и в рабочем состоянии. К тому же они огромные, шумные, и их сложно обслуживать, поскольку софт на них приходится загружать при помощи редких флоппи-дисков 5¼" объёмом 2,4 Мб – если повезёт, бывают ещё варианты с жёстким диском на 20 Мб. Поэтому я решил сделать собственный контроллер, а в процессе узнать что-то новое.

Немного истории IBM 3270

Судя по записям компании IBM, информационная система 3270 была представлена в 1972 году, а культовый терминал 3278 [2] – через пять лет, в 1977. Цветные терминалы появились в 1979 с 3279. Сложновато не запутаться в моделях и годах!

3270 – один из самых узнаваемых терминалов, работающих по блочной системе [3]. Поток данных 3270 [4] позволяет программисту описать целый экран, содержащий текст, защищённый от редактирования, доступные для редактирования поля и атрибуты его форматирования. Доступные для редактирования поля позволяют вводить или изменять данные. Вместо того, чтобы отправлять каждое сделанное вами нажатие клавиши сразу на хост, как это происходит у символьных терминалов, этот терминал хранит ввод у себя, пока вы не нажмёте особую клавишу – к примеру, Enter. Только после этого весь ввод отправляется на хост «блоком» данных. Такая система улучшает воспринимаемую отзывчивость компьютера в случае медленной или ненадёжной связи. Также это снижает требования по мощности хоста, и позволяет подключать к нему гораздо больше блочных терминалов, чем символьных. В чём-то это весьма напоминает заполнение формы на HTML-странице.

Для ранних 3270 предлагалась всякая прикольная периферия, типа световых ручек для улучшения навигации и устройств для чтения магнитных карт – к сожалению, на eBay я их не встречал.

Терминалы соединяются с контроллером коаксиальным кабелем по топологии «звезда» [5]. При помощи балуна [6] можно превратить её в более привычную схему подключения по витой паре, хотя, как мне кажется, IBM предпочла бы, чтобы вы использовали их систему подключения. Контроллер соединяется с мейнфреймом по разным интерфейсам, в зависимости от того, местный это контроллер или удалённый. Кроме того, подключение менялось со временем. Среди интерфейсов присутствовали:

  • Parallel Channel
  • ESCON Channel
  • X.21
  • V.35
  • Token Ring
  • Ethernet

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

Изготовление контроллера терминала IBM 3270 - 2
Контроллеры терминалов от IBM по часовой стрелке, начиная снизу слева: 3174-1L, 3174-23 (без передней крышки), 3174-61R и 3274-41D.

Другие компании, включая Memorex, производили совместимые терминалы и контроллеры. С распространением персональных компьютеров терминалы начали менять на ISA, PCMCIA и потом PCI-карточки, позволявшие подсоединять по тому же коаксиальному кабелю ПК с эмулятором. Позднее, с развитием LAN и TCP/IP эти подсоединения заменил телнет TN3270, которому не требовалось специальное железо или коаксиальный кабель.

Для клиентов, обзаведшихся сетью TCP/IP, но всё ещё пользующихся большим количеством физических терминалов, поздние варианты контроллеров 3174 предлагали возможность соединять их с мейнфреймом телнетом по TCP/IP. Для подсоединения к Hercules нам нужны именно такие контроллеры. Меня очень интересовал тот факт, что они также предлагали эмуляцию VT100, с помощью которой терминал 3270 можно было соединить с хостом на UNIX или VMS так, будто бы это был VT100. Для меня это было странным – ведь терминал заточен под блочную передачу, поэтому эмуляция VT100 кажется невозможной.

Последним терминалом от IBM стал 3483, представленный в конце 1990-х. К тому времени терминалы напоминали уже тонких клиентов и использовали стандартные мониторы VGA и клавиатуры с интерфейсом PS/2.

Разбираемся в протоколе

Изначальный мой поиск навёл меня на описание кабельного подключения и потока данных для 3270. Всё это было хорошо описано, однако там ничего не сказано о протоколе передачи данных между терминалом и контроллером. Его детали я смог найти, только раскопав технические описания устаревших на сегодня чипов, использовавшихся для создания интерфейсов с ПК. Их производили CHIPS и National Semiconductor:

  • CHIPS 82C570
  • NS DP8340
  • NS DP8341
  • NS DP8344

Устройства соединяются друг с другом коаксиальным кабелем с характерным импедансом 93 Ω. Кабель этот имеет тип RG-62 – в отличие от сетей на Ethernet 10BASE2, использующих топологию шины и кабель с импедансом в 50 Ω. Для уменьшения шума в длинных участках кабеля используется разностная передача сигналов, и максимальная рекомендованная длина отрезка между устройствами по спецификации составляет 1,5 км.

Данные идут с битрейтом в 2,3587 Мб/с в Манчестерском кодировании [7]. Эта схема обеспечивает перепад напряжения с низкого уровня на верхний уровень (или наоборот) в рамках каждого бита, что гарантирует надёжную передачу данных до получателя. В каждом кадре [8] содержится одно или несколько 10-битных слов. Каждое слово начинается с бита синхронизации и заканчивается битом чётности. Начало и конец кадра отмечают уникальные последовательности.

Изготовление контроллера терминала IBM 3270 - 3
Вместо тысячи слов… или, как в данном случае, 10 бит. Команда чтения состояния, отправленная с контроллера на терминал.

Все коммуникации инициирует контроллер. Он отправляет на терминал кадр, содержащий управляющее слово и опциональные слова с данными (что-то типа параметров). Терминал отвечает кадром, содержащим одно или несколько слов с данными.

Оказалось, что терминалов существует два типа — CUT и DFT. CUT перекладывают обработку потока данных 3270 на управляющий модуль, и преобразуют их в базовые операции вроде движения курсора по адресу или записи символов в буфер дисплея (он же кадровый буфер [9]). Большую часть функций, которые люди ассоциируют с терминалом 3270, выполняет контроллер – то есть, логика терминала CUT проще, чем у сравнимого по функциональности VT1000. Терминалы DFT могут обрабатывать поток данных 3270 самостоятельно, и контролер просто передаёт поток на терминал.

Подробную документацию [10] протокола я веду на GitHub.

Hello world

На eBay до сих пор можно найти передатчики DP8340 и приёмники DP8341 от National Semiconductor, поэтому я купил их и некоторые другие компоненты, перечисленные в техническом описании. Сначала я думал собрать интерфейс с нуля, однако эти интегральные схемы передатчика и приёмника в итоге обеспечили передачу данных.

Я также нашёл контроллер IBM 3174-23R для установки в стойку с интерфейсом Token Ring [11], и решил, что больше мне ничего и не надо. К сожалению, дискета с управляющей программой оказалась испорченной, и загрузить получалось только диск диагностики. Диагностическая программа показывала менюшки на терминале, чего хватило для перехвата части трафика между терминалом и контроллером для последующего анализа.

Я сделал простую схему приёмника по описанию DP8341 на макетной плате, подключил её к Arduino Mega, и при помощи т-коннектора подключился между контроллером и терминалом. Я был в восторге, впервые увидев поднятие напряжения на контакте DATA AVAILABLE и вызов моего обработчика прерываний. На то, чтобы надёжно считывать данные с приёмника, у меня ушло некоторое время. Вскоре я обнаружил, что памяти в 8 Кб на Arduino Mega мне уже не хватает, а поток данных шёл слишком быстро, чтобы в реальном времени скидывать их на ПК по последовательному порту.

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

Я также перехватил счётчик адресов загрузки и команды на запись данных, связанные с буфером дисплея. Адрес извлечь было легко, однако сначала я не нашёл данных, записываемых в буфер дисплея, в ожидаемой мною кодировке EBCDIC [12] (я ждал её, учитывая схему работы диагностического интерфейса на терминале). Также это была и не ASCII – оказалось, что терминал использует свою кодировку символов. Как она называется, я не знаю, и отсылок к ней я не нашёл. Большую часть кодировки я смог разметить при помощи диагностического интерфейса. А когда я добавил на макетную плату передатчик DP8340, то смог полностью разметить все символы – сначала, конечно же, выведя на экран «hello world»!

У терминала 3270 есть строка состояния, которая выводится в самом низу экрана. Ею, за исключением текущей позиции курсора, управляет контроллер. Сбивает с толку, что строка состояния начинается с адреса 0 в буфере экрана, хотя находится в самом низу – а адрес 80 соответствует верхней левой ячейке в режиме 80 столбцов. Также кодировка символов в строке состояния отличается от остальных, и в неё входят много необычных символов.

В итоге я смог написать библиотеку для Python, pycoax [13], для сериализации [14] и десериализации кадров 3270. Код на Python работает на ПК и общается с Arduino по последовательному порту (физически через USB).

Наконец, я разработал свою первую печатную плату при помощи KiCad и отправил на изготовление в JLCPCB. Спустя неделю и $15, я получил 5 «шилдов» для Arduino, готовых к сборке. Плата работает значительно лучше макетной, количество ошибок заметно уменьшилось. Да, и признаюсь, что мне пришлось заказывать плату дважды, поскольку в первый раз я совершил ошибку при разводке.

Изготовление контроллера терминала IBM 3270 - 4
Arduino Mega и шилд-интерфейс для коаксиала

Создание oec

Моей целью было создать замену контроллеру IBM 3174, которую можно было бы использовать совместно с Hercules. Теперь, когда я понял, что терминал типа CUT не обрабатывают поток данных 3270 самостоятельно, я понял, что реализовать сначала эмуляцию VT100 будет гораздо проще, чем TN3270.

Я нашёл pyte [15], обеспечивающий эмуляцию VT100 в памяти, и поддерживающий подключение к процессу (типа командной оболочки или SSH). Мне нужно было только опрашивать терминал на предмет нажатий клавиш, передавать их процессу, обновлять эмулятор pyte, передавая ему выходные данные с процесса, а потом выводить эмулированный экран терминала на сам терминале. А кроме этого ещё нужно было следить, включен терминал или отключен, и отслеживать здоровье процесса.

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

Вдохновившись pyte, я написал pytn3270 [16], быблиотеку TN3270 на чистом Python, обеспечивающую похожую эмуляцию в памяти. Для интеграции с контроллером потребовалось сопоставить атрибуты полей байту атрибутов терминала 3270. Я мог бы использовать x3270, однако мне хотелось лучше разобраться в протоколе telnet и потоке данных 3270. Для протокола TN3270 я реализовал необходимый минимум – но его достаточно для подключения к z/OS, а библиотека на чистом Python может оказаться полезной и вне этого проекта.

На сегодня oec ещё далёк от поддержки абсолютно всех функций контроллера IBM 3174, однако пользоваться им можно. Скачать его можно с GitHub [17].

Будущее

Во-первых, хочу добавить меню связи, чтобы можно было выбирать хоста (пока что мы умеем подключаться только к одному хосту) и поддержку нескольких логических терминалов. Потом добавлю поддержку EAB и TN3270E – для этого мне нужно будет реализовать некоторые функции в pytn3270, которых пока не хватает.

Пока я работаю над интерфейсом на основе FPGA, чтобы не полагаться на устаревшие микросхемы от National Semiconductor – и в процессе изучаю протокол и немного Verilog [18].

Автор: Вячеслав Голованов

Источник [19]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/staroe-zhelezo/354321

Ссылки в тексте:

[1] эмулятору Hercules: https://en.wikipedia.org/wiki/Hercules_(emulator)

[2] терминал 3278: https://terminals-wiki.org/wiki/index.php/IBM_3278

[3] блочной системе: https://en.wikipedia.org/wiki/Computer_terminal

[4] Поток данных 3270: https://www.ibm.com/support/knowledgecenter/zosbasics/com.ibm.zos.znetwork/znetwork_262.htm

[5] топологии «звезда»: https://ru.wikipedia.org/wiki/%D0%A1%D0%B5%D1%82%D0%B5%D0%B2%D0%B0%D1%8F_%D1%82%D0%BE%D0%BF%D0%BE%D0%BB%D0%BE%D0%B3%D0%B8%D1%8F

[6] балуна: https://ru.wikipedia.org/wiki/%D0%91%D0%B0%D0%BB%D1%83%D0%BD

[7] Манчестерском кодировании: https://ru.wikipedia.org/wiki/%D0%9C%D0%B0%D0%BD%D1%87%D0%B5%D1%81%D1%82%D0%B5%D1%80%D1%81%D0%BA%D0%BE%D0%B5_%D0%BA%D0%BE%D0%B4%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5

[8] кадре: https://ru.wikipedia.org/wiki/%D0%9A%D0%B0%D0%B4%D1%80_(%D1%82%D0%B5%D0%BB%D0%B5%D0%BA%D0%BE%D0%BC%D0%BC%D1%83%D0%BD%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8)

[9] кадровый буфер: https://ru.wikipedia.org/wiki/%D0%9A%D0%B0%D0%B4%D1%80%D0%BE%D0%B2%D1%8B%D0%B9_%D0%B1%D1%83%D1%84%D0%B5%D1%80

[10] Подробную документацию: https://github.com/lowobservable/coax/tree/master/protocol/protocol.md

[11] Token Ring: https://ru.wikipedia.org/wiki/Token_ring

[12] EBCDIC: https://ru.wikipedia.org/wiki/EBCDIC

[13] pycoax: https://github.com/lowobservable/coax/tree/master/pycoax

[14] сериализации: https://ru.wikipedia.org/wiki/%D0%A1%D0%B5%D1%80%D0%B8%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F

[15] pyte: https://pyte.readthedocs.io/en/latest/

[16] pytn3270: https://github.com/lowobservable/pytn3270

[17] Скачать его можно с GitHub: https://github.com/lowobservable/oec

[18] Verilog: https://ru.wikipedia.org/wiki/Verilog

[19] Источник: https://habr.com/ru/post/507668/?utm_source=habrahabr&utm_medium=rss&utm_campaign=507668