mirror of
https://github.com/ipxe/ipxe
synced 2025-12-12 23:15:10 +03:00
As written, if the if the UNDI ISR call clobbers the upper halves of any of the GPRs (which by convention it is permitted to do, and by paranoia should be expected to do) then nothing in the interrupt handler will recover the state. Additionally, save/restore %fs and %gs out of sheer paranoia - it's a cheap enough operation, and may prevent problems due to poorly written UNDI stacks.
83 lines
1.5 KiB
ArmAsm
83 lines
1.5 KiB
ArmAsm
#define PXENV_UNDI_ISR 0x0014
|
|
#define PXENV_UNDI_ISR_IN_START 1
|
|
#define PXENV_UNDI_ISR_OUT_OURS 0
|
|
#define PXENV_UNDI_ISR_OUT_NOT_OURS 1
|
|
|
|
#define IRQ_PIC_CUTOFF 8
|
|
#define ICR_EOI_NON_SPECIFIC 0x20
|
|
#define PIC1_ICR 0x20
|
|
#define PIC2_ICR 0xa0
|
|
|
|
.text
|
|
.arch i386
|
|
.section ".text16", "ax", @progbits
|
|
.section ".data16", "aw", @progbits
|
|
.code16
|
|
|
|
.section ".text16"
|
|
.globl undiisr
|
|
undiisr:
|
|
|
|
/* Preserve registers */
|
|
pushw %ds
|
|
pushw %es
|
|
pushw %fs
|
|
pushw %gs
|
|
pushal
|
|
|
|
/* Set up our segment registers */
|
|
movw %cs:rm_ds, %ax
|
|
movw %ax, %ds
|
|
|
|
/* Check that we have an UNDI entry point */
|
|
cmpw $0, undinet_entry_point
|
|
je chain
|
|
|
|
/* Issue UNDI API call */
|
|
movw %ax, %es
|
|
movw $undinet_params, %di
|
|
movw $PXENV_UNDI_ISR, %bx
|
|
movw $PXENV_UNDI_ISR_IN_START, funcflag
|
|
pushw %es
|
|
pushw %di
|
|
pushw %bx
|
|
lcall *undinet_entry_point
|
|
cli /* Just in case */
|
|
addw $6, %sp
|
|
cmpw $PXENV_UNDI_ISR_OUT_OURS, funcflag
|
|
jne eoi
|
|
|
|
trig: /* Record interrupt occurence */
|
|
incb undiisr_trigger_count
|
|
|
|
eoi: /* Send EOI */
|
|
movb $ICR_EOI_NON_SPECIFIC, %al
|
|
cmpb $IRQ_PIC_CUTOFF, undiisr_irq
|
|
jb 1f
|
|
outb %al, $PIC2_ICR
|
|
1: outb %al, $PIC1_ICR
|
|
jmp exit
|
|
|
|
chain: /* Chain to next handler */
|
|
pushfw
|
|
lcall *undiisr_next_handler
|
|
|
|
exit: /* Restore registers and return */
|
|
popal
|
|
popw %gs
|
|
popw %fs
|
|
popw %es
|
|
popw %ds
|
|
iret
|
|
|
|
.section ".data16"
|
|
undinet_params:
|
|
status: .word 0
|
|
funcflag: .word 0
|
|
bufferlength: .word 0
|
|
framelength: .word 0
|
|
frameheaderlength: .word 0
|
|
frame: .word 0, 0
|
|
prottype: .byte 0
|
|
pkttype: .byte 0
|