kostec Вот так с флоппи Код (Text): _universal equ 1 ; закомментировать если не используется ;----------------------------------------------------------------------------¬ ;¦ Подпрограмма инициализации ¦ ;¦ Вход: cl - дисковод ¦ ;¦ Выход: ZF=0 если инициализация успешна ¦ ;¦ ZF=1 если таймаут или ошибка посылки комманды ¦ ;L---------------------------------------------------------------------------- InitFDD: mov dx,3F2h in al,dx and al,0FBh ; бит 2 - reset out dx,al or al,0Ch out dx,al ;----------------------------------------------------------------------------¬ ;¦ Подпрограмма ожидания аппаратного прерывания IRQ6 ¦ ;¦ Вход: ¦ ;¦ Выход: ZF=0 если условие выполнилось пока счетчик не обнулился ¦ ;¦ ZF=1 если обнулился счетчик ¦ ;L---------------------------------------------------------------------------- WaitForIRQ6: mov al,0Ah ; чтение IRR out 20h,al call WaitForFDDEvent in al,20h shl al,1 jns WFELabel2 ; бит 6 - IRQ6 mov al,8 pop _bx ; Выход из ожидания SCToFDDFromEAX: push edx push ecx push eax SCFDDLabel1: call SCToFDDFromStack SCFDDLabel2: pop eax pop ecx pop edx retn ;----------------------------------------------------------------------------¬ ;¦ Подпрограмма посылки комманды ¦ ;¦ Выход: ZF=0 если условие выполнилось пока счетчик не обнулился ¦ ;¦ ZF=1 если обнулился счетчик ¦ ;L---------------------------------------------------------------------------- SendCommandFDD: push edx push ecx push eax mov cl,ah call IsDSKCHG jz SCFDDLabel2 call SCToFDDFromStack ; call WaitForIRQ6 pop eax pop ecx pop edx retn ;----------------------------------------------------------------------------¬ ;¦ Подпрограмма рекалибровки ¦ ;¦ Вход: cl - дисковод ¦ ;¦ Выход: ZF=1 если успешна ¦ ;¦ ZF=0 если ошибка таймаут при ожидании конца рекалибровки ¦ ;L---------------------------------------------------------------------------- Recalibrate: call RLabel1 ; дважды jz RLabel2 ; Поскольку 77 треков в RLabel1: mov ah,cl ; DRV mov al,7 ; RECALIBRATE FinishSeek: push _cx call SCToFDDFromEAX call WaitForIRQ6 pop _cx shl al,1 js RLabel2 RLabel3: sbb al,al RLabel2: retn ;----------------------------------------------------------------------------¬ ;¦ Подпрограмма поиска трека ¦ ;¦ Вход: cl - дисковод ch - трек ¦ ;¦ Выход: ZF=1 если успешна ¦ ;¦ ZF=0 если ошибка таймаут при ожидании конца поиска ¦ ;L---------------------------------------------------------------------------- Seek: mov _ax,_cx shl eax,8 mov al,0Fh jmp FinishSeek ;----------------------------------------------------------------------------¬ ;¦ Подпрограмма проверки смены диска ¦ ;¦ Вход: cl - дисковод ¦ ;¦ Выход: Калибровка скорости ¦ ;L---------------------------------------------------------------------------- IsDSKCHG: mov dx,3F2h in al,dx MOLabel2: test cl,1 mov ah,10h jz MOLabel1 mov ah,21h MOLabel1: or al,ah out dx,al mov dl,0F7h in al,dx shl al,1 jnc FindSpeed call Recalibrate jnz FSLabel3 ; Ошибка рекалибровки push _cx mov ch,1 call Seek pop _cx jnz FSLabel3 ; Ошибка позиционирования mov dl,0F7h ; проверка наличия дискеты in al,dx ; вообще shl al,1 jc FSLabel3 FindSpeed: mov eax,0010AF03h ; 0011AF03h call SCToFDDFromEAX ; SPECIFY jz FSLabel2 mov eax,005F0013h ; !!! Если хотим использовать FIFO, то здесь 005F0013h, но тогда при записи ; на диск - будет требоваться на 16 байт (от 1 до 16 байт) больше послать ; информации, которая на диск писаться не будет, а будет служить лишь для ; заполнения буфера FIFO, поскольку сигнал запрос данных будет выдан FDC CPU ; как только освободиться FIFO, а на диск еще последний байт не запишется, ; то есть к примеру при чтении читается 512 байт, а при записи пишется ; 512, но дополнительно посылаются 16 байт чтобы запонить FIFO - итого 528. ; При использовании DMA этого не будет. При отключеном FIFO тоже. Этот ; момент происходит лишь при использовании универсальной программы FDD_IO. call SCToFDDFromEAX ; CONFIGURE jz FSLabel2 mov al,3 FSLabel1: mov dx,3F7h out dx,al ; jmp FSLabel2 push _ax push _cx ; _cx - меняется READ ID mov ah,cl mov al,4Ah call SCToFDDFromEAX test al,0C0h stc ; для сброса ZF pop _cx pop _ax jz RLabel3 ; выход со сбросом ZF dec al jns FSLabel1 FSLabel3: cmp al,al ; ZF = 1 ошибка FSLabel2: retn ;----------------------------------------------------------------------------¬ ;¦ Подпрограмма ожидания события ¦ ;¦ Вход: mov ecx, ... ; сетчик в единицах по 15 мксек ¦ ;¦ call WaitForEvent ¦ ;¦ ... ; код проверки условия ¦ ;¦ retn ; ZF = 1 условие выполнено ¦ ;¦ Выход: ZF=0 если условие выполнилось пока счетчик не обнулился ¦ ;¦ ZF=1 если обнулился счетчик ¦ ;L---------------------------------------------------------------------------- Pause15mks: call WaitForEvent jmp short WFELabel2 WaitForHDDEvent: mov ecx,33333 ; 0.5 секунд jmp short WaitForEvent WaitForFDDEvent: mov ecx,333333 ; 5 секунд WaitForEvent: pop _bx mov ah,10h WFELabel1: call _bx jz WFELabel2 ; дождались in al,61h and al,10h xor al,ah jnz WFELabel1 xor ah,10h ifndef _32Bit db 67h endif loop WFELabel1 WFELabel2: or ecx,ecx retn ;----------------------------------------------------------------------------¬ ;¦ Подпрограмма ввода-вывода комманды-результата с использованием стека ¦ ;¦ Вход: В стеке комманда и достаточно места для результата ее исполнения ¦ ;¦ Выход: ZF=0 если комманда выполнилось пока счетчик не обнулился ¦ ;¦ ZF=1 если обнулился счетчик ¦ ;L---------------------------------------------------------------------------- SCToFDDFromStack: pop _ax ; +2 или +4 mov _si,_sp push _ax mov _di,_si ;----------------------------------------------------------------------------¬ ;¦ Подпрограмма ввода-вывода комманды-результата ¦ ;¦ Вход: esi-буфер ввода -¬ если используется ¦ ;¦ edi-буфер вывода +- режим _universal, то ¦ ;¦ ebp-буфер для фазы исполнения если есть -- адресация в ss: сегм. ¦ ;¦ Выход: ZF=0 если комманда выполнилось пока счетчик не обнулился ¦ ;¦ ZF=1 если обнулился счетчик ¦ ;L---------------------------------------------------------------------------- FDD_IO: call ReadyFDD FDD_IOLabel1: ifdef _universal db 36h ; ss: endif outsb ; послать комманду FDD_IOLabel3: call Pause15mks ReadyFDD: mov dx,3F4h call WaitForFDDEvent ; <--------------------¬ in al,dx ; ¦ shl al,1 ; ¦ jnc short WFELabel2 ; бит RQM - готовность ¦ pop _cx ; выход из ожидания ---- mov ecx,10 ; должна быть задержка inc _dx ; edx = 3F5h test al,20h ; бит CB - Command Buzy jz WFELabel2 ; выход если CB = 0 shl al,1 ; бит CB - 1 jns NoExecute ; бит NonDMA=1 mov _si,_bp mov _di,_bp db 9Ch ; pushfd или pushf mov cl,0 ; нет задержки для inc _bp ; фазы исполнения db 9Dh ; popfd или popf NoExecute: jnc FDD_IOLabel1 ; бит CPU>FDD ifdef _universal db 36h ; ss: endif insb jmp FDD_IOLabel3
kostec А вот так с HDD Код (Text): ;----------------------------------------------------------------------------¬ ;¦ScanPCI: ¦ ;L---------------------------------------------------------------------------- ; Регистр CONFADD 0CF8h ; ; 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 ; 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 ; --T-T-T-T-T-T-T-T-T-T-T-T-T-T-T-T-T-T-T-T-T-T-T-T-T-T-T-T-T-T-T-¬ ; ¦C¦ ¦ ¦ ¦ ¦ ¦Re ¦ ; ¦O¦ Reserved ¦ BUSNUM ¦ DEVNUM ¦FUNC-¦ REGNUM ¦se ¦ ; ¦N¦ ¦ ¦ ¦ NUM ¦ ¦er ¦ ; ¦E¦ ¦ ¦ ¦ ¦ ¦ved¦ ; L-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-- ; CONE - Configuration Enable (1-Enable; 2-Disable) ; REGNUM - от 0 до 252 соответсвенно определяют адрес окна в ; 4 байта для последующего доступа. ; Регистр CONDATA 0CFCh - 0CFFh - это 32 бит окно в конфигурационной ; области PCI если бит CONE = 1. ; CF = 1 не найдено ScanPCI: add esi,100h cmp esi,81000000h cmc jc RPCILabel1 ReadPCI: mov eax,esi ; Передпологается, что mov dx,0CF8h ; прочитать 0FFFFFFFFh out dx,eax ; мы не можем add dl,4 in eax,dx inc eax jz ScanPCI dec eax RPCILabel1: retn HDDControl struc BaseCommandBlock dd ? BaseControlBlock dd ? HDDFlags dd ? HDDControl ends CommandBlock struc Data db ? Error db ? SectorCount db ? SectorNumber db ? CylinderLow db ? CylinderHigh db ? Drive db ? Status db ? CommandBlock ends ; При записи Featers equ <Error> Head equ <Drive> Command equ <Status> ControlBlock struc db ? ; Reserved db ? ; Reserved AltStatus db ? Floppy db ? ControlBlock ends ; При записи DeviceControl equ <AltStatus> ;----------------------------------------------------------------------------¬ ;¦ FoundPCIIDE: Находит PCI IDE устройство. ¦ ;L---------------------------------------------------------------------------- FoundPCIIDE: FPCIIDELabel1: call ScanPCI jc FPCIIDELabel2 shr eax,10h+8 dec al jnz FPCIIDELabel1 or al,al FPCIIDELabel2: retn ;----------------------------------------------------------------------------¬ ;¦ TestIDEDevice: Находит устройство IDE. ¦ ;L---------------------------------------------------------------------------- TestIDEDevice: push edi add dl,7 ; Command call WaitForHDDBSY jz TIDEDLabel1 dec _dx in al,dx push _ax mov al,11100000b ; Device 0 call TestIDEDLabel3 jnz TIDEDLabel2 mov al,11110000b ; Device 1 call TestIDEDLabel3 TIDEDLabel2: pop _ax pushfd dec _dx popfd in al,dx mov bl,al out dx,al TIDEDLabel1: pop edi retn TestIDEDLabel3: call ChoseHDD jz TIDEDLabel4 ; Device 0 занято mov al,0ECh ; 0A1h для CDROM out dx,al ; 1F7h call WaitForHDDBSY jz TIDEDLabel4 in al,dx and al,01 dec al jz TIDEDLabel4 call WaitForHDDDRQ mov ecx,100h push eax sub dl,7 LoopCycle1: mov edi,esp insw loop LoopCycle1 add dl,7 pop eax TIDEDLabel4: retn ChoseHDD: out dx,al inc _dx WaitForHDDDRDYBSY: call WaitForHDDBSY jz WFHDDRDYLabel1 call WaitForHDDEvent in al,dx and al,40h xor al,40h WFHDDRDYLabel1: retn WaitForHDDBSY: call WaitForHDDEvent in al,dx and al,80h retn WaitForHDDDRQ: call WaitForHDDEvent in al,dx and al,08h xor al,08h retn ;----------------------------------------------------------------------------¬ ;¦ InitHDD: Находит адрес ввода вывода IDE устройства. ¦ ;L---------------------------------------------------------------------------- InitHDD: mov ebp,esp mov esi,(80000000h OR 1000b)-100h FoundAdapters: call FoundPCIIDE jc EndFoundAdapters push esi jmp FoundAdapters EndFoundAdapters: cmp esp,ebp jz EndInitHDD pop esi add esi,10h-08h call ReadPCI jnz IHDDLabel1 ; если = 0, то это Primary Onboard mov ax,01F0h IHDDLabel1: and al,0F0h xchg eax,edx ; edx - базовый порт. call TestIDEDevice jz NextChanel sub dl,6 NextChanel: add esi,8h ; 18h вторая шина call ReadPCI jnz IHDDLabel3 ; если = 0, то это Secondary Onboard mov ax,0170h IHDDLabel3: and al,0F0h xchg eax,edx call TestIDEDevice jz HDDWLabel3 sub dl,6 HDDWLabel3: xor edx,edx jmp EndFoundAdapters EndInitHDD: retn
PROFi спасибо большое. А где можно достать список комманд FDD? Booster, n0name no bios, int 13h я и так знаю.
Огромное всем спасибо! Сам я, конечно ничего не написал, но зато скатал код из исходников BOS'а и разобрался как это всё работает.