Next thing to understand

Now, path to the result becomes cleaner, but harder

The main thing to do now – install interrupt handler for NIC. Implemented by BTX vm86 monitor reflects interrupts to vm86 task. So user client application (BTX client) must find which interrupt number is needed (PXE API provides such information), and install handler for it in which call pxe_core_isr().

Installation phase is sophisticated, cause we need to change IDT and client code is executed not in ring 0 as I understand. So, there is SYS_EXEC system call (__exec() ), but according to assembler code there must not be return from code, run by this call, otherwise SYS_EXIT executed. In my case I only need to install handler, and that’s all. If I use __exec(), after IDT modification the only process flow is exit() , or stay forever in ring 0, while PXE related code will be running. The last case is not what I want, cause idea is to save as much boot functionality as possible (and thus to return control to BTX client code).

So, what I need to correctly install interrupt handler? That is the question. If I understand correctly – the one way is to modify btx.S and add another syscall, that allows to install interrupt handler (something like super2user_isr_install(), that installs handler, which calls user defined function in user space.).

Well, there is also another way – use reflected interrupts, and add handler (modify interrupt vector table) in vm86 space. In that case there must be some call to notify user code (not in vm86, but in ring 3) that interrupt occured. That is also needs system call (something like real2user() and user2real() . vm86int() does sequentially pseudocode user2real(), real_call(), real2user(), but it’s needed to be possible to make this code backwards).

I guess, if somebody ever needed installing interrupt handler in BTX client. If I’m understanding all correctly, then first variant with super2user_isr_install() seems better solution than second one.

2 Responses to “Next thing to understand”

I’m having trouble using the UNDI driver with Etherboot. The UNDI API reports interrupt 0x0b, but that interrupt never seems to be triggered.

Have you ever seen a case where the UNDI API does not report the correct interrupt number for the UNDI device? Or have you encountered UNDI implementations that do not trigger interrupts when frames are received?

Well, although I was looking sometimes to Etherboot implementation of UNDI driver, I’ve not worked with it during this project.

> Have you ever seen a case where the UNDI API does not report the correct
> interrupt number for the UNDI device?
No, it always reported correct number (at least in my tests), the same number reported BIOS at POST. But same interrupt may be shared with other devices, in such case – difficulties are probable (cause it’s needed to chain interrupt to second handler).

> Or have you encountered UNDI implementations that do not trigger
> interrupts when frames are received?
That is possible. In fact, during coding pxe_http I’ve met such problem – in some cases interrupt was not triggered (I don’t remember now, was this situation on virtual machine or on my Intel motherboard). I think problem may be in incorrect End of Interrupt (EOI sending to PICs) handling in my code (although I was writing it practicaly the same as in Intel examples and sample code from related books). But this problem was solved by omitting triggered interrupt check.

It’s possible call PXE API function PXENV_UNDI_ISR with FuncFlag PXENV_UNDI_ISR_IN_PROCESS even if there was no interrupt. In such case you will get PXENV_UNDI_ISR_OUT_DONE or new packet flag if any frame received.

So, you will get small overhead by calling function if there was no interrupt, but code will be correctly working. AFAIK, earlier Etherboot implementation worked similar (call without triggering check), look comments to undi_poll() function at /drivers/net/undi.c.