/************************************************************************************* File : isr.c Authors : Alain Greiner Date : april 2011 These routines must be "intalled" by the boot code in the interrupt vector, depending on the system architecture. *************************************************************************************/ #include "isr.h" #include "drivers.h" #define in_isr __attribute__((section (".isr"))) struct plaf; extern struct plaf seg_dma_base; extern struct plaf seg_ioc_base; extern struct plaf seg_timer_base; extern struct plaf seg_tty_base; extern struct plaf NB_TIMERS; extern struct plaf NB_TASKS; ////////////////////////////////////////////////////////////////////////////////////// // _isr_dma // Each processor controls its own private DMA. // It acknowledge the IRQ using the dma base address depending on the proc_id // as computed by the _segment_increment() function, writes the transfer // status in the _dma_status[pid] variable, and resets the _dma_busy[pid] // synchrnisation variable to signal completion. // Both variables are defined in the drivers.c file. ///////////////////////////////////////////////////////////////////////////////////// in_isr void _isr_dma() { int* dma_address; unsigned int base = (unsigned int)&seg_dma_base; unsigned int increment = _segment_increment(DMA_SPAN*4); size_t pid = _procid(); dma_address = (int*)(base + increment); _dma_status[pid] = dma_address[DMA_LEN]; // save status _dma_busy[pid] = 0; // release DMA dma_address[DMA_RESET] = 0; // reset IRQ } ////////////////////////////////////////////////////////////////////////////////////// // _isr_ioc // There is only one IOC controler shared by all tasks. // It acknowledge the IRQ using the ioc base address, save the status, // and set the _ioc_done variable to signal completion. // This variable is defined in the drivers.c file. ////////////////////////////////////////////////////////////////////////////////////// in_isr void _isr_ioc() { int* ioc_address = (int*)&seg_ioc_base; _ioc_status = ioc_address[BLOCK_DEVICE_STATUS]; // save status & reset IRQ _ioc_done = 1; // signals completion } ////////////////////////////////////////////////////////////////////////////////////// // _isr_timer* (* = 0,1,2,3) // A single processor can use up to 4 independant timers. // These 4 ISRs handle up to 4 IRQs generated by 4 independant timers, // connected to a single processor. // It acknowledge the IRQ using the timer base address depending // on both the proc_id and the timer_id (0,1,2,3). // It displays a message on TTY[proc_id,task_id]. ////////////////////////////////////////////////////////////////////////////////////// in_isr void _isr_timer_indexed(size_t timer_id) { int* timer_address; size_t ntimers = (size_t)&NB_TIMERS; unsigned int base = (unsigned int)&seg_timer_base; unsigned int increment = _segment_increment(ntimers*TIMER_SPAN*4); int date = (int)_proctime(); char buf[10]; timer_address = (int*)(base + increment + timer_id*TIMER_SPAN*4); timer_address[TIMER_RESETIRQ] = 0; // reset IRQ _itoa_dec(date, buf); // print message _tty_write("\n!!! interrupt timer0 received at cycle ", 40); _tty_write(buf, 10); _tty_write("\n\n", 2); } in_isr void _isr_timer() { _isr_timer_indexed(0); } in_isr void _isr_timer0() { _isr_timer_indexed(0); } in_isr void _isr_timer1() { _isr_timer_indexed(1); } in_isr void _isr_timer2() { _isr_timer_indexed(2); } in_isr void _isr_timer3() { _isr_timer_indexed(3); } ////////////////////////////////////////////////////////////////////////////////////// // _isr_tty_get_task* (* = 0,1,2,3) // A single processor can run up to 4 tasks in pseudo-parallelismr, // and each task has is own private terminal. // These 4 ISRs handle up to 4 IRQs associate to 4 independant terminals // connected to a single processor. // It acknowledge the IRQ using the terminal basee address depending // on both the proc_id and the task_id (0,1,2,3). // There is one communication buffer _tty_get_buf[tty_id] per terminal. // protected by a set/reset variable _tty_get_full[tty_id]. // The _tty_get_full[tty_id] synchronisation variable is set // by the ISR, and reset by the OS. // Both variables are defined in the drivers.c file. // To access these buffers, the terminal index is computed as // tty_id = proc_id*ntasks + task_id // A character is lost if the buffer is full when the ISR is executed. ////////////////////////////////////////////////////////////////////////////////////// in_isr void _isr_tty_get_indexed(size_t task_id) { char* tty_address; size_t ntasks = (size_t)&NB_TASKS; size_t tty_id = _procid()*ntasks + task_id; unsigned int base = (unsigned int)&seg_tty_base; unsigned int increment = _segment_increment(ntasks*TTY_SPAN*4); tty_address = (char*)(base + increment + task_id*TTY_SPAN*4); _tty_get_buf[tty_id] = tty_address[TTY_READ*4]; // save character and reset IRQ _tty_get_full[tty_id] = 1; // signals character available } in_isr void _isr_tty_get() { _isr_tty_get_indexed(0); } in_isr void _isr_tty_get_task0() { _isr_tty_get_indexed(0); } in_isr void _isr_tty_get_task1() { _isr_tty_get_indexed(1); } in_isr void _isr_tty_get_task2() { _isr_tty_get_indexed(2); } in_isr void _isr_tty_get_task3() { _isr_tty_get_indexed(3); } ////////////////////////////////////////////////////////////////////////////////////// // _isr_switch // This ISR is in charge of context switch. // It handles up to 4 IRQs, corresponding to 4 different processors. // If the processor uses several timers, the context switch is driven // by the IRQ associated to timer0. // It acknowledges the IRQ on TIMER[proc_id] and calls the _ctx_switch() function. ////////////////////////////////////////////////////////////////////////////////////// in_isr void _isr_switch() { int* timer_address; unsigned int base = (unsigned int)&seg_timer_base; unsigned int increment = _segment_increment(TIMER_SPAN*4); timer_address = (int*)(base + increment); timer_address[TIMER_RESETIRQ] = 0; // reset IRQ _ctx_switch(); } /* Local Variables: tab-width: 4; c-basic-offset: 4; c-file-offsets:((innamespace . 0)(inline-open . 0)); indent-tabs-mode: nil; End: */ /* vim: set filetype=c expandtab shiftwidth=4 tabstop=4 softtabstop=4: */