173 lines
2.8 KiB
PHP
173 lines
2.8 KiB
PHP
;
|
|
; 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
|