FILE_LICENCE ( GPL2_OR_LATER )

#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
	
	.section ".note.GNU-stack", "", @progbits
	.code16
	.arch i386

	.section ".text16", "ax", @progbits
	.globl undiisr
undiisr:
	
	/* Preserve registers */
	pushw	%ds
	pushw	%es
	pushw	%fs
	pushw	%gs
	pushfl
	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 */
	cli
	popal
	movzwl	%sp, %esp
	addr32	movl -20(%esp), %esp	/* %esp isn't restored by popal */
	popfl
	popw	%gs
	popw	%fs
	popw	%es
	popw	%ds
	iret

	.section ".data16", "aw", @progbits
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
