1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 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
|