/////////////////////////////////////////////////////////////////////////////////// // File : tty_driver.c // Date : 23/05/2013 // Author : alain greiner // Copyright (c) UPMC-LIP6 /////////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #if !defined(SEG_TTY_BASE) # error: You must define SEG_TTY_BASE in the hard_config.h file #endif #if !defined(NB_TTY_CHANNELS) # error: You must define NB_TTY_CHANNELS in the hard_config.h file #endif #if !defined(GIET_NO_HARD_CC) # error: You must define GIET_NO_HARD_CC in the giet_config.h file #endif #if (NB_TTY_CHANNELS < 1) # error: NB_TTY_CHANNELS cannot be smaller than 1! #endif ////////////////////////////////////////////////////////////////////////////// // global variables ////////////////////////////////////////////////////////////////////////////// #define in_unckdata __attribute__((section (".unckdata"))) #define in_kdata __attribute__((section (".kdata"))) #if GIET_NO_HARD_CC in_unckdata volatile unsigned int _tty_rx_buf[NB_TTY_CHANNELS]; in_unckdata volatile unsigned int _tty_rx_full[NB_TTY_CHANNELS]; in_unckdata giet_lock_t _tty_lock[NB_TTY_CHANNELS] __attribute__((aligned(64))); #else in_kdata volatile unsigned int _tty_rx_buf[NB_TTY_CHANNELS]; in_kdata volatile unsigned int _tty_rx_full[NB_TTY_CHANNELS]; in_kdata giet_lock_t _tty_lock[NB_TTY_CHANNELS] __attribute__((aligned(64))); #endif ////////////////////////////////////////////////////////////////////////////// // access functions ////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////// unsigned int _tty_get_register( unsigned int channel, unsigned int index ) { unsigned int* vaddr = (unsigned int*)SEG_TTY_BASE + channel*TTY_SPAN + index; return _io_extended_read( vaddr ); } ///////////////////////////////////////////// void _tty_set_register( unsigned int channel, unsigned int index, unsigned int value ) { unsigned int* vaddr = (unsigned int*)SEG_TTY_BASE + channel*TTY_SPAN + index; _io_extended_write( vaddr, value ); } //////////////////////////////////////// void _tty_rx_isr( unsigned int irq_type, // HWI / WTI unsigned int irq_id, // index returned by XCU unsigned int channel ) // TTY channel { unsigned int gpid = _get_procid(); unsigned int cluster_xy = gpid >> P_WIDTH; // get TTY status unsigned int status = _tty_get_register( channel, TTY_STATUS ); // check both TTY status and kernel buffer status: // does nothing if kernel buffer full or tty_buffer empty if ( ((status & 0x1) == 0) || (_tty_rx_full[channel] != 0) ) return; // reset WTI in XCU if WTI type if ( irq_type == IRQ_TYPE_WTI ) { unsigned int value; _xcu_get_wti_value( cluster_xy, irq_id, &value ); } // transfer character to kernel buffer and acknowledge TTY IRQ _tty_rx_buf[channel] = _tty_get_register( channel, TTY_READ ); // set kernel buffer status asm volatile( "sync" ); _tty_rx_full[channel] = 1; #if GIET_DEBUG_IRQS // we don't take the TTY lock to avoid deadlock unsigned int x = cluster_xy >> Y_WIDTH; unsigned int y = cluster_xy & ((1<