Changeset 295 for soft/giet_vm/giet_drivers/tty_driver.c
- Timestamp:
- Mar 26, 2014, 6:44:44 PM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
soft/giet_vm/giet_drivers/tty_driver.c
r258 r295 8 8 // This driver supports the SocLib vci_multi_tty component. 9 9 // 10 // It can exist only one multi_tty controler in the architecture.11 //12 10 // The total number of TTY terminals must be defined by the configuration 13 11 // parameter NB_TTY_CHANNELS in the hard_config.h file. 14 //15 // The register offsets must be defined in the hwr_mapping.h file.16 12 // 17 13 // The "system" terminal is TTY[0]. … … 19 15 // as defined in the mapping_info data structure. The corresponding tty_id must 20 16 // be stored in the context of the task by the boot code. 21 ///////////////////////////////////////////////////////////////////////////////////22 // The virtual base address of the segment associated to a channel is:23 17 // 24 // seg_tty_base + TTY_SPAN * channel_id 25 // 26 // The seg_tty_base virtual base addresses must be defined in giet_vsegs.ld file. 18 // The seg_tty_base must be defined in giet_vsegs.ld file. 19 /////////////////////////////////////////////////////////////////////////////////// 20 // Implementation note: 21 // 22 // All physical accesses to device registers are done by the two 23 // _tty_get_register(), _tty_set_register() low-level functions, 24 // that are handling virtual / physical addressing. 27 25 /////////////////////////////////////////////////////////////////////////////////// 28 26 29 27 #include <giet_config.h> 30 28 #include <tty_driver.h> 29 #include <xcu_driver.h> 31 30 #include <ctx_handler.h> 32 31 #include <utils.h> … … 42 41 #define in_unckdata __attribute__((section (".unckdata"))) 43 42 44 ///////////////// TTY global variables 45 in_unckdata volatile unsigned char _tty_get_buf[NB_TTY_CHANNELS]; 46 in_unckdata volatile unsigned char _tty_get_full[NB_TTY_CHANNELS] 43 ////////////////////////////////////////////////////////////////////////////// 44 // TTY global variables 45 ////////////////////////////////////////////////////////////////////////////// 46 47 in_unckdata volatile unsigned int _tty_rx_buf[NB_TTY_CHANNELS]; 48 in_unckdata volatile unsigned int _tty_rx_full[NB_TTY_CHANNELS] 47 49 = { [0 ... NB_TTY_CHANNELS - 1] = 0 }; 50 51 ////////////////////////////////////////////////////////////////////////////// 52 // This low level function returns the value of register (channel / index) 53 ////////////////////////////////////////////////////////////////////////////// 54 unsigned int _tty_get_register( unsigned int channel, 55 unsigned int index ) 56 { 57 unsigned int* vaddr = (unsigned int*)&seg_tty_base + channel*TTY_SPAN + index; 58 return _io_extended_read( vaddr ); 59 } 60 61 ////////////////////////////////////////////////////////////////////////////// 62 // This low level function set a new value in register (channel / index) 63 ////////////////////////////////////////////////////////////////////////////// 64 void _tty_set_register( unsigned int channel, 65 unsigned int index, 66 unsigned int value ) 67 { 68 unsigned int* vaddr = (unsigned int*)&seg_tty_base + channel*TTY_SPAN + index; 69 _io_extended_write( vaddr, value ); 70 } 48 71 49 72 ///////////////////////////////////////////////////////////////////////////////// 50 73 // This non-blocking function writes a character string from a fixed-length 51 // buffer to the TTY_WRITE register of a TTY terminal identified by the 52 // channel argument. If the channel argument is 0xFFFFFFFF, the channel 53 // index is obtained from the current taxk context. 54 // It doesn't use any interrupt. 74 // buffer to a TTY terminal identified by the channel argument. 75 // This function is intended to be used to handle a system call, and should 76 // not be used by the kernel for log messages on TTY 0. 77 // protecting exclusive access to the selected terminal. 78 // If channel argument is 0xFFFFFFFF, the TTY index is found in the task context. 55 79 // This is a non blocking call: it tests the TTY_STATUS register, and stops 56 80 // the transfer as soon as the TTY_STATUS[WRITE] bit is set. … … 62 86 unsigned int channel) // channel index 63 87 { 64 unsigned int nwritten; 65 unsigned int tty_id; 66 unsigned int* tty_address = (unsigned int *) &seg_tty_base; 67 68 // compute tty channel 69 if( channel == 0xFFFFFFFF ) 70 { 71 tty_id = _get_context_slot(CTX_TTY_ID); 72 } 73 else 74 { 75 tty_id = (unsigned int)channel; 76 } 88 unsigned int nwritten; 89 90 // compute and check tty channel 91 if( channel == 0xFFFFFFFF ) channel = _get_context_slot(CTX_TTY_ID); 92 if( channel >= NB_TTY_CHANNELS ) return -1; 77 93 78 94 // write string to TTY channel … … 80 96 { 81 97 // check tty's status 82 if ((tty_address[tty_id * TTY_SPAN + TTY_STATUS] & 0x2) == 0x2) break; 83 _tty_write_data( tty_id, buffer[nwritten] ); 84 } 98 if ( _tty_get_register( channel, TTY_STATUS ) & 0x2 ) break; 99 100 // write one byte 101 _tty_set_register( channel, TTY_WRITE, (unsigned int)buffer[nwritten] ); 102 } 103 85 104 return nwritten; 86 105 } … … 92 111 // It uses the TTY_GET_IRQ[tty_id] interrupt and the buffer must have been 93 112 // filled by the TTY_ISR. 94 // It test the _tty_ get_full[tty_id] register, read the _tty_get_buf[tty_id]113 // It test the _tty_rx_full[tty_id] variable, read the _tty_rx_buf[tty_id] 95 114 // buffer, writes this character to the target buffer, and resets the 96 // _tty_ get_full[tty_id] register.115 // _tty_rx_full[tty_id] register. 97 116 // The length argument is not used. 98 117 ////////////////////////////////////////////////////////////////////////////// … … 103 122 unsigned int channel) // channel index 104 123 { 105 106 unsigned int tty_id; 107 108 // compute tty channel 109 if( channel == 0xFFFFFFFF ) 110 { 111 tty_id = _get_context_slot(CTX_TTY_ID); 112 } 113 else 114 { 115 tty_id = (unsigned int)channel; 116 } 124 // compute and check tty channel 125 if( channel == 0xFFFFFFFF ) channel = _get_context_slot(CTX_TTY_ID); 126 if( channel >= NB_TTY_CHANNELS ) return -1; 117 127 118 128 // read one character from TTY channel 119 if (_tty_ get_full[tty_id] == 0)129 if (_tty_rx_full[channel] == 0) 120 130 { 121 131 return 0; … … 123 133 else 124 134 { 125 *buffer = _tty_ get_buf[tty_id];126 _tty_ get_full[tty_id] = 0;135 *buffer = _tty_rx_buf[channel]; 136 _tty_rx_full[channel] = 0; 127 137 return 1; 128 138 } 129 139 } 130 ////////////////////////////////////////////////////////////////////////////// 131 132 ////////////////////////////////////////////////////////////////////////////// 133 // This function try to take the hardwired lock protecting exclusive access 134 // to TTY terminal identified by the channel argument. 140 141 ////////////////////////////////////////////////////////////////////////////// 142 // This function try to take the hardwired lock protecting 143 // exclusive access to TTY terminal identified by the "channel" argument. 144 // It enters a critical section before taking the lock, and save the SR value 145 // at address defined by the "save_sr_ptr" argument. 135 146 // It returns only when the lock has been successfully taken. 136 147 ////////////////////////////////////////////////////////////////////////////// 137 void _tty_get_lock( unsigned int channel )138 { 139 unsigned int* tty_address = (unsigned int *) &seg_tty_base; 140 141 if( channel >= NB_TTY_CHANNELS )142 {143 _puts("[GIET ERROR] in _tty_get_lock() : illegal TTY index\n"); 144 _exit(); 145 } 146 147 while ( tty_address[channel * TTY_SPAN + TTY_CONFIG] ); 148 } 149 150 ////////////////////////////////////////////////////////////////////////////// 151 // This function releases the hardwired lock protecting exclusive access 152 // to TTY terminal identified by the channel argument. 153 ////////////////////////////////////////////////////////////////////////////// 154 void _tty_release_lock( unsigned int channel ) 155 { 156 unsigned int* tty_address = (unsigned int *) &seg_tty_base;157 158 if( channel >= NB_TTY_CHANNELS ) 159 { 160 _puts("[GIET ERROR] in _tty_release_lock() : illegal TTY index\n"); 161 _exit(); 162 } 163 164 tty_address[channel * TTY_SPAN + TTY_CONFIG] = 0; 165 } 166 167 ////////////////////////////////////////////////////////////////////////////// 168 // This function returns the content of the TTY_READ register in the 169 // TTY terminal identified by the channel argument. 170 ////////////////////////////////////////////////////////////////////////////// 171 unsigned int _tty_read_data( unsigned int channel ) 172 { 173 unsigned int* tty_address = (unsigned int *) &seg_tty_base; 174 175 if( channel >= NB_TTY_CHANNELS )176 {177 _ puts("[GIET ERROR] in _tty_read_data() : illegal TTY index\n");178 _exit();179 }180 181 return tty_address[channel * TTY_SPAN + TTY_READ];182 } 183 184 ////////////////////////////////////////////////////////////////////////////// 185 // This function returns the content of the TTY_STATUS register in the 186 // TTY terminal identified by the channel argument. 187 ////////////////////////////////////////////////////////////////////////////// 188 unsigned int _tty_get_status( unsigned int channel ) 189 { 190 unsigned int* tty_address = (unsigned int *) &seg_tty_base;191 192 if( channel >= NB_TTY_CHANNELS ) 193 { 194 _puts("[GIET ERROR] in _tty_get_status() : illegal TTY index\n");195 _exit(); 196 } 197 198 return tty_address[channel * TTY_SPAN + TTY_STATUS]; 199 } 200 201 ////////////////////////////////////////////////////////////////////////////// 202 // This function writes one character in the TTY_WRITE register in the 203 // TTY terminal identified by the channel argument. 204 ////////////////////////////////////////////////////////////////////////////// 205 void _tty_write_data( unsigned int channel, 206 char byte ) 207 { 208 unsigned int* tty_address = (unsigned int *) &seg_tty_base; 209 210 if( channel >= NB_TTY_CHANNELS ) 211 { 212 _puts("[GIET ERROR] in _tty_write_data() : illegal TTY index\n"); 213 _exit();214 }215 216 tty_address[channel * TTY_SPAN + TTY_WRITE] = (unsigned int) byte;217 } 218 148 void _tty_get_lock( unsigned int channel, 149 unsigned int * save_sr_ptr ) 150 { 151 if( channel >= NB_TTY_CHANNELS ) _exit(); 152 _it_disable( save_sr_ptr ); 153 while ( _tty_get_register( channel, TTY_CONFIG ) ); // busy waiting 154 } 155 156 ////////////////////////////////////////////////////////////////////////////// 157 // This function releases the hardwired lock protecting 158 // exclusive access to TTY terminal identified by the channel argument. 159 // It exit the critical section after lock release, and restore SR value 160 // from address defined by the "save_sr_ptr" argument. 161 ////////////////////////////////////////////////////////////////////////////// 162 void _tty_release_lock( unsigned int channel, 163 unsigned int * save_sr_ptr ) 164 { 165 if( channel >= NB_TTY_CHANNELS ) _exit(); 166 167 _tty_set_register( channel, TTY_CONFIG, 0 ); 168 _it_restore( save_sr_ptr ); 169 } 170 171 /////////////////////////////////////////////////////////////////////////////////// 172 // This ISR handles the IRQ signaling that the RX buffer is full. 173 // IT can be an HWI or an SWI. 174 // There is one single multi_tty component controling all channels. 175 // There is one communication buffer _tty_rx_buf[i] and one synchronisation 176 // variable _tty_rx_full[i] per channel. 177 // A character is lost if the buffer is full when the ISR is executed. 178 /////////////////////////////////////////////////////////////////////////////////// 179 void _tty_rx_isr( unsigned int irq_type, // HWI / WTI 180 unsigned int irq_id, // index returned by XCU 181 unsigned int channel ) // TTY channel 182 { 183 unsigned int cluster_xy = _get_procid() / NB_PROCS_MAX; 184 185 if ( irq_type == IRQ_TYPE_WTI ) // reset SWI in XCU if required 186 { 187 unsigned int value; 188 _xcu_get_wti_value( cluster_xy, irq_id, &value ); 189 } 190 191 // get character and reset TTY IRQ 192 _tty_rx_buf[channel] = _tty_get_register( channel, TTY_READ ); 193 194 #if GIET_DEBUG_IRQS // we don't take the TTY lock to avoid deadlock 195 unsigned int x = cluster_xy >> Y_WIDTH; 196 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 197 unsigned int lpid = _get_procid() % NB_PROCS_MAX; 198 _puts("\n[IRQS DEBUG] Processor["); 199 _putd(x ); 200 _puts(","); 201 _putd(y ); 202 _puts(","); 203 _putd(lpid ); 204 _puts("] enters _tty_rx_isr() at cycle "); 205 _putd(_get_proctime() ); 206 _puts("\n read byte = "); 207 _putx(_tty_rx_buf[channel] ); 208 _puts("\n"); 209 #endif 210 211 // signals character available 212 _tty_rx_full[channel] = 1; 213 } 214 215 /////////////////////////////////////////////////////////////////////////////////// 216 // This ISR handles the IRQ signaling that the TX buffer is empty. 217 // IT can be an HWI or an SWI. 218 // There is one single multi_tty component controling all channels. 219 // There is one communication buffer _tty_rx_buf[i] and one synchronisation 220 // variable _tty_rx_full[i] per channel. 221 // A character is lost if the buffer is full when the ISR is executed. 222 /////////////////////////////////////////////////////////////////////////////////// 223 void _tty_tx_isr( unsigned int irq_type, // HWI / WTI 224 unsigned int irq_id, // index returned by XCU 225 unsigned int channel ) // TTY channel 226 { 227 _puts("\n[GIET ERROR] the _tty_tx_isr() is not implemented\n"); 228 _exit(); 229 } 219 230 220 231 // Local Variables:
Note: See TracChangeset
for help on using the changeset viewer.