Справочник программиста на персональном компьютере фирмы IBM. Дисковые накопители - Процедура чтения диска
ОГЛАВЛЕНИЕ
Процедура чтения диска
В заключение приводим полную процедуру чтения диска, которая
читает один сектор данных с дорожки 12, сектор 1, сторона 0 нако-
пителя A в 512-байтный буфер в сегменте данных. Семь байтов ста-
туса также считываются в отведенный буфер. Эта процедура предназ-
начена для IBM PC и XT. Вам необходимо воспользоваться техничес-
ким руководством по PCjr или AT, если Вы работаете на этих маши-
нах. На AT надо изменить циклы задержки, чтобы учесть большую
скорость процессора, и не забывать добавлять оператор JMP SHORT
$+2 между последовательными командами OUT, относящимися к одному
и тому же порту. Работа с фиксированным диском осуществляется
аналагично, поэтому Вы можете перенести изученные Вами концепции
на другие ситуации.
;---в сегменте данных
BUFFER DB 512 DUP(?)
STATUS_BUFFER DB 7 DUP(?)
SECTOR_READ PROC ;начало процедуры чтения одного сектора
;---включение мотора
STI ;прерывания должны быть разрешены
MOV DX,3F2H ;адрес регистра цифрового вывода
MOV AL,28 ;устанавливаем биты 2, 3 и 4
OUT DX,AL ;посылаем команду
;---ожидаем пока мотор наберет скорость (около 1/2 сек.)
MOV CX,3500 ;счетчик цикла задержки (для IBM PC и XT)
MOTOR_DELAY: LOOP MOTOR_DELAY ;ожидаем 1/2 секунды
;---выполняем операцию поиска
MOV AH,15 ;номер кода
CALL OUT_FDC ;посылаем контроллеру НГМД
MOV AH,0 ;номер накопителя
CALL OUT_FDC ;посылаем контроллеру НГМД
MOV AH,12 ;номер дорожки
CALL OUT_FDC ;посылаем контроллеру НГМД
CALL WAIT_INTERRUPT ;ожидаем прерывания от НГМД
;---ожидаем установки головки (25 мсек.)
MOV CX,1750 ;счетчик цикла задержки (для IBM PC и XT)
WAIT_SETTLE: LOOP WAIT_SETTLE ;ожидаем 25 мсек.
;---начинаем инициализацию микросхемы DMA
MOV AL,46H ;код чтения данных контроллера НГМД
OUT 12,AL ;посылаем код по двум адресам
OUT 11,AL ;
;---вычисляем адрес буфера
MOV AX,OFFSET BUFFER ;берем смещение буфера в DS
MOV BX,DS ;помещаем DS в BX
MOV CL,4 ;готовим вращение старшего нибла
ROL BX,CL ;вращаем младшие 4 бита
MOV DL,BL ;копируем DL в BL
AND DL,0FH ;чистим старший нибл в DL
AND BL,0F0H ;чистим младший нибл в BX
ADD AX,BX ;складываем
JNC NO_CARRY ;если не было переноса, то # страницы в DL
INC DL ;увеличиваем DL, если был перенос
NO_CARRY: OUT 4,AL ;посылаем младший байт адреса
MOV AL,AH ;сдвигаем старший байт
OUT 4,AL ;посылаем младший байт адреса
MOV AL,DL ;засылаем номер страницы
OUT 81H,AL ;посылаем номер страницы
;---конец инициализации
MOV AX,511 ;значение счетчика
OUT 5,AL ;посылаем младший байт
MOV AL,AH ;готовим старший байт
OUT 5,AL ;посылаем старший байт
MOV AL,2 ;готовим разрешение канала 2
OUT 10,AL ;DMA ожидает данные
;---получаем указатель на базу диска
MOV AL,1EH ;номер вектора, указывающего на таблицу
MOV AH,35H ;номер функции
INT 21H ;выполняем функцию
;---посылаем параметры чтения
MOV AH,66H ;код чтения одного сектора
CALL OUT_FDC ;посылаем контроллеру НГМД
MOV AH,0 ;номера головки и накопителя
CALL OUT_FDC ;посылаем контроллеру НГМД
MOV AH,12 ;номер дорожки
CALL OUT_FDC ;посылаем контроллеру НГМД
MOV AH,0 ;номер головки
CALL OUT_FDC ;посылаем контроллеру НГМД
MOV AH,1 ;номер записи
CALL OUT_FDC ;посылаем контроллеру НГМД
MOV AH,ES:[BX]+3 ;код размера сектора
CALL OUT_FDC ;посылаем контроллеру НГМД
MOV AH,ES:[BX]+4 ;номер конца дорожки
CALL OUT_FDC ;посылаем контроллеру НГМД
MOV AH,ES:[BX]+5 ;длина сдвига
CALL OUT_FDC ;посылаем контроллеру НГМД
MOV AH,ES:[BX]+6 ;длина данных
CALL OUT_FDC ;посылаем контроллеру НГМД
CALL WAIT_INTERRUPT ;ожидаем прерывание от НГМД
;---читаем результирующие байты
MOV CX,7 ;берем 7 байтов статуса
LEA BX,STATUS_BUFFER ;помещаем в буфер статуса
NEXT: CALL IN_FDC ;получаем байт
MOV [BX],AL ;помещаем в буфер
INC BX ;указываем на следующий байт буфера
LOOP NEXT ;повторяем операцию
;---выключение мотора
MOV DX,3F2H ;адрес регистра цифрового вывода
MOV AL,12 ;оставляем биты 3 и 4
OUT DX,AL ;посылаем новую установку
RET ;конец процедуры
SECTOR_READ ENDP
WAIT_INTERRUPT PROC ;ожидание прерывания от НГМД
;---управление статусом прерывания 6 в байте статуса BIOS
MOV AX,40H ;сегмент области данных BIOS
MOV ES,AX ;помещаем в ES
MOV BX,3EH ;смещение для байта статуса
AGAIN: MOV DL,ES:[BX] ;получаем байт
TEST DL,80H ;проверяем бит 7
JZ AGAIN ;до тех пор пока не установлен
AND DL,01111111B ;сбрасываем бит 7
MOV ES:[BX],DL ;заменяем байт статуса
RET
WAIT_INTERRUPT ENDP
OUT_FDC PROC ;посылаем байт из AH FDC
MOV DX,3F4H ;адрес порта регистра статуса
KEEP_TRYING: IN AL,DX ;получаем значение
TEST AL,128 ;бит 7 установлен?
JZ KEEP_TRYING ;если нет, то снова проверяем
INC DX ;указываем на регистр данных
MOV AL,AH ;передаваемое значение в AH
OUT DX,AL ;посылаем значение
RET
OUT_FDC ENDP
IN_FDC PROC ;получаем байт от FDC в AL
MOV DX,3F4H ;адрес порта регистра статуса
ONCE_AGAIN: IN AL,DX ;получаем значение
TEST AL,128 ;бит 7 установлен?
JZ KEEP_TRYING ;если нет, то проверяем снова
INC DX ;указываем на регистр данных
IN AL,DX ;читаем байт из регистра данных
RET
IN_FDC ENDP