[Solved] Floppy driver malfunction with IOAPIC
Posted: Mon Nov 29, 2010 3:08 pm
I have this really strange problem on a modern AMD Athlon motherboard with four cores. When I run the floppy driver with the legacy PIC, everything seems to work just fine. When I switch the interrupt to the IOAPIC, things stops working. I first fought the IRQ-line is not correct, but it seems like there are IRQs generated, and they set the irqflag in the floppy driver. What instead seems to be happening are race-conditions. The code works just fine when single-stepped in the kernel-debugger, but malfunctions when run at full speed.
The reset controller code works just fine, and IntFlag is set. The problem is with SenseIntCmd. It will succeed the first time, but when done the second time, the status register will be D0, and the command phase will fail. If I debug the SenseIntCmd instead, and pace CommandPhase, ResultPhase will fail. If I singlestep both CommandPhase and ResultPhase, everything works just fine. It is clearly a race-condition, but where and why only with IOAPIC?
Code: Select all
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;
; NAME: FLOPPY_INT
;
; DESCRIPTION: Floppy disk interrupt
;
; PARAMETERS:
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
floppy_int Proc far
mov al,ds:IntFlag
or al,al
jnz floppy_int_done
inc al
mov ds:IntFlag,al
mov bx,ds:FloppyThread
Signal
floppy_int_done:
ret
floppy_int Endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;
; NAME: CommandPhase
;
; DESCRIPTION: Execute command phase
;
; PARAMETERS: CX Number of bytes to output
;
; RETURNS: NC Performed ok
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
CommandPhase Proc near
push ax
push bx
push dx
push si
ClearSignal
mov ds:IntFlag,0
mov si,2000
mov bx,OFFSET CmdCode
CommandPhaseLoop:
push cx
xor cx,cx
CommandPhaseReqLoop:
mov dx,3F4h
in al,dx
test al,80h
jnz CommandPhaseReqSet
mov ax,50
WaitMicroSec
sub si,1
jnc CommandPhaseReqLoop
pop cx
jmp CommandPhaseDone
CommandPhaseReqSet:
pop cx
test al,40h
stc
jnz CommandPhaseDone
;
mov dx,3F5h
mov al,[bx]
inc bx
out dx,al ; output data byte
loop CommandPhaseLoop
mov ax,30
WaitMicroSec
clc
CommandPhaseDone:
pop si
pop dx
pop bx
pop ax
ret
CommandPhase Endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;
; NAME: ResultPhase
;
; DESCRIPTION: Execute result phase
;
; RETURNS: NC Performed ok
; CX Number of bytes in result
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ResultPhase Proc near
push ax
push bx
push dx
push si
mov si,200
xor cx,cx
mov bx,OFFSET st0
ResultPhaseLoop:
mov ax,50
WaitMicroSec
;
mov dx,3F4h
in al,dx
test al,10h
clc
jz ResultPhaseDone
test al,80h
jnz ResultPhaseReqSet
mov ax,50
WaitMicroSec
sub si,1
jnc ResultPhaseLoop
jmp ResultPhaseDone
ResultPhaseReqSet:
test al,40h
stc
jz ResultPhaseDone
inc cx
mov dx,3F5h
in al,dx
mov [bx],al
inc bx
jmp ResultPhaseLoop
ResultPhaseDone:
pop si
pop dx
pop bx
pop ax
ret
ResultPhase Endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;
; NAME: SenseIntCmd
;
; DESCRIPTION: Sense interrupt command
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SenseIntCmd Proc near
push ax
push cx
mov ax,10
WaitMilliSec
mov ds:CmdCode,8
mov cx,1
call CommandPhase
jc SenseIntDone
call ResultPhase
SenseIntDone:
pop cx
pop ax
ret
SenseIntCmd Endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;
; NAME: ResetController
;
; DESCRIPTION: ResetController
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ResetController Proc near
push es
push ax
push cx
push dx
push di
mov ax,ds
mov es,ax
mov cx,100
mov ds:cTrack,-1
ResetControllerLoop:
GetThread
mov ds:FloppyThread,ax
ClearSignal
mov ds:IntFlag,0
mov al,8
mov dx,3F2h
out dx,al
mov ax,250
WaitMicroSec
;
mov al,0Ch
mov dx,3F2h
out dx,al
mov ds:DriveControl,al
;
mov ds:TimeoutCount,20
WaitForSignal
mov al,ds:IntFlag
or al,al
jz ResetControllerFailed
ResetControllerStart:
mov al,0Ch
out dx,al
mov ds:DriveControl,al
ResetControllerSense:
int 3
call SenseIntCmd
jc ResetControllerFailed
;
call SenseIntCmd
jc ResetControllerFailed
;
call SenseIntCmd
jc ResetControllerFailed
;
call SenseIntCmd
jc ResetControllerFailed