/* * XBRA example: install a handler using XBRA protocol into TOSs * timer handoff vector. Sit in a loop displaying a counter value * until any key is hit. Then remove the handler in a XBRA friendly * manner. * * ++jrb bammi@cadence.com */ #include <stddef.h> #include <xbra.h> #include <osbind.h> #include <stdio.h> unsigned short counter = 0; /* counter incremented in handler */ unsigned short divisor = 50; /* increment counter every divisor ticks */ void my_handler(void); xbra_struct tick_xbra = _XBRA_INIT(my_handler); /* XBRA element */ #define _TIME_VEC 0x100 /* * our exception handler */ void my_handler(void) { if(--divisor == 0) { counter++; divisor = 50; } __asm__ volatile (" unlk a6 /* clean up stack frame */ movl _tick_xbra+8, a0 /* jump to next handler */ jmp a0@"); } /* * unlink a handler in a xbra friendly manner from the exc chain * returns 0 on clean unlink, !0 if something if it could'nt */ int unlink_handler(me, exc) xbra_struct *me; int exc; { xbra_struct *this, *prev; long save_ssp; this = (xbra_struct *) /* get head of chain */ ((unsigned long)Setexc(exc, -1L) - offsetof(xbra_struct, jump)); if(this == me) { /* at the head, just unlink */ Setexc(exc, me->next); return 0; } /* otherwise find me in the chain and unlink */ save_ssp = Super(0L); for(prev = this; this && (this != me); prev = this, this = (xbra_struct *)((this->next) ? (((char *)(this->next)) - offsetof(xbra_struct, jump)) : 0)) { /* validate the xbra */ if(this->xbra_magic != _XBRA_MAGIC) { /* shame on you */ Super(save_ssp); Setexc(exc, me->next); /* nuke it, otherwise it may call ME */ return 1; /* after I am deinstalled */ } } if( (this == me) && (this->gnuc_magic == _GNUC_MAGIC) ) { /* unlink me from middle of the chain */ prev->next = this->next; Super(save_ssp); return 0; } /* we are screwed */ Super(save_ssp); return 2; } int main() { char out[8]; unsigned short last = 0xffff; /* install our handler */ tick_xbra.next = (xptr) Setexc(_TIME_VEC, _XBRA_VEC(tick_xbra)); /* continuously display counter until a key is hit */ do { if(last != counter) { last = counter; sprintf(out, "%05u\r", last); /* display counter */ Cconws(out); } } while( Bconstat(2) == 0 ); /* remove the handler */ return unlink_handler(&tick_xbra, _TIME_VEC); }