Главная / Цифровая археология / Музей ASV / rd_dos

Приведённый ниже исходник является набором подпрограмм низкоуровневой работы с дисководом в формате IBM PC для ПК "Специалист". Или, говоря другими словами - это драйвер дисковода. Он был использован в нашей версии BIOS для этого компьютера.

Драйвер разработан совместно Игорем Бугуновым и Анатолием Вдовичевым.

В процессе разработки драйвера возник весьма интересный момент. Контроллер дисковода не использовал возможность работы с прерываниями и прямым доступом к памяти. Всё делалось микропроцессором.

Микросхема контроллера дисковода имела буфер ровно на один байт, поэтому считывать или передавать контроллеру данные после появления сигнала DRQ надо было как можно быстрее.

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

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

Вот цикл чтения данных с дисковода:

; в HL - адрес буфера для чтения данных с дисковода
RDVG:
	MVI  A, 84H    ; команда чтения сектора
	STA  0FFF4H    ; передать команду контроллеру дисковода
	LXI  B, 0FFF7H ; адрес порта данных
	LXI  D, 0FFF3H ; адрес порта состояния
DRQ:
	LDAX D         ; считать состояние контроллера
	ADD  A         ; в переносе будет запрос данных
	RM             ; в знаке будет признак окончания чтения
	JNC  DRQ       ; ждём очередной байт
	LDAX B         ; считываем байт
	MOV  M, A      ; сохраняем в буфер
	INX  H         ; сдвигаем указатель в буфере
	JMP  DRQ       ; идём читать следующий байт

Этот цикл успевал обработать данные с дисковода. Между определением сигнала запроса данных (DRQ) и чтения из контроллера был достаточно малый интервал времени.

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

Ситуация была критической. Читать можем, а записывать - нет.

В итоге после продолжительного мозгового штурма (не меньше недели), был применён самый настоящий хак. Чтение из буфера делалось с использованием стека. Читали сразу по два байта. Сигнал окончания чтения игнорировали - в процесе записи вряд-ли контроллеру взбредёт прекратить чтение, если мы ему регулярно будем поставлять байты. Цикл записи сектора развернули. Т.е. это стал не цикл, а линейный набор команд - сэкономили на инструкции JMP, что собственно позволило применить команду POP для чтения данных из буфера.

В итоге подпрограмма записи сектора стала ощутимой по размерам, но зато наконец-то заработала запись на дисковод!

Страшно вспомнить сколько занимала подпрограмма форматирования дорожки, но она уже располагалась не в ПЗУ, а в отдельной программе FORMAT.EXE

В приведённом исходнике данная подпрограмма упоминается лишь адресом, по которому она располагалась - 0D000H

Развёрнутый цикл записи выглядел примерно так:

	LXI  SP, DTA    ;  адрес буфера записи
	LXI  H, 0FFF7H  ;  адрес порта данных
	LXI  D, 0FFF3H  ;  адрес порта состояния
	POP  B          ;  достаём из буфера два байта
DRQ0:
	LDAX  D
	ADD   A
	JNC   DRQ0
	MOV   M, C      ;  не уверен в этом месте B или C надо записывать
DRQ1:
	LDAX  D
	ADD   A
	JNC   DRQ1
	MOV   M, B
	POP   B         ; достаём из буфера следующие два байта
DRQ2:
	LDAX  D
	ADD   A
	JNC   DRQ2
	MOV   M, C

И так по кругу для 256 байт сектора.

В таком виде эта подпрограмма прожила несколько лет. Уже перед прекращением работ над развитием "Специалиста", появилась идея поменять биты в порту состояния. Это позволило бы сделать цикл записи более оптимальным и обойтись без разворачивания.

Цикл записи при этом бы выглядел так:

LOOP:
	LDAX B
DRQ:
	INR  M
	RM
	JPE  DRQ
	STAX D
	INX  B
	JMP  LOOP

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

Эта идея так и не была реализована "в железе".

Щелчёк по картинке даст скан распечатки в более высоком разрешении.