1;
2; Process a PXE interrupt
3;
4		section .text16
5
6PXEIRQ_MAX	equ 100		; Max spurious interrupts in a timer tick
7
8		global pxe_isr
9pxe_isr:
10		cld
11		pusha
12		push ds
13		push es
14		push fs
15		push gs
16
17		xor ax,ax
18		mov ds,ax
19		mov es,ax
20
21		mov bx,PXENV_UNDI_ISR
22		mov di,pxenv_undi_isr_buf
23
24		mov cx,pxenv_undi_isr_buf.size/2
25		push di
26		rep stosw
27		pop di
28
29		mov byte [pxenv_undi_isr_buf.funcflag],PXENV_UNDI_ISR_IN_START
30
31		call pxenv
32		mov ax,[__jiffies]
33		jc .notus
34
35		cmp word [pxenv_undi_isr_buf.funcflag],PXENV_UNDI_ISR_OUT_OURS
36		jne .notus
37
38		; Its ours - set the flag for the return to PM.
39		; We need to EOI this ourselves, so that the
40		; leftover BC doesn't get control.
41		mov byte [pxe_irq_pending],1
42		inc dword [pxe_irq_count]
43
44		cmp byte [pxe_irq_vector], 8
45		mov al,0x20		; Non-specific EOI
46		jb .pri_pic
47
48		out 0xA0, al		; Secondary PIC
49.pri_pic:
50		out 0x20,al		; Primary PIC
51
52		mov [pxeirq_last],ax
53		mov word [pxeirq_deadman],PXEIRQ_MAX
54
55.exit:
56		pop gs
57		pop fs
58		pop es
59		pop ds
60		popa
61		iret
62
63.notus:
64		cmp ax,[pxeirq_last]
65		jne .reset_timeout
66		dec word [pxeirq_deadman]
67		jz .timeout
68
69.chain:
70		pop gs
71		pop fs
72		pop es
73		pop ds
74		popa
75		jmp 0:0
76		global pxe_irq_chain
77pxe_irq_chain	equ $-4
78
79.reset_timeout:
80		mov [pxeirq_last],ax
81		mov word [pxeirq_deadman],PXEIRQ_MAX
82		jmp .chain
83
84		; Too many spurious interrupts, shut off the interrupts
85		; and go to polling mode
86.timeout:
87		mov al,[pxe_irq_vector]
88		mov dx,21h
89		movzx cx,al
90		shl cx,7-3
91		add dx,cx
92		and al,7
93		xchg ax,cx
94		mov ch,1
95		shl ch,cl
96		in al,dx
97		or al,ch
98		out dx,al
99		or byte [pxe_need_poll],1
100		jmp .exit
101
102
103; Emulate a PXE interrupt from the polling thread
104		global pxe_poll
105pxe_poll:
106		pushf
107		cli
108		cld
109		pusha
110		push ds
111		push es
112		push fs
113		push gs
114
115		mov bx,PXENV_UNDI_ISR
116		mov di,pxenv_undi_isr_buf
117
118		mov cx,pxenv_undi_isr_buf.size/2
119		push di
120		rep stosw
121		pop di
122
123		mov byte [pxenv_undi_isr_buf.funcflag],PXENV_UNDI_ISR_IN_START
124
125		call pxenv
126		jc .notus
127
128		cmp word [pxenv_undi_isr_buf.funcflag],PXENV_UNDI_ISR_OUT_OURS
129		jne .notus
130
131		; Its ours - set the flag for the return to PM.
132		; We need to EOI this ourselves, so that the
133		; leftover BC doesn't get control.
134		mov byte [pxe_irq_pending],1
135
136.notus:
137		pop gs
138		pop fs
139		pop es
140		pop ds
141		popa
142		popf
143		ret
144
145		section .bss16
146		alignb 4
147pxenv_undi_isr_buf:
148.status:	resw 1
149.funcflag:	resw 1
150.bufferlength:	resw 1
151.framelen:	resw 1
152.framehdrlen:	resw 1
153.frame:		resw 2
154.prottype:	resb 1
155.pkttype:	resb 1
156.size		equ $-pxenv_undi_isr_buf
157
158		alignb 4
159pxeirq_last	resw 1
160pxeirq_deadman	resw 1
161
162		global pxe_irq_count
163pxe_irq_count	resd 1			; PXE IRQ counter
164		global pxe_irq_vector
165pxe_irq_vector	resb 1			; PXE IRQ vector
166		global pxe_irq_pending
167pxe_irq_pending	resb 1			; IRQ pending flag
168		global pxe_need_poll
169pxe_need_poll	resb 1			; Bit 0 = need polling
170					; Bit 1 = polling active
171
172		section .text16
173