- Location:
- /trunk/kernel/devices
- Files:
-
- 4 added
- 6 deleted
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
/trunk/kernel/devices/dev_icu.c
r3 r1 24 24 #include <hal_types.h> 25 25 #include <hal_special.h> 26 #include < chdev.h>26 #include <device.h> 27 27 #include <thread.h> 28 28 #include <cluster.h> … … 37 37 ///////////////////////////////////////////////////////////////////////////////////////// 38 38 39 extern chdev_directory_t chdev_dir; // allocated in kernel_init.c 40 41 extern chdev_pic_input_t chdev_pic_input; // allocated in kernel_init.c 42 43 ///////////////////////////////// 44 void dev_icu_init( chdev_t * icu, 45 uint32_t hwi_nr, 46 uint32_t wti_nr, 47 uint32_t pti_nr ) 48 { 49 // set ICU chdev extension fields 50 icu->ext.icu.hwi_nr = hwi_nr; 51 icu->ext.icu.wti_nr = wti_nr; 52 icu->ext.icu.pti_nr = pti_nr; 53 icu->ext.icu.wti_bitmap = 0; 54 spinlock_init( &icu->ext.icu.wti_lock ); 39 extern devices_directory_t devices_dir; // allocated in kernel_init.c 40 41 extern devices_input_irq_t devices_input_irq; // allocated in kernel_init.c 42 43 44 /////////////////////////////////// 45 void dev_icu_init( xptr_t dev_xp, 46 uint32_t hwi_nr, 47 uint32_t wti_nr, 48 uint32_t pti_nr ) 49 { 50 // get ICU device cluster and local pointer 51 cxy_t dev_cxy = GET_CXY( dev_xp ); 52 device_t * dev_ptr = (device_t *)GET_PTR( dev_xp ); 53 54 if( dev_cxy != local_cxy ) 55 { 56 printk("\n[PANIC] %s for cluster %x must be local\n", 57 __FUNCTION__ , local_cxy ); 58 hal_core_sleep(); 59 } 60 61 // set ICU device extension fields 62 dev_ptr->ext.icu.hwi_nr = hwi_nr; 63 dev_ptr->ext.icu.wti_nr = wti_nr; 64 dev_ptr->ext.icu.pti_nr = pti_nr; 65 dev_ptr->ext.icu.wti_bitmap = 0; 66 spinlock_init( &dev_ptr->ext.icu.wti_lock ); 55 67 56 // get implementation 57 uint32_t impl = icu->impl; 58 59 // call the relevant driver init function 68 // get implementation index from ICU device descriptor 69 uint32_t impl = dev_ptr->impl; 70 71 // set field "name" in device descriptor 72 // and call the relevant driver init function 60 73 if( impl == IMPL_ICU_XCU ) 61 74 { 62 uint32_t lid; 63 for( lid = 0 ; lid < LOCAL_CLUSTER->cores_nr ; lid++ ) 64 { 65 soclib_xcu_init( icu , lid ); 66 } 67 } 68 else 69 { 70 assert( false , __FUNCTION__ , "undefined ICU implementation" ); 75 memcpy( dev_ptr->name , "ICU_XCU" , 16 ); 76 77 uint32_t lid; 78 cluster_t * cluster = LOCAL_CLUSTER; 79 for( lid = 0 ; lid < cluster->cores_nr ; lid++ ) 80 { 81 soclib_xcu_init( dev_ptr , lid ); 82 } 83 } 84 else 85 { 86 printk("\n[PANIC] %s : undefined ICU implementation for cluste %x\n", 87 __FUNCTION__ , local_cxy ); 88 hal_core_sleep(); 71 89 } 72 90 } // end dev_icu_init() 73 91 74 92 ///////////////////////////////////////////////////////////////////////////////////// 75 // This static function check the irq_type / irq_index arguments .93 // This static function check the irq_type / irq_index arguments for a remote ICU. 76 94 // It is called by the dev_icu_enable_irq() & dev_icu_disable_irq() functions. 95 // returns 0 if OK / returns non zero if invalid arguments 77 96 ///////////////////////////////////////////////////////////////////////////////////// 78 static inline void dev_icu_check_irq( chdev_t * icu,97 static inline void dev_icu_check_irq( xptr_t icu_xp, 79 98 uint32_t irq_type, 80 99 uint32_t irq_index ) 81 100 { 101 // get cluster and local pointer on remote ICU 102 cxy_t icu_cxy = GET_CXY( icu_xp ); 103 device_t * icu_ptr = (device_t *)GET_PTR( icu_xp ); 104 82 105 if( irq_type == HWI_TYPE ) 83 106 { 84 assert( (irq_index < icu->ext.icu.hwi_nr) , __FUNCTION__ , "illegal HWI" ); 107 if( irq_index >= hal_remote_lw( XPTR( icu_cxy , &icu_ptr->ext.icu.hwi_nr ) ) ) 108 { 109 printk("\n[PANIC] in %s : illegal HWI index = %d for ICU in cluster %x\n", 110 __FUNCTION__ , irq_index , icu_cxy ); 111 hal_core_sleep(); 112 } 85 113 } 86 114 if( irq_type == WTI_TYPE ) 87 115 { 88 assert( (irq_index < icu->ext.icu.wti_nr) , __FUNCTION__ , "illegal WTI" ); 116 if( irq_index >= hal_remote_lw( XPTR( icu_cxy , &icu_ptr->ext.icu.wti_nr ) ) ) 117 { 118 printk("\n[PANIC] in %s : illegal WTI index = %d for ICU in cluster %x\n", 119 __FUNCTION__ , irq_index , icu_cxy ); 120 hal_core_sleep(); 121 } 89 122 } 90 123 if( irq_type == PTI_TYPE ) 91 124 { 92 assert( (irq_index < icu->ext.icu.pti_nr) , __FUNCTION__ , "illegal PTI" ); 93 } 94 } // end dev_icu_check_irq() 95 96 //////////////////////////////////////// 97 void dev_icu_enable_irq( lid_t lid, 125 if( irq_index >= hal_remote_lw( XPTR( icu_cxy , &icu_ptr->ext.icu.pti_nr ) ) ) 126 { 127 printk("\n[PANIC] in %s : illegal PTI index = %d for ICU in cluster %x\n", 128 __FUNCTION__ , irq_index , icu_cxy ); 129 hal_core_sleep(); 130 } 131 } 132 } // end dev_icu check irq() 133 134 //////////////////////////////////////////// 135 void dev_icu_enable_irq( cxy_t icu_cxy, 136 lid_t lid, 98 137 uint32_t irq_type, 99 138 uint32_t irq_index, 100 chdev_t * src_chdev)101 { 102 // get local pointer on local ICU chdev103 xptr_t icu_xp = chdev_dir.icu[local_cxy];104 chdev_t * icu = (chdev_t *)GET_PTR( icu_xp );139 xptr_t src_dev_xp ) 140 { 141 // get extended pointer & local pointer on remote ICU device 142 xptr_t icu_xp = devices_dir.icu[icu_cxy]; 143 device_t * icu_ptr = (device_t *)GET_PTR( icu_xp ); 105 144 106 145 // check IRQ type and index 107 dev_icu_check_irq( icu , irq_type , irq_index );146 dev_icu_check_irq( icu_xp , irq_type , irq_index ); 108 147 109 148 // (1) call implementation specific ICU driver to enable IRQ 110 if( icu->impl == IMPL_ICU_XCU ) 111 { 112 soclib_xcu_enable_irq( icu , 1<<irq_index , irq_type , lid ); 113 } 114 115 // (2) get selected core local pointer, and register 116 // source chdev pointer in relevant interrupt vector 117 core_t * core = &LOCAL_CLUSTER->core_tbl[lid]; 118 core_set_irq_vector_entry( core , irq_type , irq_index , src_chdev ); 119 120 // (3) register IRQ type and index in source chdev descriptor 121 src_chdev->irq_type = irq_type; 122 src_chdev->irq_id = irq_index; 149 if( icu_ptr->impl == IMPL_ICU_XCU ) 150 { 151 soclib_xcu_enable_irq( icu_xp , 1<<irq_index , irq_type , lid ); 152 } 153 else 154 { 155 printk("\n[PANIC] in %s : undefined ICU implementation" , __FUNCTION__ ); 156 hal_core_sleep(); 157 } 158 159 // (2) get selected remote core local pointer, and register 160 // source device xptr in relevant interrupt vector 161 162 core_t * core_ptr = hal_remote_lpt( XPTR( icu_cxy , &LOCAL_CLUSTER->core_tbl[lid] ) ); 163 xptr_t core_xp = XPTR( icu_cxy , core_ptr ); 164 core_set_irq_vector_entry( core_xp , irq_type , irq_index , src_dev_xp ); 165 166 // (3) get extended pointer on source device, and 167 // register IRQ type and index in source device descriptor 168 169 cxy_t src_dev_cxy = GET_CXY( src_dev_xp ); 170 device_t * src_dev_ptr = (device_t *)GET_PTR( src_dev_xp ); 171 172 hal_remote_sw( XPTR( src_dev_cxy , &src_dev_ptr->irq_type ) , irq_type ); 173 hal_remote_sw( XPTR( src_dev_cxy , &src_dev_ptr->irq_id ) , irq_index ); 123 174 124 175 } // end dev_icu_enable_irq() 125 176 126 ///////////////////////////////////////// 127 void dev_icu_disable_irq( lid_t lid, 177 ///////////////////////////////////////////// 178 void dev_icu_disable_irq( cxy_t icu_cxy, 179 lid_t lid, 128 180 uint32_t irq_type, 129 181 uint32_t irq_index ) 130 182 { 131 // get local pointer on local ICU chdev132 xptr_t icu_xp = chdev_dir.icu[local_cxy];133 chdev_t * icu = (chdev_t *)GET_PTR( icu_xp );183 // get extended pointer & local pointer on remote ICU device 184 xptr_t icu_xp = devices_dir.icu[icu_cxy]; 185 device_t * icu_ptr = (device_t *)GET_PTR( icu_xp ); 134 186 135 187 // check IRQ type and index 136 dev_icu_check_irq( icu , irq_type , irq_index );188 dev_icu_check_irq( icu_xp , irq_type , irq_index ); 137 189 138 190 // (1) call the implementation specific ICU driver to disable IRQ 139 if( icu->impl == IMPL_ICU_XCU ) 140 { 141 soclib_xcu_disable_irq( icu , 1<<irq_index , irq_type , lid ); 191 if( icu_ptr->impl == IMPL_ICU_XCU ) 192 { 193 soclib_xcu_disable_irq( icu_xp , 1<<irq_index , irq_type , lid ); 194 } 195 else 196 { 197 printk("\n[PANIC] in %s : undefined ICU implementation" , __FUNCTION__ ); 198 hal_core_sleep(); 142 199 } 143 200 144 201 // (2) get selected remote core local pointer, and remove 145 // the source chdev xptr from relevant interrupt vector 146 147 core_t * core = &LOCAL_CLUSTER->core_tbl[lid]; 148 core_set_irq_vector_entry( core , irq_type , irq_index , NULL ); 202 // the source device xptr from relevant interrupt vector 203 204 core_t * core_ptr = hal_remote_lpt( XPTR( icu_cxy , &LOCAL_CLUSTER->core_tbl[lid] ) ); 205 xptr_t core_xp = XPTR( icu_cxy , core_ptr ); 206 core_set_irq_vector_entry( core_xp , irq_type , irq_index , XPTR_NULL ); 149 207 150 208 } // end dev_icu_disable_irq() … … 154 212 uint32_t period ) 155 213 { 156 // get local pointer on local ICU chdev157 xptr_t icu_xp = chdev_dir.icu[local_cxy];158 chdev_t * icu = (chdev_t *)GET_PTR( icu_xp );214 // get pointer on local ICU device descriptor 215 core_t * core = CURRENT_CORE; 216 device_t * icu = core->icu; 159 217 160 218 // check PTI index 161 assert( (pti_index < icu->ext.icu.pti_nr) , __FUNCTION__ , "illegal PTI index" ); 219 if( pti_index >= icu->ext.icu.pti_nr ) 220 { 221 printk("\n[PANIC] in %s : illegal PTI index = %d\n", __FUNCTION__ , pti_index ); 222 hal_core_sleep(); 223 } 162 224 163 225 // call the implementation specific driver ICU to set period … … 171 233 void dev_icu_ack_timer( uint32_t pti_index ) 172 234 { 173 // get local pointer on local ICU chdev174 xptr_t icu_xp = chdev_dir.icu[local_cxy];175 chdev_t * icu = (chdev_t *)GET_PTR( icu_xp );235 // get pointer on local ICU device descriptor 236 core_t * core = CURRENT_CORE; 237 device_t * icu = core->icu; 176 238 177 239 // check PTI index 178 assert( (pti_index < icu->ext.icu.pti_nr) , __FUNCTION__ , "illegal PTI index" ); 240 if( pti_index >= icu->ext.icu.pti_nr ) 241 { 242 printk("\n[PANIC] in %s : illegal PTI index = %d\n", __FUNCTION__ , pti_index ); 243 hal_core_sleep(); 244 } 179 245 180 246 // call the implementation specific driver ICU to acknowledge PTI IRQ … … 183 249 soclib_xcu_ack_timer( icu , pti_index ); 184 250 } 251 else 252 { 253 printk("\n[PANIC] in %s : undefined ICU implementation" , __FUNCTION__ ); 254 hal_core_sleep(); 255 } 256 185 257 } // end dev_icu_ack_timer() 186 258 … … 198 270 uint32_t y = cxy & ((1<<y_width)-1); 199 271 200 assert( ((x < x_size) && (y < y_size)) , __FUNCTION__ , "illegal cluster identifier" ); 201 202 assert( (lid < cores_nr) , __FUNCTION__ , "illegal core local index" ); 203 204 // get extended pointer on target ICU chdev 205 xptr_t icu_xp = chdev_dir.icu[cxy]; 272 if( (x >= x_size) || (y >= y_size) ) 273 { 274 hal_core_sleep("%s : illegal cluster identifier = %x\n", __FUNCTION__ , cxy ); 275 } 276 if( lid >= cores_nr ) 277 { 278 hal_core_sleep("%s : illegal core local index = %d\n", __FUNCTION__ , lid ); 279 } 280 281 // get extended pointer on target ICU device 282 xptr_t icu_xp = devices_dir.icu[cxy]; 206 283 207 284 // get target ICU cluster and local pointer 208 cxy_t icu_cxy= GET_CXY( icu_xp );209 chdev_t * icu_ptr = (chdev_t *)GET_PTR( icu_xp );210 211 // get implementation from remote ICU chdev212 uint32_t impl = hal_remote_lw( XPTR( icu_cxy , &icu_ptr->impl ) );285 cxy_t cxy_icu = GET_CXY( icu_xp ); 286 device_t * ptr_icu = (device_t *)GET_PTR( icu_xp ); 287 288 // get driver implementation from target ICU device 289 uint32_t impl = hal_remote_lw( XPTR( cxy_icu , &ptr_icu->impl ) ); 213 290 214 291 // call the implementation specific ICU driver to send IPI … … 216 293 { 217 294 soclib_xcu_send_ipi( icu_xp , lid ); 295 } 296 else 297 { 298 printk("\n[PANIC] in %s : undefined ICU implementation" , __FUNCTION__ ); 299 hal_core_sleep(); 218 300 } 219 301 } // end dev_icu_send_ipi() … … 225 307 uint32_t wti_status; // WTI index + 1 / no pending WTI if 0 226 308 uint32_t pti_status; // PTI index + 1 / no pending PTI if 0 227 chdev_t * src_chdev; // pointer on source chdev descriptor 309 xptr_t src_dev_xp; // extended pointer on source device descriptor 310 cxy_t src_dev_cxy; // source device cluster 311 device_t * src_dev_ptr; // source device local pointer 228 312 uint32_t index; // IRQ index 229 313 230 core_t * core = CURRENT_CORE; 231 232 // get local pointer on local ICU chdev 233 xptr_t icu_xp = chdev_dir.icu[local_cxy]; 234 chdev_t * icu = (chdev_t *)GET_PTR( icu_xp ); 314 // get pointer on local ICU device descriptor 315 core_t * core = CURRENT_CORE; 316 device_t * icu = core->icu; 235 317 236 318 // call the implementation specific ICU driver … … 240 322 soclib_xcu_get_status( icu , core->lid , &hwi_status , &wti_status , &pti_status ); 241 323 } 324 else 325 { 326 printk("\n[PANIC] in %s : undefined ICU implementation" , __FUNCTION__ ); 327 hal_core_sleep(); 328 } 242 329 243 330 // analyse ICU status and handle up to 3 pending IRQ (one WTI, one HWI, one PTI) 244 331 245 if( wti_status ) // pending WTI 332 if( wti_status ) // pending WTI TODO what about IPIs ??? [AG] 246 333 { 247 334 index = wti_status - 1; 248 335 249 if( index < LOCAL_CLUSTER->cores_nr ) // it is an IPI 250 { 251 assert( (index == core->lid) , __FUNCTION__ , "illegal IPI index" ); 252 253 // TODO acknowledge WTI [AG] 254 255 // TODO force scheduling [AG] 256 } 257 else // it is an external device 258 { 259 // get pointer on IRQ source chdev 260 src_chdev = core->wti_vector[index]; 261 262 if( src_chdev == NULL ) // strange, but not fatal => disable IRQ 263 { 264 printk("\n[WARNING] in %s : no handler for WTI %d on core %d in cluster %x\n", 265 __FUNCTION__ , index , core->lid , local_cxy ); 266 core->spurious_irqs ++; 267 dev_icu_disable_irq( core->lid , WTI_TYPE , index ); 268 } 269 else // call relevant ISR 270 { 271 icu_dmsg("\n[INFO] %s received WTI : index = %d for cpu %d in cluster %d\n", 272 __FUNCTION__ , index , core->lid , local_cxy ); 273 274 // call ISR 275 src_chdev->isr( src_chdev ); 276 } 336 // get extended pointer on IRQ source device 337 src_dev_xp = core->wti_vector[index]; 338 src_dev_cxy = GET_CXY( src_dev_xp ); 339 src_dev_ptr = (device_t *)GET_PTR( src_dev_xp ); 340 341 if( src_dev_xp == XPTR_NULL ) // strange, but not fatal => disable IRQ 342 { 343 printk("\n[WARNING] in %s : no handler for WTI %d on core %d in cluster %x\n", 344 __FUNCTION__ , index , core->lid , local_cxy ); 345 core->spurious_irqs ++; 346 dev_icu_disable_irq( local_cxy , core->lid , WTI_TYPE , index ); 347 } 348 else if( src_dev_cxy != local_cxy ) // WTI must be handled in device cluster 349 { 350 printk("\n[PANIC] in %s : non local WTI %d on core %d in cluster %x\n", 351 __FUNCTION__ , index , core->lid , local_cxy ); 352 hal_core_sleep(); 353 } 354 else // call relevant ISR 355 { 356 icu_dmsg("\n[INFO] %s received WTI : index = %d for cpu %d in cluster %d\n", 357 __FUNCTION__ , index , core->lid , local_cxy ); 358 359 src_dev_ptr->isr( src_dev_ptr ); 277 360 } 278 361 } … … 282 365 index = hwi_status - 1; 283 366 284 // get pointer on IRQ source chdev 285 src_chdev = core->hwi_vector[index]; 286 287 if( src_chdev == NULL ) // strange, but not fatal => disable IRQ 367 // get pointer on IRQ source device 368 src_dev_xp = core->wti_vector[index]; 369 src_dev_cxy = GET_CXY( src_dev_xp ); 370 src_dev_ptr = (device_t *)GET_PTR( src_dev_xp ); 371 372 if( src_dev_xp == XPTR_NULL ) // strange, but not fatal => disable IRQ 288 373 { 289 374 printk("\n[WARNING] in %s : no handler for HWI %d on core %d in cluster %x\n", 290 375 __FUNCTION__ , index , core->lid , local_cxy ); 291 376 core->spurious_irqs ++; 292 dev_icu_disable_irq( core->lid , HWI_TYPE , index );377 dev_icu_disable_irq( local_cxy , core->lid , HWI_TYPE , index ); 293 378 } 379 else if( src_dev_cxy != local_cxy ) // HWI must be handled in device cluster 380 { 381 printk("\n[PANIC] in %s : non local HWI %d on core %d in cluster %x\n", 382 __FUNCTION__ , index , core->lid , local_cxy ); 383 hal_core_sleep(); 384 } 294 385 else // call relevant ISR 295 386 { … … 297 388 __FUNCTION__ , index , core->lid , local_cxy ); 298 389 299 // call ISR 300 src_chdev->isr( src_chdev ); 390 src_dev_ptr->isr( src_dev_ptr ); 301 391 } 302 392 } … … 312 402 dev_icu_ack_timer( index ); 313 403 314 // TODOexecute all actions related to TICK event404 // execute all actions related to TICK event 315 405 core_clock( core ); 316 406 } … … 320 410 uint32_t dev_icu_wti_alloc() 321 411 { 322 // get local pointer on local ICU chdev323 xptr_t icu_xp = chdev_dir.icu[local_cxy];324 chdev_t * icu = (chdev_t *)GET_PTR( icu_xp );325 326 // get bitmap pointer, lock pointer, and size327 uint32_t * bitmap = &icu->ext.icu.wti_bitmap;412 // get pointer on local ICU device descriptor 413 core_t * core = CURRENT_CORE; 414 device_t * icu = core->icu; 415 416 // get bitmap pointer, lock, and size 417 bitmap_t * bitmap = &icu->ext.icu.wti_bitmap; 328 418 spinlock_t * lock = &icu->ext.icu.wti_lock; 329 419 uint32_t size = icu->ext.icu.wti_nr; … … 347 437 void dev_icu_wti_release( uint32_t index ) 348 438 { 349 // get pointer on local ICU chdevdescriptor350 xptr_t icu_xp = chdev_dir.icu[local_cxy];351 chdev_t * icu_ptr = (chdev_t *)GET_PTR( icu_xp );439 // get pointer on local ICU device descriptor 440 core_t * core = CURRENT_CORE; 441 device_t * icu = core->icu; 352 442 353 443 // get bitmap pointer, lock, and size 354 bitmap_t * bitmap = &icu _ptr->ext.icu.wti_bitmap;355 spinlock_t * lock = &icu _ptr->ext.icu.wti_lock;356 uint32_t size = icu _ptr->ext.icu.wti_nr;444 bitmap_t * bitmap = &icu->ext.icu.wti_bitmap; 445 spinlock_t * lock = &icu->ext.icu.wti_lock; 446 uint32_t size = icu->ext.icu.wti_nr; 357 447 358 448 // check index 359 assert( (index < size) , __FUNCTION__ , "illegal WTI index" ); 449 if( index >= size ) 450 { 451 printk("\n[PANIC] in %s : illegal WTI index = %d on core %d in cluster %x\n", 452 __FUNCTION__ , index , core->lid , local_cxy ); 453 hal_core_sleep(); 454 } 360 455 361 456 // get lock protecting WTI allocator … … 367 462 // release lock 368 463 spinlock_unlock( lock ); 369 370 464 } // end dev_icu_wti_release() 371 465 372 ////////////////////////////////////////////// 373 uint32_t * dev_icu_wti_ptr( uint32_t wti_id ) 374 { 375 uint32_t * wti_ptr = NULL; 376 377 // get pointer on local ICU chdev descriptor 378 xptr_t icu_xp = chdev_dir.icu[local_cxy]; 379 chdev_t * icu = (chdev_t *)GET_PTR( icu_xp ); 466 /////////////////////////////////////// 467 xptr_t dev_icu_wti_xptr( cxy_t cxy, 468 uint32_t wti_id ) 469 { 470 uint32_t * ptr = NULL; // local pointer on mailbox 471 472 // get pointer on local ICU device descriptor 473 core_t * core = CURRENT_CORE; 474 device_t * icu = core->icu; 380 475 381 476 // call implementation specific ICU driver 382 477 if( icu->impl == IMPL_ICU_XCU ) 383 478 { 384 wti_ptr = soclib_xcu_wti_ptr( icu , wti_id ); 385 } 386 387 return wti_ptr; 479 ptr = soclib_xcu_wti_ptr( icu , wti_id ); 480 } 481 else 482 { 483 printk("\n[PANIC] in %s : undefined ICU implementation" , __FUNCTION__ ); 484 hal_core_sleep(); 485 } 486 487 // return extended pointer on mailbox 488 return XPTR( cxy , ptr ); 489 388 490 } // end dev_icu_wti_xptr() 389 491 -
/trunk/kernel/devices/dev_icu.h
r3 r1 35 35 * acting in all clusters containing cores. He is in charge of concentrating all IRQs 36 36 * (interrupt requests) generated by peripherals to signal the completion of an I/O 37 * operation. Each IRQ isrouted to the core that started the I/O operation.37 * operation. Each IRQ should be routed to the core that started the I/O operation. 38 38 * The ICU device must also help the kernel to select the ISR (Interrupt Service Routine) 39 39 * that must be executed by the target core. 40 40 * 41 * This component can be implemented as a dedicated hardware componentdistributed41 * This component can be implemented as a dedicated hardware, centralized or distributed 42 42 * in all clusters, or emulated in software, as long as it implements the specified API. 43 43 * For the TSAR architecture, this generic ICU device is implemented by the two hardware 44 44 * components soclib_xicu and and soclib_iopic, and their associated drivers. 45 45 * 46 * ALMOS-MKH defines three types of IRQs, that are handled by this ICU device:46 * ALMOS-MKH defines three types of IRQs, that are handled iby this ICU device: 47 47 * - HWI : The HardWare Interrupts are generated by local internal peripherals. 48 48 * They are connected to the local ICU, to be routed to a given local core. … … 72 72 * uses three interrupts vectors, implemented as three arrays (HWI/WTI/PTI), 73 73 * stored in the core descriptor. Each entry in one interrupt vector array contains 74 * a pointer on the chdevdescriptor that is the "source" of the interrupt.75 * This chdevdescriptor contains a link to the ISR to be executed.74 * an extended pointer on the device descriptor that is the "source" of the interrupt. 75 * This device descriptor contains a link to the ISR to be executed. 76 76 * 77 77 * The ICU peripheral does not execute I/O operations, but is just acting as a 78 * dynamically configurable interrupt router for other I/O operations.79 * Therefore, ALMOS-MKH does not use the ICU device waiting queue, but calls directly78 * dynamically configurable interrupt router for another I/O operation. 79 * Therefore, ALMOS-MKH does not use the iCU device waiting queue, but calls directly 80 80 * the ICU driver blocking functions, using the device lock to get exclusive access to 81 81 * the ICU device state. … … 84 84 /**** Forward declarations ****/ 85 85 86 struct chdev_s;86 struct device_s; 87 87 88 88 /***************************************************************************************** … … 127 127 /***************************************************************************************** 128 128 * This function makes two initialisations: 129 * - It initialises the ICU specific fields of the chdevdescriptor.129 * - It initialises the ICU specific fields of the device descriptor. 130 130 * - it initialises the implementation specific ICU hardware device and associated 131 131 * data structures if required. 132 * It must be called by a local thread.133 ***************************************************************************************** 134 * @ icu : pointer on ICU chdevdescriptor.135 * @ hwi_nr : number of HWI irqs.136 * @ wti_nr : number of WTI irqs.137 * @ pti_nr : number of PTI irqs.138 ****************************************************************************************/ 139 void dev_icu_init( struct chdev_s * icu,140 uint32_t 141 uint32_t 142 uint32_t 143 144 /***************************************************************************************** 145 * This function enables the routing of a given IRQ, to a given core in the localcluster.146 * This IRQ is identified by its type (HWI/WTI/PTI) and index in the localICU.132 * It must be executed once in the cluster containing the ICU device descriptor. 133 ***************************************************************************************** 134 * @ icu_xp : extended pointer on ICU device descriptor. 135 * @ hwi_nr : number of HWI irqs. 136 * @ wti_nr : number of WTI irqs. 137 * @ pti_nr : number of PTI irqs. 138 ****************************************************************************************/ 139 void dev_icu_init( xptr_t icu_xp, 140 uint32_t hwi_nr, 141 uint32_t wti_nr, 142 uint32_t pti_nr ); 143 144 /***************************************************************************************** 145 * This function enables the routing of a given IRQ, to a given core in a remote cluster. 146 * This IRQ is identified by its type (HWI/WTI/PTI) and index in the remote ICU. 147 147 * The target core is identified by its local index. 148 * It must be called by a local thread.149 * - It unmask the selected IRQ in the ICU.150 * - It registers the pointer on the "source" chdevdescriptor in the148 * As it uses remote accesses, it can be executed by any thread in any cluster. 149 * - It unmask the selected IRQ in the remote ICU. 150 * - It registers the extended pointer on the "source" device descriptor in the 151 151 * relevant interrupt vector of the selected core. 152 * - It register the IRQ type and index in the "source" chdev descriptor. 153 ***************************************************************************************** 154 * @ lid : local index of selected core. 152 * - It register the IRQ type and index in the "source" device descriptor. 153 ***************************************************************************************** 154 * @ cxy : remote cluster identifier (can be the local custer). 155 * @ lid : local index of selected core in remote cluster. 155 156 * @ irq_type : HWI/WTI/PTI. 156 * @ irq_id : IRQ index in ICU 157 * @ chdev : pointer on source chdev descriptor. 158 ****************************************************************************************/ 159 void dev_icu_enable_irq( lid_t lid, 160 uint32_t irq_type, 161 uint32_t irq_id, 162 struct chdev_s * chdev ); 163 164 /***************************************************************************************** 165 * This function disables one given IRQ for a given core in the local cluster. 166 * This IRQ is identified by its type (HWI/WTI/PTI) and index in the local ICU. 157 * @ irq_id : IRQ index in remote ICU 158 * @ src_dev_xp : extended pointer on device descriptor source of IRQ. 159 ****************************************************************************************/ 160 void dev_icu_enable_irq( cxy_t cxy, 161 lid_t lid, 162 uint32_t irq_type, 163 uint32_t irq_id, 164 xptr_t src_dev_xp ); 165 166 /***************************************************************************************** 167 * This function disables one given IRQ for a given core in a remote cluster. 168 * This IRQ is identified by its type (HWI/WTI/PTI) and index in the remote ICU. 167 169 * The core is identified by its local index. 168 * It must be called by a local thread.169 * - It mask the selected IRQ in the ICU.170 * - It removes the pointer on the "source" chdevdescriptor from the170 * As it uses remote accesses, it can be executed by any thread in any cluster. 171 * - It mask the selected IRQ in the remote ICU. 172 * - It removes the extended pointer on the "source" device descriptor from the 171 173 * relevant interrupt vector of the selected core. 172 * - The IRQ type and index fields are not modified in the "source" chdev descriptor. 173 ***************************************************************************************** 174 * - The IRQ type and index fields are not modified in the "source" device descriptor. 175 ***************************************************************************************** 176 * @ cxy : remote cluster identifier (can be the local custer). 174 177 * @ lid : local index of selected core in remote cluster. 175 178 * @ irq_type : HWI/WTI/PTI. 176 179 * @ irq_id : IRQ index. 177 180 ****************************************************************************************/ 178 void dev_icu_disable_irq( lid_t lid, 181 void dev_icu_disable_irq( cxy_t cxy, 182 lid_t lid, 179 183 uint32_t irq_type, 180 184 uint32_t irq_id ); … … 183 187 * This function set the period value for a timer identified by the PTI index, 184 188 * in the local ICU device descriptor. 185 * It must be called by a local thread.186 189 ***************************************************************************************** 187 190 * @ pti_id : PTI index. … … 194 197 * This function acknowledge a PTI IRQ for a timer identified by the PTI index, 195 198 * in the local ICU device descriptor. 196 * It must be called by a local thread.197 199 ***************************************************************************************** 198 200 * @ pti_id : PTI index. … … 202 204 /***************************************************************************************** 203 205 * This function send an IPI (Inter Processor Interrupt) to a core identified by 204 * its cluster identifier and local index. 205 * It can be called by any thread running in any cluster. 206 * its cluster identifier and local index. 206 207 * This IPI force a context switch, and the handling of pending RPC(s). 207 208 ***************************************************************************************** … … 225 226 226 227 /***************************************************************************************** 227 * This function implements the WTI mailbox allocator for the local ICU. 228 * These mailbox are used by I/O operations for completion signaling. 229 * It must be called by a thread running in the cluster containing the target ICU. 228 * This function implements the WTI mailbox allocator. It is used by all I/O operations 229 * for completion signaling. 230 230 * If there is no mailbox available, the client thread must deschedule and retry later. 231 231 * If N is the total number of WTI mailboxes in a cluster, and NC the number of cores, … … 240 240 /***************************************************************************************** 241 241 * This function releases a dynamically allocated WTI mailbox. 242 * It must be called by a thread running in the cluster containing the target ICU.243 242 * It does not access the hardware device. 244 243 ***************************************************************************************** … … 248 247 249 248 /***************************************************************************************** 250 * This function returns a pointer on the WTI mailbox identified by its index 251 * in the local ICU device. 252 ***************************************************************************************** 253 * @ wti_id : WTI mailbox index. 254 * @ returns pointer on mailbox register. 255 ****************************************************************************************/ 256 uint32_t * dev_icu_wti_ptr( uint32_t wti_id ); 249 * This function returns an extended pointer on a WTI mailbox identified by its 250 * cluster identifier and local index in ICU. 251 * WARNING: we assume that all ICU hardware devices have the same local base address. 252 ***************************************************************************************** 253 * @ cxy : mailbox cluster identifier 254 * @ wti_id : mailbox WTI index. 255 * @ returns extended pointer on mailbox register. 256 ****************************************************************************************/ 257 xptr_t dev_icu_wti_xptr( cxy_t cxy, 258 uint32_t wti_id ); 257 259 258 260 #endif /* _DEV_ICU_H_ */ -
/trunk/kernel/devices/dev_ioc.c
r3 r1 32 32 #include <thread.h> 33 33 #include <printk.h> 34 #include <chdev.h>35 34 #include <dev_ioc.h> 36 35 … … 39 38 ///////////////////////////////////////////////////////////////////////////////////////// 40 39 41 extern chdev_directory_t chdev_dir; // allocated in kernel_init.c 42 43 extern chdev_pic_input_t chdev_pic_input; // allocated in kernel_init.c 44 45 //////////////////////////////////// 46 void dev_ioc_init( chdev_t * chdev ) 47 { 48 // the local ICU chdev must be initialized before the IOC chdev, because 49 // the IOC chdev initialisation requires allocation of a WTI from local ICU 50 xptr_t icu_xp = chdev_dir.icu[local_cxy]; 51 assert( (icu_xp != XPTR_NULL) , __FUNCTION__ , "ICU not initialised before IOC" ); 52 53 // get implementation and channel from chdev descriptor 54 uint32_t impl = chdev->impl; 55 uint32_t channel = chdev->channel; 56 57 // set driver specific fields in chdev descriptor and call driver init function 40 extern devices_directory_t devices_dir; // allocated in kernel_init.c 41 42 extern devices_input_irq_t devices_input_irq; // allocated in kernel_init.c 43 44 ////////////////////////////////// 45 void dev_ioc_init( xptr_t dev_xp ) 46 { 47 // get IOC device descriptor cluster and local pointer 48 cxy_t dev_cxy = GET_CXY( dev_xp ); 49 device_t * dev_ptr = (device_t *)GET_PTR( dev_xp ); 50 51 // get implementation from device descriptor 52 uint32_t impl = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->impl ) ); 53 54 // set driver specific fields in device descriptor 55 // and call driver init function 58 56 if( impl == IMPL_IOC_BDV ) 59 57 { 60 chdev->cmd = &soclib_bdv_cmd; 61 chdev->isr = &soclib_bdv_isr; 62 soclib_bdv_init( chdev ); 58 hal_remote_spt( XPTR( dev_cxy , &dev_ptr->cmd ) , &soclib_bdv_command ); 59 hal_remote_spt( XPTR( dev_cxy , &dev_ptr->isr ) , &soclib_bdv_isr ); 60 hal_remote_memcpy( XPTR( dev_cxy , &dev_ptr->name ), 61 XPTR( local_cxy , "IOC_BDV" ) , 16 ); 62 soclib_bdv_init( dev_xp ); 63 63 } 64 64 else if( impl == IMPL_IOC_HBA ) 65 65 { 66 chdev->cmd = &soclib_hba_command; 67 chdev->isr = &soclib_hba_isr; 68 soclib_hba_init( chdev ); 69 } 66 hal_remote_spt( XPTR( dev_cxy , &dev_ptr->cmd ) , &soclib_hba_command ); 67 hal_remote_spt( XPTR( dev_cxy , &dev_ptr->isr ) , &soclib_hba_isr ); 68 hal_remote_memcpy( XPTR( dev_cxy , &dev_ptr->name ), 69 XPTR( local_cxy , "IOC_HBA" ) , 16 ); 70 soclib_hba_init( dev_xp ); 71 } 72 // else if( impl == IMPL_IOC_SDC ) 73 // { 74 // hal_remote_spt( XPTR( dev_cxy , &dev_ptr->cmd ) , &soclib_sdc_command ); 75 // hal_remote_spt( XPTR( dev_cxy , &dev_ptr->isr ) , &soclib_sdc_isr ); 76 // hal_remote_memcpy( XPTR( dev_cxy , &dev_ptr->name ), 77 // XPTR( local_cxy , "IOC_SDC" ) , 16 ); 78 // soclib_sdc_init( dev_xp ); 79 // } 80 // else if( impl == IMPL_IOC_SPI ) 81 // { 82 // hal_remote_spt( XPTR( dev_cxy , &dev_ptr->cmd ) , &soclib_spi_command ); 83 // hal_remote_spt( XPTR( dev_cxy , &dev_ptr->isr ) , &soclib_spi_isr ); 84 // hal_remote_memcpy( XPTR( dev_cxy , &dev_ptr->name ), 85 // XPTR( local_cxy , "IOC_SPI" ) , 16 ); 86 // soclib_spi_init( dev_xp ); 87 // } 88 // else if( impl == IMPL_IOC_RDK ) 89 // { 90 // hal_remote_spt( XPTR( dev_cxy , &dev_ptr->cmd ) , &soclib_rdk_command ); 91 // hal_remote_spt( XPTR( dev_cxy , &dev_ptr->isr ) , &soclib_rdk_isr ); 92 // hal_remote_memcpy( XPTR( dev_cxy , &dev_ptr->name ), 93 // XPTR( local_cxy , "IOC_RDK" ) , 16 ); 94 // soclib_rdk_init( dev_xp ); 95 // } 70 96 else 71 97 { 72 assert( false , __FUNCTION__ , "undefined IOC device implementation" ); 73 } 74 75 // get a WTI mailbox from local ICU 76 uint32_t wti_id = dev_icu_wti_alloc(); 77 78 assert( (wti_id != -1) , __FUNCTION__ , "cannot allocate WTI mailbox" ); 79 80 // select a core 81 lid_t lid = cluster_select_local_core(); 82 83 // enable WTI IRQ and update WTI interrupt vector 84 dev_icu_enable_irq( lid , WTI_TYPE , wti_id , chdev ); 85 86 // link IOC IRQ to WTI mailbox in PIC component 87 uint32_t irq_id = chdev_pic_input.ioc[channel]; 88 dev_pic_bind_irq( irq_id , local_cxy , wti_id ); 98 printk("\n[PANIC] in %s: undefined IOC device implementation\n", __FUNCTION__ ); 99 hal_core_sleep(); 100 } 89 101 90 102 // create server thread 91 thread_t * new_thread; 103 thread_t * new_thread_ptr; 104 xptr_t new_thread_xp; 92 105 error_t error; 93 106 94 error = thread_kernel_create( &new_thread, 95 THREAD_DEV, 96 &chdev_sequencial_server, 97 chdev, 98 lid ); 99 assert( (error == 0) , __FUNCTION__ , "cannot create server thread" ); 100 101 // set "server" field in chdev descriptor 102 chdev->server = new_thread; 107 if( dev_cxy == local_cxy ) // device cluster is local 108 { 109 error = thread_kernel_create( &new_thread_ptr, 110 THREAD_DEV, 111 &dev_ioc_server, 112 dev_ptr, 113 cluster_select_local_core() ); 114 115 new_thread_xp = XPTR( local_cxy , new_thread_ptr ); 116 } 117 else // device cluster is remote 118 { 119 rpc_thread_kernel_create_client( dev_cxy, 120 THREAD_DEV, 121 &dev_ioc_server, 122 dev_ptr, 123 &new_thread_xp, 124 &error ); 125 126 new_thread_ptr = (thread_t *)GET_PTR( new_thread_xp ); 127 } 128 if( error ) 129 { 130 printk("\n[PANIC] in %s : cannot create server thread\n", __FUNCTION__ ); 131 hal_core_sleep(); 132 } 133 134 // set "server" field in device descriptor 135 hal_remote_spt( XPTR( dev_cxy , &dev_ptr->server ) , new_thread_ptr ); 103 136 104 137 // start server thread 105 thread_unblock( XPTR( local_cxy , new_thread ), THREAD_BLOCKED_GLOBAL );138 thread_unblock( new_thread_xp , THREAD_BLOCKED_GLOBAL ); 106 139 107 140 } // end dev_ioc_init() … … 111 144 // It builds and registers the command in the calling thread descriptor, after 112 145 // translation of buffer virtual address to physical address. 113 // Then, it registers the calling thead in chdevwaiting queue.146 // Then, it registers the calling thead in device waiting queue. 114 147 // Finally it blocks on the THREAD_BLOCKED_DEV condition and deschedule. 115 148 ////////////////////////////////////i///////////////////////////////////////////// … … 119 152 uint32_t count ) 120 153 { 121 thread_t * this = CURRENT_THREAD; // pointer on client thread 154 thread_t * this = CURRENT_THREAD; // pointer on client thread 155 cxy_t local_cxy = local_cxy; // client thread cluster 122 156 123 157 error_t error; 124 158 paddr_t buf_paddr; 159 bool_t ident = CONFIG_KERNEL_IDENTITY; 125 160 126 161 // Get buffer physical address 127 error = vmm_v2p_translate( CONFIG_KERNEL_IDENTITY, buffer , &buf_paddr );162 error = vmm_v2p_translate( ident , buffer , &buf_paddr ); 128 163 129 164 if( error ) return EINVAL; 130 165 131 166 ioc_dmsg("\n[INFO] in %s : thread %x in process %x" 132 " for lba = %x / vaddr = %x / paddr = %l / at cycle %d\n",167 " for lba = %x / vaddr = %x / paddr = %llx\n", 133 168 __FUNCTION__ , this->trdid , this->process->pid , 134 lba , (uint32_t)buffer , buf_paddr , hal_time_stamp());169 lba , (uint32_t)buffer , buf_paddr ); 135 170 136 171 #if USE_IOB // software L2/L3 cache coherence for memory buffer … … 141 176 #endif // end software L2/L3 cache coherence 142 177 143 // get extended pointer on IOC chdev descriptor 144 xptr_t dev_xp = chdev_dir.ioc[0]; 145 146 assert( (dev_xp != XPTR_NULL) , __FUNCTION__ , "undefined IOC chdev descriptor" ); 147 148 // register command in calling thread descriptor 149 this->command.ioc.dev_xp = dev_xp; 150 this->command.ioc.to_mem = to_mem; 151 this->command.ioc.buf_xp = XPTR( local_cxy , buffer ); 152 this->command.ioc.lba = lba; 153 this->command.ioc.count = count; 154 155 // register client thread in IOC chdev waiting queue, activate server thread, 178 // get extended pointer on IOC device descriptor 179 xptr_t dev_xp = devices_dir.ioc; 180 181 if ( dev_xp == XPTR_NULL ) 182 { 183 printk("\n[PANIC] in %s : undefined IOC device descriptor\n", __FUNCTION__ ); 184 hal_core_sleep(); 185 } 186 187 // get a free WTI mailbox 188 uint32_t wti_id; 189 while( 1 ) 190 { 191 wti_id = dev_icu_wti_alloc(); 192 if( wti_id == -1 ) sched_yield(); 193 else break; 194 } 195 196 // enable WTI IRQ in local ICU and update WTI interrupt vector 197 dev_icu_enable_irq( local_cxy, CURRENT_CORE->lid , WTI_TYPE , wti_id , dev_xp ); 198 199 // link IOC IRQ to WTI mailbox in PIC component 200 uint32_t irq_id = devices_input_irq.ioc; 201 dev_pic_bind_irq( irq_id , local_cxy , wti_id ); 202 203 // store command in thread descriptor 204 this->dev.ioc.dev_xp = dev_xp; 205 this->dev.ioc.to_mem = to_mem; 206 this->dev.ioc.buf_xp = XPTR( local_cxy , buffer ); 207 this->dev.ioc.lba = lba; 208 this->dev.ioc.count = count; 209 210 // register client thread in waiting queue, activate server thread, 156 211 // block client thread on THREAD_BLOCKED_IO and deschedule. 157 212 // it is re-activated by the ISR signaling IO operation completion. 158 chdev_register_command( dev_xp , this ); 159 160 ioc_dmsg("\n[INFO] in %s : thread %x in process %x" 161 " completes / error = %d / at cycle %d\n", 162 __FUNCTION__ , this->trdid , this->process->pid , 163 this->dev.ioc.error , hal_time_stamp() ); 213 device_register_command( dev_xp , this ); 214 215 // access PIC to unlink the IOC IRQ 216 dev_pic_unbind_irq( irq_id ); 217 218 // disable WTI IRQ in ICU and update interrupt vector 219 dev_icu_disable_irq( local_cxy , CURRENT_CORE->lid , WTI_TYPE , wti_id ); 220 221 // release WTI mailbox 222 dev_icu_wti_release( wti_id ); 223 224 ioc_dmsg("\n[INFO] in %s : thread %x in process %x completes / error = %d\n", 225 __FUNCTION__ , this->trdid , this->process->pid , this->dev.ioc.error ); 164 226 165 227 // return I/O operation status 166 return this-> command.ioc.error;228 return this->dev.ioc.error; 167 229 168 230 } // end dev_ioc_access() … … 183 245 return dev_ioc_access( false , buffer , lba , count ); 184 246 } 247 248 ///////////////////////////////////// 249 void dev_ioc_server( device_t * dev ) 250 { 251 xptr_t client_xp; // extended pointer on waiting thread 252 cxy_t client_cxy; // cluster of client thread 253 thread_t * client_ptr; // local pointer on client thread 254 thread_t * server; // local pointer on server thread 255 xptr_t root_xp; // extended pointer on device waiting queue root 256 257 server = CURRENT_THREAD; 258 259 root_xp = XPTR( local_cxy , &dev->wait_root ); 260 261 // infinite loop handling commands registered in the IOC waiting queue 262 // TODO If we want to implement an "elevator" mecanism (i.e. sort all 263 // pending command on the LBA to optimize physical device accesses), 264 // it should be done in this loop... 265 266 while( 1 ) 267 { 268 // get lock protecting queue 269 remote_spinlock_lock( XPTR( local_cxy , &dev->wait_lock ) ); 270 271 // block and deschedule server thread if waiting queue empty 272 if( xlist_is_empty( root_xp ) ) 273 { 274 thread_block( server , THREAD_BLOCKED_DEV_QUEUE ); 275 remote_spinlock_unlock( XPTR( local_cxy , &dev->wait_lock ) ); 276 sched_yield(); 277 } 278 else 279 { 280 remote_spinlock_unlock( XPTR( local_cxy , &dev->wait_lock ) ); 281 } 282 283 // get extended pointer on first client thread 284 client_xp = XLIST_FIRST_ELEMENT( root_xp , thread_t , wait_list ); 285 286 // call driver command function to start I/O operation 287 dev->cmd( client_xp ); 288 289 // get client thread cluster and local pointer 290 client_cxy = GET_CXY( client_xp ); 291 client_ptr = (thread_t *)GET_PTR( client_xp ); 292 293 // remove the client thread from waiting queue 294 remote_spinlock_lock( XPTR( local_cxy , &dev->wait_lock ) ); 295 xlist_unlink( XPTR( client_cxy , &client_ptr->wait_list ) ); 296 remote_spinlock_unlock( XPTR( local_cxy , &dev->wait_lock ) ); 297 298 } // end while 299 300 } // end dev_ioc_server() -
/trunk/kernel/devices/dev_ioc.h
r3 r1 25 25 #define _DEV_IOC_H 26 26 27 #include <almos_config.h>28 27 #include <hal_types.h> 29 28 30 29 /**** Forward declarations ****/ 31 30 32 struct chdev_s;31 struct device_s; 33 32 34 33 /***************************************************************************************** … … 105 104 106 105 /****************************************************************************************** 107 * This function completes the IOC chdevdescriptor initialisation,106 * This function completes the IOC device descriptor initialisation, 108 107 * namely the link with the implementation specific driver. 109 * The func, impl, channel, is_rx , base fields have beenpreviously initialised.108 * The func, impl, channel, is_rxt, base, and size fields must be previously initialised. 110 109 * It calls the specific driver initialisation function, to initialise the hardware 111 110 * device and the specific data structures when required. 112 * It creates the associated server thread and allocates a WTI from local ICU. 113 * It must de executed by a local thread. 111 * It creates the associated server thread. 112 * It can be executed in another cluster than the cluster containing the device descriptor 113 * or the hardware device itself. 114 114 ****************************************************************************************** 115 * @ chdev : local pointer on IOC chdevdescriptor.115 * @ xp_dev : extended pointer on IOC device descriptor. 116 116 *****************************************************************************************/ 117 void dev_ioc_init( struct chdev_s * chdev );117 void dev_ioc_init( xptr_t xp_dev ); 118 118 119 119 /****************************************************************************************** … … 149 149 uint32_t count ); 150 150 151 /****************************************************************************************** 152 * This function is executed by the server thread associated to the IOC device descriptor. 153 * This thread is created and activated by the dev_ioc_init() function. 154 * It executes an infinite loop to handle sequencially all commands registered 155 * by the client threads in the device waiting queue, calling the driver CMD function. 156 * 157 * - If the peripheral can only handle one single command, the driver block the server 158 * thread on the THREAD_BLOCKED_DEV_ISR condition, waiting I/O operation conmpletion. 159 * The server thread must be reacticated by the driver ISR function. 160 * - If the peripheral can handle several commands in parallel (AHCI is an example), the 161 * driver does not block the server thread (it is only descheduled if the number of 162 * commands exceeeds the max number of parallel commands supported by the peripheral. 163 * 164 * When the waiting queue is empty, the server thread blocks on the THREAD_BLOCKED_CMD 165 * condition and deschedule. It is re-activated by a client thread registering a command. 166 ****************************************************************************************** 167 * @ dev : local pointer on IOC device descriptor. 168 *****************************************************************************************/ 169 void dev_ioc_server( struct device_s * dev ); 170 151 171 #endif /* _DEV_IOC_H */ -
/trunk/kernel/devices/dev_mmc.c
r3 r1 26 26 #include <soclib_mmc.h> 27 27 #include <printk.h> 28 #include <chdev.h>29 28 #include <thread.h> 30 29 #include <dev_mmc.h> … … 34 33 ///////////////////////////////////////////////////////////////////////////////////////// 35 34 36 extern chdev_directory_t chdev_dir; // allocated in kernel_init.c 37 38 extern chdev_icu_input_t chdev_icu_input; // allocated in kernel_init.c 39 40 //////////////////////////////////// 41 void dev_mmc_init( chdev_t * chdev ) 42 { 35 extern devices_directory_t devices_dir; // allocated in kernel_init.c 36 37 extern devices_input_irq_t devices_input_irq; // allocated in kernel_init.c 38 39 ////////////////////////////////// 40 void dev_mmc_init( xptr_t dev_xp ) 41 { 42 // get MMC device descriptor cluster and local pointer 43 cxy_t dev_cxy = GET_CXY( dev_xp ); 44 device_t * dev_ptr = (device_t *)GET_PTR( dev_xp ); 45 43 46 // get implementation from device descriptor 44 uint32_t impl = chdev->impl; 45 46 // set driver specific fields in device descriptor and call driver init function 47 uint32_t impl = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->impl ) ); 48 49 // set driver specific fields in device descriptor 50 // and call driver init function 47 51 if( impl == IMPL_MMC_TSR ) 48 52 { 49 chdev->cmd = &soclib_mmc_cmd; 50 chdev->isr = &soclib_mmc_isr; 51 soclib_mmc_init( chdev ); 53 hal_remote_spt( XPTR( dev_cxy , &dev_ptr->cmd ) , &soclib_mmc_command ); 54 hal_remote_spt( XPTR( dev_cxy , &dev_ptr->isr ) , &soclib_mmc_isr ); 55 hal_remote_memcpy( XPTR( dev_cxy , &dev_ptr->name ), 56 XPTR( local_cxy , "MMC_TSR" ) , 16 ); 57 soclib_mmc_init( dev_xp ); 52 58 } 53 59 else 54 60 { 55 assert( false , __FUNCTION__ , "undefined MMC device implementation" ); 61 printk("\n[PANIC] in %s: undefined MMC device implementation\n", __FUNCTION__ ); 62 hal_core_sleep(); 56 63 } 57 64 } // end dev_mmc_init() … … 65 72 { 66 73 mmc_dmsg("\n[INFO] %s enters for thread %x in process %x : command = %d\n", 67 __FUNCTION__ , this->trdid , this->process->pid , this-> command.mmc.type );74 __FUNCTION__ , this->trdid , this->process->pid , this->dev.mmc.type ); 68 75 69 76 // get extended pointer on MMC device 70 xptr_t dev_xp = this->command.mmc.dev_xp; 71 72 assert( (dev_xp != XPTR_NULL) , __FUNCTION__ , "undefined MMC device descriptor" ); 77 xptr_t dev_xp = this->dev.mmc.dev_xp; 78 79 if ( dev_xp == XPTR_NULL ) 80 { 81 printk("\n[PANIC] in %s : undefined MMC device descriptor " 82 "in cluster %x for thread %x in process %x\n", 83 __FUNCTION__ , local_cxy , this->trdid , this->process->pid ); 84 hal_core_sleep(); 85 } 73 86 74 87 // get MMC device cluster identifier & local pointer 75 cxy_t dev_cxy = GET_CXY( dev_xp );76 chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp );88 cxy_t dev_cxy = GET_CXY( dev_xp ); 89 device_t * dev_ptr = (device_t *)GET_PTR( dev_xp ); 77 90 78 91 // get driver command function pointer from MMC device descriptor … … 103 116 cxy_t cxy = CXY_FROM_PADDR( buf_paddr ); 104 117 105 assert( ((buf_paddr & (CONFIG_CACHE_LINE_SIZE -1)) == 0) , __FUNCTION__ , 106 "buffer not aligned on cache line" ); 118 if ( buf_paddr & (CONFIG_CACHE_LINE_SIZE -1) ) 119 { 120 printk("\n[PANIC] in %s : buffer not aligned on cache line " 121 "for thread %x / target cluster %x\n", 122 __FUNCTION__ , this->trdid , cxy ); 123 hal_core_sleep(); 124 } 107 125 108 126 // get extended pointer on MMC device descriptor 109 xptr_t dev_xp = chdev_dir.mmc[cxy];110 111 // store command arguments in thread descriptor 112 this-> command.mmc.dev_xp = dev_xp;113 this-> command.mmc.type = MMC_CC_INVAL;114 this-> command.mmc.buf_paddr = buf_paddr;115 this-> command.mmc.buf_size = buf_size;116 117 // execute operation 118 dev_mmc_access( this ); 119 120 // return operation status 121 return this-> command.mmc.error;127 xptr_t dev_xp = devices_dir.mmc[cxy]; 128 129 // store command arguments in thread descriptor 130 this->dev.mmc.dev_xp = dev_xp; 131 this->dev.mmc.type = MMC_CC_INVAL; 132 this->dev.mmc.buf_paddr = buf_paddr; 133 this->dev.mmc.buf_size = buf_size; 134 135 // execute operation 136 dev_mmc_access( this ); 137 138 // return operation status 139 return this->dev.mmc.error; 122 140 } 123 141 … … 132 150 cxy_t cxy = CXY_FROM_PADDR( buf_paddr ); 133 151 134 assert( ((buf_paddr & (CONFIG_CACHE_LINE_SIZE -1)) == 0) , __FUNCTION__ , 135 "buffer not aligned on cache line" ); 136 137 // store command arguments in thread descriptor 138 this->command.mmc.dev_xp = chdev_dir.mmc[cxy]; 139 this->command.mmc.type = MMC_CC_SYNC; 140 this->command.mmc.buf_paddr = buf_paddr; 141 this->command.mmc.buf_size = buf_size; 142 143 // execute operation 144 dev_mmc_access( this ); 145 146 // return operation status 147 return this->command.mmc.error; 152 if ( buf_paddr & (CONFIG_CACHE_LINE_SIZE -1) ) 153 { 154 printk("\n[PANIC] in %s : buffer not aligned on cache line " 155 "for thread %x / target cluster %x\n", 156 __FUNCTION__ , this->trdid , cxy ); 157 hal_core_sleep(); 158 } 159 160 // store command arguments in thread descriptor 161 this->dev.mmc.dev_xp = devices_dir.mmc[cxy]; 162 this->dev.mmc.type = MMC_CC_SYNC; 163 this->dev.mmc.buf_paddr = buf_paddr; 164 this->dev.mmc.buf_size = buf_size; 165 166 // execute operation 167 dev_mmc_access( this ); 168 169 // return operation status 170 return this->dev.mmc.error; 148 171 } 149 172 … … 157 180 158 181 // store command arguments in thread descriptor 159 this-> command.mmc.dev_xp = chdev_dir.mmc[cxy];160 this-> command.mmc.type = MMC_SET_ERROR;161 this-> command.mmc.reg_index = index;162 this-> command.mmc.reg_ptr = &wdata;163 164 // execute operation 165 dev_mmc_access( this ); 166 167 // return operation status 168 return this-> command.mmc.error;182 this->dev.mmc.dev_xp = devices_dir.mmc[cxy]; 183 this->dev.mmc.type = MMC_SET_ERROR; 184 this->dev.mmc.reg_index = index; 185 this->dev.mmc.reg_ptr = &wdata; 186 187 // execute operation 188 dev_mmc_access( this ); 189 190 // return operation status 191 return this->dev.mmc.error; 169 192 } 170 193 … … 178 201 179 202 // store command arguments in thread descriptor 180 this-> command.mmc.dev_xp = chdev_dir.mmc[cxy];181 this-> command.mmc.type = MMC_GET_ERROR;182 this-> command.mmc.reg_index = index;183 this-> command.mmc.reg_ptr = rdata;184 185 // execute operation 186 dev_mmc_access( this ); 187 188 // return operation status 189 return this-> command.mmc.error;203 this->dev.mmc.dev_xp = devices_dir.mmc[cxy]; 204 this->dev.mmc.type = MMC_GET_ERROR; 205 this->dev.mmc.reg_index = index; 206 this->dev.mmc.reg_ptr = rdata; 207 208 // execute operation 209 dev_mmc_access( this ); 210 211 // return operation status 212 return this->dev.mmc.error; 190 213 } 191 214 … … 199 222 200 223 // store command arguments in thread descriptor 201 this-> command.mmc.dev_xp = chdev_dir.mmc[cxy];202 this-> command.mmc.type = MMC_GET_INSTRU;203 this-> command.mmc.reg_index = index;204 this-> command.mmc.reg_ptr = rdata;205 206 // execute operation 207 dev_mmc_access( this ); 208 209 // return operation status 210 return this-> command.mmc.error;224 this->dev.mmc.dev_xp = devices_dir.mmc[cxy]; 225 this->dev.mmc.type = MMC_GET_INSTRU; 226 this->dev.mmc.reg_index = index; 227 this->dev.mmc.reg_ptr = rdata; 228 229 // execute operation 230 dev_mmc_access( this ); 231 232 // return operation status 233 return this->dev.mmc.error; 211 234 } 212 235 -
/trunk/kernel/devices/dev_mmc.h
r3 r1 46 46 * As these operations consume few cycles, and access conflicts are expected to be 47 47 * rare events, the calling threads use a busy waiting strategy to get the device 48 * spinlock, butdo not register in the device waiting queue, and no server thread48 * spinlock, do not register in the device waiting queue, and no server thread 49 49 * is used for this device. 50 50 ****************************************************************************************/ 51 51 52 /**** Forward declarations ****/53 54 struct chdev_s;55 56 52 /****************************************************************************************** 57 53 * This enum defines the various implementations of the generic MMC peripheral. … … 96 92 * It must be executed once in any cluster containing an L2 cache. 97 93 ***************************************************************************************** 98 * @ chdev :pointer on MMC device descriptor.94 * @ mmc_xp : extended pointer on MMC device descriptor. 99 95 ****************************************************************************************/ 100 void dev_mmc_init( struct chdev_s * chdev);96 void dev_mmc_init( xptr_t mmc_xp ); 101 97 102 98 /***************************************************************************************** -
/trunk/kernel/devices/dev_nic.c
r3 r1 25 25 #include <hal_special.h> 26 26 #include <printk.h> 27 #include < chdev.h>27 #include <device.h> 28 28 #include <thread.h> 29 29 #include <soclib_nic.h> … … 34 34 ///////////////////////////////////////////////////////////////////////////////////////// 35 35 36 extern chdev_directory_t chdev_dir; // allocated in kernel_init.c 37 38 extern chdev_pic_input_t chdev_pic_input; // allocated in kernel_init.c 39 40 //////////////////////////////////// 41 void dev_nic_init( chdev_t * chdev ) 36 extern devices_directory_t devices_dir; // allocated in kernel_init.c 37 38 extern devices_input_irq_t devices_input_irq; // allocated in kernel_init.c 39 40 41 ////////////////////////////////// 42 void dev_nic_init( xptr_t dev_xp ) 42 43 { 43 // the local ICU chdev must be initialized before the NIC chdev, because44 // the NIC chdevs initialisation requires allocation of a WTI from local ICU45 xptr_t icu_xp = chdev_dir.icu[local_cxy];46 assert( (icu_xp != XPTR_NULL) , __FUNCTION__ , "ICU not initialised before NIC" ); 47 48 // get "impl" , "channel" , "is_rx" fields from chdev descriptor49 uint32_t i mpl = chdev->impl;50 uint32_t is_rx = chdev->is_rx;51 uint32_t channel = chdev->channel; 52 53 // set driver specific fields in chdev descriptorand call driver init function44 // get device descriptor cluster and local pointer 45 cxy_t dev_cxy = GET_CXY( dev_xp ); 46 device_t * dev_ptr = (device_t *)GET_PTR( dev_xp ); 47 48 // get "impl" , "channel" , "is_rx" fields from device descriptor 49 uint32_t impl = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->impl ) ); 50 uint32_t is_rx = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->is_rx ) ); 51 uint32_t channel = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->channel ) ); 52 53 // set driver specific fields in device descriptor 54 // and call driver init function 54 55 if( impl == IMPL_NIC_SOC ) 55 56 { 56 chdev->cmd = &soclib_nic_cmd; 57 chdev->isr = &soclib_nic_isr; 58 soclib_nic_init( chdev ); 59 } 57 hal_remote_spt( XPTR( dev_cxy , &dev_ptr->cmd ) , &soclib_nic_cmd ); 58 hal_remote_spt( XPTR( dev_cxy , &dev_ptr->isr ) , &soclib_nic_isr ); 59 hal_remote_memcpy( XPTR( dev_cxy , &dev_ptr->name ), 60 XPTR( local_cxy , "NIC_SOC" ) , 16 ); 61 soclib_nic_init( dev_xp ); 62 } 63 // else if( impl == IMPL_NIC_I86) 64 // { 65 // hal_remote_spt( XPTR( cxy , &ptr->cmd ) , &i86_nic_cmd ); 66 // hal_remote_spt( XPTR( cxy , &ptr->isr ) , &i86_nic_isr ); 67 // hal_remote_memcpy( XPTR( cxy , &ptr->name ), 68 // XPTR( local_cxy , "NIC_I86" ) , 16 ); 69 // i86_nic_init( dev ); 70 // } 60 71 else 61 72 { 62 assert( false , __FUNCTION__ , "undefined NIC device implementation" ); 63 } 64 65 // get a WTI mailbox from local ICU 66 uint32_t wti_id = dev_icu_wti_alloc(); 67 68 assert( (wti_id != -1) , __FUNCTION__ , "cannot allocate WTI mailbox" ); 69 70 // select a core 71 lid_t lid = cluster_select_local_core(); 72 73 // enable WTI IRQ and update WTI interrupt vector 74 dev_icu_enable_irq( lid , WTI_TYPE , wti_id , chdev ); 73 printk("\n[PANIC] in %s : undefined NIC device implementation\n", __FUNCTION__ ); 74 hal_core_sleep(); 75 } 76 77 // get a free WTI mailbox for this NIC device 78 uint32_t wti_id; 79 if( dev_cxy == local_cxy ) // NIC device cluster is local 80 { 81 wti_id = dev_icu_wti_alloc(); 82 } 83 else // NIC device cluster is remote 84 { 85 rpc_icu_wti_alloc_client( dev_cxy , &wti_id ); 86 } 87 88 if( wti_id == -1 ) 89 { 90 printk("\n[PANIC] in %s : cannot allocate WTI mailbox\n", __FUNCTION__ ); 91 hal_core_sleep(); 92 } 93 94 // enable WTI IRQ in remote ICU and update WTI interrupt vector 95 dev_icu_enable_irq( dev_cxy, 0 , WTI_TYPE , wti_id , dev_xp ); 75 96 76 97 // link NIC IRQ to WTI mailbox in PIC component 77 98 uint32_t irq_id; 78 if( is_rx ) irq_id = chdev_pic_input.nic_rx[channel];79 else irq_id = chdev_pic_input.nic_tx[channel];99 if( is_rx ) irq_id = devices_input_irq.nic_rx[channel]; 100 else irq_id = devices_input_irq.nic_tx[channel]; 80 101 dev_pic_bind_irq( irq_id , local_cxy , wti_id ); 81 102 82 103 // create server thread 83 thread_t * new_thread; 104 thread_t * new_thread_ptr; 105 xptr_t new_thread_xp; 84 106 error_t error; 85 107 86 error = thread_kernel_create( &new_thread, 87 THREAD_DEV, 88 &chdev_sequencial_server, 89 chdev, 90 lid ); 91 92 assert( (error == 0) , __FUNCTION__ , "cannot create server thread" ); 93 94 // set "server" field in chdev descriptor 95 chdev->server = new_thread; 108 if( dev_cxy == local_cxy ) // device cluster is local 109 { 110 error = thread_kernel_create( &new_thread_ptr, 111 THREAD_DEV, 112 &dev_ioc_server, 113 dev_ptr, 114 cluster_select_local_core() ); 115 116 new_thread_xp = XPTR( local_cxy , new_thread_ptr ); 117 } 118 else // device cluster is remote 119 { 120 rpc_thread_kernel_create_client( dev_cxy, 121 THREAD_DEV, 122 &dev_ioc_server, 123 dev_ptr, 124 &new_thread_xp, 125 &error ); 126 127 new_thread_ptr = (thread_t *)GET_PTR( new_thread_xp ); 128 } 129 if( error ) 130 { 131 printk("\n[PANIC] in %s : cannot create server thread\n", __FUNCTION__ ); 132 hal_core_sleep(); 133 } 134 135 // set "server" field in device descriptor 136 hal_remote_spt( XPTR( dev_cxy , &dev_ptr->server ) , new_thread_ptr ); 96 137 97 138 // start server thread 98 thread_unblock( XPTR( local_cxy , new_thread ), THREAD_BLOCKED_GLOBAL );139 thread_unblock( new_thread_xp , THREAD_BLOCKED_GLOBAL ); 99 140 100 141 } // end dev_nic_init() … … 115 156 __FUNCTION__ , core->lid , local_cxy ); 116 157 117 // get pointer on NIC-RX chdevdescriptor158 // get pointer on NIC-RX device descriptor 118 159 uint32_t channel = thread_ptr->dev_channel; 119 xptr_t dev_xp = chdev_dir.nic_rx[channel];160 xptr_t dev_xp = devices_dir.nic_rx[channel]; 120 161 cxy_t dev_cxy = GET_CXY( dev_xp ); 121 chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp ); 122 123 assert( (dev_xp != XPTR_NULL) , __FUNCTION__ , "undefined NIC chdev descriptor" ); 124 125 assert( (dev_cxy == local_cxy) , __FUNCTION__ , " chdev must be local" ); 162 device_t * dev_ptr = (device_t *)GET_PTR( dev_xp ); 163 164 if ( dev_xp == XPTR_NULL ) 165 { 166 printk("\n[PANIC] in %s : undefined NIC device descriptor\n", __FUNCTION__ ); 167 hal_core_sleep(); 168 } 169 170 if ( dev_cxy != local_cxy ) 171 { 172 printk("\n[PANIC] in %s : device descriptor must be local\n", __FUNCTION__ ); 173 hal_core_sleep(); 174 } 126 175 127 176 // initialize command in thread descriptor 128 thread_ptr-> command.nic.dev_xp = dev_xp;177 thread_ptr->dev.nic.dev_xp = dev_xp; 129 178 130 179 // call driver to test readable 131 thread_ptr-> command.nic.cmd = NIC_CMD_READABLE;180 thread_ptr->dev.nic.cmd = NIC_CMD_READABLE; 132 181 dev_ptr->cmd( thread_xp ); 133 182 134 183 // check error 135 error = thread_ptr-> command.nic.error;184 error = thread_ptr->dev.nic.error; 136 185 if( error ) return error; 137 186 138 187 // block and deschedule if queue non readable 139 if( thread_ptr-> command.nic.status == false )188 if( thread_ptr->dev.nic.status == false ) 140 189 { 141 190 // get NIC-RX IRQ index and type … … 144 193 145 194 // enable NIC-RX IRQ 146 dev_icu_enable_irq( core->lid , irq_type , irq_id , dev_ptr);195 dev_icu_enable_irq( local_cxy , core->lid , irq_type , irq_id , dev_xp ); 147 196 148 197 // block on THREAD_BLOCKED I/O condition and deschedule … … 151 200 152 201 // disable NIC-RX channel IRQ 153 dev_icu_disable_irq( core->lid , irq_type , irq_id );202 dev_icu_disable_irq( local_cxy , core->lid , irq_type , irq_id ); 154 203 } 155 204 156 205 // call driver for actual read 157 thread_ptr-> command.nic.cmd = NIC_CMD_READ;158 thread_ptr-> command.nic.buffer = pkd->buffer;206 thread_ptr->dev.nic.cmd = NIC_CMD_READ; 207 thread_ptr->dev.nic.buffer = pkd->buffer; 159 208 dev_ptr->cmd( thread_xp ); 160 209 161 210 // check error 162 error = thread_ptr-> command.nic.error;211 error = thread_ptr->dev.nic.error; 163 212 if( error ) return error; 164 213 165 214 // returns packet length 166 pkd->length = thread_ptr-> command.nic.length;215 pkd->length = thread_ptr->dev.nic.length; 167 216 168 217 nic_dmsg("\n[INFO] %s exit for NIC-RX thread on core %d in cluster %x\n", … … 189 238 __FUNCTION__ , core->lid , local_cxy ); 190 239 191 // get pointer on NIC-TX chdevdescriptor240 // get pointer on NIC-TX device descriptor 192 241 uint32_t channel = thread_ptr->dev_channel; 193 xptr_t dev_xp = chdev_dir.nic_tx[channel];242 xptr_t dev_xp = devices_dir.nic_tx[channel]; 194 243 cxy_t dev_cxy = GET_CXY( dev_xp ); 195 chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp ); 196 197 assert ( (dev_xp != XPTR_NULL) , __FUNCTION__ , "undefined NIC chdev descriptor" ); 198 199 assert( (dev_cxy == local_cxy) , __FUNCTION__ , " chdev must be local" ); 244 device_t * dev_ptr = (device_t *)GET_PTR( dev_xp ); 245 246 if ( dev_xp == XPTR_NULL ) 247 { 248 printk("\n[PANIC] in %s : undefined NIC device descriptor\n", __FUNCTION__ ); 249 hal_core_sleep(); 250 } 251 252 if ( dev_cxy != local_cxy ) 253 { 254 printk("\n[PANIC] in %s : device descriptor must be local\n", __FUNCTION__ ); 255 hal_core_sleep(); 256 } 200 257 201 258 // initialize command in thread descriptor 202 thread_ptr-> command.nic.dev_xp = dev_xp;259 thread_ptr->dev.nic.dev_xp = dev_xp; 203 260 204 261 // call driver to test writable 205 thread_ptr-> command.nic.cmd = NIC_CMD_WRITABLE;262 thread_ptr->dev.nic.cmd = NIC_CMD_WRITABLE; 206 263 dev_ptr->cmd( thread_xp ); 207 264 208 265 // check error 209 error = thread_ptr-> command.nic.error;266 error = thread_ptr->dev.nic.error; 210 267 if( error ) return error; 211 268 212 269 // block and deschedule if queue non writable 213 if( thread_ptr-> command.nic.status == false )270 if( thread_ptr->dev.nic.status == false ) 214 271 { 215 272 // get NIC-TX IRQ index and type … … 218 275 219 276 // enable NIC-TX IRQ 220 dev_icu_enable_irq( core->lid , irq_type , irq_id , dev_ptr);277 dev_icu_enable_irq( local_cxy , core->lid , irq_type , irq_id , dev_xp ); 221 278 222 279 // block on THREAD_BLOCKED I/O condition and deschedule … … 225 282 226 283 // disable NIC-TX IRQ 227 dev_icu_disable_irq( core->lid , irq_type , irq_id );284 dev_icu_disable_irq( local_cxy , core->lid , irq_type , irq_id ); 228 285 } 229 286 230 287 // call driver for actual write 231 thread_ptr-> command.nic.cmd = NIC_CMD_WRITE;232 thread_ptr-> command.nic.buffer = pkd->buffer;233 thread_ptr-> command.nic.length = pkd->length;288 thread_ptr->dev.nic.cmd = NIC_CMD_WRITE; 289 thread_ptr->dev.nic.buffer = pkd->buffer; 290 thread_ptr->dev.nic.length = pkd->length; 234 291 dev_ptr->cmd( thread_xp ); 235 292 236 293 // check error 237 error = thread_ptr-> command.nic.error;294 error = thread_ptr->dev.nic.error; 238 295 if( error ) return error; 239 296 -
/trunk/kernel/devices/dev_nic.h
r3 r1 75 75 /**** Forward declarations ****/ 76 76 77 struct chdev_s;77 struct device_s; 78 78 79 79 /****************************************************************************************** … … 137 137 138 138 /****************************************************************************************** 139 * This function completes the NIC-RX and NIC-TX chdev descriptors initialisation. 140 * namely the link with the implementation specific driver. 141 * The func, impl, channel, is_rx, base fields have been previously initialised. 142 * It calls the specific driver initialisation function, to initialise the hardware 143 * device and the specific data structures when required. 144 * It creates the associated server thread and allocates a WTI from local ICU. 145 * It must de executed by a local thread. 146 ****************************************************************************************** 147 * @ chdev : local pointer on NIC chdev descriptor. 148 *****************************************************************************************/ 149 void dev_nic_init( struct chdev_s * chdev ); 139 * This function completes the NIC-RX and NIC-TX devices descriptors initialisation. 140 * The func, impl, channel, is_rx, base, and size have been previously initialised. 141 * It calls the driver initialisation function. 142 ****************************************************************************************** 143 * @ dev_xp : extended pointer on NIC-RX or NIC-TX device descriptor. 144 *****************************************************************************************/ 145 void dev_nic_init( xptr_t dev_xp ); 150 146 151 147 /****************************************************************************************** … … 223 219 * becomes non empty. 224 220 ****************************************************************************************** 225 * @ dev : local pointer on NIC ch devdescriptor.226 *****************************************************************************************/ 227 void dev_nic_server( struct chdev_s * chdev );221 * @ dev : local pointer on NIC channel device descriptor. 222 *****************************************************************************************/ 223 void dev_nic_server( struct device_s * dev ); 228 224 229 225 -
/trunk/kernel/devices/dev_pic.c
r3 r1 25 25 #include <hal_special.h> 26 26 #include <dev_icu.h> 27 #include < chdev.h>27 #include <device.h> 28 28 #include <memcpy.h> 29 29 #include <printk.h> … … 35 35 ///////////////////////////////////////////////////////////////////////////////////////// 36 36 37 extern chdev_directory_t chdev_dir; // allocated in kernel_init.c37 extern devices_directory_t devices_dir; // allocated in kernel_init.c 38 38 39 extern chdev_pic_input_t chdev_pic_input; // allocated in kernel_init.c 39 extern devices_input_irq_t devices_input_irq; // allocated in kernel_init.c 40 41 40 42 41 43 /////////////////////////////////// 42 void dev_pic_init( chdev_t * chdev,43 uint32_t 44 void dev_pic_init( xptr_t dev_xp, 45 uint32_t irq_nr ) 44 46 { 45 // set PIC chdev extension field 46 chdev->ext.pic.irq_nr = irq_nr; 47 // get PIC device cluster and local pointer 48 cxy_t dev_cxy = GET_CXY( dev_xp ); 49 device_t * dev_ptr = (device_t *)GET_PTR( dev_xp ); 47 50 48 // get implementation49 uint32_t impl = chdev->impl;51 // set PIC device extension field 52 dev_ptr->ext.pic.irq_nr = irq_nr; 50 53 51 // call the relevant driver init function 54 // get implementation index from PIC device descriptor 55 uint32_t impl = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->impl ) ); 56 57 // set the "name" field in PIC device descriptor 58 // and call the relevant driver init function 52 59 if( impl == IMPL_PIC_SOC ) 53 60 { 54 soclib_pic_init( chdev ); 61 memcpy( dev_ptr->name , "PIC_TSR" , 16 ); 62 soclib_pic_init( dev_xp ); 55 63 } 56 64 else 57 65 { 58 assert( false , __FUNCTION__ , "illegal PIC device implementation" ); 66 printk("PANIC in %s: illegal PIC device implementation\n", __FUNCTION__ ); 67 hal_core_sleep(); 59 68 } 60 69 } // end dev_pic_init() … … 66 75 { 67 76 // get extended pointer on WTI mailbox 68 xptr_t wti_xp = XPTR( cxy , dev_icu_wti_ptr( wti_id ));77 xptr_t wti_xp = dev_icu_wti_xptr( cxy , wti_id ); 69 78 70 // get extended pointer on PIC chdevfrom directory71 xptr_t dev_xp = chdev_dir.pic;79 // get extended pointer on PIC device from directory 80 xptr_t dev_xp = devices_dir.pic; 72 81 73 // get PIC chdevcluster and local pointer74 cxy_t dev_cxy = GET_CXY( dev_xp );75 chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp );82 // get PIC device cluster and local pointer 83 cxy_t dev_cxy = GET_CXY( dev_xp ); 84 device_t * dev_ptr = (device_t *)GET_PTR( dev_xp ); 76 85 77 86 // get implementation index and segment base … … 83 92 soclib_pic_bind_irq( dev_xp , irq_id , wti_xp ); 84 93 } 94 else 95 { 96 printk("PANIC in %s: illegal PIC device implementation\n", __FUNCTION__ ); 97 hal_core_sleep(); 98 } 85 99 } // end dev_pic_link_wti() 86 100 … … 88 102 void dev_pic_unbind_irq( uint32_t irq_id ) 89 103 { 90 // get extended pointer on PIC chdevfrom directory91 xptr_t dev_xp = chdev_dir.pic;104 // get extended pointer on PIC device from directory 105 xptr_t dev_xp = devices_dir.pic; 92 106 93 // get PIC chdevcluster and local pointer94 cxy_t dev_cxy = GET_CXY( dev_xp );95 chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp );107 // get PIC device cluster and local pointer 108 cxy_t dev_cxy = GET_CXY( dev_xp ); 109 device_t * dev_ptr = (device_t *)GET_PTR( dev_xp ); 96 110 97 111 // get implementation index … … 103 117 soclib_pic_unbind_irq( dev_xp , irq_id ); 104 118 } 119 else 120 { 121 printk("PANIC in %s: illegal PIC device implementation\n", __FUNCTION__ ); 122 hal_core_sleep(); 123 } 124 105 125 } // end dev_pic_disable_irq() 106 126 -
/trunk/kernel/devices/dev_pic.h
r3 r1 39 39 * in the PIC device extension. 40 40 * The "source" device for each input IRQ is also defined in the ''arch_info'' file, 41 * and are stored in the '' chdev_input_irq'' global variable in kernel initialization.41 * and are stored in the ''devices_input_irq'' global variable in kernel initialization. 42 42 * 43 43 * This external peripheral does not execute I/O operations, but is just acting as a … … 48 48 ****************************************************************************************/ 49 49 50 /**** Forward declarations ****/51 52 struct chdev_s;53 54 50 /***************************************************************************************** 55 * This defines the (implementation independant) extension for the PICdevice.51 * This defines the (implementation independant) extension for the generic ICU device. 56 52 ****************************************************************************************/ 57 53 … … 76 72 /***************************************************************************************** 77 73 * This function makes two initialisations: 78 * - It initializes the PIC specific fields of the chdevdescriptor.74 * - It initializes the PIC specific fields of the device descriptor. 79 75 * - it initializes the implementation specific PIC hardware device. 80 76 * It must be executed once in the kernel initialisation phase. … … 83 79 * @ uint32_t : actual number of input IRQs. 84 80 ****************************************************************************************/ 85 void dev_pic_init( struct chdev_s * chdev,86 uint32_t 81 void dev_pic_init( xptr_t xp_dev, 82 uint32_t irq_nr ); 87 83 88 84 /***************************************************************************************** -
/trunk/kernel/devices/dev_txt.c
r3 r1 35 35 ///////////////////////////////////////////////////////////////////////////////////////// 36 36 37 extern chdev_directory_t chdev_dir; // allocated in kernel_init.c 38 39 extern chdev_pic_input_t chdev_pic_input; // allocated in kernel_init.c 40 41 //////////////////////////////////// 42 void dev_txt_init( chdev_t * chdev ) 43 { 44 // the local ICU chdev must be initialized before the TXT chdev, because 45 // the TXT chdev initialisation requires allocation of a WTI from local ICU 46 xptr_t icu_xp = chdev_dir.icu[local_cxy]; 47 assert( (icu_xp != XPTR_NULL) , __FUNCTION__ , "ICU not initialised before TXT" ); 48 49 // get implementation and channel index 50 uint32_t impl = chdev->impl; 51 uint32_t channel = chdev->channel; 52 53 // set fields "cmd", "isr", and call driver init function 37 extern devices_directory_t devices_dir; // allocated in kernel_init.c 38 39 extern devices_input_irq_t devices_input_irq; // allocated in kernel_init.c 40 41 ////////////////////////////////// 42 void dev_txt_init( xptr_t dev_xp ) 43 { 44 // get device descriptor cluster and local pointer 45 cxy_t dev_cxy = GET_CXY( dev_xp ); 46 device_t * dev_ptr = (device_t *)GET_PTR( dev_xp ); 47 48 // get implementation index from device descriptor 49 uint32_t impl = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->impl ) ); 50 51 // get channel index from device descriptor 52 // uint32_t channel = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->channel ) ); 53 54 // set fields "cmd", "isr", and "name" in device descriptor 55 // and call implementation specific init function 56 57 // TODO replace fixed "TXT_TTY" name by a channel indexed "TXT_TTY%d" name 58 // as soon as the sprintk() function is available 59 54 60 if( impl == IMPL_TXT_TTY ) 55 61 { 56 chdev->cmd = &soclib_tty_cmd; 57 chdev->isr = &soclib_tty_isr; 58 soclib_tty_init( chdev ); 62 hal_remote_spt( XPTR( dev_cxy , &dev_ptr->cmd ) , &soclib_tty_command ); 63 hal_remote_spt( XPTR( dev_cxy , &dev_ptr->isr ) , &soclib_tty_isr ); 64 // sprintk( name , "TXT_TTY%d" , channel ) 65 hal_remote_memcpy( XPTR( dev_cxy , &dev_ptr->name ), 66 XPTR( local_cxy , "TXT_TTY" ) , 16 ); 67 soclib_tty_init( dev_xp ); 59 68 } 60 69 else 61 70 { 62 assert( false , __FUNCTION__ , "undefined TXT device implementation" ); 63 } 64 65 // get a WTI mailbox from local ICU 66 uint32_t wti_id = dev_icu_wti_alloc(); 67 68 assert( (wti_id != -1) , __FUNCTION__ , "cannot allocate WTI mailbox" ); 69 70 // select a core 71 lid_t lid = cluster_select_local_core(); 72 73 // enable WTI IRQ and update WTI interrupt vector 74 dev_icu_enable_irq( lid , WTI_TYPE , wti_id , chdev ); 75 76 // link IOC IRQ to WTI mailbox in PIC component 77 uint32_t irq_id = chdev_pic_input.txt[channel]; 78 dev_pic_bind_irq( irq_id , local_cxy , wti_id ); 71 printk("\n[PANIC] in %s: undefined TXT device implementation\n", __FUNCTION__ ); 72 hal_core_sleep(); 73 } 79 74 80 75 // create server thread 81 thread_t * new_thread; 76 xptr_t new_thread_xp; 77 thread_t * new_thread_ptr; 82 78 error_t error; 83 79 84 error = thread_kernel_create( &new_thread, 85 THREAD_DEV, 86 &chdev_sequencial_server, 87 chdev, 88 lid ); 89 assert( (error == 0) , __FUNCTION__ , "cannot create server thread" ); 90 91 // set "server" field in chdev descriptor 92 chdev->server = new_thread; 80 if( dev_cxy == local_cxy ) // device cluster is local 81 { 82 error = thread_kernel_create( &new_thread_ptr, 83 THREAD_DEV, 84 &dev_txt_server, 85 dev_ptr, 86 cluster_select_local_core() ); 87 88 new_thread_xp = XPTR( local_cxy , new_thread_ptr ); 89 } 90 else // device cluster is remote 91 { 92 rpc_thread_kernel_create_client( dev_cxy, 93 THREAD_DEV, 94 &dev_txt_server, 95 dev_ptr, 96 &new_thread_xp, 97 &error ); 98 99 new_thread_ptr = (thread_t *)GET_PTR( new_thread_xp ); 100 } 101 if( error ) 102 { 103 printk("\n[PANIC] in %s : cannot create server thread\n", __FUNCTION__ ); 104 hal_core_sleep(); 105 } 106 107 // initialises server field in device descriptor 108 hal_remote_spt( XPTR( dev_cxy , &dev_ptr->server ) , new_thread_ptr ); 93 109 94 110 // start server thread 95 thread_unblock( XPTR( local_cxy , new_thread ), THREAD_BLOCKED_GLOBAL );111 thread_unblock( new_thread_xp , THREAD_BLOCKED_GLOBAL ); 96 112 97 113 } // end dev_txt_init() … … 99 115 100 116 ////////////////////////////////////////////////////////////////////////////////// 101 // This static function is called by dev_txt_read(), dev_txt_write() functions. 117 // This static function is called by dev_txt_read(), dev_txt_write(), and 118 // dev_txt_sync_write() functions. 119 // For the TXT_READ and TXT_WRITE operation types: 120 // - it build the command, and registers it in the calling thread descriptor. 121 // - then, it registers the calling thead in device waiting queue. 122 // - finally, it blocks on the THREAD_BLOCKED_DEV condition and deschedule. 123 // For the TXT_SYNC_WRITE operation type: 124 // - it directly call the relevant driver, using a busy waiting policy. 102 125 ////////////////////////////////////i///////////////////////////////////////////// 103 126 static error_t dev_txt_access( uint32_t type, … … 112 135 113 136 // check channel argument 114 assert( (channel < CONFIG_MAX_TXT_CHANNELS) , __FUNCTION__ , "illegal channel index" ); 115 116 // get extended pointer on remote TXT chdev descriptor 117 xptr_t dev_xp = chdev_dir.txt[channel]; 118 119 assert( (dev_xp != XPTR_NULL) , __FUNCTION__ , "undefined TXT chdev descriptor" ); 137 if( channel >= CONFIG_MAX_TXT_CHANNELS ) 138 { 139 printk("\n[PANIC] in %s : illegal channel index = %d\n", __FUNCTION__ , channel ); 140 hal_core_sleep(); 141 } 142 143 // get extended pointer on remote TXT device descriptor 144 xptr_t dev_xp = devices_dir.txt[channel]; 145 146 if ( dev_xp == XPTR_NULL ) 147 { 148 printk("\n[PANIC] in %s : undefined TXT device descriptor for channel %d\n", 149 __FUNCTION__ , channel ); 150 hal_core_sleep(); 151 } 120 152 121 153 // register command in calling thread descriptor 122 this->command.txt.dev_xp = dev_xp; 123 this->command.txt.type = type; 124 this->command.txt.buf_xp = XPTR( local_cxy , buffer ); 125 this->command.txt.count = count; 126 127 // register client thread in waiting queue, activate server thread 128 // block client thread on THREAD_BLOCKED_IO and deschedule. 129 // it is re-activated by the ISR signaling IO operation completion. 130 chdev_register_command( dev_xp , this ); 131 132 txt_dmsg("\n[INFO] in %s : thread %x in process %x completes / error = %d\n", 133 __FUNCTION__ , this->trdid , this->process->pid , this->command.txt.error ); 154 this->dev.txt.dev_xp = dev_xp; 155 this->dev.txt.type = type; 156 this->dev.txt.buf_xp = XPTR( local_cxy , buffer ); 157 this->dev.txt.count = count; 158 159 160 if( (type == TXT_READ) || (type == TXT_WRITE) ) // descheduling policy 161 { 162 // get a free WTI mailbox 163 uint32_t wti_id; 164 while( 1 ) 165 { 166 wti_id = dev_icu_wti_alloc(); 167 if( wti_id == -1 ) sched_yield(); 168 else break; 169 } 170 171 // enable WTI IRQ in local ICU and update WTI interrupt vector 172 dev_icu_enable_irq( local_cxy , CURRENT_CORE->lid , WTI_TYPE , wti_id , dev_xp ); 173 174 // link TXT IRQ to WTI mailbox in PIC component 175 uint32_t irq_id = devices_input_irq.txt[channel]; 176 dev_pic_bind_irq( irq_id , local_cxy , wti_id ); 177 178 // register client thread in waiting queue, activate server thread 179 // block client thread on THREAD_BLOCKED_IO and deschedule. 180 // it is re-activated by the ISR signaling IO operation completion. 181 device_register_command( dev_xp , this ); 182 183 // access PIC to unlink the IOC IRQ 184 dev_pic_unbind_irq( irq_id ); 185 186 // disable WTI IRQ in ICU and update interrupt vector 187 dev_icu_disable_irq( local_cxy , CURRENT_CORE->lid , WTI_TYPE , wti_id ); 188 189 // release WTI mailbox 190 dev_icu_wti_release( wti_id ); 191 192 txt_dmsg("\n[INFO] in %s : thread %x in process %x completes / error = %d\n", 193 __FUNCTION__ , this->trdid , this->process->pid , this->dev.txt.error ); 194 } 195 else if( type == TXT_SYNC_WRITE ) // busy waiting policy 196 { 197 // get driver command function pointer from remote TXT device descriptor 198 cxy_t dev_cxy = GET_CXY( dev_xp ); 199 device_t * dev_ptr = (device_t *)GET_PTR( dev_xp ); 200 dev_cmd_t * cmd = (dev_cmd_t *)hal_remote_lpt( XPTR( dev_cxy , &dev_ptr->cmd ) ); 201 202 // take the TXT device lock, because the calling thread does NOT 203 // register in device waiting queue for this synchronous command, 204 // and has exclusive access to the terminal... 205 remote_spinlock_lock( XPTR( dev_cxy , &dev_ptr->wait_lock ) ); 206 207 // call directly driver command 208 cmd( XPTR( local_cxy , this ) ); 209 210 // release the TXT device lock 211 remote_spinlock_unlock( XPTR( dev_cxy , &dev_ptr->wait_lock ) ); 212 } 134 213 135 214 // return I/O operation status from calling thread descriptor 136 return this-> command.txt.error;215 return this->dev.txt.error; 137 216 138 217 } // end dev_txt_access() … … 146 225 } 147 226 148 /////////////////////////////////////////149 error_t dev_txt_read( uint32_t channel,150 char * buffer )151 {152 return dev_txt_access( TXT_READ , channel , buffer , 1 );153 }154 155 227 /////////////////////////////////////////////// 156 228 error_t dev_txt_sync_write( uint32_t channel, … … 158 230 uint32_t count ) 159 231 { 160 // get pointer on calling thread 161 thread_t * this = CURRENT_THREAD; 162 163 // get extended pointer on TXT[0] chdev 164 xptr_t dev_xp = chdev_dir.txt[channel]; 165 166 // register command in calling thread 167 this->command.txt.dev_xp = dev_xp; 168 this->command.txt.type = TXT_SYNC_WRITE; 169 this->command.txt.buf_xp = XPTR( local_cxy , buffer ); 170 this->command.txt.count = count; 171 172 // get driver command function 173 cxy_t dev_cxy = GET_CXY( dev_xp ); 174 chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp ); 175 dev_cmd_t * cmd = (dev_cmd_t *)hal_remote_lpt( XPTR( dev_cxy , &dev_ptr->cmd ) ); 176 177 // call directly driver command after taking chdev lock 178 remote_spinlock_lock( XPTR( dev_cxy , &dev_ptr->wait_lock ) ); 179 cmd( XPTR( local_cxy , this ) ); 180 remote_spinlock_unlock( XPTR( dev_cxy , &dev_ptr->wait_lock ) ); 181 182 // return I/O operation status from calling thread descriptor 183 return this->command.txt.error; 184 185 } // end dev_txt_sync_write() 186 232 return dev_txt_access( TXT_SYNC_WRITE , channel , buffer , count ); 233 } 234 235 ///////////////////////////////////////// 236 error_t dev_txt_read( uint32_t channel, 237 char * buffer ) 238 { 239 return dev_txt_access( TXT_READ , channel , buffer , 1 ); 240 } 241 242 ///////////////////////////////////// 243 void dev_txt_server( device_t * dev ) 244 { 245 xptr_t client_xp; // extended pointer on waiting thread 246 cxy_t client_cxy; // cluster of client thread 247 thread_t * client_ptr; // local pointer on client thread 248 thread_t * server; // local pointer on server thread 249 xptr_t root_xp; // extended pointer on device waiting queue root 250 251 server = CURRENT_THREAD; 252 253 root_xp = XPTR( local_cxy , &dev->wait_root ); 254 255 // infinite loop handling commands of threads 256 // registered in the TXT waiting queue 257 while( 1 ) 258 { 259 // get lock protecting queue 260 remote_spinlock_lock( XPTR( local_cxy , &dev->wait_lock ) ); 261 262 // block and deschedule server thread if waiting queue empty 263 if( xlist_is_empty( root_xp ) ) 264 { 265 thread_block( server , THREAD_BLOCKED_DEV_QUEUE ); 266 remote_spinlock_unlock( XPTR( local_cxy , &dev->wait_lock ) ); 267 sched_yield(); 268 } 269 else 270 { 271 remote_spinlock_unlock( XPTR( local_cxy , &dev->wait_lock ) ); 272 } 273 274 // get extended pointer on first client thread 275 client_xp = XLIST_FIRST_ELEMENT( root_xp , thread_t , wait_list ); 276 277 // call driver command function to start I/O operation 278 dev->cmd( client_xp ); 279 280 // get client thread cluster and local pointer 281 client_cxy = GET_CXY( client_xp ); 282 client_ptr = (thread_t *)GET_PTR( client_xp ); 283 284 // remove the client thread from waiting queue 285 remote_spinlock_lock( XPTR( local_cxy , &dev->wait_lock ) ); 286 xlist_unlink( XPTR( client_cxy , &client_ptr->wait_list ) ); 287 remote_spinlock_unlock( XPTR( local_cxy , &dev->wait_lock ) ); 288 289 } // end while 290 291 } // end dev_txt_server() 292 -
/trunk/kernel/devices/dev_txt.h
r3 r1 30 30 /**** Forward declarations ****/ 31 31 32 struct chdev_s ;32 struct device_s ; 33 33 34 34 /****************************************************************************************** … … 79 79 80 80 /****************************************************************************************** 81 * This function completes the TXT chdevdescriptor initialisation,81 * This function completes the TXT device descriptor initialisation, 82 82 * namely the link with the implementation specific driver. 83 * The func, impl, channel, is_rxt, base fields have beenpreviously initialised.83 * The func, impl, channel, is_rxt, base, and size fields must be previously initialised. 84 84 * It calls the specific driver initialisation function, to initialise the hardware 85 85 * device and the driver specific data structures when required. 86 * It creates the associated server thread and allocates a WTI from local ICU. 87 * It must de executed by a local thread. 86 * It creates the associated server thread. 87 * It can be executed in another cluster than cluster containing the device descriptor 88 * or the hardware device itself. 88 89 ****************************************************************************************** 89 * @ chdev : localpointer on TXT device descriptor.90 * @ xp_dev : extended pointer on TXT device descriptor. 90 91 *****************************************************************************************/ 91 void dev_txt_init( struct chdev_s * chdev );92 void dev_txt_init( xptr_t xp_dev ); 92 93 93 94 /****************************************************************************************** 94 95 * This blocking function read a single character from the terminal identified 95 96 * by the "channel" argument. The corresponding request is actually registered in the 96 * chdevrequests queue, and the calling thread is descheduled, blocked until97 * device pending requests queue, and the calling thread is descheduled, blocked until 97 98 * transfer completion. 98 99 * It must be called in the client cluster. … … 108 109 * This blocking function writes a character string on the terminal identified 109 110 * by the "channel" argument. The corresponding request is actually registered in the 110 * chdevrequests queue, and the calling thread is descheduled, blocked until111 * device pending requests queue, and the calling thread is descheduled, blocked until 111 112 * transfer completion. 112 113 * It must be called in the client cluster. … … 122 123 123 124 /*************************************************************************************** 124 * This low-level blocking function is used by the kernel to display one stringon a125 * This low-level blocking function is used by the kernel to display one character on a 125 126 * given TXT channel without descheduling the calling thread, without registering it 126 127 * in the TXT device waiting queue, and without using the TXT irq. … … 135 136 uint32_t count ); 136 137 138 /****************************************************************************************** 139 * This function is executed by the server thread associated to the TXT device descriptor. 140 * This thread is created and lauched by the dev_txt_init() function, and is used 141 * by the TXT_READ and TXT_WRITE operation types. It executes an infinite loop to handle 142 * sequencially all commands registered by the client threads in the device waiting queue. 143 * 144 * The driver CMD function is blocking, and returns only when the command is completed. 145 * can use a busy waiting policy, or block the server thread on the THREAD_BLOCKED_IO_ISR 146 * condition and deschedule, using the ISR to reactivate the server thread. 147 * 148 * When the waiting queue is empty, the server thread blocks on the THREAD_BLOCKED_IO_CMD 149 * condition and deschedule. It is re-activated by a client thread registering a command. 150 ****************************************************************************************** 151 * @ dev : local pointer on device descriptor. 152 *****************************************************************************************/ 153 void dev_txt_server( struct device_s * dev ); 154 137 155 138 156 #endif /* _DEV_TXT_H_ */
Note: See TracChangeset
for help on using the changeset viewer.