Changeset 570 for trunk/hal/tsar_mips32/drivers/soclib_mty.c
- Timestamp:
- Oct 5, 2018, 12:08:35 AM (6 years ago)
- File:
-
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/hal/tsar_mips32/drivers/soclib_mty.c
r562 r570 1 1 /* 2 * soclib_mt ty.c - soclib tty driver implementation.2 * soclib_mty.c - soclib mty driver implementation. 3 3 * 4 4 * Author Alain Greiner (2016,2017,2018) … … 26 26 #include <dev_txt.h> 27 27 #include <chdev.h> 28 #include <soclib_mtty.h> 29 #include <remote_spinlock.h> 28 #include <soclib_mty.h> 30 29 #include <thread.h> 31 30 #include <printk.h> 32 31 #include <hal_special.h> 33 32 34 #if (DEBUG_SYS_READ & 1)35 extern uint32_t enter_tty_cmd_read;36 extern uint32_t exit_tty_cmd_read;37 38 extern uint32_t enter_tty_isr_read;39 extern uint32_t exit_tty_isr_read;40 #endif41 42 #if (DEBUG_SYS_WRITE & 1)43 extern uint32_t enter_tty_cmd_write;44 extern uint32_t exit_tty_cmd_write;45 46 extern uint32_t enter_tty_isr_write;47 extern uint32_t exit_tty_isr_write;48 #endif49 50 33 extern chdev_directory_t chdev_dir; // allocated in the kernel_init.c file. 51 extern spinlock_t txt0_lock; // Initialized in kernel_init.c 34 52 35 //////////////////////////////////////////////////////////////////////////////////// 53 // These global variables implement the MT TY_RX FIFOs (one per channel)36 // These global variables implement the MTY_RX FIFOs (one per channel) 54 37 //////////////////////////////////////////////////////////////////////////////////// 55 56 __attribute__((section(".kdata"))) 57 mtty_fifo_t mtty_rx_fifo[CONFIG_MAX_TXT_CHANNELS]; 58 59 __attribute__((section(".kdata"))) 60 mtty_fifo_t mtty_tx_fifo[CONFIG_MAX_TXT_CHANNELS]; 38 // Implementation note: 39 // We allocate - in each cluster - two arrays of FIFOs containing as many entries 40 // as the total number of TXT channels, but all entries are not used in all 41 // clusters: for a given cluster K, a given entry corresponding to a given channel 42 // and a given direction is only used if the associated chdev is in cluster K. 43 // With this policy, the driver can ignore the actual placement of chdevs. 44 //////////////////////////////////////////////////////////////////////////////////// 45 46 __attribute__((section(".kdata"))) 47 mty_fifo_t mty_rx_fifo[CONFIG_MAX_TXT_CHANNELS]; 48 49 __attribute__((section(".kdata"))) 50 mty_fifo_t mty_tx_fifo[CONFIG_MAX_TXT_CHANNELS]; 51 52 //////////////////////////////////////////////////////////////////////////////////// 53 // These global variables define the physical channel RX and TX state, 54 // as required by the virtual channels handling. 55 //////////////////////////////////////////////////////////////////////////////////// 56 // Implementation note: 57 // These state variables are required, because the ISR is called twice for each 58 // character on the physical channel (for index and value), and does not the same 59 // actions for index and value. They are also used to implement the round-robin 60 // policy between TX_FIFOs. 61 //////////////////////////////////////////////////////////////////////////////////// 62 63 __attribute__((section(".kdata"))) 64 bool_t mty_rx_not_new; // RX first byte if false 65 66 __attribute__((section(".kdata"))) 67 uint32_t mty_rx_channel; // RX virtual channel index 68 69 __attribute__((section(".kdata"))) 70 bool_t mty_tx_not_new; // TX first byte if false 71 72 __attribute__((section(".kdata"))) 73 uint32_t mty_tx_value; // TX character ascii value 74 75 __attribute__((section(".kdata"))) 76 uint32_t mty_tx_last; // TX last selected virtual channel 61 77 62 78 /////////////////////////////////////// 63 void soclib_mt ty_init( chdev_t * chdev )79 void soclib_mty_init( chdev_t * chdev ) 64 80 { 65 81 xptr_t reg_xp; 66 82 67 83 // initialise function pointers in chdev 68 chdev->cmd = &soclib_mt ty_cmd;69 chdev->isr = &soclib_mt ty_isr;70 chdev->aux = &soclib_mt ty_aux;71 72 // get TTY channel and extended pointer on TTY peripheral base address73 xptr_t tty_xp = chdev->base;84 chdev->cmd = &soclib_mty_cmd; 85 chdev->isr = &soclib_mty_isr; 86 chdev->aux = &soclib_mty_aux; 87 88 // get MTY channel and extended pointer on MTY peripheral base address 89 xptr_t mty_xp = chdev->base; 74 90 uint32_t channel = chdev->channel; 75 91 bool_t is_rx = chdev->is_rx; 76 92 77 // get SOCLIB_ TTY device cluster and local pointer78 cxy_t tty_cxy = GET_CXY( tty_xp );79 uint32_t * tty_ptr = GET_PTR( tty_xp );80 81 // enable interruptions for RX but not for TX82 reg_xp = XPTR( tty_cxy , tty_ptr + MTTY_CONFIG );83 hal_remote_s w( reg_xp , MTTY_CONFIG_RX_ENABLE );93 // get SOCLIB_MTY device cluster and local pointer 94 cxy_t mty_cxy = GET_CXY( mty_xp ); 95 uint32_t * mty_ptr = GET_PTR( mty_xp ); 96 97 // enable interruptions for RX 98 reg_xp = XPTR( mty_cxy , mty_ptr + MTY_CONFIG ); 99 hal_remote_s32( reg_xp , MTY_CONFIG_RX_ENABLE ); 84 100 85 101 // reset relevant FIFO 86 102 if( is_rx ) 87 103 { 88 mt ty_rx_fifo[channel].sts = 0;89 mt ty_rx_fifo[channel].ptr = 0;90 mt ty_rx_fifo[channel].ptw = 0;104 mty_rx_fifo[channel].sts = 0; 105 mty_rx_fifo[channel].ptr = 0; 106 mty_rx_fifo[channel].ptw = 0; 91 107 } 92 108 else 93 109 { 94 mt ty_tx_fifo[channel].sts = 0;95 mt ty_tx_fifo[channel].ptr = 0;96 mt ty_tx_fifo[channel].ptw = 0;110 mty_tx_fifo[channel].sts = 0; 111 mty_tx_fifo[channel].ptr = 0; 112 mty_tx_fifo[channel].ptw = 0; 97 113 } 98 } // end soclib_mt ty_init()114 } // end soclib_mty_init() 99 115 100 116 ////////////////////////////////////////////////////////////// 101 void __attribute__ ((noinline)) soclib_mt ty_cmd( xptr_t th_xp )117 void __attribute__ ((noinline)) soclib_mty_cmd( xptr_t th_xp ) 102 118 { 103 mt ty_fifo_t * fifo; // MTTY_RX or MTTY_TX FIFO119 mty_fifo_t * fifo; // MTY_RX or MTY_TX FIFO 104 120 char byte; // byte value 105 121 uint32_t done; // number of bytes moved … … 110 126 111 127 // get command arguments 112 uint32_t type = hal_remote_l w( XPTR( th_cxy , &th_ptr->txt_cmd.type ) );113 xptr_t buf_xp = hal_remote_l wd( XPTR( th_cxy , &th_ptr->txt_cmd.buf_xp ) );114 uint32_t count = hal_remote_l w( XPTR( th_cxy , &th_ptr->txt_cmd.count ) );128 uint32_t type = hal_remote_l32 ( XPTR( th_cxy , &th_ptr->txt_cmd.type ) ); 129 xptr_t buf_xp = hal_remote_l64( XPTR( th_cxy , &th_ptr->txt_cmd.buf_xp ) ); 130 uint32_t count = hal_remote_l32 ( XPTR( th_cxy , &th_ptr->txt_cmd.count ) ); 115 131 xptr_t error_xp = XPTR( th_cxy , &th_ptr->txt_cmd.error ); 116 132 117 #if (DEBUG_SYS_READ & 1)118 if( type == TXT_READ) enter_tty_cmd_read = (uint32_t)hal_get_cycles();119 #endif120 121 #if (DEBUG_SYS_WRITE & 1)122 if( type == TXT_WRITE) enter_tty_cmd_write = (uint32_t)hal_get_cycles();123 #endif124 125 133 // get TXT device cluster and pointers 126 xptr_t dev_xp = (xptr_t)hal_remote_l wd( XPTR( th_cxy , &th_ptr->txt_cmd.dev_xp ) );134 xptr_t dev_xp = (xptr_t)hal_remote_l64( XPTR( th_cxy , &th_ptr->txt_cmd.dev_xp ) ); 127 135 cxy_t dev_cxy = GET_CXY( dev_xp ); 128 136 chdev_t * dev_ptr = GET_PTR( dev_xp ); 129 137 130 // get cluster and pointers for SOCLIB_TTY peripheral base segment 131 xptr_t tty_xp = (xptr_t)hal_remote_lwd( XPTR( dev_cxy , &dev_ptr->base ) ); 132 cxy_t tty_cxy = GET_CXY( tty_xp ); 133 uint32_t * tty_ptr = GET_PTR( tty_xp ); 134 135 // get TTY channel index and channel base address 136 uint32_t channel = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->channel ) ); 137 uint32_t * base = tty_ptr; 138 // get MTY channel index and channel base address 139 uint32_t channel = hal_remote_l32( XPTR( dev_cxy , &dev_ptr->channel ) ); 138 140 139 141 /////////////////////// 140 if( type == TXT_WRITE ) // write bytes to MT TY_TX FIFO141 { 142 fifo = &mt ty_tx_fifo[channel];142 if( type == TXT_WRITE ) // write bytes to MTY_TX FIFO 143 { 144 fifo = &mty_tx_fifo[channel]; 143 145 144 146 done = 0; … … 146 148 while( done < count ) 147 149 { 148 if( fifo->sts < MT TY_FIFO_DEPTH ) // put one byte to FIFO if TX_FIFO not full150 if( fifo->sts < MTY_FIFO_DEPTH ) // put one byte to FIFO if TX_FIFO not full 149 151 { 150 152 // get one byte from command buffer … … 164 166 165 167 // update FIFO state 166 fifo->ptw = (fifo->ptw + 1) % MT TY_FIFO_DEPTH;168 fifo->ptw = (fifo->ptw + 1) % MTY_FIFO_DEPTH; 167 169 hal_atomic_add( &fifo->sts , 1 ); 168 170 169 171 // udate number of bytes moved 170 172 done++; 171 172 // enable TX_IRQ173 // vci_multi_tty devices never raise TX IRQs174 // so the following instructions are useless175 // and moreover they kernel panic176 // xptr_t config_xp = XPTR( tty_cxy , base + MTTY_CONFIG );177 // uint32_t old = hal_remote_lw( config_xp );178 // uint32_t new = old | MTTY_CONFIG_TX_ENABLE;179 // hal_remote_atomic_cas( config_xp , old , new );180 // hal_remote_sw( XPTR( tty_cxy , base + MTTY_CONFIG ) , MTTY_CONFIG_TX_ENABLE );181 173 } 182 174 else // block & deschedule if TX_FIFO full … … 186 178 187 179 // deschedule 188 sched_yield( "MT TY_TX_FIFO full" );180 sched_yield( "MTY_TX_FIFO full" ); 189 181 } 190 182 } 191 183 192 184 // set error status in command and return 193 hal_remote_s w( error_xp , 0 );185 hal_remote_s32( error_xp , 0 ); 194 186 } 195 187 /////////////////////////// 196 else if( type == TXT_READ ) // read bytes from MT TY_RX FIFO197 { 198 fifo = &mt ty_rx_fifo[channel];188 else if( type == TXT_READ ) // read bytes from MTY_RX FIFO 189 { 190 fifo = &mty_rx_fifo[channel]; 199 191 200 192 done = 0; … … 214 206 #endif 215 207 // update FIFO state 216 fifo->ptr = (fifo->ptr + 1) % MT TY_FIFO_DEPTH;208 fifo->ptr = (fifo->ptr + 1) % MTY_FIFO_DEPTH; 217 209 hal_atomic_add( &fifo->sts , -1 ); 218 210 … … 229 221 230 222 // deschedule 231 sched_yield( "MT TY_RX_FIFO empty" );223 sched_yield( "MTY_RX_FIFO empty" ); 232 224 } 233 225 } // end while 234 226 235 227 // set error status in command 236 hal_remote_s w( error_xp , 0 );228 hal_remote_s32( error_xp , 0 ); 237 229 } 238 230 else … … 241 233 } 242 234 243 #if (DEBUG_SYS_READ & 1) 244 if( type == TXT_READ ) exit_tty_cmd_read = (uint32_t)hal_get_cycles(); 245 #endif 246 247 #if (DEBUG_SYS_WRITE & 1) 248 if( type == TXT_WRITE ) exit_tty_cmd_write = (uint32_t)hal_get_cycles(); 249 #endif 250 251 } // end soclib_mtty_cmd() 235 } // end soclib_mty_cmd() 252 236 253 237 ///////////////////////////////////////////////////////////////// 254 void __attribute__ ((noinline)) soclib_mt ty_isr( chdev_t * chdev )238 void __attribute__ ((noinline)) soclib_mty_isr( chdev_t * chdev ) 255 239 { 256 240 thread_t * server; // pointer on TXT chdev server thread 257 241 lid_t server_lid; // local index of core running the server thread 258 uint32_t channel; // TXT chdev channel 242 uint32_t channel; // TXT chdev channel (virtual channel index) 259 243 bool_t is_rx; // TXT chdev direction 260 244 char byte; // byte value … … 263 247 process_t * owner_ptr; // local pointer on TXT owner process 264 248 pid_t owner_pid; // TXT owner process identifier 265 mtty_fifo_t * fifo; // pointer on MTTY_TX or MTTY_RX FIFO 266 cxy_t tty_cxy; // soclib_mtty cluster 267 uint32_t * tty_ptr; // soclib_mtty segment base address 268 uint32_t * base; // soclib_mtty channel base address 269 xptr_t status_xp; // extended pointer on MTTY_STATUS register 270 xptr_t write_xp; // extended pointer on MTTY_WRITE register 271 xptr_t read_xp; // extended pointer on MTTY_READ register 249 mty_fifo_t * fifo; // pointer on MTY_TX or MTY_RX FIFO 250 cxy_t mty_cxy; // soclib_mty cluster 251 uint32_t * mty_ptr; // soclib_mty segment base address 252 xptr_t status_xp; // extended pointer on MTY_STATUS register 253 xptr_t write_xp; // extended pointer on MTY_WRITE register 254 xptr_t read_xp; // extended pointer on MTY_READ register 272 255 xptr_t parent_xp; // extended pointer on parent process 273 256 cxy_t parent_cxy; // parent process cluster 274 257 process_t * parent_ptr; // local pointer on parent process 275 xptr_t children_lock_xp; // extended pointer on children processes lock276 258 thread_t * parent_main_ptr; // extended pointer on parent process main thread 277 259 xptr_t parent_main_xp; // local pointer on parent process main thread 260 uint32_t n; // index in loop 261 bool_t found; 262 263 #if DEBUG_HAL_TXT_RX 264 uint32_t rx_cycle = (uint32_t)hal_get_cycles(); 265 #endif 266 267 #if DEBUG_HAL_TXT_TX 268 uint32_t tx_cycle = (uint32_t)hal_get_cycles(); 269 #endif 278 270 279 271 // get TXT chdev channel, direction and server thread 280 channel = chdev->channel;281 272 is_rx = chdev->is_rx; 282 273 server = chdev->server; 283 274 server_lid = server->core->lid; 284 275 285 #if (DEBUG_SYS_READ & 1) 286 if( is_rx ) enter_tty_isr_read = (uint32_t)hal_get_cycles(); 287 #endif 288 289 #if (DEBUG_SYS_WRITE & 1) 290 if( is_rx == 0 ) enter_tty_isr_write = (uint32_t)hal_get_cycles(); 291 #endif 292 293 #if DEBUG_HAL_TXT_RX 294 uint32_t rx_cycle = (uint32_t)hal_get_cycles(); 295 #endif 296 297 #if DEBUG_HAL_TXT_TX 298 uint32_t tx_cycle = (uint32_t)hal_get_cycles(); 299 #endif 300 301 // get SOCLIB_TTY peripheral cluster and local pointer 302 tty_cxy = GET_CXY( chdev->base ); 303 tty_ptr = GET_PTR( chdev->base ); 304 305 // get channel base address 306 base = tty_ptr; 307 308 // get extended pointer on TTY registers 309 status_xp = XPTR( tty_cxy , base + MTTY_STATUS ); 310 write_xp = XPTR( tty_cxy , base + MTTY_WRITE ); 311 read_xp = XPTR( tty_cxy , base + MTTY_READ ); 276 // get SOCLIB_MTY peripheral cluster and local pointer 277 mty_cxy = GET_CXY( chdev->base ); 278 mty_ptr = GET_PTR( chdev->base ); 279 280 // get extended pointer on MTY registers 281 status_xp = XPTR( mty_cxy , mty_ptr + MTY_STATUS ); 282 write_xp = XPTR( mty_cxy , mty_ptr + MTY_WRITE ); 283 read_xp = XPTR( mty_cxy , mty_ptr + MTY_READ ); 312 284 313 285 /////////////////////////// handle RX ////////////////////// 314 286 if( is_rx ) 315 287 { 316 fifo = &mtty_rx_fifo[channel]; 317 318 // try to move bytes until MTTY_READ register empty 319 while( hal_remote_lw( status_xp ) & MTTY_STATUS_RX_FULL ) 288 // check one byte available in MTY_READ register 289 if( hal_remote_l32( status_xp ) & MTY_STATUS_RX_FULL ) 320 290 { 321 // get one byte from MT TY_READ register & acknowledge RX_IRQ291 // get one byte from MTY_READ register & acknowledge RX_IRQ 322 292 byte = (char)hal_remote_lb( read_xp ); 323 293 324 // Ignore Carriage Returns 325 if( byte == 0xD ) 326 { 327 continue; 328 } 329 330 // This is the MTTY multiplexing 331 // When a extended ASCII char are received (typing Ctrl-Shift-U then 100+n for example on the terminal) 332 // Two characters are received : 0xFFFFFFc4 then 0xFFFFFF80 + n 333 // When this second char is received, it is considered a metachar that determines the tty dest number 334 // Thus, if you want to make tty 5 the new target, type Ctrl+Shift+U then 105 335 // Now all keystrokes IRQs will be handled by the server DEV thread 336 // associated to RX channel number 5 337 if( (byte & 0xFF) > 0x80 && (byte & 0xFF) <= 0x89 ) 338 { 339 // Disable MTTY IRQ for the core owning 340 // the current channel's server DEV thread 341 dev_pic_disable_irq( server_lid, XPTR( local_cxy , chdev ) ); 342 343 int tty_destnb = (int)(byte & 0xFF) - 0x80; 344 chdev_t * new_chdev = chdev_dir.txt_rx[tty_destnb]; 345 lid_t new_lid = new_chdev->server->core->lid; 346 347 // Bind MTTY IRQ to the core owning the new channel's server DEV thread 348 dev_pic_bind_irq( new_lid , new_chdev ); 349 350 // Enable MTTY IRQ for the core owning 351 // the new channel's server DEV thread 352 dev_pic_enable_irq( new_lid , XPTR( local_cxy , new_chdev ) ); 353 354 channel = new_chdev->channel; 355 is_rx = new_chdev->is_rx; 356 server = new_chdev->server; 357 server_lid = new_lid; 358 fifo = &mtty_rx_fifo[channel]; 359 continue; 360 } 361 362 // filter special character ^Z => block TXT owner process 363 if( byte == 0x1A ) 364 { 294 // test physical RX channel state 295 if( mty_rx_not_new == false ) // get first byte (virtual channel index) 296 { 297 // register virtual channel index 298 mty_rx_channel = (uint32_t)byte; 299 300 // update physical RX channel state 301 mty_rx_not_new = true; 302 } 303 else // get second byte (character value) 304 { 305 // get virtual channel index registered 306 channel = mty_rx_channel; 307 308 // get destination TX_FIFO 309 fifo = &mty_rx_fifo[channel]; 310 311 // filter special character ^Z => block TXT owner process 312 if( byte == 0x1A ) 313 { 365 314 366 315 #if DEBUG_HAL_TXT_RX … … 368 317 printk("\n[DBG] %s : read ^Z character from TXT%d\n", __FUNCTION__, channel ); 369 318 #endif 370 // get pointers on TXT owner process in owner cluster371 owner_xp = process_txt_get_owner( channel );319 // get pointers on TXT owner process in owner cluster 320 owner_xp = process_txt_get_owner( channel ); 372 321 373 // check process exist 374 assert( (owner_xp != XPTR_NULL) , __FUNCTION__, 375 "TXT owner process not found\n" ); 376 377 // get relevant infos on TXT owner process 378 owner_cxy = GET_CXY( owner_xp ); 379 owner_ptr = GET_PTR( owner_xp ); 380 owner_pid = hal_remote_lw( XPTR( owner_cxy , &owner_ptr->pid ) ); 381 382 // block TXT owner process only if it is not the INIT process 383 if( owner_pid != 1 ) 322 // check process exist 323 assert( (owner_xp != XPTR_NULL) , __FUNCTION__, 324 "TXT owner process not found\n" ); 325 326 // get relevant infos on TXT owner process 327 owner_cxy = GET_CXY( owner_xp ); 328 owner_ptr = GET_PTR( owner_xp ); 329 owner_pid = hal_remote_l32( XPTR( owner_cxy , &owner_ptr->pid ) ); 330 331 // block TXT owner process only if it is not the INIT process 332 if( owner_pid != 1 ) 333 { 334 // get parent process descriptor pointers 335 parent_xp = hal_remote_l64( XPTR( owner_cxy , 336 &owner_ptr->parent_xp ) ); 337 parent_cxy = GET_CXY( parent_xp ); 338 parent_ptr = GET_PTR( parent_xp ); 339 340 // get pointers on the parent process main thread 341 parent_main_ptr = hal_remote_lpt( XPTR(parent_cxy, 342 &parent_ptr->th_tbl[0])); 343 parent_main_xp = XPTR( parent_cxy , parent_main_ptr ); 344 345 // transfer TXT ownership 346 process_txt_transfer_ownership( owner_xp ); 347 348 // block all threads in all clusters, but the main thread 349 process_sigaction( owner_pid , BLOCK_ALL_THREADS ); 350 351 // block the main thread 352 xptr_t main_xp = XPTR( owner_cxy , &owner_ptr->th_tbl[0] ); 353 thread_block( main_xp , THREAD_BLOCKED_GLOBAL ); 354 355 // atomically update owner process termination state 356 hal_remote_atomic_or( XPTR( owner_cxy , &owner_ptr->term_state ) , 357 PROCESS_TERM_STOP ); 358 359 // take the children lock and unblock the parent process main thread 360 thread_unblock( parent_main_xp , THREAD_BLOCKED_WAIT ); 361 362 return; 363 } 364 } 365 366 // filter special character ^C => kill TXT owner process 367 if( byte == 0x03 ) 384 368 { 385 // get parent process descriptor pointers386 parent_xp = hal_remote_lwd( XPTR( owner_cxy , &owner_ptr->parent_xp ) );387 parent_cxy = GET_CXY( parent_xp );388 parent_ptr = GET_PTR( parent_xp );389 390 // get extended pointer on lock protecting children list in parent process391 children_lock_xp = XPTR( parent_cxy , &parent_ptr->children_lock );392 393 // get pointers on the parent process main thread394 parent_main_ptr = hal_remote_lpt(XPTR(parent_cxy,&parent_ptr->th_tbl[0]));395 parent_main_xp = XPTR( parent_cxy , parent_main_ptr );396 397 // transfer TXT ownership398 process_txt_transfer_ownership( owner_xp );399 400 // block all threads in all clusters, but the main thread401 process_sigaction( owner_pid , BLOCK_ALL_THREADS );402 403 // block the main thread404 xptr_t main_xp = XPTR( owner_cxy , &owner_ptr->th_tbl[0] );405 thread_block( main_xp , THREAD_BLOCKED_GLOBAL );406 407 // atomically update owner process termination state408 hal_remote_atomic_or( XPTR( owner_cxy , &owner_ptr->term_state ) ,409 PROCESS_TERM_STOP );410 411 // take the children lock and unblock the parent process main thread412 remote_spinlock_lock( children_lock_xp );413 thread_unblock( parent_main_xp , THREAD_BLOCKED_WAIT );414 remote_spinlock_unlock( children_lock_xp );415 416 return;417 }418 }419 420 // filter special character ^C => kill TXT owner process421 if( byte == 0x03 )422 {423 369 424 370 #if DEBUG_HAL_TXT_RX … … 426 372 printk("\n[DBG] %s : read ^C character from TXT%d\n", __FUNCTION__, channel ); 427 373 #endif 428 // get pointer on TXT owner process in owner cluster 429 owner_xp = process_txt_get_owner( channel ); 430 431 // check process exist 432 assert( (owner_xp != XPTR_NULL) , __FUNCTION__, 433 "TXT owner process not found\n" ); 434 435 // get relevant infos on TXT owner process 436 owner_cxy = GET_CXY( owner_xp ); 437 owner_ptr = GET_PTR( owner_xp ); 438 owner_pid = hal_remote_lw( XPTR( owner_cxy , &owner_ptr->pid ) ); 439 440 // kill TXT owner process only if it is not the INIT process 441 if( owner_pid != 1 ) 374 // get pointer on TXT owner process in owner cluster 375 owner_xp = process_txt_get_owner( channel ); 376 377 // check process exist 378 assert( (owner_xp != XPTR_NULL) , __FUNCTION__, 379 "TXT owner process not found\n" ); 380 381 // get relevant infos on TXT owner process 382 owner_cxy = GET_CXY( owner_xp ); 383 owner_ptr = GET_PTR( owner_xp ); 384 owner_pid = hal_remote_l32( XPTR( owner_cxy , &owner_ptr->pid ) ); 385 386 // kill TXT owner process only if it is not the INIT process 387 if( owner_pid != 1 ) 388 { 389 // get parent process descriptor pointers 390 parent_xp = hal_remote_l64( XPTR( owner_cxy, 391 &owner_ptr->parent_xp ) ); 392 parent_cxy = GET_CXY( parent_xp ); 393 parent_ptr = GET_PTR( parent_xp ); 394 395 // get pointers on the parent process main thread 396 parent_main_ptr = hal_remote_lpt( XPTR( parent_cxy, 397 &parent_ptr->th_tbl[0])); 398 parent_main_xp = XPTR( parent_cxy , parent_main_ptr ); 399 400 // remove process from TXT list 401 process_txt_detach( owner_xp ); 402 403 // mark for delete all thread in all clusters, but the main 404 process_sigaction( owner_pid , DELETE_ALL_THREADS ); 405 406 // block main thread 407 xptr_t main_xp = XPTR( owner_cxy , &owner_ptr->th_tbl[0] ); 408 thread_block( main_xp , THREAD_BLOCKED_GLOBAL ); 409 410 // atomically update owner process termination state 411 hal_remote_atomic_or( XPTR( owner_cxy , &owner_ptr->term_state ) , 412 PROCESS_TERM_KILL ); 413 414 // take the children lock and unblock the parent process main thread 415 thread_unblock( parent_main_xp , THREAD_BLOCKED_WAIT ); 416 417 return; 418 } 419 } 420 421 // write byte in RX FIFO if not full / discard byte if full 422 if ( fifo->sts < MTY_FIFO_DEPTH ) 442 423 { 443 // get parent process descriptor pointers444 parent_xp = hal_remote_lwd( XPTR( owner_cxy , &owner_ptr->parent_xp ) );445 parent_cxy = GET_CXY( parent_xp );446 parent_ptr = GET_PTR( parent_xp );447 448 // get extended pointer on lock protecting children list in parent process449 children_lock_xp = XPTR( parent_cxy , &parent_ptr->children_lock );450 451 // get pointers on the parent process main thread452 parent_main_ptr = hal_remote_lpt(XPTR(parent_cxy,&parent_ptr->th_tbl[0]));453 parent_main_xp = XPTR( parent_cxy , parent_main_ptr );454 455 // remove process from TXT list456 process_txt_detach( owner_xp );457 458 // mark for delete all thread in all clusters, but the main459 process_sigaction( owner_pid , DELETE_ALL_THREADS );460 461 // block main thread462 xptr_t main_xp = XPTR( owner_cxy , &owner_ptr->th_tbl[0] );463 thread_block( main_xp , THREAD_BLOCKED_GLOBAL );464 465 // atomically update owner process termination state466 hal_remote_atomic_or( XPTR( owner_cxy , &owner_ptr->term_state ) ,467 PROCESS_TERM_KILL );468 469 // take the children lock and unblock the parent process main thread470 remote_spinlock_lock( children_lock_xp );471 thread_unblock( parent_main_xp , THREAD_BLOCKED_WAIT );472 remote_spinlock_unlock( children_lock_xp );473 474 return;475 }476 }477 478 // write byte in MTTY_RX FIFO if not full / discard byte if full479 if ( fifo->sts < MTTY_FIFO_DEPTH )480 {481 424 482 425 #if DEBUG_HAL_TXT_RX … … 485 428 __FUNCTION__, byte, channel ); 486 429 #endif 487 // store byte into FIFO 488 fifo->data[fifo->ptw] = (char)byte; 489 490 // avoid race 491 hal_fence(); 492 493 // update RX_FIFO state 494 fifo->ptw = (fifo->ptw + 1) % MTTY_FIFO_DEPTH; 495 hal_atomic_add( &fifo->sts , 1 ); 496 497 // unblock TXT_RX server thread 498 thread_unblock( XPTR( local_cxy , server ) , THREAD_BLOCKED_ISR ); 499 500 // send IPI to core running server thread 501 dev_pic_send_ipi( local_cxy , server_lid ); 502 } 503 else 504 { 505 printk("\n[WARNING] %s : MTTY_RX_FIFO[%d] full => discard character <%x>\n", 506 __FUNCTION__, channel, (uint32_t)byte ); 507 } 508 } // end while MTTY_READ register full 509 430 // store byte into FIFO 431 fifo->data[fifo->ptw] = (char)byte; 432 433 // avoid race 434 hal_fence(); 435 436 // update RX_FIFO state 437 fifo->ptw = (fifo->ptw + 1) % MTY_FIFO_DEPTH; 438 hal_atomic_add( &fifo->sts , 1 ); 439 440 // unblock TXT_RX server thread 441 thread_unblock( XPTR( local_cxy , server ) , THREAD_BLOCKED_ISR ); 442 443 // send IPI to core running server thread 444 dev_pic_send_ipi( local_cxy , server_lid ); 445 } 446 else 447 { 448 printk("\n[WARNING] %s : MTY_RX_FIFO[%d] full => discard char <%x>\n", 449 __FUNCTION__, channel, (uint32_t)byte ); 450 } 451 452 // update physical RX channel state 453 mty_rx_not_new = true; 454 455 } // end get character value 456 } // end if byte available in MTY_READ register 510 457 } // end RX 511 458 … … 513 460 else 514 461 { 515 fifo = &mtty_tx_fifo[channel]; 516 517 // try to move bytes until TX_FIFO empty 518 while( fifo->sts > 0 ) 462 // test physical TX channel state 463 if( mty_tx_not_new == false ) // send first byte (virtual channel index) 519 464 { 520 // write one byte to MTTY_WRITE register if empty / exit loop if full 521 if( (hal_remote_lw( status_xp ) & MTTY_STATUS_TX_FULL) == 0 ) 522 { 523 // get one byte from TX_FIFO 465 // scan the set of the TX_FIFO 466 for( n = 0 , found = false ; n < CONFIG_MAX_TXT_CHANNELS ; n++ ) 467 { 468 // implement round-robin policy 469 channel = (n + mty_tx_last + 1) % CONFIG_MAX_TXT_CHANNELS; 470 471 // get pointer on TX_FIFO[channel] 472 fifo = &mty_tx_fifo[channel]; 473 474 if( fifo->sts > 0 ) 475 { 476 found = true; 477 break; 478 } 479 } 480 481 // get one byte from TX_FIFO if found and send channel index 482 if( found ) 483 { 484 // get one byte from selected TX_FIFO 524 485 byte = fifo->data[fifo->ptr]; 525 486 … … 530 491 #endif 531 492 // update TX_FIFO state 532 fifo->ptr = (fifo->ptr + 1) % MT TY_FIFO_DEPTH;493 fifo->ptr = (fifo->ptr + 1) % MTY_FIFO_DEPTH; 533 494 hal_atomic_add( &fifo->sts , -1 ); 534 495 535 // write byte to MTTY_WRITE register & acknowledge TX_IRQ 536 hal_remote_sb( write_xp , byte ); 496 // update TX physical channel state 497 mty_tx_value = (uint32_t)byte; 498 mty_tx_not_new = true; 499 mty_tx_last = channel; 500 501 // write virtual channel index to TX_WRITE register 502 hal_remote_sb( write_xp , (uint8_t)channel ); 503 504 // unblock TXT_TX server thread 505 thread_unblock( XPTR( local_cxy , server ) , THREAD_BLOCKED_ISR ); 506 507 // send IPI to core running server thread 508 dev_pic_send_ipi( local_cxy , server_lid ); 537 509 } 538 510 } 539 540 // disable TX_IRQ 541 // vci_multi_tty devices never raise TX IRQs 542 // so the following instructions are useless 543 // and moreover they kernel panic 544 // xptr_t config_xp = XPTR( tty_cxy , base + MTTY_CONFIG ); 545 // uint32_t old = hal_remote_lw( config_xp ); 546 // uint32_t new = old & ~(MTTY_CONFIG_TX_ENABLE); 547 // hal_remote_atomic_cas( config_xp , old , new ); 548 // hal_remote_sw( XPTR( tty_cxy , base + MTTY_CONFIG ) , 0 ); 549 550 // unblock TXT_TX server thread 551 thread_unblock( XPTR( local_cxy , server ) , THREAD_BLOCKED_ISR ); 552 553 // send IPI to core running server thread 554 dev_pic_send_ipi( local_cxy , server_lid ); 555 511 else // send second byte (character value) 512 { 513 // write registered character value to TX_WRITE register 514 hal_remote_sb( write_xp , (uint8_t)mty_tx_value ); 515 516 // update TX physical channel state 517 mty_tx_not_new = false; 518 } // end if MTY_WRITE register empty 556 519 } // end TX 557 520 558 521 hal_fence(); 559 522 560 #if (DEBUG_SYS_READ & 1) 561 if( is_rx ) exit_tty_isr_read = (uint32_t)hal_get_cycles(); 562 #endif 563 564 #if (DEBUG_SYS_WRITE & 1) 565 if( is_rx == 0 ) exit_tty_isr_write = (uint32_t)hal_get_cycles(); 566 #endif 567 568 } // end soclib_mtty_isr() 523 } // end soclib_mty_isr() 569 524 570 525 ///////////////////////////////////////////////////////////// 571 void __attribute__ ((noinline)) soclib_mt ty_aux( void * args )526 void __attribute__ ((noinline)) soclib_mty_aux( void * args ) 572 527 { 573 xptr_t dev_xp = ((txt_sync_args_t *)args)->dev_xp; 574 char * buffer = ((txt_sync_args_t *)args)->buffer; 575 uint32_t count = ((txt_sync_args_t *)args)->count; 576 uint32_t channel = ((txt_sync_args_t *)args)->channel; 528 uint32_t i; 529 530 xptr_t dev_xp = ((txt_sync_args_t *)args)->dev_xp; 531 const char * buffer = ((txt_sync_args_t *)args)->buffer; 532 uint32_t count = ((txt_sync_args_t *)args)->count; 533 uint32_t channel = ((txt_sync_args_t *)args)->channel; 577 534 578 // get TXT0chdev cluster and local pointer535 // get chdev cluster and local pointer 579 536 cxy_t dev_cxy = GET_CXY( dev_xp ); 580 chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp ); 581 582 // get extended pointer on TTY channel base address 583 xptr_t tty_xp = (xptr_t)hal_remote_lwd( XPTR( dev_cxy , &dev_ptr->base ) ); 584 585 // get TTY channel segment cluster and local pointer 586 cxy_t tty_cxy = GET_CXY( tty_xp ); 587 uint32_t * tty_ptr = (uint32_t *)GET_PTR( tty_xp ); 588 589 // get extended pointers on MTTY_WRITE & MTTY_STATUS registers 590 xptr_t write_xp = XPTR( tty_cxy , tty_ptr + MTTY_WRITE ); 591 xptr_t status_xp = XPTR( tty_cxy , tty_ptr + MTTY_STATUS ); 592 593 // loop on characters (busy waiting policy) 594 uint32_t i; 537 chdev_t * dev_ptr = GET_PTR( dev_xp ); 538 539 // get extended pointer on MTY channel base address 540 xptr_t mty_xp = (xptr_t)hal_remote_l64( XPTR( dev_cxy , &dev_ptr->base ) ); 541 542 // get MTY channel segment cluster and local pointer 543 cxy_t mty_cxy = GET_CXY( mty_xp ); 544 uint32_t * mty_ptr = GET_PTR( mty_xp ); 545 546 // get extended pointers on MTY_WRITE & MTY_STATUS registers 547 xptr_t write_xp = XPTR( mty_cxy , mty_ptr + MTY_WRITE ); 548 xptr_t status_xp = XPTR( mty_cxy , mty_ptr + MTY_STATUS ); 549 550 // loop on characters (two bytes per character) 595 551 for( i = 0 ; i < count ; i++ ) 596 552 { 597 // This is the MTTY multiplexing 598 // Before each character, we send the destination (RX) TTY number for this char. 599 // The two bytes (dest number + char) must be sent consecutively, 600 // so to guarantee this atomicity, we use a lock to prevent other 601 // concurrent server DEV threads to write a byte in between our two bytes 602 603 // Send the destination TTY number 604 // HACK: Remove this on the Lety physical prototype. 605 // This 'if' is here so that the kernel messages in simulation are readable 606 bool_t empty = false; 607 if (channel > 0) { 608 // For examples, "Hello" would appear "0H0e0l0l0o" on the simulation terminal 609 do { 610 // get MTTY_STATUS 611 uint32_t status = hal_remote_lw( status_xp ); 612 empty = ( (status & MTTY_STATUS_TX_FULL) == 0 ); 613 614 // transfer one byte if TX buffer empty 615 if ( empty ) { 616 hal_remote_sb( write_xp , channel + '0' ); 617 } 618 } while ( empty == false ); 619 } 620 621 // Send the character 622 do { 623 // get MTTY_STATUS 624 uint32_t status = hal_remote_lw( status_xp ); 625 empty = ( (status & MTTY_STATUS_TX_FULL) == 0 ); 626 627 // transfer one byte if TX buffer empty 628 if ( empty ) { 629 hal_remote_sb( write_xp , buffer[i] ); 630 } 631 } while ( empty == false ); 553 // write virtual channel index to MTY_WRITE register 554 hal_remote_sb( write_xp , (uint8_t)channel ); 555 556 // write character value to MTY_WRITE register 557 hal_remote_sb( write_xp , buffer[i] ); 632 558 } 633 } // end soclib_mt ty_aux()634 635 636 559 } // end soclib_mty_aux() 560 561 562
Note: See TracChangeset
for help on using the changeset viewer.