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
|
;
; 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
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_count],PXEIRQ_MAX
.exit:
pop gs
pop fs
pop es
pop ds
popa
iret
.notus:
cmp ax,[pxeirq_last]
jne .reset_timeout
dec word [pxeirq_count]
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_count],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 2
pxeirq_last resw 1
pxeirq_count resw 1
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
|