Столкнулся с такой проблемой, как можно реализовать работу дисковода в режиме дма находясь в защищенном режиме, очень буду признателен, если мне покажут исходник (лучше на асме). Спасибо заранее.
пойдет и для PM. Код (Text): use16 org 7C00h STACK_BASE equ 9000h ; заносим в ss STACK_PTR equ 9F00h ; заносим в sp KERNEL_SIZE equ 1024 ; размер ядра в байтах include "..\drivers\floppy\floppy.inc" include "..\kernel\kernel.inc" start: ; отключаем прерывания cli ; ds = cs = 0 push cs pop ds ; настраиваем стек mov ax, STACK_BASE mov ss, ax mov sp, STACK_PTR ; ставим свой обработчик IRQ6 xor cx, cx mov word [0Eh * 4], irq6_handler mov word [0Eh * 4 + 2], cx ; ставим свой обработчик IRQ0 mov word [08h * 4], irq0_handler mov word [08h * 4 + 2], cx ; включаем прерывания sti ; сохраняем адрес DPT, а в es ее сегмент mov ax, [78h] mov [DPT_table], ax mov ax, [78h + 2] mov es, ax ; врубаем мотор call FDD_init ; ждём запуска мотора, ~1000ms mov bh, 18 call delay ; устанавливаем скорость в 500 кб/с mov dx, FLOP_DIR xor al, al out dx, al ; 3 попытки рекалибровать mov cl, 3 recalibre_retry: ; рекалибровка call FDD_recalibrate jc error ; проверяем успешность опреации call FDD_sense_interrupt_status jnc recalibre_success ; после трех неудачных попыток рекалибровать, выходим loop recalibre_retry jmp error recalibre_success: ; переходим к первой дорожке call FDD_seek jc error call FDD_sense_interrupt_status jc error ; задержка для установки головки в новое положение mov bh, 1 call delay ; считаем размер сектора в байтах mov bx, [DPT_table] mov cl, [es: bx + 3] mov bx, 128 shl bx, cl ; считаем размер ядра в секторах mov ax, KERNEL_SIZE xor dx, dx div bx ; в ch - номер последнего сектора ядра, в cl - первого - 1 inc al mov ch, al mov cl, 1 ; читаем ядро в память mov si, KERNEL_BASE read_kernel: call DMA_init inc cl call FDD_read_sector jc error add si, bx cmp cl, ch jne read_kernel call FDD_stop jmp KERNEL_BASE error: mov si, error_msg call putstr stop: jmp stop ; Задержка ; bh - на сколько в (1/18.2)с отрезках delay: mov [t_count], 0 delay_loop: cmp [t_count], bh jne delay_loop ret send_EOI: push ax mov al, 00100000b out 20h, al pop ax iret ; обработчик прерываний от дисковода irq6_handler: ; ставим флаг того, что подали сигнал mov [int_active], 1 jmp send_EOI ; обработчик прерываний таймера irq0_handler: inc [t_count] jmp send_EOI ; Инициализация DMA DMA_init: cli ; mov al, 0 ; out 10, al ; команда READ DMA mov al, 46h ; сброс указателя байта out 12, al ; утсанавливаем режим работы контроллера DMA out 11, al ; загружаем линейное смещение нашего буфера, тк ds = 0, то модно избежать лишних вычислений с базой сегмента mov ax, si ; младший байт адреса буфера out 4, al mov al, ah ; старший байт адреса буфера out 4, al ; номер страницы, у нас он 0, тк ds = 0, а регистры 16-юитные xor al, al out 81h, al ; загружаем размер данных - 1 mov ax, bx dec ax ; младший байт размера данных out 5, al mov al, ah ; старший байт размера данных out 5, al ; разрешаем наш проинициализированный канал mov al, 2 out 10, al sti ret ; Инициализация FDD FDD_init: mov dx, FLOP_DOR xor ax, ax out dx, al mov al, 00011100b ; Motor0, Reset, DMA out dx, al ret ; Остановка FDD FDD_stop: mov al, 00001100b ; DMA, Reset mov dx, FLOP_DOR out dx, al xor al, al out dx, al ret ; Отсылка байта в порт данных ; al - байт для пересылки FDD_send_byte: pusha clc mov dx, FLOP_MSR mov cx, 0FFFFh push ax FDD_send_byte_loop: in al, dx and al, 11000000b cmp al, 10000000b je FDD_send_byte_rdy loop FDD_send_byte_loop FDD_send_byte_rdy: pop ax mov dx, FLOP_FIFO out dx, al popa ret FDD_send_byte_err: stc popa ret ; Чтение байта из порта данных ; al - байт результата FDD_recv_byte: push cx clc mov dx, FLOP_MSR mov cx, 0FFFFh FDD_recv_byte_loop: in al, dx and al, 11000000b cmp al, 11000000b jne FDD_recv_byte_rdy loop FDD_recv_byte_loop FDD_recv_byte_rdy: mov dx, FLOP_FIFO in al, dx FDD_recv_byte_exit: pop cx ret FDD_recv_byte_err: stc pop cx ret ; Посылаем команду SENSE INTERRUPT STATUS FDD_sense_interrupt_status: ; код команды mov al, 00001000b call FDD_send_byte jc FDD_sense_interrupt_status_exit ; читаем st0 call FDD_recv_byte jc FDD_sense_interrupt_status_exit and al, 11110000b cmp al, 00100000b jne FDD_sense_interrupt_status_error ; читаем PCN call FDD_recv_byte jc FDD_sense_interrupt_status_exit ; PCN должен быть равен 0 test al, al jnz FDD_sense_interrupt_status_error FDD_sense_interrupt_status_exit: ret FDD_sense_interrupt_status_error: stc ret ; Посылаем команду рекалибровки FDD_recalibrate: ; код команды mov al, 00000111b call FDD_send_byte jc FDD_recalibrate_exit ; 0 0 0 0 0 0 DS1 DS0 xor al, al ; 00000000b call FDD_send_byte jc FDD_recalibrate_exit call FDD_wait_end FDD_recalibrate_exit: ret ; Посылаем команду SEEK FDD_seek: mov al, 00001111b call FDD_send_byte jc FDD_seek_exit xor al, al ; 00000000b call FDD_send_byte jc FDD_seek_exit call FDD_send_byte jc FDD_seek_exit call FDD_wait_end FDD_seek_exit: ret ; Читаем сектор ; cl - номер сектора FDD_read_sector: pusha ; в bx - адрес DPT mov bx, [DPT_table] ; READ DATA, Code 1 mov al, 66h call FDD_send_byte jc FDD_read_sector_exit ; READ DATA, Code 2 xor al, al call FDD_send_byte jc FDD_read_sector_exit ; Cyl call FDD_send_byte jc FDD_read_sector_exit ; Head call FDD_send_byte jc FDD_read_sector_exit ; Sector mov al, cl call FDD_send_byte jc FDD_read_sector_exit ; Sector Size mov al, [es: bx + 3] call FDD_send_byte jc FDD_read_sector_exit ; End of track mov al, [es: bx + 4] call FDD_send_byte jc FDD_read_sector_exit ; GPL mov al, [es: bx + 5] call FDD_send_byte jc FDD_read_sector_exit ; DTL mov al, 0FFh call FDD_send_byte jc FDD_read_sector_exit ; ждём когда закончится фаза исполнения call FDD_wait_end ; ST0 call FDD_recv_byte jc FDD_read_sector_exit test al, 11111100b jnz FDD_read_sector_error ; ST1 & ST2 xor cx, cx mov cl, 2 FDD_read_sector_STX: call FDD_recv_byte jc FDD_read_sector_exit test al, al jnz FDD_read_sector_error loop FDD_read_sector_STX ; C H R N mov cl, 4 FDD_read_sector_result: call FDD_recv_byte loop FDD_read_sector_result FDD_read_sector_exit: popa ret FDD_read_sector_error: stc popa ret ; Ждём завершения опреации FDD_wait_end: mov dx, FLOP_MSR FDD_wait_end_loop: cmp [int_active], 1 jne FDD_wait_end_loop FDD_wait_end_exit: mov [int_active], 0 ret putstr: lodsb or al,al jz putstrd mov ah, 0x0E mov bx, 0x0007 int 0x10 jmp putstr putstrd: retn int_active db 0 t_count db 0 DPT_table dw 0 error_msg db 'Error',0 rb 7C00h + 512 - 2 - $ db 055h,0AAh
n0name спасибо за код уже начал разбираться, но это я так понял написано на фасме или насме? и ещё есть некоторые переменные, которые неописаны в коде, я так понял они на ходятся в этих подключаемых в инклуидах? можно их тоже дать?
угу, это фасм. Код (Text): FLOP_SRB equ 3F1h FLOP_DOR equ 3F2h ; 0 0 Motor1 Motor0 DMA Reset 0 Disk FLOP_TDR equ 3F3h FLOP_MSR equ 3F4h FLOP_DSR equ 3F4h FLOP_FIFO equ 3F5h FLOP_DIR equ 3F7h FLOP_CCR equ 3F7h