miércoles, 21 de abril de 2010

Phase 2: Make it breath [Done]

Add graphics mode support, and native IRQ setup and handling
Graphics mode

After the nice suprise that GRUB had graphic mode switching almost ready to be used, we jumped into making it work for us, and we chose a graphic mode that is really nice AND maps 1 to 1 from Squeak's representation to video RAM: 1024x768x32 bits is our choice although any 32 bits mode would suit the needs. Hacking a ioShowDisplay() that works was easy: it's no more than a bounded memcpy(). With this we got some graphic output in SqueakNOS' screen!

With the old SqueakNOS we had some problems at this point, mainly because Squeak does not refresh the screen upon entering, so this time we solved it really fast, by doing a "self currentWorld fullRepaintNeeded" after a small Delay, and voila! Squeak's full screen was shown!

Now we were facing the most delicate part: making IRQs properly work. Subtasks: set a void handler for every IRQ and enable IRQs (see that it doesn't halt). Add an infinite loop handler for the keyboard IRQ (see that it hangs on a keypress). Set a visible handler for the timer interrupt (see that it draws something on the screen... you can still see it in the upper right corner of SqueakNOS). Finally change all void handlers for code that will trigger a Squeak Semaphore and exit, also add the primitive to register the Semaphores (see that it doesn't hang, then see that the Semaphore gets triggered from inside Squeak). At last, loop waiting on the semaphore for keyboard's IRQ, read keyboard's port, and signla IRQ end all from inside Squeak. [Done]

SqueakNOS IRQ Handling

Squeak VM lets you signal Squeak Semaphores from the native world by calling signalSemaphoreWithIndex(). We want to serve IRQs from Squeak, using interpreted code, not native code. We seriously think that with hardware close to 1000 times faster than 20 years go we should be able to do it without any problems. Of course we cannot set the native IRQs handlers to jump to Squeak code, so our idea is to have a different Semaphore for every IRQ and have a Squeak Process with highIOPriority blocking on the Semaphore.

The code inside Squeak, taken from InterruptRequestDispatcher>>installOn: looks like:
installOn: aComputer
self registerSemaphore.
process := [
[
semaphore wait.
self handleOn: aComputer.
aComputer interruptController signalEndOfInterrupt: interruptNumber.
] repeat
] fork priority: Processor highIOPriority.
aComputer interruptController enableIRQ: interruptNumber

And the native code to signal the Semaphore, taken from ints.h, is similar to:
 void irq_1_handler();
asmlinkage void ISR_1() {
if (0!=IRQSemaphores[number])
signalSemaphoreWithIndex(IRQSemaphores[number]);
}

asm(
".text"
".align 16"
"irq_1_handler:"
"pusha"
"call ISR_1"
"popa"
"iret"
)

There is an interesting detail in all this: the software interrupt ending (IRET) and the hardware IRQ ending (outb(0x20,0x20)) are detached in SqueakNOS, were they are almost always done at the same time in every other code we saw. This gives a really desirable result: The IRET lets the software continue, going back to the interpreter and letting the Process waiting on the Semaphore be rescheduled, however, the hardware part (Interrupt Controller) still thinks the IRQ has not been served yet, and will wait until the Squeak side of the handler (shown above) signals the end of the interrupt (aComputer interruptController signalEndOfInterrupt: interruptNumber.

We seriously believe that with computers close to 1000 times faster than 20 years ago this should be ok, however we are not sure yet if it may bring any problems later, and we are open, although reluctant, to the possibility of coding some glue code, or even complete "device drivers" natively (or hopefully using Exupery). Probably for sound and video I/O, we'll see.

We were successfully using the very same scheme in the old SqueakNOS, so we just ported it to the new code base.

No hay comentarios:

Publicar un comentario