blob: 93c73ed560e87a0ce8da5500310ec37e501d5603 [file] [log] [blame]
;
; Process a PXE interrupt
;
section .text16
PXEIRQ_MAX equ 100 ; Max spurious interrupts in a timer tick
global pxe_isr
pxe_isr:
cld
pusha
push ds
push es
push fs
push gs
xor ax,ax
mov ds,ax
mov es,ax
mov bx,PXENV_UNDI_ISR
mov di,pxenv_undi_isr_buf
mov cx,pxenv_undi_isr_buf.size/2
push di
rep stosw
pop di
mov byte [pxenv_undi_isr_buf.funcflag],PXENV_UNDI_ISR_IN_START
call pxenv
mov ax,[__jiffies]
jc .notus
cmp word [pxenv_undi_isr_buf.funcflag],PXENV_UNDI_ISR_OUT_OURS
jne .notus
; Its ours - set the flag for the return to PM.
; We need to EOI this ourselves, so that the
; leftover BC doesn't get control.
mov byte [pxe_irq_pending],1
inc dword [pxe_irq_count]
cmp byte [pxe_irq_vector], 8
mov al,0x20 ; Non-specific EOI
jb .pri_pic
out 0xA0, al ; Secondary PIC
.pri_pic:
out 0x20,al ; Primary PIC
mov [pxeirq_last],ax
mov word [pxeirq_deadman],PXEIRQ_MAX
.exit:
pop gs
pop fs
pop es
pop ds
popa
iret
.notus:
cmp ax,[pxeirq_last]
jne .reset_timeout
dec word [pxeirq_deadman]
jz .timeout
.chain:
pop gs
pop fs
pop es
pop ds
popa
jmp 0:0
global pxe_irq_chain
pxe_irq_chain equ $-4
.reset_timeout:
mov [pxeirq_last],ax
mov word [pxeirq_deadman],PXEIRQ_MAX
jmp .chain
; Too many spurious interrupts, shut off the interrupts
; and go to polling mode
.timeout:
mov al,[pxe_irq_vector]
mov dx,21h
movzx cx,al
shl cx,7-3
add dx,cx
and al,7
xchg ax,cx
mov ch,1
shl ch,cl
in al,dx
or al,ch
out dx,al
or byte [pxe_need_poll],1
jmp .exit
; Emulate a PXE interrupt from the polling thread
global pxe_poll
pxe_poll:
pushf
cli
cld
pusha
push ds
push es
push fs
push gs
mov bx,PXENV_UNDI_ISR
mov di,pxenv_undi_isr_buf
mov cx,pxenv_undi_isr_buf.size/2
push di
rep stosw
pop di
mov byte [pxenv_undi_isr_buf.funcflag],PXENV_UNDI_ISR_IN_START
call pxenv
jc .notus
cmp word [pxenv_undi_isr_buf.funcflag],PXENV_UNDI_ISR_OUT_OURS
jne .notus
; Its ours - set the flag for the return to PM.
; We need to EOI this ourselves, so that the
; leftover BC doesn't get control.
mov byte [pxe_irq_pending],1
.notus:
pop gs
pop fs
pop es
pop ds
popa
popf
ret
section .bss16
alignb 4
pxenv_undi_isr_buf:
.status: resw 1
.funcflag: resw 1
.bufferlength: resw 1
.framelen: resw 1
.framehdrlen: resw 1
.frame: resw 2
.prottype: resb 1
.pkttype: resb 1
.size equ $-pxenv_undi_isr_buf
alignb 4
pxeirq_last resw 1
pxeirq_deadman resw 1
global pxe_irq_count
pxe_irq_count resd 1 ; PXE IRQ counter
global pxe_irq_vector
pxe_irq_vector resb 1 ; PXE IRQ vector
global pxe_irq_pending
pxe_irq_pending resb 1 ; IRQ pending flag
global pxe_need_poll
pxe_need_poll resb 1 ; Bit 0 = need polling
; Bit 1 = polling active
section .text16