Справочник программиста на персональном компьютере фирмы IBM. Дисковые накопители
Страница 30. Процедура чтения диска


Процедура чтения диска

   В заключение приводим полную  процедуру  чтения диска, которая
читает один сектор данных с дорожки 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

 
« Предыдущая статья   Следующая статья »