aboutsummaryrefslogtreecommitdiffstats
path: root/core/pxeisr.inc
blob: 93c73ed560e87a0ce8da5500310ec37e501d5603 (plain)
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