mirror of https://github.com/ipxe/ipxe.git
Working code to call the PXE stack from within the ISR.
parent
976a8514cb
commit
027fed72c1
|
@ -0,0 +1,70 @@
|
||||||
|
#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
|
||||||
|
pusha
|
||||||
|
|
||||||
|
/* Issue UNDI API call */
|
||||||
|
movw %cs:rm_ds, %ax
|
||||||
|
movw %ax, %ds
|
||||||
|
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
|
||||||
|
addw $6, %sp
|
||||||
|
cmpw $PXENV_UNDI_ISR_OUT_OURS, funcflag
|
||||||
|
jne chain
|
||||||
|
|
||||||
|
ack: /* Record interrupt occurence */
|
||||||
|
incb undiisr_trigger_count
|
||||||
|
/* 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 */
|
||||||
|
popa
|
||||||
|
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
|
|
@ -146,7 +146,7 @@ static union u_PXENV_ANY __data16 ( undinet_params );
|
||||||
* Used as the indirection vector for all UNDI API calls. Resides in
|
* Used as the indirection vector for all UNDI API calls. Resides in
|
||||||
* base memory.
|
* base memory.
|
||||||
*/
|
*/
|
||||||
static SEGOFF16_t __data16 ( undinet_entry_point );
|
SEGOFF16_t __data16 ( undinet_entry_point );
|
||||||
#define undinet_entry_point __use_data16 ( undinet_entry_point )
|
#define undinet_entry_point __use_data16 ( undinet_entry_point )
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -245,17 +245,21 @@ static int undinet_call ( struct undi_nic *undinic, unsigned int function,
|
||||||
/**
|
/**
|
||||||
* UNDI interrupt service routine
|
* UNDI interrupt service routine
|
||||||
*
|
*
|
||||||
* The UNDI ISR simply increments a counter (@c trigger_count) and
|
* The UNDI ISR increments a counter (@c trigger_count) and exits.
|
||||||
* exits.
|
|
||||||
*/
|
*/
|
||||||
extern void undinet_isr ( void );
|
extern void undiisr ( void );
|
||||||
|
|
||||||
/** Dummy chain vector */
|
/** IRQ number */
|
||||||
static struct segoff prev_handler[ IRQ_MAX + 1 ];
|
uint8_t __data16 ( undiisr_irq );
|
||||||
|
#define undiisr_irq __use_data16 ( undiisr_irq )
|
||||||
|
|
||||||
|
/** IRQ chain vector */
|
||||||
|
struct segoff __data16 ( undiisr_next_handler );
|
||||||
|
#define undiisr_next_handler __use_data16 ( undiisr_next_handler )
|
||||||
|
|
||||||
/** IRQ trigger count */
|
/** IRQ trigger count */
|
||||||
static volatile uint8_t __text16 ( trigger_count ) = 0;
|
volatile uint8_t __data16 ( undiisr_trigger_count ) = 0;
|
||||||
#define trigger_count __use_text16 ( trigger_count )
|
#define undiisr_trigger_count __use_data16 ( undiisr_trigger_count )
|
||||||
|
|
||||||
/** Last observed trigger count */
|
/** Last observed trigger count */
|
||||||
static unsigned int last_trigger_count = 0;
|
static unsigned int last_trigger_count = 0;
|
||||||
|
@ -275,16 +279,12 @@ static unsigned int last_trigger_count = 0;
|
||||||
static void undinet_hook_isr ( unsigned int irq ) {
|
static void undinet_hook_isr ( unsigned int irq ) {
|
||||||
|
|
||||||
assert ( irq <= IRQ_MAX );
|
assert ( irq <= IRQ_MAX );
|
||||||
|
assert ( undiisr_irq == 0 );
|
||||||
|
|
||||||
__asm__ __volatile__ ( TEXT16_CODE ( "\nundinet_isr:\n\t"
|
undiisr_irq = irq;
|
||||||
"incb %%cs:%c0\n\t"
|
|
||||||
"iret\n\t" )
|
|
||||||
: : "p" ( & __from_text16 ( trigger_count ) ) );
|
|
||||||
|
|
||||||
hook_bios_interrupt ( IRQ_INT ( irq ),
|
hook_bios_interrupt ( IRQ_INT ( irq ),
|
||||||
( ( unsigned int ) undinet_isr ),
|
( ( unsigned int ) undiisr ),
|
||||||
&prev_handler[irq] );
|
&undiisr_next_handler );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -297,8 +297,9 @@ static void undinet_unhook_isr ( unsigned int irq ) {
|
||||||
assert ( irq <= IRQ_MAX );
|
assert ( irq <= IRQ_MAX );
|
||||||
|
|
||||||
unhook_bios_interrupt ( IRQ_INT ( irq ),
|
unhook_bios_interrupt ( IRQ_INT ( irq ),
|
||||||
( ( unsigned int ) undinet_isr ),
|
( ( unsigned int ) undiisr ),
|
||||||
&prev_handler[irq] );
|
&undiisr_next_handler );
|
||||||
|
undiisr_irq = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -310,7 +311,7 @@ static int undinet_isr_triggered ( void ) {
|
||||||
unsigned int this_trigger_count;
|
unsigned int this_trigger_count;
|
||||||
|
|
||||||
/* Read trigger_count. Do this only once; it is volatile */
|
/* Read trigger_count. Do this only once; it is volatile */
|
||||||
this_trigger_count = trigger_count;
|
this_trigger_count = undiisr_trigger_count;
|
||||||
|
|
||||||
if ( this_trigger_count == last_trigger_count ) {
|
if ( this_trigger_count == last_trigger_count ) {
|
||||||
/* Not triggered */
|
/* Not triggered */
|
||||||
|
@ -424,6 +425,7 @@ static void undinet_poll ( struct net_device *netdev ) {
|
||||||
if ( ! undinet_isr_triggered() )
|
if ( ! undinet_isr_triggered() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* See if this was our interrupt */
|
/* See if this was our interrupt */
|
||||||
memset ( &undi_isr, 0, sizeof ( undi_isr ) );
|
memset ( &undi_isr, 0, sizeof ( undi_isr ) );
|
||||||
undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_START;
|
undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_START;
|
||||||
|
@ -443,6 +445,7 @@ static void undinet_poll ( struct net_device *netdev ) {
|
||||||
/* If this wasn't our interrupt, exit now */
|
/* If this wasn't our interrupt, exit now */
|
||||||
if ( undi_isr.FuncFlag != PXENV_UNDI_ISR_OUT_OURS )
|
if ( undi_isr.FuncFlag != PXENV_UNDI_ISR_OUT_OURS )
|
||||||
return;
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Start ISR processing */
|
/* Start ISR processing */
|
||||||
undinic->isr_processing = 1;
|
undinic->isr_processing = 1;
|
||||||
|
|
Loading…
Reference in New Issue