summaryrefslogtreecommitdiff
path: root/core/pxeisr.inc
diff options
context:
space:
mode:
Diffstat (limited to 'core/pxeisr.inc')
-rw-r--r--core/pxeisr.inc172
1 files changed, 172 insertions, 0 deletions
diff --git a/core/pxeisr.inc b/core/pxeisr.inc
new file mode 100644
index 00000000..93c73ed5
--- /dev/null
+++ b/core/pxeisr.inc
@@ -0,0 +1,172 @@
+;
+; 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