[Solved] Floppy driver malfunction with IOAPIC

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
rdos
Member
Member
Posts: 3310
Joined: Wed Oct 01, 2008 1:55 pm

[Solved] Floppy driver malfunction with IOAPIC

Post by rdos »

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.

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

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?
Last edited by rdos on Mon Dec 06, 2010 3:26 am, edited 1 time in total.
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: Floppy driver malfunction with IOAPIC

Post by Owen »

My guess: the IOAPIC is ~1000 times faster than the legacy PIC. This means that race conditions which were masked by the PIC's slowness show up.
rdos
Member
Member
Posts: 3310
Joined: Wed Oct 01, 2008 1:55 pm

Re: Floppy driver malfunction with IOAPIC

Post by rdos »

Owen wrote:My guess: the IOAPIC is ~1000 times faster than the legacy PIC. This means that race conditions which were masked by the PIC's slowness show up.
At least related. I've concluded now that it is the 30 us delay at the end of CommandPhase that is not enough when using IOAPIC. It will leave the CommandPhase procedure with floppy MSR=00 when configured for IOAPIC. This state is interpreted incorrectly by the ResultPhase. My guess is that when I configure with legacy PIC, such short delays as 30 us will end up as much longer delays because of the slowness of the PIC, while they get much shorter with the much faster IOAPIC. That's probably why the code fails with IOAPIC.
rdos
Member
Member
Posts: 3310
Joined: Wed Oct 01, 2008 1:55 pm

Re: Floppy driver malfunction with IOAPIC

Post by rdos »

The issue is solved. Here is how the CommandPhase and ResultPhase looks like after the modifications:

Code: Select all

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
;    
    mov ax,5
    WaitMicroSec
    loop CommandPhaseLoop
;
    mov si,2000

CommandPhaseEndLoop:
    mov ax,5
    WaitMicroSec
;
    mov dx,3F4h
    in al,dx
    test al,90h
    clc
    jnz CommandPhaseDone
;
    sub si,1
    jnc CommandPhaseEndLoop
;
    stc    

CommandPhaseDone:
    pop si
    pop dx
    pop bx
    pop ax
    ret
CommandPhase    Endp

ResultPhase   Proc near
    push ax
    push bx
    push dx
    push si
    mov si,200
    xor cx,cx
    mov bx,OFFSET st0
ResultPhaseLoop:
    mov dx,3F4h
    in al,dx
    test al,10h
    clc
    jz ResultPhaseDone      
;
    test al,80h
    jnz ResultPhaseReqSet

ResultPhaseWait:    
    mov ax,50
    WaitMicroSec
    sub si,1
    jnc ResultPhaseLoop
    jmp ResultPhaseDone

ResultPhaseReqSet:
    test al,40h
    jz ResultPhaseWait
;
    inc cx
    mov dx,3F5h
    in al,dx
    mov [bx],al
    inc bx
    mov ax,5
    WaitMicroSec
    jmp ResultPhaseLoop
    
ResultPhaseDone:
    pop si
    pop dx
    pop bx
    pop ax
    ret
ResultPhase   Endp


Post Reply