Changes in trunk/kernel/devices/dev_icu.c [3:1]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/devices/dev_icu.c
r3 r1 24 24 #include <hal_types.h> 25 25 #include <hal_special.h> 26 #include < chdev.h>26 #include <device.h> 27 27 #include <thread.h> 28 28 #include <cluster.h> … … 37 37 ///////////////////////////////////////////////////////////////////////////////////////// 38 38 39 extern chdev_directory_t chdev_dir; // allocated in kernel_init.c 40 41 extern chdev_pic_input_t chdev_pic_input; // allocated in kernel_init.c 42 43 ///////////////////////////////// 44 void dev_icu_init( chdev_t * icu, 45 uint32_t hwi_nr, 46 uint32_t wti_nr, 47 uint32_t pti_nr ) 48 { 49 // set ICU chdev extension fields 50 icu->ext.icu.hwi_nr = hwi_nr; 51 icu->ext.icu.wti_nr = wti_nr; 52 icu->ext.icu.pti_nr = pti_nr; 53 icu->ext.icu.wti_bitmap = 0; 54 spinlock_init( &icu->ext.icu.wti_lock ); 39 extern devices_directory_t devices_dir; // allocated in kernel_init.c 40 41 extern devices_input_irq_t devices_input_irq; // allocated in kernel_init.c 42 43 44 /////////////////////////////////// 45 void dev_icu_init( xptr_t dev_xp, 46 uint32_t hwi_nr, 47 uint32_t wti_nr, 48 uint32_t pti_nr ) 49 { 50 // get ICU device cluster and local pointer 51 cxy_t dev_cxy = GET_CXY( dev_xp ); 52 device_t * dev_ptr = (device_t *)GET_PTR( dev_xp ); 53 54 if( dev_cxy != local_cxy ) 55 { 56 printk("\n[PANIC] %s for cluster %x must be local\n", 57 __FUNCTION__ , local_cxy ); 58 hal_core_sleep(); 59 } 60 61 // set ICU device extension fields 62 dev_ptr->ext.icu.hwi_nr = hwi_nr; 63 dev_ptr->ext.icu.wti_nr = wti_nr; 64 dev_ptr->ext.icu.pti_nr = pti_nr; 65 dev_ptr->ext.icu.wti_bitmap = 0; 66 spinlock_init( &dev_ptr->ext.icu.wti_lock ); 55 67 56 // get implementation 57 uint32_t impl = icu->impl; 58 59 // call the relevant driver init function 68 // get implementation index from ICU device descriptor 69 uint32_t impl = dev_ptr->impl; 70 71 // set field "name" in device descriptor 72 // and call the relevant driver init function 60 73 if( impl == IMPL_ICU_XCU ) 61 74 { 62 uint32_t lid; 63 for( lid = 0 ; lid < LOCAL_CLUSTER->cores_nr ; lid++ ) 64 { 65 soclib_xcu_init( icu , lid ); 66 } 67 } 68 else 69 { 70 assert( false , __FUNCTION__ , "undefined ICU implementation" ); 75 memcpy( dev_ptr->name , "ICU_XCU" , 16 ); 76 77 uint32_t lid; 78 cluster_t * cluster = LOCAL_CLUSTER; 79 for( lid = 0 ; lid < cluster->cores_nr ; lid++ ) 80 { 81 soclib_xcu_init( dev_ptr , lid ); 82 } 83 } 84 else 85 { 86 printk("\n[PANIC] %s : undefined ICU implementation for cluste %x\n", 87 __FUNCTION__ , local_cxy ); 88 hal_core_sleep(); 71 89 } 72 90 } // end dev_icu_init() 73 91 74 92 ///////////////////////////////////////////////////////////////////////////////////// 75 // This static function check the irq_type / irq_index arguments .93 // This static function check the irq_type / irq_index arguments for a remote ICU. 76 94 // It is called by the dev_icu_enable_irq() & dev_icu_disable_irq() functions. 95 // returns 0 if OK / returns non zero if invalid arguments 77 96 ///////////////////////////////////////////////////////////////////////////////////// 78 static inline void dev_icu_check_irq( chdev_t * icu,97 static inline void dev_icu_check_irq( xptr_t icu_xp, 79 98 uint32_t irq_type, 80 99 uint32_t irq_index ) 81 100 { 101 // get cluster and local pointer on remote ICU 102 cxy_t icu_cxy = GET_CXY( icu_xp ); 103 device_t * icu_ptr = (device_t *)GET_PTR( icu_xp ); 104 82 105 if( irq_type == HWI_TYPE ) 83 106 { 84 assert( (irq_index < icu->ext.icu.hwi_nr) , __FUNCTION__ , "illegal HWI" ); 107 if( irq_index >= hal_remote_lw( XPTR( icu_cxy , &icu_ptr->ext.icu.hwi_nr ) ) ) 108 { 109 printk("\n[PANIC] in %s : illegal HWI index = %d for ICU in cluster %x\n", 110 __FUNCTION__ , irq_index , icu_cxy ); 111 hal_core_sleep(); 112 } 85 113 } 86 114 if( irq_type == WTI_TYPE ) 87 115 { 88 assert( (irq_index < icu->ext.icu.wti_nr) , __FUNCTION__ , "illegal WTI" ); 116 if( irq_index >= hal_remote_lw( XPTR( icu_cxy , &icu_ptr->ext.icu.wti_nr ) ) ) 117 { 118 printk("\n[PANIC] in %s : illegal WTI index = %d for ICU in cluster %x\n", 119 __FUNCTION__ , irq_index , icu_cxy ); 120 hal_core_sleep(); 121 } 89 122 } 90 123 if( irq_type == PTI_TYPE ) 91 124 { 92 assert( (irq_index < icu->ext.icu.pti_nr) , __FUNCTION__ , "illegal PTI" ); 93 } 94 } // end dev_icu_check_irq() 95 96 //////////////////////////////////////// 97 void dev_icu_enable_irq( lid_t lid, 125 if( irq_index >= hal_remote_lw( XPTR( icu_cxy , &icu_ptr->ext.icu.pti_nr ) ) ) 126 { 127 printk("\n[PANIC] in %s : illegal PTI index = %d for ICU in cluster %x\n", 128 __FUNCTION__ , irq_index , icu_cxy ); 129 hal_core_sleep(); 130 } 131 } 132 } // end dev_icu check irq() 133 134 //////////////////////////////////////////// 135 void dev_icu_enable_irq( cxy_t icu_cxy, 136 lid_t lid, 98 137 uint32_t irq_type, 99 138 uint32_t irq_index, 100 chdev_t * src_chdev)101 { 102 // get local pointer on local ICU chdev103 xptr_t icu_xp = chdev_dir.icu[local_cxy];104 chdev_t * icu = (chdev_t *)GET_PTR( icu_xp );139 xptr_t src_dev_xp ) 140 { 141 // get extended pointer & local pointer on remote ICU device 142 xptr_t icu_xp = devices_dir.icu[icu_cxy]; 143 device_t * icu_ptr = (device_t *)GET_PTR( icu_xp ); 105 144 106 145 // check IRQ type and index 107 dev_icu_check_irq( icu , irq_type , irq_index );146 dev_icu_check_irq( icu_xp , irq_type , irq_index ); 108 147 109 148 // (1) call implementation specific ICU driver to enable IRQ 110 if( icu->impl == IMPL_ICU_XCU ) 111 { 112 soclib_xcu_enable_irq( icu , 1<<irq_index , irq_type , lid ); 113 } 114 115 // (2) get selected core local pointer, and register 116 // source chdev pointer in relevant interrupt vector 117 core_t * core = &LOCAL_CLUSTER->core_tbl[lid]; 118 core_set_irq_vector_entry( core , irq_type , irq_index , src_chdev ); 119 120 // (3) register IRQ type and index in source chdev descriptor 121 src_chdev->irq_type = irq_type; 122 src_chdev->irq_id = irq_index; 149 if( icu_ptr->impl == IMPL_ICU_XCU ) 150 { 151 soclib_xcu_enable_irq( icu_xp , 1<<irq_index , irq_type , lid ); 152 } 153 else 154 { 155 printk("\n[PANIC] in %s : undefined ICU implementation" , __FUNCTION__ ); 156 hal_core_sleep(); 157 } 158 159 // (2) get selected remote core local pointer, and register 160 // source device xptr in relevant interrupt vector 161 162 core_t * core_ptr = hal_remote_lpt( XPTR( icu_cxy , &LOCAL_CLUSTER->core_tbl[lid] ) ); 163 xptr_t core_xp = XPTR( icu_cxy , core_ptr ); 164 core_set_irq_vector_entry( core_xp , irq_type , irq_index , src_dev_xp ); 165 166 // (3) get extended pointer on source device, and 167 // register IRQ type and index in source device descriptor 168 169 cxy_t src_dev_cxy = GET_CXY( src_dev_xp ); 170 device_t * src_dev_ptr = (device_t *)GET_PTR( src_dev_xp ); 171 172 hal_remote_sw( XPTR( src_dev_cxy , &src_dev_ptr->irq_type ) , irq_type ); 173 hal_remote_sw( XPTR( src_dev_cxy , &src_dev_ptr->irq_id ) , irq_index ); 123 174 124 175 } // end dev_icu_enable_irq() 125 176 126 ///////////////////////////////////////// 127 void dev_icu_disable_irq( lid_t lid, 177 ///////////////////////////////////////////// 178 void dev_icu_disable_irq( cxy_t icu_cxy, 179 lid_t lid, 128 180 uint32_t irq_type, 129 181 uint32_t irq_index ) 130 182 { 131 // get local pointer on local ICU chdev132 xptr_t icu_xp = chdev_dir.icu[local_cxy];133 chdev_t * icu = (chdev_t *)GET_PTR( icu_xp );183 // get extended pointer & local pointer on remote ICU device 184 xptr_t icu_xp = devices_dir.icu[icu_cxy]; 185 device_t * icu_ptr = (device_t *)GET_PTR( icu_xp ); 134 186 135 187 // check IRQ type and index 136 dev_icu_check_irq( icu , irq_type , irq_index );188 dev_icu_check_irq( icu_xp , irq_type , irq_index ); 137 189 138 190 // (1) call the implementation specific ICU driver to disable IRQ 139 if( icu->impl == IMPL_ICU_XCU ) 140 { 141 soclib_xcu_disable_irq( icu , 1<<irq_index , irq_type , lid ); 191 if( icu_ptr->impl == IMPL_ICU_XCU ) 192 { 193 soclib_xcu_disable_irq( icu_xp , 1<<irq_index , irq_type , lid ); 194 } 195 else 196 { 197 printk("\n[PANIC] in %s : undefined ICU implementation" , __FUNCTION__ ); 198 hal_core_sleep(); 142 199 } 143 200 144 201 // (2) get selected remote core local pointer, and remove 145 // the source chdev xptr from relevant interrupt vector 146 147 core_t * core = &LOCAL_CLUSTER->core_tbl[lid]; 148 core_set_irq_vector_entry( core , irq_type , irq_index , NULL ); 202 // the source device xptr from relevant interrupt vector 203 204 core_t * core_ptr = hal_remote_lpt( XPTR( icu_cxy , &LOCAL_CLUSTER->core_tbl[lid] ) ); 205 xptr_t core_xp = XPTR( icu_cxy , core_ptr ); 206 core_set_irq_vector_entry( core_xp , irq_type , irq_index , XPTR_NULL ); 149 207 150 208 } // end dev_icu_disable_irq() … … 154 212 uint32_t period ) 155 213 { 156 // get local pointer on local ICU chdev157 xptr_t icu_xp = chdev_dir.icu[local_cxy];158 chdev_t * icu = (chdev_t *)GET_PTR( icu_xp );214 // get pointer on local ICU device descriptor 215 core_t * core = CURRENT_CORE; 216 device_t * icu = core->icu; 159 217 160 218 // check PTI index 161 assert( (pti_index < icu->ext.icu.pti_nr) , __FUNCTION__ , "illegal PTI index" ); 219 if( pti_index >= icu->ext.icu.pti_nr ) 220 { 221 printk("\n[PANIC] in %s : illegal PTI index = %d\n", __FUNCTION__ , pti_index ); 222 hal_core_sleep(); 223 } 162 224 163 225 // call the implementation specific driver ICU to set period … … 171 233 void dev_icu_ack_timer( uint32_t pti_index ) 172 234 { 173 // get local pointer on local ICU chdev174 xptr_t icu_xp = chdev_dir.icu[local_cxy];175 chdev_t * icu = (chdev_t *)GET_PTR( icu_xp );235 // get pointer on local ICU device descriptor 236 core_t * core = CURRENT_CORE; 237 device_t * icu = core->icu; 176 238 177 239 // check PTI index 178 assert( (pti_index < icu->ext.icu.pti_nr) , __FUNCTION__ , "illegal PTI index" ); 240 if( pti_index >= icu->ext.icu.pti_nr ) 241 { 242 printk("\n[PANIC] in %s : illegal PTI index = %d\n", __FUNCTION__ , pti_index ); 243 hal_core_sleep(); 244 } 179 245 180 246 // call the implementation specific driver ICU to acknowledge PTI IRQ … … 183 249 soclib_xcu_ack_timer( icu , pti_index ); 184 250 } 251 else 252 { 253 printk("\n[PANIC] in %s : undefined ICU implementation" , __FUNCTION__ ); 254 hal_core_sleep(); 255 } 256 185 257 } // end dev_icu_ack_timer() 186 258 … … 198 270 uint32_t y = cxy & ((1<<y_width)-1); 199 271 200 assert( ((x < x_size) && (y < y_size)) , __FUNCTION__ , "illegal cluster identifier" ); 201 202 assert( (lid < cores_nr) , __FUNCTION__ , "illegal core local index" ); 203 204 // get extended pointer on target ICU chdev 205 xptr_t icu_xp = chdev_dir.icu[cxy]; 272 if( (x >= x_size) || (y >= y_size) ) 273 { 274 hal_core_sleep("%s : illegal cluster identifier = %x\n", __FUNCTION__ , cxy ); 275 } 276 if( lid >= cores_nr ) 277 { 278 hal_core_sleep("%s : illegal core local index = %d\n", __FUNCTION__ , lid ); 279 } 280 281 // get extended pointer on target ICU device 282 xptr_t icu_xp = devices_dir.icu[cxy]; 206 283 207 284 // get target ICU cluster and local pointer 208 cxy_t icu_cxy= GET_CXY( icu_xp );209 chdev_t * icu_ptr = (chdev_t *)GET_PTR( icu_xp );210 211 // get implementation from remote ICU chdev212 uint32_t impl = hal_remote_lw( XPTR( icu_cxy , &icu_ptr->impl ) );285 cxy_t cxy_icu = GET_CXY( icu_xp ); 286 device_t * ptr_icu = (device_t *)GET_PTR( icu_xp ); 287 288 // get driver implementation from target ICU device 289 uint32_t impl = hal_remote_lw( XPTR( cxy_icu , &ptr_icu->impl ) ); 213 290 214 291 // call the implementation specific ICU driver to send IPI … … 216 293 { 217 294 soclib_xcu_send_ipi( icu_xp , lid ); 295 } 296 else 297 { 298 printk("\n[PANIC] in %s : undefined ICU implementation" , __FUNCTION__ ); 299 hal_core_sleep(); 218 300 } 219 301 } // end dev_icu_send_ipi() … … 225 307 uint32_t wti_status; // WTI index + 1 / no pending WTI if 0 226 308 uint32_t pti_status; // PTI index + 1 / no pending PTI if 0 227 chdev_t * src_chdev; // pointer on source chdev descriptor 309 xptr_t src_dev_xp; // extended pointer on source device descriptor 310 cxy_t src_dev_cxy; // source device cluster 311 device_t * src_dev_ptr; // source device local pointer 228 312 uint32_t index; // IRQ index 229 313 230 core_t * core = CURRENT_CORE; 231 232 // get local pointer on local ICU chdev 233 xptr_t icu_xp = chdev_dir.icu[local_cxy]; 234 chdev_t * icu = (chdev_t *)GET_PTR( icu_xp ); 314 // get pointer on local ICU device descriptor 315 core_t * core = CURRENT_CORE; 316 device_t * icu = core->icu; 235 317 236 318 // call the implementation specific ICU driver … … 240 322 soclib_xcu_get_status( icu , core->lid , &hwi_status , &wti_status , &pti_status ); 241 323 } 324 else 325 { 326 printk("\n[PANIC] in %s : undefined ICU implementation" , __FUNCTION__ ); 327 hal_core_sleep(); 328 } 242 329 243 330 // analyse ICU status and handle up to 3 pending IRQ (one WTI, one HWI, one PTI) 244 331 245 if( wti_status ) // pending WTI 332 if( wti_status ) // pending WTI TODO what about IPIs ??? [AG] 246 333 { 247 334 index = wti_status - 1; 248 335 249 if( index < LOCAL_CLUSTER->cores_nr ) // it is an IPI 250 { 251 assert( (index == core->lid) , __FUNCTION__ , "illegal IPI index" ); 252 253 // TODO acknowledge WTI [AG] 254 255 // TODO force scheduling [AG] 256 } 257 else // it is an external device 258 { 259 // get pointer on IRQ source chdev 260 src_chdev = core->wti_vector[index]; 261 262 if( src_chdev == NULL ) // strange, but not fatal => disable IRQ 263 { 264 printk("\n[WARNING] in %s : no handler for WTI %d on core %d in cluster %x\n", 265 __FUNCTION__ , index , core->lid , local_cxy ); 266 core->spurious_irqs ++; 267 dev_icu_disable_irq( core->lid , WTI_TYPE , index ); 268 } 269 else // call relevant ISR 270 { 271 icu_dmsg("\n[INFO] %s received WTI : index = %d for cpu %d in cluster %d\n", 272 __FUNCTION__ , index , core->lid , local_cxy ); 273 274 // call ISR 275 src_chdev->isr( src_chdev ); 276 } 336 // get extended pointer on IRQ source device 337 src_dev_xp = core->wti_vector[index]; 338 src_dev_cxy = GET_CXY( src_dev_xp ); 339 src_dev_ptr = (device_t *)GET_PTR( src_dev_xp ); 340 341 if( src_dev_xp == XPTR_NULL ) // strange, but not fatal => disable IRQ 342 { 343 printk("\n[WARNING] in %s : no handler for WTI %d on core %d in cluster %x\n", 344 __FUNCTION__ , index , core->lid , local_cxy ); 345 core->spurious_irqs ++; 346 dev_icu_disable_irq( local_cxy , core->lid , WTI_TYPE , index ); 347 } 348 else if( src_dev_cxy != local_cxy ) // WTI must be handled in device cluster 349 { 350 printk("\n[PANIC] in %s : non local WTI %d on core %d in cluster %x\n", 351 __FUNCTION__ , index , core->lid , local_cxy ); 352 hal_core_sleep(); 353 } 354 else // call relevant ISR 355 { 356 icu_dmsg("\n[INFO] %s received WTI : index = %d for cpu %d in cluster %d\n", 357 __FUNCTION__ , index , core->lid , local_cxy ); 358 359 src_dev_ptr->isr( src_dev_ptr ); 277 360 } 278 361 } … … 282 365 index = hwi_status - 1; 283 366 284 // get pointer on IRQ source chdev 285 src_chdev = core->hwi_vector[index]; 286 287 if( src_chdev == NULL ) // strange, but not fatal => disable IRQ 367 // get pointer on IRQ source device 368 src_dev_xp = core->wti_vector[index]; 369 src_dev_cxy = GET_CXY( src_dev_xp ); 370 src_dev_ptr = (device_t *)GET_PTR( src_dev_xp ); 371 372 if( src_dev_xp == XPTR_NULL ) // strange, but not fatal => disable IRQ 288 373 { 289 374 printk("\n[WARNING] in %s : no handler for HWI %d on core %d in cluster %x\n", 290 375 __FUNCTION__ , index , core->lid , local_cxy ); 291 376 core->spurious_irqs ++; 292 dev_icu_disable_irq( core->lid , HWI_TYPE , index );377 dev_icu_disable_irq( local_cxy , core->lid , HWI_TYPE , index ); 293 378 } 379 else if( src_dev_cxy != local_cxy ) // HWI must be handled in device cluster 380 { 381 printk("\n[PANIC] in %s : non local HWI %d on core %d in cluster %x\n", 382 __FUNCTION__ , index , core->lid , local_cxy ); 383 hal_core_sleep(); 384 } 294 385 else // call relevant ISR 295 386 { … … 297 388 __FUNCTION__ , index , core->lid , local_cxy ); 298 389 299 // call ISR 300 src_chdev->isr( src_chdev ); 390 src_dev_ptr->isr( src_dev_ptr ); 301 391 } 302 392 } … … 312 402 dev_icu_ack_timer( index ); 313 403 314 // TODOexecute all actions related to TICK event404 // execute all actions related to TICK event 315 405 core_clock( core ); 316 406 } … … 320 410 uint32_t dev_icu_wti_alloc() 321 411 { 322 // get local pointer on local ICU chdev323 xptr_t icu_xp = chdev_dir.icu[local_cxy];324 chdev_t * icu = (chdev_t *)GET_PTR( icu_xp );325 326 // get bitmap pointer, lock pointer, and size327 uint32_t * bitmap = &icu->ext.icu.wti_bitmap;412 // get pointer on local ICU device descriptor 413 core_t * core = CURRENT_CORE; 414 device_t * icu = core->icu; 415 416 // get bitmap pointer, lock, and size 417 bitmap_t * bitmap = &icu->ext.icu.wti_bitmap; 328 418 spinlock_t * lock = &icu->ext.icu.wti_lock; 329 419 uint32_t size = icu->ext.icu.wti_nr; … … 347 437 void dev_icu_wti_release( uint32_t index ) 348 438 { 349 // get pointer on local ICU chdevdescriptor350 xptr_t icu_xp = chdev_dir.icu[local_cxy];351 chdev_t * icu_ptr = (chdev_t *)GET_PTR( icu_xp );439 // get pointer on local ICU device descriptor 440 core_t * core = CURRENT_CORE; 441 device_t * icu = core->icu; 352 442 353 443 // get bitmap pointer, lock, and size 354 bitmap_t * bitmap = &icu _ptr->ext.icu.wti_bitmap;355 spinlock_t * lock = &icu _ptr->ext.icu.wti_lock;356 uint32_t size = icu _ptr->ext.icu.wti_nr;444 bitmap_t * bitmap = &icu->ext.icu.wti_bitmap; 445 spinlock_t * lock = &icu->ext.icu.wti_lock; 446 uint32_t size = icu->ext.icu.wti_nr; 357 447 358 448 // check index 359 assert( (index < size) , __FUNCTION__ , "illegal WTI index" ); 449 if( index >= size ) 450 { 451 printk("\n[PANIC] in %s : illegal WTI index = %d on core %d in cluster %x\n", 452 __FUNCTION__ , index , core->lid , local_cxy ); 453 hal_core_sleep(); 454 } 360 455 361 456 // get lock protecting WTI allocator … … 367 462 // release lock 368 463 spinlock_unlock( lock ); 369 370 464 } // end dev_icu_wti_release() 371 465 372 ////////////////////////////////////////////// 373 uint32_t * dev_icu_wti_ptr( uint32_t wti_id ) 374 { 375 uint32_t * wti_ptr = NULL; 376 377 // get pointer on local ICU chdev descriptor 378 xptr_t icu_xp = chdev_dir.icu[local_cxy]; 379 chdev_t * icu = (chdev_t *)GET_PTR( icu_xp ); 466 /////////////////////////////////////// 467 xptr_t dev_icu_wti_xptr( cxy_t cxy, 468 uint32_t wti_id ) 469 { 470 uint32_t * ptr = NULL; // local pointer on mailbox 471 472 // get pointer on local ICU device descriptor 473 core_t * core = CURRENT_CORE; 474 device_t * icu = core->icu; 380 475 381 476 // call implementation specific ICU driver 382 477 if( icu->impl == IMPL_ICU_XCU ) 383 478 { 384 wti_ptr = soclib_xcu_wti_ptr( icu , wti_id ); 385 } 386 387 return wti_ptr; 479 ptr = soclib_xcu_wti_ptr( icu , wti_id ); 480 } 481 else 482 { 483 printk("\n[PANIC] in %s : undefined ICU implementation" , __FUNCTION__ ); 484 hal_core_sleep(); 485 } 486 487 // return extended pointer on mailbox 488 return XPTR( cxy , ptr ); 489 388 490 } // end dev_icu_wti_xptr() 389 491
Note: See TracChangeset
for help on using the changeset viewer.