diff options
Diffstat (limited to 'core/pxeisr.inc')
-rw-r--r-- | core/pxeisr.inc | 172 |
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 |