/////////////////////////////////////////////////////////////////////////// // File : irq_handler.c // Date : 01/04/2012 // Author : alain greiner // Copyright (c) UPMC-LIP6 /////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include ///////////////////////////////////////////////////////////////////////// // Global variables ///////////////////////////////////////////////////////////////////////// // array of external IRQ indexes for each (isr/channel) couple __attribute__((section(".kdata"))) unsigned char _ext_irq_index[GIET_ISR_TYPE_MAX][GIET_ISR_CHANNEL_MAX]; // WTI mailbox allocators for external IRQ routing (3 allocators per proc) __attribute__((section(".kdata"))) unsigned char _wti_alloc_one[X_SIZE][Y_SIZE][NB_PROCS_MAX]; __attribute__((section(".kdata"))) unsigned char _wti_alloc_two[X_SIZE][Y_SIZE][NB_PROCS_MAX]; __attribute__((section(".kdata"))) unsigned char _wti_alloc_ter[X_SIZE][Y_SIZE][NB_PROCS_MAX]; ///////////////////////////////////////////////////////////////////////// // this array is allocated in the boot.c or kernel_init.c ///////////////////////////////////////////////////////////////////////// extern static_scheduler_t* _schedulers[X_SIZE][Y_SIZE][NB_PROCS_MAX]; ///////////////////////////////////////////////////////////////////////// // These ISR_TYPE names for display must be consistent with values in // irq_handler.h / mapping.py / xml_driver.c ///////////////////////////////////////////////////////////////////////// __attribute__((section(".kdata"))) char* _isr_type_name[] = { "DEFAULT", "TICK" , "TTY_RX" , "TTY_TX" , "BDV" , "TIMER" , "WAKUP" , "NIC_RX" , "NIC_TX" , "CMA" , "MMC" , "DMA" , "SPI" , "MWR" , "HBA" }; //////////////////// void _ext_irq_init() { mapping_header_t* header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE; mapping_cluster_t* cluster = _get_cluster_base(header); mapping_periph_t* periph = _get_periph_base(header); mapping_irq_t* irq = _get_irq_base(header); unsigned int periph_id; // peripheral index in mapping_info unsigned int irq_id; // irq index in mapping_info // get cluster_io index in mapping unsigned int x_io = header->x_io; unsigned int y_io = header->y_io; unsigned int cluster_io = (x_io * Y_SIZE) + y_io; mapping_periph_t* pic = NULL; // scan external peripherals to find XCU unsigned int min = cluster[cluster_io].periph_offset ; unsigned int max = min + cluster[cluster_io].periphs ; for ( periph_id = min ; periph_id < max ; periph_id++ ) { if ( periph[periph_id].type == PERIPH_TYPE_PIC ) { pic = &periph[periph_id]; break; } } if ( pic == NULL ) { _printf("\n[GIET ERROR] in _ext_irq_init() : No PIC component found\n"); _exit(); } // scan PIC IRQS defined in mapping for ( irq_id = pic->irq_offset ; irq_id < pic->irq_offset + pic->irqs ; irq_id++ ) { unsigned int type = irq[irq_id].srctype; unsigned int srcid = irq[irq_id].srcid; unsigned int isr = irq[irq_id].isr; unsigned int channel = irq[irq_id].channel; if ( (type != IRQ_TYPE_HWI) || (srcid > 31) || (isr >= GIET_ISR_TYPE_MAX) || (channel >= GIET_ISR_CHANNEL_MAX) ) { _printf("\n[GIET ERROR] in _ext_irq_init() : Bad PIC IRQ\n" " type = %d / srcid = %d / isr = %d / channel = %d\n", type , srcid , isr , channel ); _exit(); } _ext_irq_index[isr][channel] = srcid; } } // end _ext_irq_init() //////////////////////////////////////////// void _ext_irq_alloc( unsigned int isr_type, unsigned int isr_channel, unsigned int* wti_index ) { unsigned int wti_id; // allocated WTI mailbox index in XCU unsigned int irq_id; // external IRQ index in PIC (input) unsigned int wti_addr; // WTI mailbox physical address (32 lsb bits) // check arguments if ( isr_type >= GIET_ISR_TYPE_MAX ) { _printf("\n[GIET ERROR] in _ext_irq_alloc() : illegal ISR type\n"); _exit(); } if ( isr_channel >= GIET_ISR_CHANNEL_MAX ) { _printf("\n[GIET ERROR] in _ext_irq_alloc() : illegal ISR channel\n"); _exit(); } // get processor coordinates [x,y,p] unsigned int gpid = _get_procid(); unsigned int cluster_xy = gpid >> P_WIDTH; unsigned int x = cluster_xy >> Y_WIDTH; unsigned int y = cluster_xy & ((1<wti_vector[wti_id] = isr_channel<<16 | isr_type; } // end ext_irq_alloc() //////////////////////////////////////////// void _ext_irq_release( unsigned int isr_type, unsigned int isr_channel, unsigned int wti_index ) { unsigned int irq_id; // external IRQ index in PIC (input) // get processor coordinates [x,y,p] unsigned int gpid = _get_procid(); unsigned int cluster_xy = gpid >> P_WIDTH; unsigned int x = cluster_xy >> Y_WIDTH; unsigned int y = cluster_xy & ((1<= GIET_ISR_TYPE_MAX ) { _printf("\n[GIET ERROR] in _ext_irq_release() illegal ISR type\n"); _exit(); } if ( isr_channel >= GIET_ISR_CHANNEL_MAX ) { _printf("\n[GIET ERROR] in _ext_irq_release() : illegal ISR channel\n"); _exit(); } // desactivates dynamically allocated PIC entry irq_id = _ext_irq_index[isr_type][isr_channel]; _pic_set_register( irq_id , IOPIC_MASK , 0 ); // releases dynamically allocated WTI mailbox if ( wti_index == p + NB_PROCS_MAX ) _wti_alloc_one[x][y][p] = 0; else if ( wti_index == p + 2*NB_PROCS_MAX ) _wti_alloc_two[x][y][p] = 0; else if ( wti_index == p + 3*NB_PROCS_MAX ) _wti_alloc_ter[x][y][p] = 0; else { _printf("\n[GIET ERROR] in _ext_irq_release() : illegal WTI index\n"); _exit(); } } // end ext_irq_release() ///////////////// void _irq_demux() { unsigned int gpid = _get_procid(); unsigned int cluster_xy = gpid >> P_WIDTH; unsigned int x = cluster_xy >> Y_WIDTH; unsigned int y = cluster_xy & ((1<hwi_vector[irq_id]; else if (irq_type == IRQ_TYPE_PTI) entry = psched->pti_vector[irq_id]; else if (irq_type == IRQ_TYPE_WTI) entry = psched->wti_vector[irq_id]; else { _printf("\n[GIET ERROR] illegal irq_type in irq_demux()\n"); _exit(); } isr_type = (entry ) & 0x0000FFFF; channel = (entry>>16) & 0x00007FFF; #if GIET_DEBUG_IRQS // we don't take the TTY lock to avoid deadlocks char* irq_type_str[] = { "HWI", "WTI", "PTI" }; _puts("\n[IRQS DEBUG] Processor["); _putd(x); _puts(","); _putd(y); _puts(","); _putd(lpid); _puts("] enters _irq_demux() at cycle "); _putd(_get_proctime() ); _puts("\n "); _puts(irq_type_str[irq_type] ); _puts(" : irq_id = "); _putd(irq_id); _puts(" / isr_type = "); _putd(isr_type); _puts(" / channel = "); _putd(channel); _puts("\n"); #endif // ISR call if ( isr_type == ISR_TICK ) _isr_tick ( irq_type, irq_id, channel ); else if ( isr_type == ISR_WAKUP ) _isr_wakup ( irq_type, irq_id, channel ); else if ( isr_type == ISR_BDV ) _bdv_isr ( irq_type, irq_id, channel ); else if ( isr_type == ISR_CMA ) _cma_isr ( irq_type, irq_id, channel ); else if ( isr_type == ISR_TTY_RX ) _tty_rx_isr ( irq_type, irq_id, channel ); else if ( isr_type == ISR_TTY_TX ) _tty_tx_isr ( irq_type, irq_id, channel ); else if ( isr_type == ISR_NIC_RX ) _nic_rx_isr ( irq_type, irq_id, channel ); else if ( isr_type == ISR_NIC_TX ) _nic_tx_isr ( irq_type, irq_id, channel ); else if ( isr_type == ISR_TIMER ) _timer_isr ( irq_type, irq_id, channel ); else if ( isr_type == ISR_MMC ) _mmc_isr ( irq_type, irq_id, channel ); else if ( isr_type == ISR_DMA ) _dma_isr ( irq_type, irq_id, channel ); else if ( isr_type == ISR_SPI ) _spi_isr ( irq_type, irq_id, channel ); else if ( isr_type == ISR_MWR ) _mwr_isr ( irq_type, irq_id, channel ); else { _printf("\n[GIET ERROR] in _irq_demux() :" " illegal ISR type on processor[%d,%d,%d] at cycle %d\n" " - irq_type = %d\n" " - irq_id = %d\n" " - isr_type = %x\n", x, y, lpid, _get_proctime(), irq_type, irq_id, isr_type ); } } else // no interrupt active { _isr_default(); } } /////////////////// void _isr_default() { unsigned int gpid = _get_procid(); unsigned int cluster_xy = gpid >> P_WIDTH; unsigned int x = cluster_xy >> Y_WIDTH; unsigned int y = cluster_xy & ((1<> P_WIDTH; unsigned int x = cluster_xy >> Y_WIDTH; unsigned int y = cluster_xy & ((1<> P_WIDTH; unsigned int x = cluster_xy >> Y_WIDTH; unsigned int y = cluster_xy & ((1<