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