Changeset 3 for trunk/kernel/devices
- Timestamp:
- Apr 26, 2017, 2:08:13 PM (8 years ago)
- Location:
- trunk/kernel/devices
- Files:
-
- 4 added
- 12 edited
- 2 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/devices/dev_icu.c
r1 r3 24 24 #include <hal_types.h> 25 25 #include <hal_special.h> 26 #include < device.h>26 #include <chdev.h> 27 27 #include <thread.h> 28 28 #include <cluster.h> … … 37 37 ///////////////////////////////////////////////////////////////////////////////////////// 38 38 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 ); 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 ); 67 55 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 56 // get implementation 57 uint32_t impl = icu->impl; 58 59 // call the relevant driver init function 73 60 if( impl == IMPL_ICU_XCU ) 74 61 { 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++ ) 62 uint32_t lid; 63 for( lid = 0 ; lid < LOCAL_CLUSTER->cores_nr ; lid++ ) 80 64 { 81 soclib_xcu_init( dev_ptr, lid );65 soclib_xcu_init( icu , lid ); 82 66 } 83 67 } 84 68 else 85 69 { 86 printk("\n[PANIC] %s : undefined ICU implementation for cluste %x\n", 87 __FUNCTION__ , local_cxy ); 88 hal_core_sleep(); 70 assert( false , __FUNCTION__ , "undefined ICU implementation" ); 89 71 } 90 72 } // end dev_icu_init() 91 73 92 74 ///////////////////////////////////////////////////////////////////////////////////// 93 // This static function check the irq_type / irq_index arguments for a remote ICU.75 // This static function check the irq_type / irq_index arguments. 94 76 // It is called by the dev_icu_enable_irq() & dev_icu_disable_irq() functions. 95 // returns 0 if OK / returns non zero if invalid arguments96 77 ///////////////////////////////////////////////////////////////////////////////////// 97 static inline void dev_icu_check_irq( xptr_t icu_xp,78 static inline void dev_icu_check_irq( chdev_t * icu, 98 79 uint32_t irq_type, 99 80 uint32_t irq_index ) 100 81 { 101 // get cluster and local pointer on remote ICU102 cxy_t icu_cxy = GET_CXY( icu_xp );103 device_t * icu_ptr = (device_t *)GET_PTR( icu_xp );104 105 82 if( irq_type == HWI_TYPE ) 106 83 { 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 } 84 assert( (irq_index < icu->ext.icu.hwi_nr) , __FUNCTION__ , "illegal HWI" ); 113 85 } 114 86 if( irq_type == WTI_TYPE ) 115 87 { 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 } 88 assert( (irq_index < icu->ext.icu.wti_nr) , __FUNCTION__ , "illegal WTI" ); 122 89 } 123 90 if( irq_type == PTI_TYPE ) 124 91 { 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, 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, 137 98 uint32_t irq_type, 138 99 uint32_t irq_index, 139 xptr_t src_dev_xp)140 { 141 // get extended pointer & local pointer on remote ICU device142 xptr_t icu_xp = devices_dir.icu[icu_cxy];143 device_t * icu_ptr = (device_t *)GET_PTR( icu_xp );100 chdev_t * src_chdev ) 101 { 102 // get local pointer on local ICU chdev 103 xptr_t icu_xp = chdev_dir.icu[local_cxy]; 104 chdev_t * icu = (chdev_t *)GET_PTR( icu_xp ); 144 105 145 106 // check IRQ type and index 146 dev_icu_check_irq( icu _xp, irq_type , irq_index );107 dev_icu_check_irq( icu , irq_type , irq_index ); 147 108 148 109 // (1) call implementation specific ICU driver to enable IRQ 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 ); 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; 174 123 175 124 } // end dev_icu_enable_irq() 176 125 177 ///////////////////////////////////////////// 178 void dev_icu_disable_irq( cxy_t icu_cxy, 179 lid_t lid, 126 ///////////////////////////////////////// 127 void dev_icu_disable_irq( lid_t lid, 180 128 uint32_t irq_type, 181 129 uint32_t irq_index ) 182 130 { 183 // get extended pointer & local pointer on remote ICU device184 xptr_t icu_xp = devices_dir.icu[icu_cxy];185 device_t * icu_ptr = (device_t *)GET_PTR( icu_xp );131 // get local pointer on local ICU chdev 132 xptr_t icu_xp = chdev_dir.icu[local_cxy]; 133 chdev_t * icu = (chdev_t *)GET_PTR( icu_xp ); 186 134 187 135 // check IRQ type and index 188 dev_icu_check_irq( icu _xp, irq_type , irq_index );136 dev_icu_check_irq( icu , irq_type , irq_index ); 189 137 190 138 // (1) call the implementation specific ICU driver to disable IRQ 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(); 139 if( icu->impl == IMPL_ICU_XCU ) 140 { 141 soclib_xcu_disable_irq( icu , 1<<irq_index , irq_type , lid ); 199 142 } 200 143 201 144 // (2) get selected remote core local pointer, and remove 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 ); 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 ); 207 149 208 150 } // end dev_icu_disable_irq() … … 212 154 uint32_t period ) 213 155 { 214 // get pointer on local ICU device descriptor215 core_t * core = CURRENT_CORE;216 device_t * icu = core->icu;156 // get local pointer on local ICU chdev 157 xptr_t icu_xp = chdev_dir.icu[local_cxy]; 158 chdev_t * icu = (chdev_t *)GET_PTR( icu_xp ); 217 159 218 160 // check 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 } 161 assert( (pti_index < icu->ext.icu.pti_nr) , __FUNCTION__ , "illegal PTI index" ); 224 162 225 163 // call the implementation specific driver ICU to set period … … 233 171 void dev_icu_ack_timer( uint32_t pti_index ) 234 172 { 235 // get pointer on local ICU device descriptor236 core_t * core = CURRENT_CORE;237 device_t * icu = core->icu;173 // get local pointer on local ICU chdev 174 xptr_t icu_xp = chdev_dir.icu[local_cxy]; 175 chdev_t * icu = (chdev_t *)GET_PTR( icu_xp ); 238 176 239 177 // check 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 } 178 assert( (pti_index < icu->ext.icu.pti_nr) , __FUNCTION__ , "illegal PTI index" ); 245 179 246 180 // call the implementation specific driver ICU to acknowledge PTI IRQ … … 249 183 soclib_xcu_ack_timer( icu , pti_index ); 250 184 } 251 else252 {253 printk("\n[PANIC] in %s : undefined ICU implementation" , __FUNCTION__ );254 hal_core_sleep();255 }256 257 185 } // end dev_icu_ack_timer() 258 186 … … 270 198 uint32_t y = cxy & ((1<<y_width)-1); 271 199 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]; 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]; 283 206 284 207 // get target ICU cluster and local pointer 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 device289 uint32_t impl = hal_remote_lw( XPTR( cxy_icu , &ptr_icu->impl ) );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 chdev 212 uint32_t impl = hal_remote_lw( XPTR( icu_cxy , &icu_ptr->impl ) ); 290 213 291 214 // call the implementation specific ICU driver to send IPI … … 293 216 { 294 217 soclib_xcu_send_ipi( icu_xp , lid ); 295 }296 else297 {298 printk("\n[PANIC] in %s : undefined ICU implementation" , __FUNCTION__ );299 hal_core_sleep();300 218 } 301 219 } // end dev_icu_send_ipi() … … 307 225 uint32_t wti_status; // WTI index + 1 / no pending WTI if 0 308 226 uint32_t pti_status; // PTI index + 1 / no pending PTI if 0 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 227 chdev_t * src_chdev; // pointer on source chdev descriptor 312 228 uint32_t index; // IRQ index 313 229 314 // get pointer on local ICU device descriptor315 230 core_t * core = CURRENT_CORE; 316 device_t * icu = core->icu; 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 ); 317 235 318 236 // call the implementation specific ICU driver … … 322 240 soclib_xcu_get_status( icu , core->lid , &hwi_status , &wti_status , &pti_status ); 323 241 } 324 else325 {326 printk("\n[PANIC] in %s : undefined ICU implementation" , __FUNCTION__ );327 hal_core_sleep();328 }329 242 330 243 // analyse ICU status and handle up to 3 pending IRQ (one WTI, one HWI, one PTI) 331 244 332 if( wti_status ) // pending WTI TODO what about IPIs ??? [AG]245 if( wti_status ) // pending WTI 333 246 { 334 247 index = wti_status - 1; 335 248 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 249 if( index < LOCAL_CLUSTER->cores_nr ) // it is an IPI 349 250 { 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(); 251 assert( (index == core->lid) , __FUNCTION__ , "illegal IPI index" ); 252 253 // TODO acknowledge WTI [AG] 254 255 // TODO force scheduling [AG] 353 256 } 354 else // call relevant ISR257 else // it is an external device 355 258 { 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 ); 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 } 360 277 } 361 278 } … … 365 282 index = hwi_status - 1; 366 283 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 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 373 288 { 374 289 printk("\n[WARNING] in %s : no handler for HWI %d on core %d in cluster %x\n", 375 290 __FUNCTION__ , index , core->lid , local_cxy ); 376 291 core->spurious_irqs ++; 377 dev_icu_disable_irq( local_cxy ,core->lid , HWI_TYPE , index );292 dev_icu_disable_irq( core->lid , HWI_TYPE , index ); 378 293 } 379 else if( src_dev_cxy != local_cxy ) // HWI must be handled in device cluster380 {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 }385 294 else // call relevant ISR 386 295 { … … 388 297 __FUNCTION__ , index , core->lid , local_cxy ); 389 298 390 src_dev_ptr->isr( src_dev_ptr ); 299 // call ISR 300 src_chdev->isr( src_chdev ); 391 301 } 392 302 } … … 402 312 dev_icu_ack_timer( index ); 403 313 404 // execute all actions related to TICK event314 // TODO execute all actions related to TICK event 405 315 core_clock( core ); 406 316 } … … 410 320 uint32_t dev_icu_wti_alloc() 411 321 { 412 // get pointer on local ICU device descriptor413 core_t * core = CURRENT_CORE;414 device_t * icu = core->icu;415 416 // get bitmap pointer, lock , and size417 bitmap_t * bitmap = &icu->ext.icu.wti_bitmap;322 // get local pointer on local ICU chdev 323 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 size 327 uint32_t * bitmap = &icu->ext.icu.wti_bitmap; 418 328 spinlock_t * lock = &icu->ext.icu.wti_lock; 419 329 uint32_t size = icu->ext.icu.wti_nr; … … 437 347 void dev_icu_wti_release( uint32_t index ) 438 348 { 439 // get pointer on local ICU devicedescriptor440 core_t * core = CURRENT_CORE;441 device_t * icu = core->icu;349 // get pointer on local ICU chdev descriptor 350 xptr_t icu_xp = chdev_dir.icu[local_cxy]; 351 chdev_t * icu_ptr = (chdev_t *)GET_PTR( icu_xp ); 442 352 443 353 // get bitmap pointer, lock, and size 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;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; 447 357 448 358 // check 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 } 359 assert( (index < size) , __FUNCTION__ , "illegal WTI index" ); 455 360 456 361 // get lock protecting WTI allocator … … 462 367 // release lock 463 368 spinlock_unlock( lock ); 369 464 370 } // end dev_icu_wti_release() 465 371 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; 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 ); 475 380 476 381 // call implementation specific ICU driver 477 382 if( icu->impl == IMPL_ICU_XCU ) 478 383 { 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 384 wti_ptr = soclib_xcu_wti_ptr( icu , wti_id ); 385 } 386 387 return wti_ptr; 490 388 } // end dev_icu_wti_xptr() 491 389 -
trunk/kernel/devices/dev_icu.h
r1 r3 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 should berouted to the core that started the I/O operation.37 * operation. Each IRQ is 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 , centralized ordistributed41 * This component can be implemented as a dedicated hardware component 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 iby this ICU device:46 * ALMOS-MKH defines three types of IRQs, that are handled by 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 n extended pointer on the devicedescriptor that is the "source" of the interrupt.75 * This devicedescriptor contains a link to the ISR to be executed.74 * a pointer on the chdev descriptor that is the "source" of the interrupt. 75 * This chdev 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 another I/O operation.79 * Therefore, ALMOS-MKH does not use the iCU device waiting queue, but calls directly78 * dynamically configurable interrupt router for other I/O operations. 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 device_s;86 struct chdev_s; 87 87 88 88 /***************************************************************************************** … … 127 127 /***************************************************************************************** 128 128 * This function makes two initialisations: 129 * - It initialises the ICU specific fields of the devicedescriptor.129 * - It initialises the ICU specific fields of the chdev descriptor. 130 130 * - it initialises the implementation specific ICU hardware device and associated 131 131 * data structures if required. 132 * It must be executed once in the cluster containing the ICU device descriptor.133 ***************************************************************************************** 134 * @ icu _xp : extended pointer on ICU devicedescriptor.135 * @ hwi_nr 136 * @ wti_nr 137 * @ pti_nr 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 remotecluster.146 * This IRQ is identified by its type (HWI/WTI/PTI) and index in the remoteICU.132 * It must be called by a local thread. 133 ***************************************************************************************** 134 * @ icu : pointer on ICU chdev 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( struct chdev_s * icu, 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 the local cluster. 146 * This IRQ is identified by its type (HWI/WTI/PTI) and index in the local ICU. 147 147 * The target core is identified by its local index. 148 * As it uses remote accesses, it can be executed by any thread in any cluster.149 * - It unmask the selected IRQ in the remoteICU.150 * - It registers the extended pointer on the "source" devicedescriptor in the148 * 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" chdev descriptor in the 151 151 * relevant interrupt vector of the 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. 152 * - It register the IRQ type and index in the "source" chdev descriptor. 153 ***************************************************************************************** 154 * @ lid : local index of selected core. 156 155 * @ irq_type : HWI/WTI/PTI. 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. 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. 169 167 * The core is identified by its local index. 170 * As it uses remote accesses, it can be executed by any thread in any cluster.171 * - It mask the selected IRQ in the remoteICU.172 * - It removes the extended pointer on the "source" devicedescriptor from the168 * 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" chdev descriptor from the 173 171 * relevant interrupt vector of the selected core. 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). 172 * - The IRQ type and index fields are not modified in the "source" chdev descriptor. 173 ***************************************************************************************** 177 174 * @ lid : local index of selected core in remote cluster. 178 175 * @ irq_type : HWI/WTI/PTI. 179 176 * @ irq_id : IRQ index. 180 177 ****************************************************************************************/ 181 void dev_icu_disable_irq( cxy_t cxy, 182 lid_t lid, 178 void dev_icu_disable_irq( lid_t lid, 183 179 uint32_t irq_type, 184 180 uint32_t irq_id ); … … 187 183 * This function set the period value for a timer identified by the PTI index, 188 184 * in the local ICU device descriptor. 185 * It must be called by a local thread. 189 186 ***************************************************************************************** 190 187 * @ pti_id : PTI index. … … 197 194 * This function acknowledge a PTI IRQ for a timer identified by the PTI index, 198 195 * in the local ICU device descriptor. 196 * It must be called by a local thread. 199 197 ***************************************************************************************** 200 198 * @ pti_id : PTI index. … … 204 202 /***************************************************************************************** 205 203 * This function send an IPI (Inter Processor Interrupt) to a core identified by 206 * its cluster identifier and local index. 204 * its cluster identifier and local index. 205 * It can be called by any thread running in any cluster. 207 206 * This IPI force a context switch, and the handling of pending RPC(s). 208 207 ***************************************************************************************** … … 226 225 227 226 /***************************************************************************************** 228 * This function implements the WTI mailbox allocator. It is used by all I/O operations 229 * for completion signaling. 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. 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. 242 243 * It does not access the hardware device. 243 244 ***************************************************************************************** … … 247 248 248 249 /***************************************************************************************** 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 ); 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 ); 259 257 260 258 #endif /* _DEV_ICU_H_ */ -
trunk/kernel/devices/dev_iob.c
r1 r3 1 1 /* 2 * dev_io x.c - IOX(bridge to external I/O) generic device API implementation.2 * dev_iob.c - IOB (bridge to external I/O) generic device API implementation. 3 3 * 4 4 * Authors Alain Greiner (2017) … … 14 14 * ALMOS-MKH is distributed in the hope that it will be useful, but 15 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTIO XLAR PURPOSE. See the GNU16 * MERCHANTABILITY or FITNESS FOR A PARTIOBLAR PURPOSE. See the GNU 17 17 * General Public License for more details. 18 18 * … … 26 26 #include <hal_special.h> 27 27 #include <remote_spinlock.h> 28 #include < device.h>28 #include <chdev.h> 29 29 #include <printk.h> 30 30 #include <soclib_iob.h> 31 #include <dev_io x.h>31 #include <dev_iob.h> 32 32 33 ////////////////////////////////// 34 void dev_io x_init( xptr_t dev_xp)33 //////////////////////////////////// 34 void dev_iob_init( chdev_t * chdev ) 35 35 { 36 // get IOX device descriptor cluster and local pointer 37 cxy_t dev_cxy = GET_CXY( dev_xp ); 38 device_t * dev_ptr = (device_t *)GET_PTR( dev_xp ); 39 40 // get implementation from device descriptor 41 uint32_t impl = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->impl ) ); 36 // get implementation 37 uint32_t impl = chdev->impl; 42 38 43 39 // call driver init function 44 if( impl == IMPL_IO X_IOB)40 if( impl == IMPL_IOB_TSR ) 45 41 { 46 soclib_iob_init( dev_xp);42 soclib_iob_init( chdev ); 47 43 } 48 44 else 49 45 { 50 printk("\n[PANIC] in %s: undefined IOX device implementation\n", __FUNCTION__ ); 51 hal_core_sleep(); 46 assert( false , __FUNCTION__ , "undefined IOB device implementation\n" ); 52 47 } 53 48 } 54 49 55 50 ////////////////////////////////////////// 56 void dev_io x_iommu_enable( xptr_t dev_xp )51 void dev_iob_iommu_enable( xptr_t dev_xp ) 57 52 { 58 // get IO X devicedescriptor cluster and local pointer59 cxy_t 60 device_t * dev_ptr = (device_t *)GET_PTR( dev_xp );53 // get IOB chdev descriptor cluster and local pointer 54 cxy_t dev_cxy = GET_CXY( dev_xp ); 55 chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp ); 61 56 62 // get implementation from devicedescriptor57 // get implementation from chdev descriptor 63 58 uint32_t impl = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->impl ) ); 64 59 65 60 // call driver function 66 if( impl == IMPL_IO X_IOB)61 if( impl == IMPL_IOB_TSR ) 67 62 { 68 63 remote_spinlock_lock( XPTR( dev_cxy , &dev_ptr->wait_lock ) ); … … 72 67 else 73 68 { 74 printk("\n[PANIC] in %s: undefined IO Xdevice implementation\n", __FUNCTION__ );69 printk("\n[PANIC] in %s: undefined IOB device implementation\n", __FUNCTION__ ); 75 70 hal_core_sleep(); 76 71 } … … 78 73 79 74 /////////////////////////////////////////// 80 void dev_io x_iommu_disable( xptr_t dev_xp )75 void dev_iob_iommu_disable( xptr_t dev_xp ) 81 76 { 82 // get IO X devicedescriptor cluster and local pointer83 cxy_t 84 device_t * dev_ptr = (device_t *)GET_PTR( dev_xp );77 // get IOB chdev descriptor cluster and local pointer 78 cxy_t dev_cxy = GET_CXY( dev_xp ); 79 chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp ); 85 80 86 // get implementation from devicedescriptor81 // get implementation from chdev descriptor 87 82 uint32_t impl = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->impl ) ); 88 83 89 84 // call driver function 90 if( impl == IMPL_IO X_IOB)85 if( impl == IMPL_IOB_TSR ) 91 86 { 92 87 remote_spinlock_lock( XPTR( dev_cxy , &dev_ptr->wait_lock ) ); … … 96 91 else 97 92 { 98 printk("\n[PANIC] in %s: undefined IO Xdevice implementation\n", __FUNCTION__ );93 printk("\n[PANIC] in %s: undefined IOB device implementation\n", __FUNCTION__ ); 99 94 hal_core_sleep(); 100 95 } … … 102 97 103 98 //////////////////////////////////////// 104 void dev_io x_set_ptpr( xptr_t dev_xp,99 void dev_iob_set_ptpr( xptr_t dev_xp, 105 100 uint32_t wdata ) 106 101 { 107 // get IO X devicedescriptor cluster and local pointer108 cxy_t 109 device_t * dev_ptr = (device_t *)GET_PTR( dev_xp );102 // get IOB chdev descriptor cluster and local pointer 103 cxy_t dev_cxy = GET_CXY( dev_xp ); 104 chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp ); 110 105 111 // get implementation from devicedescriptor106 // get implementation from chdev descriptor 112 107 uint32_t impl = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->impl ) ); 113 108 114 109 // call driver function 115 if( impl == IMPL_IO X_IOB)110 if( impl == IMPL_IOB_TSR ) 116 111 { 117 112 remote_spinlock_lock( XPTR( dev_cxy , &dev_ptr->wait_lock ) ); … … 121 116 else 122 117 { 123 printk("\n[PANIC] in %s: undefined IO Xdevice implementation\n", __FUNCTION__ );118 printk("\n[PANIC] in %s: undefined IOB device implementation\n", __FUNCTION__ ); 124 119 hal_core_sleep(); 125 120 } … … 127 122 128 123 //////////////////////////////////////// 129 void dev_io x_inval_page( xptr_t dev_xp,124 void dev_iob_inval_page( xptr_t dev_xp, 130 125 vpn_t vpn ) 131 126 { 132 // get IO X devicedescriptor cluster and local pointer133 cxy_t 134 device_t * dev_ptr = (device_t *)GET_PTR( dev_xp );127 // get IOB chdev descriptor cluster and local pointer 128 cxy_t dev_cxy = GET_CXY( dev_xp ); 129 chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp ); 135 130 136 // get implementation from devicedescriptor131 // get implementation from chdev descriptor 137 132 uint32_t impl = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->impl ) ); 138 133 139 134 // call driver function 140 if( impl == IMPL_IO X_IOB)135 if( impl == IMPL_IOB_TSR ) 141 136 { 142 137 remote_spinlock_lock( XPTR( dev_cxy , &dev_ptr->wait_lock ) ); … … 146 141 else 147 142 { 148 printk("\n[PANIC] in %s: undefined IO Xdevice implementation\n", __FUNCTION__ );143 printk("\n[PANIC] in %s: undefined IOB device implementation\n", __FUNCTION__ ); 149 144 hal_core_sleep(); 150 145 } … … 152 147 153 148 /////////////////////////////////////////// 154 void dev_io x_get_status( xptr_t dev_xp,149 void dev_iob_get_status( xptr_t dev_xp, 155 150 uint32_t * error, 156 151 uint32_t * bvar, 157 152 uint32_t * srcid ) 158 153 { 159 // get IO X devicedescriptor cluster and local pointer160 cxy_t 161 device_t * dev_ptr = (device_t *)GET_PTR( dev_xp );154 // get IOB chdev descriptor cluster and local pointer 155 cxy_t dev_cxy = GET_CXY( dev_xp ); 156 chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp ); 162 157 163 // get implementation from devicedescriptor158 // get implementation from chdev descriptor 164 159 uint32_t impl = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->impl ) ); 165 160 166 161 // call driver function 167 if( impl == IMPL_IO X_IOB)162 if( impl == IMPL_IOB_TSR ) 168 163 { 169 164 remote_spinlock_lock( XPTR( dev_cxy , &dev_ptr->wait_lock ) ); … … 175 170 else 176 171 { 177 printk("\n[PANIC] in %s: undefined IO Xdevice implementation\n", __FUNCTION__ );172 printk("\n[PANIC] in %s: undefined IOB device implementation\n", __FUNCTION__ ); 178 173 hal_core_sleep(); 179 174 } -
trunk/kernel/devices/dev_iob.h
r1 r3 1 1 /* 2 * dev_io x.h - IOX(bridge to external I/O) generic device API.2 * dev_iob.h - IOB (bridge to external I/O) generic device API. 3 3 * 4 4 * Authors Alain Greiner (2016) … … 14 14 * ALMOS-MKH is distributed in the hope that it will be useful, but 15 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTIO XLAR PURPOSE. See the GNU16 * MERCHANTABILITY or FITNESS FOR A PARTIOBLAR PURPOSE. See the GNU 17 17 * General Public License for more details. 18 18 * … … 22 22 */ 23 23 24 #ifndef _DEV_IO X_H_25 #define _DEV_IO X_H_24 #ifndef _DEV_IOB_H_ 25 #define _DEV_IOB_H_ 26 26 27 27 #include <almos_config.h> … … 30 30 31 31 /***************************************************************************************** 32 * Generic IO X(bridge to external IO peripherals) definition.32 * Generic IOB (bridge to external IO peripherals) definition. 33 33 * 34 * The IO Xdevice is used to access external peripherals. It implements an IO-MMU service34 * The IOB device is used to access external peripherals. It implements an IO-MMU service 35 35 * for DMA transactions launched by DMA capable external peripherals. 36 * This IO Xperipheral is acting as a dynamically configurable bridge, used for others37 * I/O operations. Therefore, ALMOS-MKH does not use the IO Xdevice waiting queue,38 * and calls directly the IO Xdriver blocking functions, using the device lock to39 * get exclusive access to the IO Xbridge internal state.36 * This IOB peripheral is acting as a dynamically configurable bridge, used for others 37 * I/O operations. Therefore, ALMOS-MKH does not use the IOB device waiting queue, 38 * and calls directly the IOB driver blocking functions, using the device lock to 39 * get exclusive access to the IOB bridge internal state. 40 40 ****************************************************************************************/ 41 41 42 /**** Forward declarations ****/ 43 44 struct chdev_s; 42 45 43 46 /***************************************************************************************** 44 * This enum defines the various implementations of the IO Xgeneric device.47 * This enum defines the various implementations of the IOB generic device. 45 48 * This array must be kept consistent with the define in arch_info.h file 46 49 ****************************************************************************************/ 47 50 48 enum io x_impl_e51 enum iob_impl_e 49 52 { 50 IMPL_IO X_IOB= 0, /* vci_iob component used in TSAR */51 IMPL_IO X_I86 = 1, /* TBD */53 IMPL_IOB_TSR = 0, /* vci_iob component used in TSAR */ 54 IMPL_IOB_I86 = 1, /* TBD */ 52 55 } 53 io x_impl_t;56 iob_impl_t; 54 57 55 58 /***************************************************************************************** 56 * This function initializes the IO Xdevice descriptor with IOMMU disabled.59 * This function initializes the IOB device descriptor with IOMMU disabled. 57 60 ***************************************************************************************** 58 * @ dev_xp : extended pointer on IOX devicedescriptor.61 * @ chdev : pointer on IOB chdev descriptor. 59 62 ****************************************************************************************/ 60 void dev_io x_init( xptr_t dev_xp);63 void dev_iob_init( struct chdev_s * chdev ); 61 64 62 65 /***************************************************************************************** 63 * This function activates the IOMMU for the IO Xdevice identified by its66 * This function activates the IOMMU for the IOB device identified by its 64 67 * extended pointer. 65 68 ***************************************************************************************** 66 * @ dev_xp : extended pointer on IO Xdevice descriptor.69 * @ dev_xp : extended pointer on IOB device descriptor. 67 70 ****************************************************************************************/ 68 void dev_io x_iommu_enable( xptr_t dev_xp );71 void dev_iob_iommu_enable( xptr_t dev_xp ); 69 72 70 73 /***************************************************************************************** 71 * This function desactivates the IO-MMU for the IO Xdevice identified by its74 * This function desactivates the IO-MMU for the IOB device identified by its 72 75 * extended pointer. 73 76 ***************************************************************************************** 74 * @ dev_xp : extended pointer on IO Xdevice descriptor.77 * @ dev_xp : extended pointer on IOB device descriptor. 75 78 ****************************************************************************************/ 76 void dev_io x_iommu_disable( xptr_t dev_xp );79 void dev_iob_iommu_disable( xptr_t dev_xp ); 77 80 78 81 /***************************************************************************************** 79 82 * This function set a new value in the IO-MMU PTPR register. 80 83 ***************************************************************************************** 81 * @ dev_xp : extended pointer on IO Xdevice descriptor.84 * @ dev_xp : extended pointer on IOB device descriptor. 82 85 * @ wdata : value to be written in PTPR register. 83 86 ****************************************************************************************/ 84 void dev_io x_set_ptpr( xptr_t dev_xp,87 void dev_iob_set_ptpr( xptr_t dev_xp, 85 88 uint32_t wdata ); 86 89 … … 88 91 * This function invalidates an IOMMU TLB entry identified by its vpn. 89 92 ***************************************************************************************** 90 * @ dev_xp : extended pointer on IO Xdevice descriptor.93 * @ dev_xp : extended pointer on IOB device descriptor. 91 94 * @ vpn : virtual page number in IO virtual space. 92 95 ****************************************************************************************/ 93 void dev_io x_inval_page( xptr_t dev_xp,96 void dev_iob_inval_page( xptr_t dev_xp, 94 97 vpn_t vpn ); 95 98 … … 97 100 * This function return informations relative to an error reported by the IOMMU. 98 101 ***************************************************************************************** 99 * @ dev_xp : extended pointer on IO Xdevice descriptor.102 * @ dev_xp : extended pointer on IOB device descriptor. 100 103 * @ error : [out] pointer on buffer for erro type. 101 104 * @ bvar : [out] pointer on buffer for bad virtual address. 102 105 * @ srcid : [out] pointer on buffer for faulty peripheral index. 103 106 ****************************************************************************************/ 104 void dev_io x_get_status( xptr_t dev_xp,107 void dev_iob_get_status( xptr_t dev_xp, 105 108 uint32_t * error, 106 109 uint32_t * bvar, 107 110 uint32_t * srcid ); 108 111 109 #endif /* _DEV_IO X_H_ */112 #endif /* _DEV_IOB_H_ */ -
trunk/kernel/devices/dev_ioc.c
r1 r3 32 32 #include <thread.h> 33 33 #include <printk.h> 34 #include <chdev.h> 34 35 #include <dev_ioc.h> 35 36 … … 38 39 ///////////////////////////////////////////////////////////////////////////////////////// 39 40 40 extern devices_directory_t devices_dir; // allocated in kernel_init.c41 extern chdev_directory_t chdev_dir; // allocated in kernel_init.c 41 42 42 extern devices_input_irq_t devices_input_irq; // allocated in kernel_init.c43 extern chdev_pic_input_t chdev_pic_input; // allocated in kernel_init.c 43 44 44 ////////////////////////////////// 45 void dev_ioc_init( xptr_t dev_xp)45 //////////////////////////////////// 46 void dev_ioc_init( chdev_t * chdev ) 46 47 { 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 ); 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" ); 50 52 51 // get implementation from device descriptor 52 uint32_t impl = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->impl ) ); 53 // get implementation and channel from chdev descriptor 54 uint32_t impl = chdev->impl; 55 uint32_t channel = chdev->channel; 53 56 54 // set driver specific fields in device descriptor 55 // and call driver init function 57 // set driver specific fields in chdev descriptor and call driver init function 56 58 if( impl == IMPL_IOC_BDV ) 57 59 { 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 ); 60 chdev->cmd = &soclib_bdv_cmd; 61 chdev->isr = &soclib_bdv_isr; 62 soclib_bdv_init( chdev ); 63 63 } 64 64 else if( impl == IMPL_IOC_HBA ) 65 65 { 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 ); 66 chdev->cmd = &soclib_hba_command; 67 chdev->isr = &soclib_hba_isr; 68 soclib_hba_init( chdev ); 71 69 } 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 // }96 70 else 97 71 { 98 printk("\n[PANIC] in %s: undefined IOC device implementation\n", __FUNCTION__ ); 99 hal_core_sleep(); 72 assert( false , __FUNCTION__ , "undefined IOC device implementation" ); 100 73 } 101 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 ); 89 102 90 // create server thread 103 thread_t * new_thread_ptr; 104 xptr_t new_thread_xp; 91 thread_t * new_thread; 105 92 error_t error; 106 93 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() ); 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" ); 114 100 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 ); 101 // set "server" field in chdev descriptor 102 chdev->server = new_thread; 136 103 137 104 // start server thread 138 thread_unblock( new_thread_xp, THREAD_BLOCKED_GLOBAL );105 thread_unblock( XPTR( local_cxy , new_thread ) , THREAD_BLOCKED_GLOBAL ); 139 106 140 107 } // end dev_ioc_init() … … 144 111 // It builds and registers the command in the calling thread descriptor, after 145 112 // translation of buffer virtual address to physical address. 146 // Then, it registers the calling thead in devicewaiting queue.113 // Then, it registers the calling thead in chdev waiting queue. 147 114 // Finally it blocks on the THREAD_BLOCKED_DEV condition and deschedule. 148 115 ////////////////////////////////////i///////////////////////////////////////////// … … 152 119 uint32_t count ) 153 120 { 154 thread_t * this = CURRENT_THREAD; // pointer on client thread 155 cxy_t local_cxy = local_cxy; // client thread cluster 121 thread_t * this = CURRENT_THREAD; // pointer on client thread 156 122 157 123 error_t error; 158 124 paddr_t buf_paddr; 159 bool_t ident = CONFIG_KERNEL_IDENTITY;160 125 161 126 // Get buffer physical address 162 error = vmm_v2p_translate( ident, buffer , &buf_paddr );127 error = vmm_v2p_translate( CONFIG_KERNEL_IDENTITY , buffer , &buf_paddr ); 163 128 164 129 if( error ) return EINVAL; 165 130 166 131 ioc_dmsg("\n[INFO] in %s : thread %x in process %x" 167 " for lba = %x / vaddr = %x / paddr = %l lx\n",132 " for lba = %x / vaddr = %x / paddr = %l / at cycle %d\n", 168 133 __FUNCTION__ , this->trdid , this->process->pid , 169 lba , (uint32_t)buffer , buf_paddr );134 lba , (uint32_t)buffer , buf_paddr , hal_time_stamp() ); 170 135 171 136 #if USE_IOB // software L2/L3 cache coherence for memory buffer … … 176 141 #endif // end software L2/L3 cache coherence 177 142 178 // get extended pointer on IOC devicedescriptor179 xptr_t dev_xp = devices_dir.ioc;143 // get extended pointer on IOC chdev descriptor 144 xptr_t dev_xp = chdev_dir.ioc[0]; 180 145 181 if ( dev_xp == XPTR_NULL ) 182 { 183 printk("\n[PANIC] in %s : undefined IOC device descriptor\n", __FUNCTION__ ); 184 hal_core_sleep(); 185 } 146 assert( (dev_xp != XPTR_NULL) , __FUNCTION__ , "undefined IOC chdev descriptor" ); 186 147 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 } 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; 195 154 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, 155 // register client thread in IOC chdev waiting queue, activate server thread, 211 156 // block client thread on THREAD_BLOCKED_IO and deschedule. 212 157 // it is re-activated by the ISR signaling IO operation completion. 213 device_register_command( dev_xp , this );158 chdev_register_command( dev_xp , this ); 214 159 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 ); 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() ); 226 164 227 165 // return I/O operation status 228 return this-> dev.ioc.error;166 return this->command.ioc.error; 229 167 230 168 } // end dev_ioc_access() … … 245 183 return dev_ioc_access( false , buffer , lba , count ); 246 184 } 247 248 /////////////////////////////////////249 void dev_ioc_server( device_t * dev )250 {251 xptr_t client_xp; // extended pointer on waiting thread252 cxy_t client_cxy; // cluster of client thread253 thread_t * client_ptr; // local pointer on client thread254 thread_t * server; // local pointer on server thread255 xptr_t root_xp; // extended pointer on device waiting queue root256 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 queue262 // TODO If we want to implement an "elevator" mecanism (i.e. sort all263 // 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 queue269 remote_spinlock_lock( XPTR( local_cxy , &dev->wait_lock ) );270 271 // block and deschedule server thread if waiting queue empty272 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 else279 {280 remote_spinlock_unlock( XPTR( local_cxy , &dev->wait_lock ) );281 }282 283 // get extended pointer on first client thread284 client_xp = XLIST_FIRST_ELEMENT( root_xp , thread_t , wait_list );285 286 // call driver command function to start I/O operation287 dev->cmd( client_xp );288 289 // get client thread cluster and local pointer290 client_cxy = GET_CXY( client_xp );291 client_ptr = (thread_t *)GET_PTR( client_xp );292 293 // remove the client thread from waiting queue294 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 while299 300 } // end dev_ioc_server() -
trunk/kernel/devices/dev_ioc.h
r1 r3 25 25 #define _DEV_IOC_H 26 26 27 #include <almos_config.h> 27 28 #include <hal_types.h> 28 29 29 30 /**** Forward declarations ****/ 30 31 31 struct device_s;32 struct chdev_s; 32 33 33 34 /***************************************************************************************** … … 104 105 105 106 /****************************************************************************************** 106 * This function completes the IOC devicedescriptor initialisation,107 * This function completes the IOC chdev descriptor initialisation, 107 108 * namely the link with the implementation specific driver. 108 * The func, impl, channel, is_rx t, base, and size fields must bepreviously initialised.109 * The func, impl, channel, is_rx, base fields have been previously initialised. 109 110 * It calls the specific driver initialisation function, to initialise the hardware 110 111 * device and the specific data structures when required. 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. 112 * It creates the associated server thread and allocates a WTI from local ICU. 113 * It must de executed by a local thread. 114 114 ****************************************************************************************** 115 * @ xp_dev : extended pointer on IOC devicedescriptor.115 * @ chdev : local pointer on IOC chdev descriptor. 116 116 *****************************************************************************************/ 117 void dev_ioc_init( xptr_t xp_dev );117 void dev_ioc_init( struct chdev_s * chdev ); 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 registered155 * 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 server158 * 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), the161 * driver does not block the server thread (it is only descheduled if the number of162 * 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_CMD165 * 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 171 151 #endif /* _DEV_IOC_H */ -
trunk/kernel/devices/dev_mmc.c
r1 r3 26 26 #include <soclib_mmc.h> 27 27 #include <printk.h> 28 #include <chdev.h> 28 29 #include <thread.h> 29 30 #include <dev_mmc.h> … … 33 34 ///////////////////////////////////////////////////////////////////////////////////////// 34 35 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 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 { 46 43 // get implementation from device descriptor 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 44 uint32_t impl = chdev->impl; 45 46 // set driver specific fields in device descriptor and call driver init function 51 47 if( impl == IMPL_MMC_TSR ) 52 48 { 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 ); 49 chdev->cmd = &soclib_mmc_cmd; 50 chdev->isr = &soclib_mmc_isr; 51 soclib_mmc_init( chdev ); 58 52 } 59 53 else 60 54 { 61 printk("\n[PANIC] in %s: undefined MMC device implementation\n", __FUNCTION__ ); 62 hal_core_sleep(); 55 assert( false , __FUNCTION__ , "undefined MMC device implementation" ); 63 56 } 64 57 } // end dev_mmc_init() … … 72 65 { 73 66 mmc_dmsg("\n[INFO] %s enters for thread %x in process %x : command = %d\n", 74 __FUNCTION__ , this->trdid , this->process->pid , this-> dev.mmc.type );67 __FUNCTION__ , this->trdid , this->process->pid , this->command.mmc.type ); 75 68 76 69 // get extended pointer on MMC device 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 } 70 xptr_t dev_xp = this->command.mmc.dev_xp; 71 72 assert( (dev_xp != XPTR_NULL) , __FUNCTION__ , "undefined MMC device descriptor" ); 86 73 87 74 // get MMC device cluster identifier & local pointer 88 cxy_t 89 device_t * dev_ptr = (device_t *)GET_PTR( dev_xp );75 cxy_t dev_cxy = GET_CXY( dev_xp ); 76 chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp ); 90 77 91 78 // get driver command function pointer from MMC device descriptor … … 116 103 cxy_t cxy = CXY_FROM_PADDR( buf_paddr ); 117 104 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 } 105 assert( ((buf_paddr & (CONFIG_CACHE_LINE_SIZE -1)) == 0) , __FUNCTION__ , 106 "buffer not aligned on cache line" ); 125 107 126 108 // get extended pointer on MMC device descriptor 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;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; 140 122 } 141 123 … … 150 132 cxy_t cxy = CXY_FROM_PADDR( buf_paddr ); 151 133 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; 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; 171 148 } 172 149 … … 180 157 181 158 // store command arguments in thread descriptor 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;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; 192 169 } 193 170 … … 201 178 202 179 // store command arguments in thread descriptor 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;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; 213 190 } 214 191 … … 222 199 223 200 // store command arguments in thread descriptor 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;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; 234 211 } 235 212 -
trunk/kernel/devices/dev_mmc.h
r1 r3 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, do not register in the device waiting queue, and no server thread48 * spinlock, but 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 52 56 /****************************************************************************************** 53 57 * This enum defines the various implementations of the generic MMC peripheral. … … 92 96 * It must be executed once in any cluster containing an L2 cache. 93 97 ***************************************************************************************** 94 * @ mmc_xp : extendedpointer on MMC device descriptor.98 * @ chdev : pointer on MMC device descriptor. 95 99 ****************************************************************************************/ 96 void dev_mmc_init( xptr_t mmc_xp);100 void dev_mmc_init( struct chdev_s * chdev ); 97 101 98 102 /***************************************************************************************** -
trunk/kernel/devices/dev_nic.c
r1 r3 25 25 #include <hal_special.h> 26 26 #include <printk.h> 27 #include < device.h>27 #include <chdev.h> 28 28 #include <thread.h> 29 29 #include <soclib_nic.h> … … 34 34 ///////////////////////////////////////////////////////////////////////////////////////// 35 35 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 ) 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 ) 43 42 { 44 // get device descriptor cluster and local pointer45 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 i s_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 function43 // the local ICU chdev must be initialized before the NIC chdev, because 44 // the NIC chdevs initialisation requires allocation of a WTI from local ICU 45 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 descriptor 49 uint32_t impl = chdev->impl; 50 uint32_t is_rx = chdev->is_rx; 51 uint32_t channel = chdev->channel; 52 53 // set driver specific fields in chdev descriptor and call driver init function 55 54 if( impl == IMPL_NIC_SOC ) 56 55 { 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 // } 56 chdev->cmd = &soclib_nic_cmd; 57 chdev->isr = &soclib_nic_isr; 58 soclib_nic_init( chdev ); 59 } 71 60 else 72 61 { 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 ); 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 ); 96 75 97 76 // link NIC IRQ to WTI mailbox in PIC component 98 77 uint32_t irq_id; 99 if( is_rx ) irq_id = devices_input_irq.nic_rx[channel];100 else irq_id = devices_input_irq.nic_tx[channel];78 if( is_rx ) irq_id = chdev_pic_input.nic_rx[channel]; 79 else irq_id = chdev_pic_input.nic_tx[channel]; 101 80 dev_pic_bind_irq( irq_id , local_cxy , wti_id ); 102 81 103 82 // create server thread 104 thread_t * new_thread_ptr; 105 xptr_t new_thread_xp; 83 thread_t * new_thread; 106 84 error_t error; 107 85 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 ); 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; 137 96 138 97 // start server thread 139 thread_unblock( new_thread_xp, THREAD_BLOCKED_GLOBAL );98 thread_unblock( XPTR( local_cxy , new_thread ) , THREAD_BLOCKED_GLOBAL ); 140 99 141 100 } // end dev_nic_init() … … 156 115 __FUNCTION__ , core->lid , local_cxy ); 157 116 158 // get pointer on NIC-RX devicedescriptor117 // get pointer on NIC-RX chdev descriptor 159 118 uint32_t channel = thread_ptr->dev_channel; 160 xptr_t dev_xp = devices_dir.nic_rx[channel];119 xptr_t dev_xp = chdev_dir.nic_rx[channel]; 161 120 cxy_t dev_cxy = GET_CXY( dev_xp ); 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 } 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" ); 175 126 176 127 // initialize command in thread descriptor 177 thread_ptr-> dev.nic.dev_xp = dev_xp;128 thread_ptr->command.nic.dev_xp = dev_xp; 178 129 179 130 // call driver to test readable 180 thread_ptr-> dev.nic.cmd = NIC_CMD_READABLE;181 dev_ptr->cmd( thread_xp ); 182 183 // check error 184 error = thread_ptr-> dev.nic.error;131 thread_ptr->command.nic.cmd = NIC_CMD_READABLE; 132 dev_ptr->cmd( thread_xp ); 133 134 // check error 135 error = thread_ptr->command.nic.error; 185 136 if( error ) return error; 186 137 187 138 // block and deschedule if queue non readable 188 if( thread_ptr-> dev.nic.status == false )139 if( thread_ptr->command.nic.status == false ) 189 140 { 190 141 // get NIC-RX IRQ index and type … … 193 144 194 145 // enable NIC-RX IRQ 195 dev_icu_enable_irq( local_cxy , core->lid , irq_type , irq_id , dev_xp);146 dev_icu_enable_irq( core->lid , irq_type , irq_id , dev_ptr ); 196 147 197 148 // block on THREAD_BLOCKED I/O condition and deschedule … … 200 151 201 152 // disable NIC-RX channel IRQ 202 dev_icu_disable_irq( local_cxy ,core->lid , irq_type , irq_id );153 dev_icu_disable_irq( core->lid , irq_type , irq_id ); 203 154 } 204 155 205 156 // call driver for actual read 206 thread_ptr-> dev.nic.cmd = NIC_CMD_READ;207 thread_ptr-> dev.nic.buffer = pkd->buffer;208 dev_ptr->cmd( thread_xp ); 209 210 // check error 211 error = thread_ptr-> dev.nic.error;157 thread_ptr->command.nic.cmd = NIC_CMD_READ; 158 thread_ptr->command.nic.buffer = pkd->buffer; 159 dev_ptr->cmd( thread_xp ); 160 161 // check error 162 error = thread_ptr->command.nic.error; 212 163 if( error ) return error; 213 164 214 165 // returns packet length 215 pkd->length = thread_ptr-> dev.nic.length;166 pkd->length = thread_ptr->command.nic.length; 216 167 217 168 nic_dmsg("\n[INFO] %s exit for NIC-RX thread on core %d in cluster %x\n", … … 238 189 __FUNCTION__ , core->lid , local_cxy ); 239 190 240 // get pointer on NIC-TX devicedescriptor191 // get pointer on NIC-TX chdev descriptor 241 192 uint32_t channel = thread_ptr->dev_channel; 242 xptr_t dev_xp = devices_dir.nic_tx[channel];193 xptr_t dev_xp = chdev_dir.nic_tx[channel]; 243 194 cxy_t dev_cxy = GET_CXY( dev_xp ); 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 } 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" ); 257 200 258 201 // initialize command in thread descriptor 259 thread_ptr-> dev.nic.dev_xp = dev_xp;202 thread_ptr->command.nic.dev_xp = dev_xp; 260 203 261 204 // call driver to test writable 262 thread_ptr-> dev.nic.cmd = NIC_CMD_WRITABLE;263 dev_ptr->cmd( thread_xp ); 264 265 // check error 266 error = thread_ptr-> dev.nic.error;205 thread_ptr->command.nic.cmd = NIC_CMD_WRITABLE; 206 dev_ptr->cmd( thread_xp ); 207 208 // check error 209 error = thread_ptr->command.nic.error; 267 210 if( error ) return error; 268 211 269 212 // block and deschedule if queue non writable 270 if( thread_ptr-> dev.nic.status == false )213 if( thread_ptr->command.nic.status == false ) 271 214 { 272 215 // get NIC-TX IRQ index and type … … 275 218 276 219 // enable NIC-TX IRQ 277 dev_icu_enable_irq( local_cxy , core->lid , irq_type , irq_id , dev_xp);220 dev_icu_enable_irq( core->lid , irq_type , irq_id , dev_ptr ); 278 221 279 222 // block on THREAD_BLOCKED I/O condition and deschedule … … 282 225 283 226 // disable NIC-TX IRQ 284 dev_icu_disable_irq( local_cxy ,core->lid , irq_type , irq_id );227 dev_icu_disable_irq( core->lid , irq_type , irq_id ); 285 228 } 286 229 287 230 // call driver for actual write 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;291 dev_ptr->cmd( thread_xp ); 292 293 // check error 294 error = thread_ptr-> dev.nic.error;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; 234 dev_ptr->cmd( thread_xp ); 235 236 // check error 237 error = thread_ptr->command.nic.error; 295 238 if( error ) return error; 296 239 -
trunk/kernel/devices/dev_nic.h
r1 r3 75 75 /**** Forward declarations ****/ 76 76 77 struct device_s;77 struct chdev_s; 78 78 79 79 /****************************************************************************************** … … 137 137 138 138 /****************************************************************************************** 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 ); 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 ); 146 150 147 151 /****************************************************************************************** … … 219 223 * becomes non empty. 220 224 ****************************************************************************************** 221 * @ dev : local pointer on NIC ch annel devicedescriptor.222 *****************************************************************************************/ 223 void dev_nic_server( struct device_s *dev );225 * @ dev : local pointer on NIC chdev descriptor. 226 *****************************************************************************************/ 227 void dev_nic_server( struct chdev_s * chdev ); 224 228 225 229 -
trunk/kernel/devices/dev_pic.c
r1 r3 25 25 #include <hal_special.h> 26 26 #include <dev_icu.h> 27 #include < device.h>27 #include <chdev.h> 28 28 #include <memcpy.h> 29 29 #include <printk.h> … … 35 35 ///////////////////////////////////////////////////////////////////////////////////////// 36 36 37 extern devices_directory_t devices_dir; // allocated in kernel_init.c37 extern chdev_directory_t chdev_dir; // allocated in kernel_init.c 38 38 39 extern devices_input_irq_t devices_input_irq; // allocated in kernel_init.c 40 41 39 extern chdev_pic_input_t chdev_pic_input; // allocated in kernel_init.c 42 40 43 41 /////////////////////////////////// 44 void dev_pic_init( xptr_t dev_xp,45 uint32_t irq_nr )42 void dev_pic_init( chdev_t * chdev, 43 uint32_t irq_nr ) 46 44 { 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 ); 45 // set PIC chdev extension field 46 chdev->ext.pic.irq_nr = irq_nr; 50 47 51 // set PIC device extension field52 dev_ptr->ext.pic.irq_nr = irq_nr;48 // get implementation 49 uint32_t impl = chdev->impl; 53 50 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 51 // call the relevant driver init function 59 52 if( impl == IMPL_PIC_SOC ) 60 53 { 61 memcpy( dev_ptr->name , "PIC_TSR" , 16 ); 62 soclib_pic_init( dev_xp ); 54 soclib_pic_init( chdev ); 63 55 } 64 56 else 65 57 { 66 printk("PANIC in %s: illegal PIC device implementation\n", __FUNCTION__ ); 67 hal_core_sleep(); 58 assert( false , __FUNCTION__ , "illegal PIC device implementation" ); 68 59 } 69 60 } // end dev_pic_init() … … 75 66 { 76 67 // get extended pointer on WTI mailbox 77 xptr_t wti_xp = dev_icu_wti_xptr( cxy , wti_id);68 xptr_t wti_xp = XPTR( cxy , dev_icu_wti_ptr( wti_id ) ); 78 69 79 // get extended pointer on PIC devicefrom directory80 xptr_t dev_xp = devices_dir.pic;70 // get extended pointer on PIC chdev from directory 71 xptr_t dev_xp = chdev_dir.pic; 81 72 82 // get PIC devicecluster and local pointer83 cxy_t 84 device_t * dev_ptr = (device_t *)GET_PTR( dev_xp );73 // get PIC chdev cluster and local pointer 74 cxy_t dev_cxy = GET_CXY( dev_xp ); 75 chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp ); 85 76 86 77 // get implementation index and segment base … … 92 83 soclib_pic_bind_irq( dev_xp , irq_id , wti_xp ); 93 84 } 94 else95 {96 printk("PANIC in %s: illegal PIC device implementation\n", __FUNCTION__ );97 hal_core_sleep();98 }99 85 } // end dev_pic_link_wti() 100 86 … … 102 88 void dev_pic_unbind_irq( uint32_t irq_id ) 103 89 { 104 // get extended pointer on PIC devicefrom directory105 xptr_t dev_xp = devices_dir.pic;90 // get extended pointer on PIC chdev from directory 91 xptr_t dev_xp = chdev_dir.pic; 106 92 107 // get PIC devicecluster and local pointer108 cxy_t 109 device_t * dev_ptr = (device_t *)GET_PTR( dev_xp );93 // get PIC chdev cluster and local pointer 94 cxy_t dev_cxy = GET_CXY( dev_xp ); 95 chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp ); 110 96 111 97 // get implementation index … … 117 103 soclib_pic_unbind_irq( dev_xp , irq_id ); 118 104 } 119 else120 {121 printk("PANIC in %s: illegal PIC device implementation\n", __FUNCTION__ );122 hal_core_sleep();123 }124 125 105 } // end dev_pic_disable_irq() 126 106 -
trunk/kernel/devices/dev_pic.h
r1 r3 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 '' devices_input_irq'' global variable in kernel initialization.41 * and are stored in the ''chdev_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 50 54 /***************************************************************************************** 51 * This defines the (implementation independant) extension for the generic ICUdevice.55 * This defines the (implementation independant) extension for the PIC device. 52 56 ****************************************************************************************/ 53 57 … … 72 76 /***************************************************************************************** 73 77 * This function makes two initialisations: 74 * - It initializes the PIC specific fields of the devicedescriptor.78 * - It initializes the PIC specific fields of the chdev descriptor. 75 79 * - it initializes the implementation specific PIC hardware device. 76 80 * It must be executed once in the kernel initialisation phase. … … 79 83 * @ uint32_t : actual number of input IRQs. 80 84 ****************************************************************************************/ 81 void dev_pic_init( xptr_t xp_dev,82 uint32_t irq_nr );85 void dev_pic_init( struct chdev_s * chdev, 86 uint32_t irq_nr ); 83 87 84 88 /***************************************************************************************** -
trunk/kernel/devices/dev_txt.c
r1 r3 35 35 ///////////////////////////////////////////////////////////////////////////////////////// 36 36 37 extern devices_directory_t devices_dir; // allocated in kernel_init.c37 extern chdev_directory_t chdev_dir; // allocated in kernel_init.c 38 38 39 extern devices_input_irq_t devices_input_irq; // allocated in kernel_init.c39 extern chdev_pic_input_t chdev_pic_input; // allocated in kernel_init.c 40 40 41 ////////////////////////////////// 42 void dev_txt_init( xptr_t dev_xp)41 //////////////////////////////////// 42 void dev_txt_init( chdev_t * chdev ) 43 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 ); 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" ); 47 48 48 // get implementation index from device descriptor 49 uint32_t impl = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->impl ) ); 49 // get implementation and channel index 50 uint32_t impl = chdev->impl; 51 uint32_t channel = chdev->channel; 50 52 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 53 // set fields "cmd", "isr", and call driver init function 60 54 if( impl == IMPL_TXT_TTY ) 61 55 { 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 ); 56 chdev->cmd = &soclib_tty_cmd; 57 chdev->isr = &soclib_tty_isr; 58 soclib_tty_init( chdev ); 68 59 } 69 60 else 70 61 { 71 printk("\n[PANIC] in %s: undefined TXT device implementation\n", __FUNCTION__ ); 72 hal_core_sleep(); 62 assert( false , __FUNCTION__ , "undefined TXT device implementation" ); 73 63 } 74 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 ); 79 75 80 // create server thread 76 xptr_t new_thread_xp; 77 thread_t * new_thread_ptr; 81 thread_t * new_thread; 78 82 error_t error; 79 83 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 ); 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" ); 98 90 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 ); 91 // set "server" field in chdev descriptor 92 chdev->server = new_thread; 109 93 110 94 // start server thread 111 thread_unblock( new_thread_xp, THREAD_BLOCKED_GLOBAL );95 thread_unblock( XPTR( local_cxy , new_thread ) , THREAD_BLOCKED_GLOBAL ); 112 96 113 97 } // end dev_txt_init() … … 115 99 116 100 ////////////////////////////////////////////////////////////////////////////////// 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. 101 // This static function is called by dev_txt_read(), dev_txt_write() functions. 125 102 ////////////////////////////////////i///////////////////////////////////////////// 126 103 static error_t dev_txt_access( uint32_t type, … … 135 112 136 113 // check channel argument 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 } 114 assert( (channel < CONFIG_MAX_TXT_CHANNELS) , __FUNCTION__ , "illegal channel index" ); 142 115 143 // get extended pointer on remote TXT devicedescriptor144 xptr_t dev_xp = devices_dir.txt[channel];116 // get extended pointer on remote TXT chdev descriptor 117 xptr_t dev_xp = chdev_dir.txt[channel]; 145 118 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 } 119 assert( (dev_xp != XPTR_NULL) , __FUNCTION__ , "undefined TXT chdev descriptor" ); 152 120 153 121 // register command in calling thread descriptor 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;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; 158 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 ); 159 131 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 } 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 ); 213 134 214 135 // return I/O operation status from calling thread descriptor 215 return this-> dev.txt.error;136 return this->command.txt.error; 216 137 217 138 } // end dev_txt_access() … … 225 146 } 226 147 227 ///////////////////////////////////////////////228 error_t dev_txt_sync_write( uint32_t channel,229 char * buffer,230 uint32_t count )231 {232 return dev_txt_access( TXT_SYNC_WRITE , channel , buffer , count );233 }234 235 148 ///////////////////////////////////////// 236 149 error_t dev_txt_read( uint32_t channel, … … 240 153 } 241 154 242 ///////////////////////////////////// 243 void dev_txt_server( device_t * dev ) 155 /////////////////////////////////////////////// 156 error_t dev_txt_sync_write( uint32_t channel, 157 char * buffer, 158 uint32_t count ) 244 159 { 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 160 // get pointer on calling thread 161 thread_t * this = CURRENT_THREAD; 250 162 251 server = CURRENT_THREAD; 163 // get extended pointer on TXT[0] chdev 164 xptr_t dev_xp = chdev_dir.txt[channel]; 252 165 253 root_xp = XPTR( local_cxy , &dev->wait_root ); 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; 254 171 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 ) ); 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 ) ); 261 176 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 } 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 ) ); 273 181 274 // get extended pointer on first client thread 275 client_xp = XLIST_FIRST_ELEMENT( root_xp , thread_t , wait_list ); 182 // return I/O operation status from calling thread descriptor 183 return this->command.txt.error; 184 185 } // end dev_txt_sync_write() 276 186 277 // call driver command function to start I/O operation278 dev->cmd( client_xp );279 280 // get client thread cluster and local pointer281 client_cxy = GET_CXY( client_xp );282 client_ptr = (thread_t *)GET_PTR( client_xp );283 284 // remove the client thread from waiting queue285 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 while290 291 } // end dev_txt_server()292 -
trunk/kernel/devices/dev_txt.h
r1 r3 30 30 /**** Forward declarations ****/ 31 31 32 struct device_s ;32 struct chdev_s ; 33 33 34 34 /****************************************************************************************** … … 79 79 80 80 /****************************************************************************************** 81 * This function completes the TXT devicedescriptor initialisation,81 * This function completes the TXT chdev descriptor initialisation, 82 82 * namely the link with the implementation specific driver. 83 * The func, impl, channel, is_rxt, base , and size fields must bepreviously initialised.83 * The func, impl, channel, is_rxt, base fields have been 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. 87 * It can be executed in another cluster than cluster containing the device descriptor 88 * or the hardware device itself. 86 * It creates the associated server thread and allocates a WTI from local ICU. 87 * It must de executed by a local thread. 89 88 ****************************************************************************************** 90 * @ xp_dev : extendedpointer on TXT device descriptor.89 * @ chdev : local pointer on TXT device descriptor. 91 90 *****************************************************************************************/ 92 void dev_txt_init( xptr_t xp_dev );91 void dev_txt_init( struct chdev_s * chdev ); 93 92 94 93 /****************************************************************************************** 95 94 * This blocking function read a single character from the terminal identified 96 95 * by the "channel" argument. The corresponding request is actually registered in the 97 * device pendingrequests queue, and the calling thread is descheduled, blocked until96 * chdev requests queue, and the calling thread is descheduled, blocked until 98 97 * transfer completion. 99 98 * It must be called in the client cluster. … … 109 108 * This blocking function writes a character string on the terminal identified 110 109 * by the "channel" argument. The corresponding request is actually registered in the 111 * device pendingrequests queue, and the calling thread is descheduled, blocked until110 * chdev requests queue, and the calling thread is descheduled, blocked until 112 111 * transfer completion. 113 112 * It must be called in the client cluster. … … 123 122 124 123 /*************************************************************************************** 125 * This low-level blocking function is used by the kernel to display one characteron a124 * This low-level blocking function is used by the kernel to display one string on a 126 125 * given TXT channel without descheduling the calling thread, without registering it 127 126 * in the TXT device waiting queue, and without using the TXT irq. … … 136 135 uint32_t count ); 137 136 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 used141 * by the TXT_READ and TXT_WRITE operation types. It executes an infinite loop to handle142 * 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_ISR146 * 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_CMD149 * 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 155 137 156 138 #endif /* _DEV_TXT_H_ */
Note: See TracChangeset
for help on using the changeset viewer.