| 1 | /*
|
|---|
| 2 | * dev_icu.c - ICU (Interrupt Controler Unit) generic device API implementation.
|
|---|
| 3 | *
|
|---|
| 4 | * Authors Alain Greiner (2016)
|
|---|
| 5 | *
|
|---|
| 6 | * Copyright (c) UPMC Sorbonne Universites
|
|---|
| 7 | *
|
|---|
| 8 | * This file is part of ALMOS-MKH.
|
|---|
| 9 | *
|
|---|
| 10 | * ALMOS-MKH is free software; you can redistribute it and/or modify it
|
|---|
| 11 | * under the terms of the GNU General Public License as published by
|
|---|
| 12 | * the Free Software Foundation; version 2.0 of the License.
|
|---|
| 13 | *
|
|---|
| 14 | * ALMOS-MKH is distributed in the hope that it will be useful, but
|
|---|
| 15 | * WITHOUT ANY WARRANTY; without even the implied warranty of
|
|---|
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|---|
| 17 | * General Public License for more details.
|
|---|
| 18 | *
|
|---|
| 19 | * You should have received a copy of the GNU General Public License
|
|---|
| 20 | * along with ALMOS-MKH; if not, write to the Free Software Foundation,
|
|---|
| 21 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|---|
| 22 | */
|
|---|
| 23 |
|
|---|
| 24 | #include <hal_types.h>
|
|---|
| 25 | #include <hal_special.h>
|
|---|
| 26 | #include <chdev.h>
|
|---|
| 27 | #include <thread.h>
|
|---|
| 28 | #include <cluster.h>
|
|---|
| 29 | #include <printk.h>
|
|---|
| 30 | #include <memcpy.h>
|
|---|
| 31 | #include <spinlock.h>
|
|---|
| 32 | #include <soclib_xcu.h>
|
|---|
| 33 | #include <dev_icu.h>
|
|---|
| 34 |
|
|---|
| 35 | /////////////////////////////////////////////////////////////////////////////////////////
|
|---|
| 36 | // Extern global variables
|
|---|
| 37 | /////////////////////////////////////////////////////////////////////////////////////////
|
|---|
| 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 chdev name
|
|---|
| 50 | snprintf( icu->name , 16 , "icu_%x" , local_cxy );
|
|---|
| 51 |
|
|---|
| 52 | // set ICU chdev extension fields
|
|---|
| 53 | icu->ext.icu.hwi_nr = hwi_nr;
|
|---|
| 54 | icu->ext.icu.wti_nr = wti_nr;
|
|---|
| 55 | icu->ext.icu.pti_nr = pti_nr;
|
|---|
| 56 | icu->ext.icu.wti_bitmap = 0;
|
|---|
| 57 | spinlock_init( &icu->ext.icu.wti_lock );
|
|---|
| 58 |
|
|---|
| 59 | // get implementation
|
|---|
| 60 | uint32_t impl = icu->impl;
|
|---|
| 61 |
|
|---|
| 62 | // call the relevant driver init function
|
|---|
| 63 | if( impl == IMPL_ICU_XCU )
|
|---|
| 64 | {
|
|---|
| 65 | uint32_t lid;
|
|---|
| 66 | for( lid = 0 ; lid < LOCAL_CLUSTER->cores_nr ; lid++ )
|
|---|
| 67 | {
|
|---|
| 68 | soclib_xcu_init( icu , lid );
|
|---|
| 69 | }
|
|---|
| 70 | }
|
|---|
| 71 | else
|
|---|
| 72 | {
|
|---|
| 73 | assert( false , __FUNCTION__ , "undefined ICU implementation" );
|
|---|
| 74 | }
|
|---|
| 75 | }
|
|---|
| 76 |
|
|---|
| 77 | /////////////////////////////////////////////////////////////////////////////////////
|
|---|
| 78 | // This static function check the irq_type / irq_index arguments.
|
|---|
| 79 | // It is called by the dev_icu_enable_irq() & dev_icu_disable_irq() functions.
|
|---|
| 80 | /////////////////////////////////////////////////////////////////////////////////////
|
|---|
| 81 | static inline void dev_icu_check_irq( chdev_t * icu,
|
|---|
| 82 | uint32_t irq_type,
|
|---|
| 83 | uint32_t irq_index )
|
|---|
| 84 | {
|
|---|
| 85 | if( irq_type == HWI_TYPE )
|
|---|
| 86 | {
|
|---|
| 87 | if( irq_index >= icu->ext.icu.hwi_nr )
|
|---|
| 88 | {
|
|---|
| 89 | printk("\n[PANIC] in %s : illegal HWI index = %d / max = %d\n",
|
|---|
| 90 | __FUNCTION__ , irq_index , icu->ext.icu.hwi_nr );
|
|---|
| 91 | hal_core_sleep();
|
|---|
| 92 | }
|
|---|
| 93 | }
|
|---|
| 94 | else if( irq_type == WTI_TYPE )
|
|---|
| 95 | {
|
|---|
| 96 | if( irq_index >= icu->ext.icu.wti_nr )
|
|---|
| 97 | {
|
|---|
| 98 | printk("\n[PANIC] in %s : illegal WTI index = %d / max = %d\n",
|
|---|
| 99 | __FUNCTION__ , irq_index , icu->ext.icu.wti_nr );
|
|---|
| 100 | hal_core_sleep();
|
|---|
| 101 | }
|
|---|
| 102 | }
|
|---|
| 103 | else // irq_type == PTI_TYPE
|
|---|
| 104 | {
|
|---|
| 105 | if( irq_index >= icu->ext.icu.pti_nr )
|
|---|
| 106 | {
|
|---|
| 107 | printk("\n[PANIC] in %s : illegal PTI index = %d / max = %d\n",
|
|---|
| 108 | __FUNCTION__ , irq_index , icu->ext.icu.pti_nr );
|
|---|
| 109 | hal_core_sleep();
|
|---|
| 110 | }
|
|---|
| 111 | }
|
|---|
| 112 | }
|
|---|
| 113 |
|
|---|
| 114 | ////////////////////////////////////////
|
|---|
| 115 | void dev_icu_enable_irq( lid_t lid,
|
|---|
| 116 | uint32_t irq_type,
|
|---|
| 117 | uint32_t irq_index,
|
|---|
| 118 | chdev_t * src_chdev )
|
|---|
| 119 | {
|
|---|
| 120 | // get local pointer on local ICU chdev
|
|---|
| 121 | xptr_t icu_xp = chdev_dir.icu[local_cxy];
|
|---|
| 122 | chdev_t * icu = (chdev_t *)GET_PTR( icu_xp );
|
|---|
| 123 |
|
|---|
| 124 | // check IRQ type and index
|
|---|
| 125 | dev_icu_check_irq( icu , irq_type , irq_index );
|
|---|
| 126 |
|
|---|
| 127 | // call implementation specific ICU driver to enable IRQ
|
|---|
| 128 | if( icu->impl == IMPL_ICU_XCU )
|
|---|
| 129 | {
|
|---|
| 130 | soclib_xcu_enable_irq( icu , 1<<irq_index , irq_type , lid );
|
|---|
| 131 | }
|
|---|
| 132 |
|
|---|
| 133 | // This is only done for an HWI, or for a WTI that is not an IPI
|
|---|
| 134 | if( (irq_type != PTI_TYPE) && (src_chdev != NULL) )
|
|---|
| 135 | {
|
|---|
| 136 | // get selected core local pointer, and register
|
|---|
| 137 | // source chdev pointer in relevant interrupt vector
|
|---|
| 138 | core_t * core = &LOCAL_CLUSTER->core_tbl[lid];
|
|---|
| 139 | core_set_irq_vector_entry( core , irq_type , irq_index , src_chdev );
|
|---|
| 140 |
|
|---|
| 141 | // (3) register IRQ type and index in source chdev descriptor
|
|---|
| 142 | src_chdev->irq_type = irq_type;
|
|---|
| 143 | src_chdev->irq_id = irq_index;
|
|---|
| 144 | }
|
|---|
| 145 | }
|
|---|
| 146 |
|
|---|
| 147 | /////////////////////////////////////////
|
|---|
| 148 | void dev_icu_disable_irq( lid_t lid,
|
|---|
| 149 | uint32_t irq_type,
|
|---|
| 150 | uint32_t irq_index )
|
|---|
| 151 | {
|
|---|
| 152 | // get local pointer on local ICU chdev
|
|---|
| 153 | xptr_t icu_xp = chdev_dir.icu[local_cxy];
|
|---|
| 154 | chdev_t * icu = (chdev_t *)GET_PTR( icu_xp );
|
|---|
| 155 |
|
|---|
| 156 | // check IRQ type and index
|
|---|
| 157 | dev_icu_check_irq( icu , irq_type , irq_index );
|
|---|
| 158 |
|
|---|
| 159 | // call the implementation specific ICU driver to disable IRQ
|
|---|
| 160 | if( icu->impl == IMPL_ICU_XCU )
|
|---|
| 161 | {
|
|---|
| 162 | soclib_xcu_disable_irq( icu , 1<<irq_index , irq_type , lid );
|
|---|
| 163 | }
|
|---|
| 164 |
|
|---|
| 165 | // This is only done for HWI or WTI that are not IPI
|
|---|
| 166 | if( irq_type != PTI_TYPE )
|
|---|
| 167 | {
|
|---|
| 168 | // get selected remote core local pointer, and remove
|
|---|
| 169 | // the source chdev xptr from relevant interrupt vector
|
|---|
| 170 | core_t * core = &LOCAL_CLUSTER->core_tbl[lid];
|
|---|
| 171 | core_set_irq_vector_entry( core , irq_type , irq_index , NULL );
|
|---|
| 172 | }
|
|---|
| 173 | }
|
|---|
| 174 |
|
|---|
| 175 | ///////////////////////////////////////
|
|---|
| 176 | void dev_icu_get_masks( lid_t lid,
|
|---|
| 177 | uint32_t * hwi_mask,
|
|---|
| 178 | uint32_t * wti_mask,
|
|---|
| 179 | uint32_t * pti_mask )
|
|---|
| 180 | {
|
|---|
| 181 | // get local pointer on local ICU chdev
|
|---|
| 182 | xptr_t icu_xp = chdev_dir.icu[local_cxy];
|
|---|
| 183 | chdev_t * icu = (chdev_t *)GET_PTR( icu_xp );
|
|---|
| 184 |
|
|---|
| 185 | if( icu->impl == IMPL_ICU_XCU )
|
|---|
| 186 | {
|
|---|
| 187 | soclib_xcu_get_masks( icu , lid , hwi_mask , wti_mask , pti_mask );
|
|---|
| 188 | }
|
|---|
| 189 | }
|
|---|
| 190 |
|
|---|
| 191 | //////////////////////////////////////////////
|
|---|
| 192 | void dev_icu_set_period( uint32_t pti_index,
|
|---|
| 193 | uint32_t period )
|
|---|
| 194 | {
|
|---|
| 195 | // get local pointer on local ICU chdev
|
|---|
| 196 | xptr_t icu_xp = chdev_dir.icu[local_cxy];
|
|---|
| 197 | chdev_t * icu = (chdev_t *)GET_PTR( icu_xp );
|
|---|
| 198 |
|
|---|
| 199 | // check PTI index
|
|---|
| 200 | assert( (pti_index < icu->ext.icu.pti_nr) , __FUNCTION__ , "illegal PTI index" );
|
|---|
| 201 |
|
|---|
| 202 | // call the implementation specific driver ICU to set period
|
|---|
| 203 | if( icu->impl == IMPL_ICU_XCU )
|
|---|
| 204 | {
|
|---|
| 205 | soclib_xcu_set_period( icu , pti_index , period );
|
|---|
| 206 | }
|
|---|
| 207 | }
|
|---|
| 208 |
|
|---|
| 209 | ////////////////////////////////////////////
|
|---|
| 210 | void dev_icu_ack_timer( uint32_t pti_index )
|
|---|
| 211 | {
|
|---|
| 212 | // get local pointer on local ICU chdev
|
|---|
| 213 | xptr_t icu_xp = chdev_dir.icu[local_cxy];
|
|---|
| 214 | chdev_t * icu = (chdev_t *)GET_PTR( icu_xp );
|
|---|
| 215 |
|
|---|
| 216 | // check PTI index
|
|---|
| 217 | assert( (pti_index < icu->ext.icu.pti_nr) , __FUNCTION__ , "illegal PTI index" );
|
|---|
| 218 |
|
|---|
| 219 | // call the implementation specific driver ICU to acknowledge PTI IRQ
|
|---|
| 220 | if( icu->impl == IMPL_ICU_XCU )
|
|---|
| 221 | {
|
|---|
| 222 | soclib_xcu_ack_timer( icu , pti_index );
|
|---|
| 223 | }
|
|---|
| 224 | }
|
|---|
| 225 |
|
|---|
| 226 | ////////////////////////////////////
|
|---|
| 227 | void dev_icu_send_ipi( cxy_t cxy,
|
|---|
| 228 | lid_t lid )
|
|---|
| 229 | {
|
|---|
| 230 | // check arguments
|
|---|
| 231 | cluster_t * cluster = LOCAL_CLUSTER;
|
|---|
| 232 | uint32_t y_width = cluster->y_width;
|
|---|
| 233 | uint32_t x_size = cluster->x_size;
|
|---|
| 234 | uint32_t y_size = cluster->y_size;
|
|---|
| 235 | uint32_t cores_nr = cluster->cores_nr;
|
|---|
| 236 | uint32_t x = cxy >> y_width;
|
|---|
| 237 | uint32_t y = cxy & ((1<<y_width)-1);
|
|---|
| 238 |
|
|---|
| 239 | assert( ((x < x_size) && (y < y_size)) , __FUNCTION__ , "illegal cluster identifier" );
|
|---|
| 240 |
|
|---|
| 241 | assert( (lid < cores_nr) , __FUNCTION__ , "illegal core local index" );
|
|---|
| 242 |
|
|---|
| 243 | // get extended pointer on target ICU chdev
|
|---|
| 244 | xptr_t icu_xp = chdev_dir.icu[cxy];
|
|---|
| 245 |
|
|---|
| 246 | // get target ICU cluster and local pointer
|
|---|
| 247 | cxy_t icu_cxy = GET_CXY( icu_xp );
|
|---|
| 248 | chdev_t * icu_ptr = (chdev_t *)GET_PTR( icu_xp );
|
|---|
| 249 |
|
|---|
| 250 | // get implementation from remote ICU chdev
|
|---|
| 251 | uint32_t impl = hal_remote_lw( XPTR( icu_cxy , &icu_ptr->impl ) );
|
|---|
| 252 |
|
|---|
| 253 | // call the implementation specific ICU driver to send IPI
|
|---|
| 254 | if( impl == IMPL_ICU_XCU )
|
|---|
| 255 | {
|
|---|
| 256 | soclib_xcu_send_ipi( icu_xp , lid );
|
|---|
| 257 | }
|
|---|
| 258 | }
|
|---|
| 259 |
|
|---|
| 260 | //////////////////////////
|
|---|
| 261 | void dev_icu_irq_handler()
|
|---|
| 262 | {
|
|---|
| 263 | uint32_t hwi_status; // HWI index + 1 / no pending HWI if 0
|
|---|
| 264 | uint32_t wti_status; // WTI index + 1 / no pending WTI if 0
|
|---|
| 265 | uint32_t pti_status; // PTI index + 1 / no pending PTI if 0
|
|---|
| 266 | chdev_t * src_chdev; // pointer on source chdev descriptor
|
|---|
| 267 | uint32_t index; // IRQ index
|
|---|
| 268 |
|
|---|
| 269 | core_t * core = CURRENT_CORE;
|
|---|
| 270 |
|
|---|
| 271 | // get local pointer on local ICU chdev
|
|---|
| 272 | xptr_t icu_xp = chdev_dir.icu[local_cxy];
|
|---|
| 273 | chdev_t * icu = (chdev_t *)GET_PTR( icu_xp );
|
|---|
| 274 |
|
|---|
| 275 | // call the implementation specific ICU driver
|
|---|
| 276 | // to return highest priority pending IRQ of each type
|
|---|
| 277 | if( icu->impl == IMPL_ICU_XCU )
|
|---|
| 278 | {
|
|---|
| 279 | soclib_xcu_get_status( icu , core->lid , &hwi_status , &wti_status , &pti_status );
|
|---|
| 280 | }
|
|---|
| 281 |
|
|---|
| 282 | // analyse ICU status and handle up to 3 pending IRQ (one WTI, one HWI, one PTI)
|
|---|
| 283 |
|
|---|
| 284 | if( wti_status ) // pending WTI
|
|---|
| 285 | {
|
|---|
| 286 | index = wti_status - 1;
|
|---|
| 287 |
|
|---|
| 288 | if( index < LOCAL_CLUSTER->cores_nr ) // it is an IPI
|
|---|
| 289 | {
|
|---|
| 290 | assert( (index == core->lid) , __FUNCTION__ , "illegal IPI index" );
|
|---|
| 291 |
|
|---|
| 292 | // TODO acknowledge WTI [AG]
|
|---|
| 293 |
|
|---|
| 294 | // TODO force scheduling [AG]
|
|---|
| 295 | }
|
|---|
| 296 | else // it is an external device
|
|---|
| 297 | {
|
|---|
| 298 | // get pointer on IRQ source chdev
|
|---|
| 299 | src_chdev = core->wti_vector[index];
|
|---|
| 300 |
|
|---|
| 301 | if( src_chdev == NULL ) // strange, but not fatal => disable IRQ
|
|---|
| 302 | {
|
|---|
| 303 | printk("\n[WARNING] in %s : no handler for WTI %d on core %d in cluster %x\n",
|
|---|
| 304 | __FUNCTION__ , index , core->lid , local_cxy );
|
|---|
| 305 | core->spurious_irqs ++;
|
|---|
| 306 | dev_icu_disable_irq( core->lid , WTI_TYPE , index );
|
|---|
| 307 | }
|
|---|
| 308 | else // call relevant ISR
|
|---|
| 309 | {
|
|---|
| 310 | icu_dmsg("\n[INFO] %s received WTI : index = %d for cpu %d in cluster %d\n",
|
|---|
| 311 | __FUNCTION__ , index , core->lid , local_cxy );
|
|---|
| 312 |
|
|---|
| 313 | // call ISR
|
|---|
| 314 | src_chdev->isr( src_chdev );
|
|---|
| 315 | }
|
|---|
| 316 | }
|
|---|
| 317 | }
|
|---|
| 318 |
|
|---|
| 319 | if( hwi_status ) // pending HWI
|
|---|
| 320 | {
|
|---|
| 321 | index = hwi_status - 1;
|
|---|
| 322 |
|
|---|
| 323 | // get pointer on IRQ source chdev
|
|---|
| 324 | src_chdev = core->hwi_vector[index];
|
|---|
| 325 |
|
|---|
| 326 | if( src_chdev == NULL ) // strange, but not fatal => disable IRQ
|
|---|
| 327 | {
|
|---|
| 328 | printk("\n[WARNING] in %s : no handler for HWI %d on core %d in cluster %x\n",
|
|---|
| 329 | __FUNCTION__ , index , core->lid , local_cxy );
|
|---|
| 330 | core->spurious_irqs ++;
|
|---|
| 331 | dev_icu_disable_irq( core->lid , HWI_TYPE , index );
|
|---|
| 332 | }
|
|---|
| 333 | else // call relevant ISR
|
|---|
| 334 | {
|
|---|
| 335 | icu_dmsg("\n[INFO] %s received HWI : index = %d for cpu %d in cluster %d\n",
|
|---|
| 336 | __FUNCTION__ , index , core->lid , local_cxy );
|
|---|
| 337 |
|
|---|
| 338 | // call ISR
|
|---|
| 339 | src_chdev->isr( src_chdev );
|
|---|
| 340 | }
|
|---|
| 341 | }
|
|---|
| 342 |
|
|---|
| 343 | if( pti_status ) // pending PTI
|
|---|
| 344 | {
|
|---|
| 345 | index = pti_status - 1;
|
|---|
| 346 |
|
|---|
| 347 | icu_dmsg("\n[INFO] %s received PTI : index = %d for cpu %d in cluster %d\n",
|
|---|
| 348 | __FUNCTION__ , index , core->lid , local_cxy );
|
|---|
| 349 |
|
|---|
| 350 | // acknowledge PTI
|
|---|
| 351 | dev_icu_ack_timer( index );
|
|---|
| 352 |
|
|---|
| 353 | if( index < LOCAL_CLUSTER->cores_nr ) // its a TICK event
|
|---|
| 354 | {
|
|---|
| 355 | // TODO execute all actions related to TICK event
|
|---|
| 356 | core_clock( core );
|
|---|
| 357 | }
|
|---|
| 358 | else
|
|---|
| 359 | {
|
|---|
| 360 | printk("\n[WARNING] in %s : no handler for PTI %d on core %d in cluster %x\n",
|
|---|
| 361 | __FUNCTION__ , index , core->lid , local_cxy );
|
|---|
| 362 | core->spurious_irqs ++;
|
|---|
| 363 | dev_icu_disable_irq( core->lid , PTI_TYPE , index );
|
|---|
| 364 | }
|
|---|
| 365 | }
|
|---|
| 366 | }
|
|---|
| 367 |
|
|---|
| 368 | ////////////////////////////
|
|---|
| 369 | uint32_t dev_icu_wti_alloc()
|
|---|
| 370 | {
|
|---|
| 371 | // get local pointer on local ICU chdev
|
|---|
| 372 | xptr_t icu_xp = chdev_dir.icu[local_cxy];
|
|---|
| 373 | chdev_t * icu = (chdev_t *)GET_PTR( icu_xp );
|
|---|
| 374 |
|
|---|
| 375 | // get bitmap pointer, lock pointer, and size
|
|---|
| 376 | uint32_t * bitmap = &icu->ext.icu.wti_bitmap;
|
|---|
| 377 | spinlock_t * lock = &icu->ext.icu.wti_lock;
|
|---|
| 378 | uint32_t size = icu->ext.icu.wti_nr;
|
|---|
| 379 |
|
|---|
| 380 | // get lock protecting WTI allocator
|
|---|
| 381 | spinlock_lock( lock );
|
|---|
| 382 |
|
|---|
| 383 | // get first free mailbox index
|
|---|
| 384 | uint32_t index = (uint32_t)bitmap_ffc( bitmap , size );
|
|---|
| 385 |
|
|---|
| 386 | // set bitmap entry if found
|
|---|
| 387 | if( index < size ) bitmap_set( bitmap , index );
|
|---|
| 388 |
|
|---|
| 389 | // release lock
|
|---|
| 390 | spinlock_unlock( lock );
|
|---|
| 391 |
|
|---|
| 392 | return index;
|
|---|
| 393 | }
|
|---|
| 394 |
|
|---|
| 395 | //////////////////////////////////////////
|
|---|
| 396 | void dev_icu_wti_release( uint32_t index )
|
|---|
| 397 | {
|
|---|
| 398 | // get pointer on local ICU chdev descriptor
|
|---|
| 399 | xptr_t icu_xp = chdev_dir.icu[local_cxy];
|
|---|
| 400 | chdev_t * icu_ptr = (chdev_t *)GET_PTR( icu_xp );
|
|---|
| 401 |
|
|---|
| 402 | // get bitmap pointer, lock, and size
|
|---|
| 403 | bitmap_t * bitmap = &icu_ptr->ext.icu.wti_bitmap;
|
|---|
| 404 | spinlock_t * lock = &icu_ptr->ext.icu.wti_lock;
|
|---|
| 405 | uint32_t size = icu_ptr->ext.icu.wti_nr;
|
|---|
| 406 |
|
|---|
| 407 | // check index
|
|---|
| 408 | assert( (index < size) , __FUNCTION__ , "illegal WTI index" );
|
|---|
| 409 |
|
|---|
| 410 | // get lock protecting WTI allocator
|
|---|
| 411 | spinlock_lock( lock );
|
|---|
| 412 |
|
|---|
| 413 | // clear bitmap entry
|
|---|
| 414 | bitmap_clear( bitmap , index );
|
|---|
| 415 |
|
|---|
| 416 | // release lock
|
|---|
| 417 | spinlock_unlock( lock );
|
|---|
| 418 | }
|
|---|
| 419 |
|
|---|
| 420 | //////////////////////////////////////////////
|
|---|
| 421 | uint32_t * dev_icu_wti_ptr( uint32_t wti_id )
|
|---|
| 422 | {
|
|---|
| 423 | uint32_t * wti_ptr = NULL;
|
|---|
| 424 |
|
|---|
| 425 | // get pointer on local ICU chdev descriptor
|
|---|
| 426 | xptr_t icu_xp = chdev_dir.icu[local_cxy];
|
|---|
| 427 | chdev_t * icu = (chdev_t *)GET_PTR( icu_xp );
|
|---|
| 428 |
|
|---|
| 429 | // call implementation specific ICU driver
|
|---|
| 430 | if( icu->impl == IMPL_ICU_XCU )
|
|---|
| 431 | {
|
|---|
| 432 | wti_ptr = soclib_xcu_wti_ptr( icu , wti_id );
|
|---|
| 433 | }
|
|---|
| 434 |
|
|---|
| 435 | return wti_ptr;
|
|---|
| 436 | }
|
|---|
| 437 |
|
|---|