Ata interrupt never stops firing on real hardware
Posted: Sun Jun 11, 2023 11:59 pm
On virtual machines such as Qemu the IDE controller is in compatibility mode and uses these ports: 0x1F0, 0x170, and interrupts: IRQ14/IRQ15
To get my Ata driver to work on my real machine I had to scan the PCI to find the IDE controllers and then ports via the base address registers. That worked fine and I could now read from disk on real hardware. There is only one problem, Atapi requires interrupts so I need to get those working. By reading the interrupt line field on the PCI IDE controller I determined that IRQ11 is the one I should unmask.
When I unmask IRQ11 the entire system freezes. After changing the interrupt handler to writing a "B" on screen the screen gets compleatly filled over and over. By inserting wait statements in my Ata code I found that as soon as I issue an identify command (0xEC) I get an endless stream of IRQ11. I am a beginner, and I wounder if there is something curcial missing in my code?
Code in handler:
Code for issuing Identify command:
To get my Ata driver to work on my real machine I had to scan the PCI to find the IDE controllers and then ports via the base address registers. That worked fine and I could now read from disk on real hardware. There is only one problem, Atapi requires interrupts so I need to get those working. By reading the interrupt line field on the PCI IDE controller I determined that IRQ11 is the one I should unmask.
When I unmask IRQ11 the entire system freezes. After changing the interrupt handler to writing a "B" on screen the screen gets compleatly filled over and over. By inserting wait statements in my Ata code I found that as soon as I issue an identify command (0xEC) I get an endless stream of IRQ11. I am a beginner, and I wounder if there is something curcial missing in my code?
Code in handler:
Code: Select all
irq_handler_11:
pushad
mov al, 'B'
mov ah, 0x0C
push ax
call write_char
push word 0
call update_screen
push word 11
call send_end_interrupt
popad
iret
Code for issuing Identify command:
Code: Select all
ata_identify_master:
mov dx, si
add dx, 6
mov al, 0xA0
out dx, al ;Select drive
jmp ata_identify_continue
ata_identify_slave:
mov dx, si
add dx, 6
mov al, 0xB0
out dx, al ;Select drive
ata_identify_continue:
push 10 ;Make sure controller has time to process
call wait_milliseconds
;Wiki says these should e set to 0
;(This could be written a bit shorter)
mov dx, si
add dx, 2
mov al, 0
out dx, al ;Set to 0
mov dx, si
add dx, 3
mov al, 0
out dx, al ;Set to 0
mov dx, si
add dx, 4
mov al, 0
out dx, al ;Set to 0
mov dx, si
add dx, 5
mov al, 0
out dx, al ;Set to 0
;Send identify command
mov dx, si
add dx, 7
mov al, 0xEC
out dx, al