Код
- 1 -
В каждой глупости есть
своя доля логики, особен-
но, если там ее найти.
Уважаемые читатели! Вы держите в руках текст 326 прошивки в
блоке КНГМД. Он получен дизассемблированием программы, зашитой
в микросхеме КР1801РЕ2-326. Этот текст появился на свет благо-
даря дизассемблеру DIZAKS4 v4 17.04.88 (KSA corp.), текстовому
редактору EDALT3E (фирма ALTEC), моему желанию, ну, и конечно,
дисководу.
На сегодня все больше и больше людей приобретают дисководы
и подключают их к БК. Но очень мало тех, кто знает, как работа-
ет их любимый дисковод. У нас на БК стало дурной традицией сде-
лать что-нибудь хорошее, а всю информацию, как и с чем это
едят, припрятать или раздать очень узкому кругу лиц. Кстати,
это повелось с выпуска самой БК. Ее пустили в продажу, а ни
схем, ни описания принципов работы не опубликовали. Думаю, что
если бы это сделали, то в 1989 году мы бы уже имели на БК дис-
ковод, расширение памяти, и, следовательно, много хороших прог-
рамм. Точно так же произошло с контроллером дисковода. Господин
Саяпин написал драйвер для работы с НГМД, а информацию по этому
драйверу никому не дал. Кстати, я его в этом не виню, может
быть, эту информацию у него никто и не просил. Имеются, конеч-
но, какие-то обрывки, но полной информации все же нет. Вот по-
чему я принялся за эту каторжную работу. Понять и прокомменти-
ровать эту программу было довольно сложно, так как в своем рас-
поряжении я имел всего лишь распределение ячеек в рабочей об-
ласти драйвера, известное по руководству системного программис-
та для БК0011.
Конечно, это не исходник, но я думаю, что с помощью данного
текста Вы сможете кое-что узнать об этой прошивке и составить о
ней собственное мнение. Думаю, что Вы поймете, что эта програм-
ма далека от совершенства, что многие операции можно было сде-
лать лучше, и что в некоторых случаях применялись не самые хо-
рошие алгоритмы.
Самое главное, что теперь это положение не изменить, так как
эта прошивка стала стандартной для БК, и ее изменение приведет
к несовместимости некоторых программ с новой зашивкой. Хотя,
конечно, это относится только к таким программам, которые ис-
пользуют подпрограммы зашивки не через стандартные точки входа.
Вот вроде и все что я хотел сказать по этому поводу. Сидите,
разбирайтесь. Огромная просьба к тем, кто заметит допущенные
неточности, ошибки или имеет сказать что-нибудь интересное по
этому поводу - позвоните мне, и мы с Вами поговорим об этом.
Москва 1993 г. Гаршенин К.В. (095)4675093
Дополнения и исправления внесли:
Войлуков А.А, Рузаков А.С. - 1992
"Black beards" - 1992
Dale Publishing co. - 1992-94
- 2 -
Регистр состояния КНГМД (177130).
Формат регистра по записи.
┌──────┬─────────────────────────────────────────┐
│разряд│ назначение │
├──────┼─────────────────────────────────────────┤
│ 00 │Выбор накопителя с номером 0 │
│ 01 │Выбор накопителя с номером 1 │
│ 02 │Выбор накопителя с номером 2 │
│ 03 │Выбор накопителя с номером 3 │
│ 04 │Включение электродвигателя │
│ 05 │Выбор головки накопителя: 0=верх. 1=нижн.│
│ 06 │Направление шага │
│ 07 │Шаг │
│ 08 │Признак "НАЧАЛО ЧТЕНИЯ" │
│ 09 │Признак "ЗАПИСЬ МАРКЕРА" │
│ 10 │Переключение схемы прекоррекции │
│11-15 │Не используются │
└──────┴─────────────────────────────────────────┘
Формат регистра по чтению.
┌────────┬──────────────────────────────────────┐
│ разряд │ назначение │
├────────┼──────────────────────────────────────┤
│ 00 │Признак "дорожка 00" │
│ 01 │Признак готовности накопителя │
│ 02 │Запрет записи │
│ 07 │Требование съема информации с регистра│
│ │данных или записи в него нового кода │
│ 14 │В режиме чтения признак записи цикли-│
│ │ческого контрольного кода на диск │
│ 15 │Индекс │
│3-6 8-13│Не используются │
└────────┴──────────────────────────────────────┘
Регистр данных КНГМД (177132).
Все разряды регистра доступны по чтению и записи.
Драйвер НГМД размещен в ПЗУ, находящемся в контроллере НГМД,
и доступен при подключении контроллера к микро-ЭВМ.
Для работы драйвера необходима область ОЗУ размером 66 байт
для размещения параметров и рабочих ячеек.
- 3 -
Формат рабочей оласти драйвера:
┌───────┬────┬──────┬────────┬────────────────────────────────┐
│Смеще- │Дли-│Симво-│Началь- │ Назначение ячейки │
│ние от │на, │личес-│ное зна-│ │
│начала │байт│кое │чение │ │
│области│ │имя │ │ │
├───────┼────┼──────┼────────┼────────────────────────────────┤
│ 0 │ 2 │CSRW │ 000000 │Копия по записи РС КНГМД │
│ 2 │ 2 │CURTRK│ - │Адрес текущей дорожки │
│ 4 │ 4 │TRKTAB│ 177777 │Таблица текущих дорожек (*) │
│ 10 │ 2 │TDOWN │ 020000 │Задержка опускания головки │
│ 12 │ 2 │TSTEP │ - │Задержка перехода дорожки │
│ 14 │ 1 │TRKCOR│ 000036 │Дорожка начала предкомпенсации │
│ 15 │ 1 │BRETRY│ 000030 │Число попыток повтора при ошибке│
│ 16 │ 1 │FLAGS │ 000000 │Рабочая ячейка драйвера (**) │
│ 17 │ 1 │FILLB │ - │Код заполнения при форматиров. │
│ 20 │ 2 │FLGPTR│ - │Указатель на байт признаков │
│ 22 │ 4 │FLGTAB│ 000000 │Таблица признаков (***) │
│ 26 │ 2 │ADDR │ - │Адрес буфера ОЗУ │
│ 30 │ 2 │WCNT │ - │Число слов для пересылки │
│ 32 │ 1 │SIDE │ - │Номер стороны диска │
│ 33 │ 1 │TRK │ - │Номер дорожки │
│ 34 │ 1 │UNIT │ - │Номер привода │
│ 35 │ 1 │SECTOR│ - │Номер сектора │
│ 36 │ 2 │WRTVAR│ (****) │Записываемое значение при форм. │
│ 40 │ 2 │MARKER│ (****) │Буфер маркера при записи │
│ 42 │ 2 │FREE │ (****) │Размер пустого остатка сектора │
│ 44 │ 2 │INTIME│ (****) │Время от перепада индекса │
│ 46 │ 2 │BUF4 │ (****) │Буфер @#4 │
│ 50 │ 2 │BUFSP │ (****) │Буфер SP │
│ 52 │ 2 │BUFPSW│ (*+**) │Буфер PSW │
│ 54 │ 1 │CRETRY│ (****) │Счетчик повторов по BRETRY │
│ 55 │ 1 │TURNS │ (****) │Число оборотов диска на операцию│
│ 56 │ 1 │SECRET│ (****) │Число повторных поисков сектора │
│ 57 │ 1 │ERRNUM│ (****) │Буфер для номера ошибки │
│ 60 │ 2 │MAXSEC│ 000012 │Число секторов на дорожке │
│ 62 │ 2 │HOLTIN│ - │Время задержки после индекса │
│ 64 │ 2 │SECLEN│ 000400 │Длина сектора в словах (*****) │
└───────┴────┴──────┴────────┴────────────────────────────────┘
(*) Старший бит каждого байта при установке в 1 задает воз-
врат соответствующего дисковода к дорожке 00 перед операцией
позиционирования (для случая, когда положение головки заранее
неизвестно).
(**) Флаги имеют следующие значения:
Бит 0 (001) - разрешение читать/записывать скрытые данные
Бит 2 (004) - двигатель уже был включен перед операцией
Бит 4 (020) - признак записи информации на диск
Бит 5 (040) - текущее состояние индекса
Бит 6 (100) - отмена двойного шага при возврате на 00.
- 4 -
(***) Таблица признаков содержит по одному байту на привод и
используется для обработки нестандартных дисков. В каждом байте
используется четыре бита для указания параметров операции.
Бит 0 - при установке драйвер производит пропуск дорожек при
поиске, т.е. фактически обрабатываются лишь четные дорожки. Эта
возможность используется для обработки на 80-дорожечном диско-
воде 40-дорожечных дисков;
Бит 1 - при установке драйвер производит обращение только
к нижней стороне диска. Эта возможность используется при под-
ключении одностороннего дисковода, а также при обработке на
двустороннем дисководе односторонних дисков;
Бит 2 - при установке обрабатываются сектора длиной 2000
байт, иначе - 1000 байт (Внимание! Работа с секторами длиной
2000 байт организована неверно!);
Бит 3 - при установке начало первого сектора задается задер-
жкой HOLTIN от индекса, в противном случае - своим заголовком.
(****) Значения заносятся в процессе работы драйвера.
(*****) Внимание! Следите, чтобы при записи ячейка SECLEN
содержала соответствующее значение, в противном случае портится
разметка диска!
Перед самым первым вызовом драйвера нужно инициализировать
рабочую область. Это делает специальная подпрограмма инициали-
зацми.
После завершения операций обмена с диском драйвер оставляет
двигатель дисковода включенным. Для остановки двигателя про-
грамма пользователя должна обнулить ячейки @#177130 и CSRW.
Просьба не выключать двигатель командой RESET, думайте о тех,
кто имеет БК0010+ДОЗУ32Кб.
Диагностика ошибок в драйвере НГМД.
При возникновении ошибки бит С в слове состояния процессора
устанавливается в 1 и в байт @#52 помещается код ошибки:
1 При чтении - ошибка CRC в зоне данных
При записи - установлена защита записи
2 Ошибка CRC в зоне заголовка сектора
3 Нет позиционирования на нулевую дорожку
4 Ошибка позиционирования
5 Не найден сектор
6 Нет диска или диск не вращается
7 Прерывание по вектору 4 во время операции
10 Не найден адресный маркер
11 Не найден маркер данных
12 Недопустимые параметры команды или нестандартный формат
диска
13 Попытка считывания скрытых данных без соответствующего
разрешения
ъ - 5 -
Драйвер имеет несколько точек входа:
160000 Автоматическая загрузка
160002 Загрузка с выбранного привода
160004 Чтение-запись по номеру блока
160006 Чтение-запись по номеру сектора
160010 Инициализация рабочей области драйвера
160012 Форматирование дорожки
Автоматическая загрузка
Вызов:
JSR PC,@#160000
Можно также произвести загрузку непосредственно из пускового
монитора:
<СТОП>С160000<ВВОД>
Входные параметры отсутствуют.
Действие: производится попытка загрузить операционную систе-
му с привода 0. Если попытка загрузки была неудачной, то драй-
вер пытается загрузить систему с 1 привода. Если все попытки
оказались неудачными, драйвер возвращает управление с установ-
ленным битом "C" процессора.
Алгоритм загрузки:
1. Инициализируется рабочая область драйвера в ОЗУ (базовый
адрес 2000) с параметрами для НГМД 6022;
2. В ОЗУ, начиная с адреса 1000, считывается сектор 1 дорож-
ки 0 выбранного дисковода;
3. В следующих случаях:
- в приводе нет диска;
- привод не защелкнут;
- привод неисправен;
- диск не отформатирован;
- ошибка чтения;
- отсутствует начальный загрузчик,
попытка загрузки считается неудачной. При успешной загрузке
драйвер передает управление по адресу 1000, при этом в R0 поме-
щается номер привода, с которого производилась загрузка.
Драйвер прошивки 253 пытается загрузиться с приводов 0...3.
Поскольку он использует EMT 0,16,122, их необходимо перехваты-
вать. EMT 112 заменяется на NOP, ЕМТ 0 восстанавливает стек.
Загрузка с выбранного привода
Вызов:
MOV #N,R0
JSR PC,@#160002
ИЗ ВСТРОЕННЫХ МОНИТОРОВ БК ВЫБОРОЧНАЯ ЗАГРУЗКА НЕВОЗМОЖНА.
Действие аналогично предыдущему пункту, но загрузка начина-
ется сразу с выбранного привода, и при неудачной загрузке попы-
ток загрузиться с других приводов не предпринимается.
- 6 -
Чтение-запись логического блока
Вызов:
JSR PC,@#160004 ;BCC WORK или BCS ERROR
Входные параметры:
R0 - номер блока на диске;
R1 - длина пересылаемого массива в словах;
R2 - начальный адрес массива данных;
R3 - базовый адрес рабочей области драйвера;
в рабочей области: UNIT - номер привода.
Блок является логической единицей информации на внешних но-
сителях и равен 1000 байт. В используемом формате записи размер
блока совпадает с размером сектора. Первый сектор нулевой до-
рожки нижней стороны соответствует блоку 0. Вычисление номера
сектора и дорожки по номеру блока производится с учетом уста-
новленных признаков в таблице FLGTAB. Алговитм этого вычисления
совпадает с алгоритмом драйвера MY для микроЭВМ ДВК.
Длина массива данных задает число слов, подлежащих пересыл-
ке, а также тип операции: положительное - чтение, отрицательное
- запись. При записи пересылаемое число слов равно абсолютному
значению длины. Если заданное число слов превышает размер сек-
тора, осуществляется автоматический переход к следующему секто-
ру, а если необходимо, то и на другую сторону и дорожку. Если
при записи число слов не кратно размеру сектора, то остаток
последнего сектора заполняется нулями.
Перед самым первым вызовом драйвера поля CSRW, TRKTAB, FLAGS
в рабочей области должны быть заполнены значениями, указанными
в таблице, и не должны изменяться программой пользователя. Поля
TDOWN, TSTEP, TRKCOR, BRETRY, FLGTAB рекомендуется заполнять
значениями, указанными в таблице, однако они могут быть измене-
ны в зависимости от конкретных условий.
Возврат из драйвера осуществляется командой RTS PC, содержи-
мое регистров (кроме R3) не сохраняется.
Возникновение прерывания по вектору 4 при записи на диск
приводит к появлению сбоя в секторе, в который производилась
запись. Сбой может быть устранен повторной записью этого секто-
ра.
Чтение-запись по номеру сектора и дорожки
Вызов:
JSR PC,@#160006
Входные параметры:
R3 - адрес рабочей области;
ADDR - начальный адрес массива данных;
WCNT - длина массива данных;
SIDE - номер стороны (0 - нижняя, 1 - верхняя);
TRK - номер дорожки;
UNIT - номер привода (0...3);
SECTOR - номер сектора (1...12).
Действие аналогично предыдущему пункту.
- 7 -
Инициализация рабочей области
Эта точка входа является вспомогательной и служит для облег-
чения написания программ, использующих драйвер НГМД.
Вызов:
JSR PC,@#160010
Входной параметр:
R3 - базовый адрес рабочей области.
Действие: заполняются следующие поля рабочей области:
CSRW - 0
TRKTAB - 177777,177777
TDOWN - 10000
TSTEP - 10000
TRKCOR - 30. (253); 32. (326)
BRETRY - 30. (253); 20. (326)
FLAGS - 0
FLGTAB - 0,0
MAXSEC - 12 (только 326)
Форматирование дорожки
Вызов:
JSR PC,@#160012
Входные параметры:
R3 - базовый адрес рабочей области;
FILLB - код заполнения секторов при форматировании;
SIDE - номер стороны;
TRK - номер дорожки;
UNIT - номер привода.
Действие: форматируется указанная дорожка с указанной сторо-
ны, поле данных всех секторов заполняется кодом FILLB.
Команды расширенной арифметики
В 326 прошивке помимо драйвера дисковода зашит эмулятор ко-
манд расширенной арифметики процессора К1801ВМ2, т.е. на данной
машине возможно использование программного обеспечения, напи-
санного для этого процессора.
Для организации работы с блоком расширенной арифметики необ-
ходимо перед ее использованием в программе инициализировать
эмулятор. Инициализация производится занесением в ячейку @#10
числа 160016. При поступлении кода команды расширенной арифме-
тики происходит прерывание по вектору 10 и обработка соответ-
ствующей команды.
- 8 -
Мнемоника команд расширенной арифметики реализована в ассем-
блерах MICRO Коренкова В.С., TURBO Надежина А.М:
1. MUL S,Rn Деление
2. DIV S,Rn Умножение
3. FMUL Rn Умножение с плавающей запятой
4. FDIV Rn Деление с плавающей запятой
5. FADD Rn Сложение чисел с плавающей запятой
6. FSUB Rn Вычитание чисел с плавающей запятой
7. ASH S,Rn Арифметический сдвиг на заданное число бит
8. ASHC S,Rn Арифметический сдвиг двойного слова на заданное
число бит
Автор не стал комментировать блок расширенной арифметики,
т.к. его основной целью было комментирование работы драйвера
дисковода.
Описание команд расширенной арифметики.
DIV S,D
Деление 32-разрядного слова RnRn+1 на число или регистр. Ре-
гистр результата (D) в команде должен быть четным.
MOV #75.,R1
CLR R0
DIV #10.,R0 ;Деление числа 75. на 10.
;R0 - результат, R1 - остаток.
MUL S,D
Умножение регистра на число. Если номер регистра нечетный,
сохраняется младшая часть результата. Регистр результата (D)
должен быть нечетным.
MOV #7,R1
MUL #10.,R1 ;умножение 7*10.=70. в регистре R1.
ASH S,D
Арифметический сдвиг регистра вправо/влево на (-32...+32)
позиции в зависимости от значения 5-го бита аргумента сдвига.
При 1 в 5 бите - сдвиг вправо, при 0 - влево.
ASH #5,R1 ;сдвиг регистра R1 на 5 позиций влево.
ASHC S,D
Арифметический сдвиг двойного слова, причем регистр с нечет-
ным номером содержит младшую часть слова, а с четным - старшую,
остальное аналогично команде ASH.
- 9 -
FADD Rn
Сложение чисел с плавающей запятой. Регистр указывает на ад-
рес нахождения аргументов. A←A+B - результат помещается на мес-
то аргумента A.
FSUB Rn
Вычитание чисел с плавающей запятой. A←A-B - результат в A.
FSUB R5 ;R5 указывает на адрес MET
HALT
MET: A ;два слова аргумента A
B ;два слова аргумента B
Формат чисел с плавающей запятой:
Первое слово : 15 14 07 06 00
├───┼─────────┼───┼──────────────────┤
S Порядок ст. часть мантиссы
Второе слово : 15 00
├────────────────────────────────────┤
младшая часть мантиссы
FMUL Rn
Умножение чисел с плавающей запятой. A←A*B - результат на
месте аргумента A.
FDIV Rn
Деление чисел с плавающей запятой. A←A/B - результат на мес-
те аргумента A. Если делитель (B) равен нулю, то результат в
стек не записывается.
Подробнее об использовании команд расширенной арифметики
можно узнать в документациях к программам MICRO или TURBO.
Коренков Василий Семенович тел. (095) 4359514
Надежин Алексей тел. (095) 1803002
ъ - 10 -
BR BOOT0 ;Aвтоматическая загрузка 160000
BR BOOT1 ;Загрузка с выбранного привода 160002
BR RWBLK ;Чтение-запись по номеру блока 160004
BR RWSEC ;Чтение-запись по номеру сектора 160006
BR INIT ;Инициализация рабочей области 160010
JMP FORMAT ;Форматирование дорожки 160012
JMP EXT ;Расширенная арифметика 160016
*** 160022 П/п автоматической загрузки ***
BOOT0: CLR R0 ;Начнем с нулевого привода
CALL BOOT ;Пробуем загрузиться
MOV #1,R0 ;Там не получилось, попробуем с первого
CALL BOOT ;Загружаем...
BR STOP ;Загрузчика нигде нет, выходим
*** 160042 Загрузка с выбранного привода ***
BOOT1: MOV #1000,SP ;Установим стек
CALL BOOT ;Попробуем загрузиться
*** 160052 Остановка двигателя НГМД и выход из п/п ***
STOP: CLR (R3)
CLR @#177130
CLR @#177760
RET
*** 160066 П/п загрузки и запуска загрузчика ***
BOOT: MOV #2000,R3 ;Установим адрес рабочей области
CALL INIT ; и инициализируем ее
MOVB R0,34(R3) ;Занесем номер привода
CLR R0 ;Читаем нулевой блок
MOV #400,R1 ; длиной 400 слов (1000 байт)
MOV #1000,R2 ; с адреса 1000
CALL RWBLK ;Прочитаем...
BCS 1$ ; не получилось - выход
CMP @#1000,#240 ;Загрузчик начинается с NOP?
BNE 1$ ;Нет - выход
CMP @#1002,#5 ;Вторая команда - RESET?
BEQ 1$ ;Да - диск не системный, выход
MOVB 34(R3),R0 ;Вспомним, откуда это мы загрузились
CALL @#1000 ;Запускаем загрузчик...
1$: RET ;Вот и все
*** 160154 Чтение-запись по номеру сектора ***
RWSEC: BR SUBRW
*** 160156 П/п инициализации рабочей области ***
INIT: CLR (R3) ;Очистим копию РС КНГМД
MOV #177777,4(R3);Заполним таблицу текущих дорожек
MOV #177777,6(R3)
MOV #23420,10(R3);Время опускания головки
MOV #23420,12(R3);Время перехода дорожки
MOVB #40,14(R3) ;Дорожка начала предкомпенсации
- 11 -
MOVB #24,15(R3) ;Число повторов при ошибке
CLRB 16(R3) ;Очистим флаги
CLR 22(R3) ; и таблицу признаков
CLR 24(R3)
MOV #12,60(R3) ;Занесем число секторов на дорожке
RET
*** 160250 П/п чтения-записи по номеру блока ***
Входные параметры:
R0 - номер блока
R1 - длина массива в словах (отрицательная - запись)
R2 - адрес начала массива
R3 - адрес рабочей области
RWBLK: MOV #10,R4
MOVB 60(R3),R5;число секторов на дорожке
SWAB R5 ;делим ст. байт R0 на ст. байт R5
1$: CMP R5,R0
BHI 2$
SUB R5,R0
SEC
2$: ROL R0 ;Частное накапливается в мл. байте R0
SOB R4,1$
MOVB R0,R4 ;В мл. байте номер дорожки, сохраним его
CLRB R0
SWAB R0 ;Получили остаток от деления
INC R0 ;Номер сектора на единичку больше
CLRB 32(R3) ;Пока мы на нижней стороне
CMP R0,60(R3);Этот сектор за пределами дорожки?
BLE 3$ ;Нет - полный порядок
INCB 32(R3) ;Да - значит, он на другой стороне
SUB 60(R3),R0; и номер у него другой
3$: CALL SETPTR ;Установим указатель на байт признаков
BITB #2,@20(R3);Диск односторонний?
BEQ 4$ ;Нет - оставим все как есть
ASRB 32(R3) ;Да - сторона всегда 0,
ROLB R4 ; а дорожка уже другая
4$: MOVB R4,33(R3);Запишем результаты: дорожка,
MOVB R0,35(R3); сектор,
MOV R1,30(R3); число слов,
MOV R2,26(R3); адрес буфера
*** 160372 П/п чтения-записи по номеру сектора ***
Входные параметры:
R3 - базовый адрес рабочей области
ADDR, WCNT, SIDE, TRK, UNIT, SECTOR - соответственно
SUBRW: MOV SP,50(R3) ;Сохраняем SP,
MFPS 52(R3) ; PSW,
MOV #4,R0
MOV (R0),46(R3) ; @#4 в соответствующих буферах
MOV PC,(R0) ;Переназначаем вектор @#4 на себя,
ADD #1076,(R0) ; теперь он равен 161512
TSTB 35(R3) ;Какой сектор нужен?
BEQ ERR12 ;Нулевых у нас нет, ошибка 12
CMPB 35(R3),60(R3);Сектор больше максимального?
BGT ERR12 ;Таких тоже нет, ошибка 12
- 12 -
CLRB @#52 ;Пока ошибок нет
BICB #30,16(R3) ;Пока не записываем
TST 30(R3) ;Сколько слов будем пересылать?
BEQ QUIT ;0 - ничего делать не надо, выход
BPL READ ;больше 0 - будем читать
*** 160460 П/п записи массива ***
NEG 30(R3) ;Нормализуем длину
BISB #20,16(R3) ;Установим признак записи
MOV #175641,40(R3);Запомним маркер данных
BITB #1,16(R3) ;Записываем скрытно?
BEQ 1$ ;Нет - идем дальше
MOV #174241,40(R3);Да - запомним специальный маркер
1$: CALL ENGINE ;Включим двигатель, запомним привод
BIT #4,(R4) ;Защита записи есть?
BEQ MAIN ;Нет - продолжить работу
MOV #1,R0 ;Есть - ошибка 1
BR ERR
*** 160536 П/п чтения массива ***
READ: CALL ENGINE ;Включим двигатель, запомним привод
MOV #400,64(R3) ;Сектора стандартной длины
BITB #4,@20(R3) ;А они ли нам нужны?
BEQ MAIN ;Да - продолжить работу
MOV #1000,64(R3) ;Нет - секторы удвоенной длины
*** Основная часть п/п чтения/записи массива ***
MAIN: CALL GOTRK ;Спозиционируем на нужную дорожку
CALL CORR ;Включим схему прекоррекции
MOVB 15(R3),54(R3);Число попыток - в буфер
*** Получение заголовка сектора ***
MOVB #10,57(R3) ;Предполагаем ошибку 10
MOVB #24,55(R3) ;На операцию отводим 20. оборотов
1$: CALL FINDH ;Найдем маркер заголовка
BCC 3$ ;Нашли - идем дальше
2$: MOVB 57(R3),R0 ;Не нашли - выходим с ошибкой
BR ERR
3$: TSTB (R4) ;Информация получена?
BPL 3$ ;Нет - подождем
MOV (R5),R0 ;Теперь прочитаем ее
4$: TSTB (R4) ;Хотим еще информации!
BPL 4$ ;Дождемся ее появления
MOV (R5),R1 ; и заберем ее
CALL TSTCRC ;Проверим CRC
BNE 5$ ;Ошибки нет - идем дальше
MOVB #2,57(R3) ;Ошибка 2!
DECB 54(R3) ;Остались еще попытки?
BNE 1$ ;Да - повторим чтение
BR 2$ ;Видно, не судьба! Выходим с ошибкой
5$: BIC #177774,R1 ;Выделяем код длины сектора
BITB #4,@20(R3) ;Какие сектора нам были нужны?
BNE LONG ;Длинные - посмотрим...
CMPB R1,#2 ;Короткие. А на диске какие?
BEQ WORK ;Тоже короткие. Порядок, идем дальше
ъ - 13 -
DECB 54(R3) ;Как там дела с попытками?
BNE 1$ ;Есть еще - повторим все сначала
*** 160724 Выход с ошибкой ***
ERR12: MOV #12,R0 ;Выходим с ошибкой 12
ERR: JMP ERROR ;Идем на обработку и выход
QUIT: JMP EXIT ;Идем на нормальный выход
LONG: CMPB R1,#2 ;Нужны длинные сектора, а какие здесь?
; ОШИБКА: На самом деле код длинных
; секторов - 3, а не 2
BNE ERR12 ;Длинные - выходим с ошибкой 12
*** Собственно п/п чтения ***
WORK: MOVB 15(R3),54(R3);Восстановим счетчик по BRETRY
MOVB #6,56(R3) ;На поиск сектора - 6 попыток
CLR 42(R3) ;Остаток сектора отсутствует
CMP 30(R3),64(R3);Читать надо больше одного сектора?
BHI 1$ ;Да - идем читать
MOV 64(R3),42(R3)
SUB 30(R3),42(R3);Вычислим длину остатка
1$: MOVB #5,57(R3) ;Прогнозируем ошибку 5
2$: MOVB #24,55(R3) ;На операцию отводим 20. оборотов
3$: CALL FINDH ;Ищем маркер заголовка
BCC 4$ ;Нашли - идем дальше
MOVB 57(R3),R0 ;Кончились обороты - выходим
BR ERR ; с ошибкой
4$: TSTB (R4) ;Готовность данных есть?
BPL 4$ ;Нет - подождем
CMP 32(R3),(R5) ;Нужная дорожка и сторона?
BEQ 5$ ;Да - идем дальше
DECB 56(R3) ;Минус одна попытка
BEQ 6$ ;Кончились - выход с ошибкой
CALL GOTO00 ;Спозиционируем на дорожку 00,
CALL GOTRK ; вернемся на нужную
BR 3$ ; и попытаемся еще раз
6$: MOV #4,R0 ;Выходим с ошибкой 4
BR ERR
5$: TSTB (R4) ;Ждем готовности данных
BPL 5$ ;Не готовы - повторять...
MOV (R5),R1 ;Получим номер сектора,
SWAB R1 ; поместим его в младший байт
CMPB 35(R3),R1 ;Этот сектор ищем?
BEQ 7$ ;Да - будем его читать
MOV 64(R3),R0 ;Нет - возьмем длину данных,
ADD #27,R0 ; прибавим длину заголовка
CALL FICT ; и пропустим их
BR 3$ ;Повторим процедуру еще раз
7$: CALL TSTCRC ;Проверим CRC
BNE 8$ ;Совпала - идем дальше
MOVB #2,57(R3) ;Если что, это будет ошибка 2
DECB 54(R3) ;Одной попыткой меньше
BNE 2$ ;Еще остались - поищем снова
MOVB 57(R3),R0 ;Нет - выходим с ошибкой
BR ERROR
8$: MOV 64(R3),R1 ;Получим длину сектора
SUB 42(R3),R1 ;Вычислим длину используемой части
- 14 -
*** 161176 Чтение сектора ***
BITB #20,16(R3);Будем записывать?
BEQ 9$ ;Нет - значит, читать
JMP WRSEC ;Да - идем на запись сектора
9$: CALL FINDS ;Ищем зону синхронизации
TSTB 56(R3) ;Нашли?
BEQ 11$ ;Нет - пробуем снова
CALL STREAD ;Начинаем чтение!
MOV #1130,R0 ;
10$: TSTB (R4) ;Данные готовы?
BMI 12$ ;Да - посмотрим их
SOB R0,10$ ;Больше ждать нельзя?
11$: MOVB #11,57(R3);Да - прогнозируем ошибку 11
DECB 54(R3) ;Одной попыткой меньше
BNE 2$ ;Попытки есть - повторим операцию
MOVB 57(R3),R0;Кончились - выйдем с ошибкой
BR ERROR
12$: TST (R5) ;Пропустим маркер A1A1
13$: TSTB (R4) ;Готовность данных есть?
BPL 13$ ;Нет - ждем
MOV (R5),R0 ;Прочитаем данные
CMP #120773,R0;Обычный сектор?
BEQ 14$ ;Да - идем дальше
CMP #120770,R0;Скрытый сектор?
BNE 11$ ;Что-то иное - ошибка
BITB #1,16(R3);Можно читать скрытые данные?
BNE 14$ ;Да - будем читать
MOV #13,R0 ;Нельзя - выходим с ошибкой 13
BR ERROR
14$: CALL RDSEC ;Прочитаем сектор
CALL TSTCRC ;Проверим CRC
BNE NEXT ;Совпала - посмотрим следующий сектор
MOVB #1,57(R3);Не совпала - ошибка 1
DECB 54(R3) ;Попытки кончились?
BNE 2$ ;Нет - попробуем еще раз
MOVB 57(R3),R0;Кончились - выходим с ошибкой
BR ERROR
*** 161362 Мультисекторные операции **+
NEXT: SUB 64(R3),30(R3);Сектор обработали, вычтем из длины
BLE EXIT ;Массив кончился - выход
INCB 35(R3) ;Нет - следующий сектор
CMPB 35(R3),60(R3);Конец дорожки?
BLOS 3$ ;Нет - продолжим обработку
BIT #40,(R3) ;Верхняя сторона?
BNE 1$ ;Да - следующая дорожка
BITB #2,@20(R3) ;Диск односторонний?
BNE 1$ ;Да - продолжим обработку
MOVB #1,32(R3) ;Нет - установим верхнюю сторону
BIS #40,(R3)
BR 2$ ;Перейдем к обработке
1$: INCB 33(R3) ;Следующая дорожка
CALL GOTRK ;Спозиционируем на нее
CLRB 32(R3) ;Установим нижнюю сторону
BIC #40,(R3)
2$: MOVB #1,35(R3) ;Теперь сектор будет первым
CALL CORR ;Переключить прекоррекцию
- 15 -
3$: ADD 64(R3),26(R3);Получим новый начальный адрес
ADD 64(R3),26(R3)
JMP WORK ;Идем на чтение очередного сектора
*** 161512 Обработка прерывания по вектору 4 ***
TST (R5) ;Сбросить данные
MOV #7,R0 ;Заносим код ошибки 7
*** Выход с ошибкой ***
ERROR: MOVB R0,@#52 ;Код ошибки - на место!
MOVB #1,56(R3);Установим бит C в буфере
BR EXIT1 ;Идем на выход
*** Выход без ошибки ***
EXIT: CLRB 56(R3) ;Сбросим бит C в буфере
EXIT1: MOV 46(R3),@#4;Восстановить вектор 4
MTPS 52(R3) ;Восстановить PSW
CCC ;Сбросить все признаки
RORB 56(R3) ;Бит C - из буфера в PSW
MOV 50(R3),SP;Восстановить SP
RET ;Возврат
*** 161566 П/п проверки CRC ***
TSTCRC: TSTB (R4) ;Ждем готовности данных
BPL TSTCRC
MOV #17,R2 ;CRC появится не позже 15. циклов
1$: BIT #40000,(R4) ;CRC сошлась?
BNE 2$ ;Да - выход
SOB R2,1$ ;Нет - очередной цикл
2$: RET ;Если бит Z=1, то произошла ошибка
*** 161610 П/п чтения сектора в буфер ***
Входные параметры: R1 - число слов для пересылки
RDSEC: MTPS #340 ;Маскируем прерывания
MOV 26(R3),R2;Получим адрес буфера
1$: TSTB (R4) ;Ожидаем данные
BPL 1$
MOV (R5),R0 ;Читаем два байта,
SWAB R0 ; делаем из них нормальное слово,
MOV R0,(R2)+ ; которое суем в буфер
SOB R1,1$ ;Читаем заказанное число слов
MOV 42(R3),R1;Получаем длину остатка
BEQ 3$ ;Остатка нет - сразу выходим
2$: TSTB (R4) ;Ждем данные
BPL 2$
TST (R5) ;Вхолостую читаем остаток
SOB R1,2$ ; требуемой длины
MTPS 52(R3) ;Восстанавливаем PSW
3$: RET
ъ - 16 -
*** 161660 П/п поиска синхропоследовательности ***
FINDS: TST (R5) ;Сбрасываем прочитанное значение
MOVB #144,56(R3) ;Будем искать 100. циклов
1$: TSTB (R4) ;Ждем готовности
BPL 1$
MOV (R5),R0 ;Получим прочитанные данные
BEQ 2$ ;Это 0 - на выход
INC R0 ;Это 177777?
BEQ 2$ ;Да - на выход
DECB 56(R3) ;Циклы кончились?
BNE 1$ ;Нет - повторяем поиск
2$: RET
*** 161714 П/п чтения двух слов (не используется) ***
01$: TSTB (R4) ;Ждем готовности
BPL 01$
MOV (R5),R0 ;Получаем первое слово
02$: TSTB (R4) ;Ждем готовности
BPL 02$
MOV (R5),R1 ;Получаем второе слово
RET
*** 161732 П/п запуска чтения ***
STREAD: BIS #400,(R3);Установим признак "начало чтения"
MOV (R3),(R4); и запишем в регистр
BIC #400,(R3);Снимем признак
MOV #10,R0
1$: SOB R0,1$ ;Небольшая задержка...
MOV (R3),(R4); и снова запишем в регистр
RET
*** 161756 П/п поиска начала индекса (не используется) ***
01$: TST (R4) ;Индекс есть?
BMI 01$ ;Да - ждем исчезновения
BIS #400,(R3);Установим признак "начало чтения"
MOV (R3),(R4); и запишем в регистр
02$: TST (R4) ;Индекса еще нет?
BPL 02$ ;Да - ждать появления
MOV 62(R3),R0
03$: SOB R0,03$ ;Задержимся...
BIC #400,(R3);Сбросим признак "начало чтения"
MOV (R3),(R4); и запишем в регистр
RET
*** 162012 П/п поиска адресного маркера ***
FINDH: MOV #17,R0
1$: TST (R5) ;Вхолостую прочитаем
SOB R0,1$ ; 15. слов
CLR 44(R3) ;Начинаем ожидание индекса
BICB #40,16(R3);Пока индекса нет
2$: BITB #10,@20(R3);Сектор задан задержкой?
BEQ 7$ ;Нет - обрабатывать
CMPB 35(R3),#1;Да - нужен первый сектор?
BNE 7$ ;Второй и далее задаются заголовками
- 17 -
BIS #400,(R3);Установим признак "начало чтения"
MOV (R3),(R4); и перешлем в регистр
3$: TST (R4) ;Индекс есть?
BMI 3$ ;Да - ждем исчезновения
4$: TST (R4) ;Индекс есть?
BPL 4$ ;Нет - ждем появления
DECB 55(R3) ;Один оборот окончен
BNE 5$ ;Не кончились - продолжаем
SEC ;Кончились - выходим с битом C
BR 18$
5$: MOV 62(R3),R0;Получим задержку после индекса
6$: SOB R0,6$
BR 12$ ;Сектор, похоже, найден, идем дальше
7$: CALL INDEX ;Проверим наличие диска и обороты
BCS 18$ ;Обороты кончились - выходим
BEQ 7$ ;Какие данные? Нули пропустим
COM R0 ;177777?
BEQ 7$ ;Да - тоже пропустим
8$: CALL INDEX ;Проверим наличие диска и обороты
BCS 18$ ;Обороты кончились - выходим
BEQ 9$ ;Какие данные? Нули - синхро
COM R0 ;177777?
BNE 8$ ;Нет - пропустим
*** Проверка адресного маркера ***
9$: MOV #3,R1
10$: MOV (R5),R0 ;Читаем данные
BEQ 11$ ;Нули - продолжаем
COM R0 ;177777?
BNE 7$ ;Нет - повторяем поиск
11$: SOB R1,10$ ;Да - повторяем 3 раза
12$: CALL STREAD ;Запускаем на чтение
MOV #74,R0 ;ОШИБКА! Здесь должно быть 2000
13$: TSTB (R4) ;Готовность есть?
BMI 14$ ;Есть - считываем данные
SOB R0,13$ ;Нет - ждем
BR 2$ ;Надоело ждать - повторяем поиск
14$: TST (R5) ;Пропускаем A1A1
15$: TSTB (R4) ;Ждем готовности
BPL 15$
MOV (R5),R0 ;Есть - берем данные
CMP #120776,R0 ;Адресный маркер (A1FE)?
BEQ 17$ ;Да - нормальный выход
CMP #120773,R0 ;Нет - маркер данных (A1FB)?
BEQ 16$ ;Да - пропускаем сектор
CMP #120770,R0 ;Нет - маркер скрытых данных (A1F8)?
BNE 2$ ;Нет - повторяем поиск сначала
16$: CALL FRESEC ;Да - пропускаем сектор
BR 2$ ;Повторяем поиск сначала
17$: CLC
18$: RET
*** 162246 П/п проверки наличия диска и числа оборотов ***
INDEX: TST (R4) ;Индекс есть?
BPL 2$ ;Нет - идем проверять
BITB #40,16(R3) ;Индекс есть - он уже был?
BNE 3$ ;Был - идем увеличивать время
- 18 -
CLR 44(R3) ;Только что появился - очистим время
BISB #40,16(R3) ; и запомним факт появления
DECB 55(R3) ;Закончился последний оборот?
BNE 1$ ;Нет - нормальный выход
SEC ;Да - выход с ошибкой
RET
1$: CLC
MOV (R5),R0 ;Забираем данные
RET
2$: BITB #40,16(R3) ;Индекса нет - а он был?
BEQ 3$ ;Нет и не было - идем считать время
CLR 44(R3) ;Только что исчез - очистим время
BICB #40,16(R3) ; и запомним факт исчезновения
BR 1$ ;Нормально выходим
3$: INC 44(R3) ;Еще один такт индекс не менялся
CMP 44(R3),#60000;Ну сколько можно! Пора кончать?
BLOS 1$ ;Не пора - нормальный выход
MOV #6,R0 ;Терпение кончилось -
JMP ERROR ; значит, диска нет - ошибка 6
*** 162364 П/п выбора устройства ***
ENGINE: MOV #177130,R4 ;Заполняем рабочие регистры
MOV R4,R5 ; адресами РС и
TST (R5)+ ; РД КНГМД
BICB #4,16(R3) ;Очистим признак работы двигателя
BIT #20,(R3) ;Двигатель уже включен?
BEQ 1$ ;Нет - включим
BISB #4,16(R3) ;Да - установим признак
1$: BIS #20,(R3) ;Включим двигатель
MOV (R3),(R4) ; и запишем в регистр
BIC #57,(R3) ;Сбросим все другие режимы
TSTB 32(R3) ;Сторона верхняя?
BEQ 2$ ;Да - идем дальше
BIS #40,(R3) ;Нет - включим нижнюю
2$: BICB #177774,34(R3);Сбросим лишние биты
MOVB 34(R3),R1 ;Получим номер привода
MOV PC,R0 ;Получим базовый адрес
ADD #56,R0 ; таблицы масок для приводов
ADD R1,R0 ;Получим адрес нужной маски
BISB (R0),(R3) ;Установим бит нужного привода
ADD R3,R1 ;Получим базовый адрес
ADD #4,R1 ; таблицы TRKTAB
MOV R1,2(R3) ;Настроим указатель CURTRK
CALL SETPTR ;Настроим указатель FLGPTR
BITB #4,16(R3) ;Мотор включен только что?
BNE 5$ ;Нет - выходим
CLR R1 ;Да - подождем раскручивания
3$: SOB R1,3$
4$: SOB R1,4$
5$: MOV (R3),(R4) ;Записываем установки в регистр
MOV 10(R3),R1 ;Подождем опускания головки
6$: SOB R1,6$
RET
- 19 -
*** Таблица масок для включения приводов ***
.B:1 ;A:
.B:2 ;B:
.B:4 ;C:
.B:10 ;D:
*** 162540 П/п настройки указателя FLGPTR ***
SETPTR: CLR 20(R3) ;Очистим указатель FLGPTR
BICB #177774,34(R3);Отбросим лишние биты
MOVB 34(R3),20(R3);Перешлем номер привода в FLGPTR
ADD R3,20(R3) ;Прибавляя базовый адрес FLGTAB,
ADD #22,20(R3) ; получаем искомый адрес
RET
*** 162574 П/п позиционирования ***
GOTRK: TSTB 33(R3) ;Нужна дорожка 00?
BEQ GOTO00 ;Да - позиционируем прямо на нее
TSTB @2(R3) ;Положение головки известно?
BPL 1$ ;Да - будем искать требуемую
CALL GOTO00 ;Нет - придется сориентироваться
1$: CMPB @2(R3),33(R3);Нужная дорожка совпадает с текущей?
BEQ 3$ ;Да - так что же мы тут делаем?
BHI 2$ ;Нет - искомая ближе к центру?
CALL GOUP ;Да - шагнем к центру
BR 1$ ;Проверим, дошли ли
2$: CALL GODOWN ;Нет - шагнем к периферии
BR 1$ ;Проверим, дошли ли
3$: MOV #23420,R0;Подождем успокоения головки
4$: SOB R0,4$ ;Теперь можно и выйти
RET
*** Шаг к центру ***
GOUP: INCB @2(R3) ;Номер дорожки станет на 1 больше
BMI 1$ ;Таких дорожек нет - выходим с ошибкой
BIS #100,(R3);Все в порядке - шагать будем вперед
BR STEP ;Пойдем шагать
1$: MOV #4,R0 ;Выход с ошибкой 4
JMP ERROR
*** Шаг к периферии ***
GODOWN: DECB @2(R3) ;Номер дорожки станет на 1 меньше
BIT #1,(R4) ;Дошли до дорожки 00?
BEQ 1$ ;Нет - можно шагать
CLRB @2(R3) ;Дошли: теперь текущая - 00
RET ; и можно выйти
1$: BIC #100,(R3);Шагать будем назад
STEP: MOV #310,R0 ;Подготовим задержку
MOV (R3),(R4);Перешлем направление шага в регистр
3$: SOB R0,3$ ;Подождем, пока контроллер "переварит"
BIS #200,(R3);Установим признак шага
MOV (R3),(R4); и запишем в регистр
MOV 12(R3),R0;Получим задержку перехода дорожки
4$: SOB R0,4$ ; и задержимся
- 20 -
BITB #1,@20(R3);Двойной шаг?
BEQ 6$ ;Нет - можно выходить
BITB #100,16(R3);Мы возвращаемся на 00?
BNE 6$ ;Да - возвращаться надо одинарным шагом
MOV (R3),(R4);Нет - придется шагнуть еще
MOV 12(R3),R0;Получим задержку перехода дорожки
5$: SOB R0,5$ ; и задержимся
6$: BIC #200,(R3);Очистим признак шага
RET
*** 163004 П/п возврата на дорожку 00 ***
GOTO00: MOVB #200,@2(R3) ;Установим счетчик дорожек
BISB #100,16(R3) ;Возвращаться надо одинарным шагом
1$: CALL GOUP ;Шагнем к периферии
BIT #1,(R4) ;Дошли до 00?
BNE 2$ ;Да - выходим
TSTB @2(R3) ;На какой дорожке должны находиться?
BNE 1$ ;Не на нулевой - еще шагнем
MOV #3,R0 ;На нулевой, а ее нет - ошибка 3
BICB #100,16(R3) ;Сбросим режим одинарного шага
JMP ERROR ;Выходим с ошибкой
2$: CLRB @2(R3) ;Дошли - текущая теперь нулевая
BICB #100,16(R3) ;Сбросим режим одинарного шага
RET
*** 163072 П/п пропуска сектора ***
FRESEC: MOV 64(R3),R0;Получим длину сектора
FICT: TST (R4) ;Индекс есть?
BMI 4$ ;Да - ждем начала оборота
1$: TST (R4) ;Индекс все еще есть?
BMI 3$ ;Да - оборот завершен
2$: TSTB (R4) ;Данные готовы?
BPL 1$ ;Нет - снова
TST (R5) ;Прочитаем данные вхолостую
SOB R0,1$ ; требуемое число раз
BR 6$ ; и выйдем
3$: DECB 55(R3) ;Все обороты вышли?
BNE 5$ ;Нет - попытаемся снова
MOV #5,R0 ;Да - выходим с ошибкой 5
JMP ERROR
4$: TST (R4) ;Индекс исчез?
BPL 2$ ;Да - оборот начался
5$: TSTB (R4) ;Данные готовы?
BPL 4$ ;Нет - проверим индекс
TST (R5) ;Прочитаем данные вхолостую
SOB R0,4$ ; требуемое число раз
6$: RET ; и вернемся к основной работе
*** 163154 П/п записи сектора ***
Входные параметры:
R1 - число слов для записи
WRSEC: MOV 26(R3),R2;Получим начальный адрес массива
MOV #13,R0 ;В маркере будет 11. 4E4E
MTPS #340 ;При записи нам не мешать!
- 21 -
CALL WRMAR ;Запишем маркер данных
1$: TSTB (R4) ;Готовность есть?
BPL 1$ ;Нет - ждем
MOV (R2)+,(R5);Запишем первое слово данных
MOV (R3),(R4);Снимем признак записи маркера
BR 3$ ; и пойдем записывать данные
2$: TSTB (R4) ;Готовность есть?
BPL 2$ ;Нет - дождемся
MOV (R2)+,(R5);Запишем слово данных
3$: SOB R1,2$ ; и так до конца
MOV 42(R3),R1;Получим длину пустого остатка сектора
BEQ 5$ ;Остатка нет - выходим сразу
4$: TSTB (R4) ;Готовность есть?
BPL 4$ ;Дожидаемся
MOV #0,(R5) ;Записываем нули
SOB R1,4$ ; в нужном количестве
5$: BIT #40000,(R4);Ждем записи CRC
BEQ 5$
MOV #47116,(R5);Записываем 4E4E
6$: TSTB (R4) ;Готовность есть?
BPL 6$ ;Нет - ждем
TST (R5) ;Прекращаем запись
MTPS 52(R3) ;Восстанавливаем PSW
JMP NEXT ;Продолжаем запись массива
*** 163266 П/п записи маркера данных ***
Входные данные:
R0 - число записываемых слов 4Е4Е
WRMAR: MOV #47116,(R5) ;Запишем 4E4E
BR 2$ ;Идем на повтор записи
1$: TSTB (R4) ;Готовность есть?
BPL 1$ ;Нет - дождемся
MOV #47116,(R5) ;Запишем 4E4E
2$: SOB R0,1$ ;Повторим заданное число раз
MOV #6,R0 ;Запишем 12. нулевых байтов
3$: TSTB (R4) ;Готовность есть?
BPL 3$ ;Нет - ожидаем
MOV #0,(R5) ;Записываем нули
SOB R0,3$ ; в нужном количестве
BIS #1000,(R3) ;Подготовим признак записи маркера
4$: TSTB (R4) ;Контроллер готов?
BPL 4$ ;Нет - ждем
MOV #120641,(R5) ;Записываем маркер A1A1
MOV (R3),(R4) ;Передаем признак в контроолер
BIC #1000,(R3) ;Заранее снимем признак
5$: TSTB (R4) ;Готовность есть?
BPL 5$ ;Нет - ожидаем
MOV 40(R3),(R5) ;Записываем маркер из буфера
RET
*** 163360 П/п установки прекоррекции ***
CORR: BIC #2000,(R3) ;Снимем прекоррекцию
CMPB 14(R3),@2(R3);Надо включать на текущей дорожке?
BHI 1$ ;Нет - пропустим
BIS #2000,(R3) ;Пора - включим
- 22 -
1$: MOV (R3),(R4) ;Перешлем управляющее слово
MOV #310,R0
2$: SOB R0,2$ ;Подождем, пока контроллер воспримет
RET
*** 163412 П/п форматирования ***
FORMAT: MOV SP,50(R3) ;Сохраним SP,
MFPS 52(R3) ; PSW,
MOV #4,R0
MOV (R0),46(R3) ; @#4 в соответствующих буферах
MOV PC,(R0) ;Переназначаем вектор @#4 на себя,
ADD #176056,(R0) ; теперь он равен 161512
CALL ENGINE ;Запустим двигатель
CALL GOTRK ;Спозиционируем на нужную дорожку
CALL CORR ;Установим прекоррекцию
BIT #4,(R4) ;Защита записи включена?
BEQ 2$ ;Нет - начнем форматировать
MOV #1,R0 ;Да - ошибка 1
1$: JMP ERROR ;Выходим с ошибкой
2$: SWAB 32(R3) ;Обмениваем номера стороны и дорожки
MOVB 17(R3),36(R3);Делаем слово-заполнитель
MOVB 17(R3),37(R3); из байта-заполнителя
MOVB 60(R3),R1 ;Получим длину сектора
MOV #1001,R2 ;Запомним номер сектора и код длины
MOV #1750,R0 ;Время ожидания индекса
3$: TST (R4) ;Индекс есть?
BPL 5$ ;Исчез - начнем записывать
SOB R0,3$ ;Есть - ждем исчезновения
4$: TST (R5) ;Так и не исчез - прекратим запись
MOV #6,R0 ;Диск не вращается - ошибка 6
SWAB 32(R3) ;Вернем все на место
BR 1$ ;Выходим с ошибкой
*** Запись на дорожку кода 4E4E ***
5$: MOV #6200,R0 ;Установим максимальную длину
MTPS #340 ;При записи нам не мешать!!!
MOV #47116,(R5);Записываем 4E4E
6$: TST (R4) ;Индекс появился?
BMI 8$ ;Да - начнем запись
7$: TSTB (R4) ;Готовность есть?
BPL 7$ ;Нет - ждем
MOV #47116,(R5);Записываем 4E4E
SOB R0,6$ ;И так до конца дорожки
BR 4$ ;Однако, дорожка длинная, ошибка!
8$: MOV #20,R0 ;В маркере будет 16. 4E4E (GAP1)
MOV #177241,40(R3);Адресный маркер (FEA1) - в буфер
9$: CALL WRMAR ;Записываем адресный маркер
10$: TSTB (R4) ;Готовность есть?
BPL 10$ ;Нет - ожидаем
MOV 32(R3),(R5);Записываем номер стороны и дорожки
MOV (R3),(R4);Перешлем управляющее слово
11$: TSTB (R4) ;Готовность есть?
BPL 11$ ;Нет - дождемся
MOV R2,(R5) ;Записываем номер сектора и код длины
MOV #13,R0 ;В маркере будет 11. 4E4E (GAP2)
MOV #175641,40(R3);Маркер данных (FBA1) - в буфер
- 23 -
12$: BIT #40000,(R4) ;Ждем записи CRC
BEQ 12$
CALL WRMAR ;Записываем маркер данных
MOV 64(R3),R0;Получаем длину сектора
DEC R0 ;Одно слово запишем сейчас
13$: TSTB (R4) ;Готовность есть?
BPL 13$ ;Нет - ожидаем
MOV 36(R3),(R5);Записываем заполнитель
MOV (R3),(R4);Перешлем управляющее слово
14$: TSTB (R4) ;Готовность есть?
BPL 14$ ;Нет - дождемся
MOV 36(R3),(R5);Записываем заполнитель
SOB R0,14$ ;И так до конца сектора
INC R2 ;Увеличим номер сектора
MOV #22,R0 ;В маркере будет 18. 4E4E (GAP3)
;Примечание. Если увеличить GAP3 до 24-27 слов, то запись будет
;производиться так же быстро, как и чтение (обычно заголовок
;очередного сектора проскакивает, и дорожка записывается не за
;один, а за 10. оборотов). Однако при превышении этой величиной
;определенного значения конец последнего сектора дорожки может
;наложиться на ее же начало.
BIT #4,@20(R3);Сектора длинные?
BEQ 15$ ;Нет - все нормально
MOV #72,R0 ;Да - будет 116. 4E4E (можно увеличить
; до 75)
15$: MOV #177241,40(R3);Адресный маркер (FEA1) - в буфер
16$: BIT #40000,(R4);Ждем записи CRC
BEQ 16$
SOB R1,9$ ;И так все сектора до конца дорожки
*** Окончание записи дорожки ***
17$: TSTB (R4) ;Готовность есть?
BPL 17$ ;Нет - ждем
MOV #47116,(R5);Запишем 4E4E
TST (R4) ;Индекс есть?
BPL 17$ ;Нет - продолжим запись до появления
18$: TSTB (R4) ;Готовность есть?
BPL 18$ ;Нет - дождемся
MOV #47116,(R5);Запишем 4E4E
TST (R5) ;Прекратим запись
MTPS 52(R3) ;Восстановим PSW
SWAB 32(R3) ;Вернем все на место
JMP EXIT ;Выходим
*** Конец текста драйвера НГМД ***
EXT: *** Драйвер расширенной арифметики ***