Changeset 658 for trunk/hal/tsar_mips32/drivers/soclib_nic.c
- Timestamp:
- Oct 10, 2020, 3:48:50 PM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/hal/tsar_mips32/drivers/soclib_nic.c
r657 r658 2 2 * soclib_nic.c - SOCLIB_NIC (Network Interface Controler) driver implementation. 3 3 * 4 * Author Alain Greiner (2016,2017,2018,2019,2020 :)4 * Author Alain Greiner (2016,2017,2018,2019,2020) 5 5 * 6 6 * Copyright (c) UPMC Sorbonne Universites … … 33 33 #include <soclib_nic.h> 34 34 35 36 //////////////////////////////////////////////////////////////////////////////////////// 37 // Extern global variables 38 //////////////////////////////////////////////////////////////////////////////////////// 39 40 extern chdev_directory_t chdev_dir; // allocated in kernel_init.c 41 42 #if DEBUG_HAL_NIC_TX || DEBUG_HAL_NIC_RX 43 44 //////////////////////////////////////////////////////////////////////////////////////// 45 // static function used for SOCLIB_NIC driver debug 46 //////////////////////////////////////////////////////////////////////////////////////// 47 static void soclib_nic_chbuf_display( nic_chbuf_t * chbuf, 48 char * name ) 49 { 50 uint32_t i; 51 52 // software L2/L3 cache coherence for chbuf WID & RID read 53 if( chdev_dir.iob ) dev_mmc_inval( XPTR ( local_cxy , chbuf ) , 8 ); 54 55 // get pointers on TXT0 chdev 56 xptr_t txt0_xp = chdev_dir.txt_tx[0]; 57 cxy_t txt0_cxy = GET_CXY( txt0_xp ); 58 chdev_t * txt0_ptr = GET_PTR( txt0_xp ); 59 60 // get extended pointer on remote TXT0 chdev lock 61 xptr_t lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock ); 62 63 // get TXT0 lock 64 remote_busylock_acquire( lock_xp ); 65 66 nolock_printk("\n***** chbuf %s : ptr %x / wid %d / rid %d *****\n", 67 name, chbuf, chbuf->wid, chbuf->rid ); 68 69 for( i = 0 ; i < SOCLIB_NIC_CHBUF_DEPTH ; i++ ) 70 { 71 uint32_t * container = chbuf->cont_ptr[i]; 72 73 // software L2/L3 cache coherence for container STS & PLEN read 74 if( chdev_dir.iob ) dev_mmc_inval( XPTR( local_cxy , container + 510 ), 8 ); 75 76 if( container[511] ) 77 { 78 nolock_printk(" - %d : FULL / cont_ptr %x / cont_pad [%x,%x] / plen %d\n", 79 i, chbuf->cont_ptr[i], 80 (uint32_t)(chbuf->cont_pad[i]>>32), 81 (uint32_t)chbuf->cont_pad[i], 82 container[510] ); 83 } 84 else 85 { 86 nolock_printk(" - %d : EMPTY / cont_ptr %x / cont_pad [%x,%x]\n", 87 i, chbuf->cont_ptr[i], 88 (uint32_t)(chbuf->cont_pad[i]>>32), 89 (uint32_t)chbuf->cont_pad[i] ); 90 } 91 } 92 93 // release TXT0 lock 94 remote_busylock_release( lock_xp ); 95 96 } // end soclib_nic_chbuf_display() 97 98 #endif 99 35 100 /////////////////////////////////////// 36 101 void soclib_nic_init( chdev_t * chdev ) … … 38 103 uint32_t i; 39 104 kmem_req_t req; 105 ppn_t ppn; 106 uint64_t padr; 40 107 41 108 // set driver specific fields in chdev descriptor 42 109 chdev->cmd = &soclib_nic_cmd; 43 110 chdev->isr = &soclib_nic_isr; 111 112 // get chdev channel & direction 113 bool_t is_rx = chdev->is_rx; 114 uint32_t channel = chdev->channel; 44 115 45 // get hardwaredevice cluster and local pointer116 // get NIC device cluster and local pointer 46 117 cxy_t nic_cxy = GET_CXY( chdev->base ); 47 uint32_t * nic_ptr = (uint32_t *)GET_PTR( chdev->base ); 48 49 // initialize Soclib NIC global registers 50 hal_remote_s32( XPTR( nic_cxy , nic_ptr + NIC_GLOBAL_SPAN + NIC_G_BC_ENABLE ) , 0 ); 51 hal_remote_s32( XPTR( nic_cxy , nic_ptr + NIC_GLOBAL_SPAN + NIC_G_RUN ) , 0 ); 52 53 // allocate memory for chbuf descriptor (one page) 54 assert( (sizeof(nic_chbuf_t) <= CONFIG_PPM_PAGE_SIZE ) , 55 "chbuf descriptor exceeds one page" ); 56 57 req.type = KMEM_PPM; 58 req.order = 0; 118 uint32_t * nic_ptr = GET_PTR( chdev->base ); 119 120 #if DEBUG_HAL_NIC_TX || DEBUG_HAL_NIC_RX 121 thread_t * this = CURRENT_THREAD; 122 uint32_t cycle = (uint32_t)hal_get_cycles(); 123 if( (is_rx == false) && DEBUG_HAL_NIC_RX < cycle ) 124 printk("\n[%s] thread[%x,%x] enter : NIC_TX channel %d / chdev %x / base %x / cycle %d\n", 125 __FUNCTION__, this->process->pid, this->trdid, channel, chdev, nic_ptr, cycle ); 126 if( is_rx && DEBUG_HAL_NIC_RX < cycle ) 127 printk("\n[%s] thread[%x,%x] enter : NIC_RX channel %d / chdev %x / base %x / cycle %d\n", 128 __FUNCTION__, this->process->pid, this->trdid, channel, chdev, nic_ptr, cycle ); 129 #endif 130 131 // get number of channels from hardware 132 uint32_t channels = hal_remote_l32( XPTR( nic_cxy, 133 nic_ptr + NIC_GLOBAL_OFFSET + NIC_G_CHANNELS )); 134 135 // check value registered in cluster descriptor 136 if( LOCAL_CLUSTER->nb_nic_channels != channels ) 137 { 138 printk("\n[PANIC] in %s : channels[soft] (%d) != channels[hard] (%d)\n", 139 __FUNCTION__, LOCAL_CLUSTER->nb_nic_channels, channels ); 140 return; 141 } 142 143 // check channel index 144 if( channel >= channels ) 145 { 146 printk("\n[PANIC] in %s illegal channel index\n", __FUNCTION__ ); 147 return; 148 } 149 150 // allocate memory for chbuf descriptor 151 req.type = KMEM_KCM; 152 req.order = bits_log2( sizeof(nic_chbuf_t) ); 59 153 req.flags = AF_KERNEL; 60 61 154 nic_chbuf_t * chbuf = kmem_alloc( &req ); 62 155 63 156 if( chbuf == NULL ) 64 157 { 65 printk("\n[PANIC] in %s : cannot allocate chbuf descriptor\n", 66 __FUNCTION__ ); 67 } 68 69 // initialise chbuf state 70 chbuf->cont_id = 0; 71 chbuf->pkt_id = 0; 72 chbuf->word_id = 34; 158 printk("\n[PANIC] in %s : cannot allocate chbuf descriptor\n", __FUNCTION__ ); 159 return; 160 } 161 162 // initialise chbuf indexes 163 chbuf->wid = 0; 164 chbuf->rid = 0; 165 166 // software L2/L3 cache coherence for chbuf WID & RID 167 if( chdev_dir.iob ) dev_mmc_sync( XPTR( local_cxy , chbuf ) , 8 ); 73 168 74 // allocate containers (one page per container) 75 // and complete chbuf descriptor initialization 76 assert( (CONFIG_PPM_PAGE_SIZE == 4096) , 77 "chbuf container must be 4 Kbytes" ); 78 79 for( i = 0 ; i < CONFIG_NIC_CHBUF_DEPTH ; i++ ) 80 { 81 uint32_t * container = kmem_alloc( &req ); 82 83 assert( (container != NULL) , 84 "cannot allocate container" ); 169 // allocate containers and complete chbuf initialisation 170 for( i = 0 ; i < SOCLIB_NIC_CHBUF_DEPTH ; i++ ) 171 { 172 // 2048 bytes per container 173 req.type = KMEM_KCM; 174 req.order = 11; 175 req.flags = AF_KERNEL; 176 uint32_t * container = kmem_alloc( &req ); 177 178 if( container == NULL ) 179 { 180 printk("\n[PANIC] in %s : cannot allocate container\n", __FUNCTION__ ); 181 return; 182 } 183 184 // initialize container as empty 185 container[511] = 0; 186 187 // software L2/L3 cache coherence for container STS 188 if( chdev_dir.iob ) dev_mmc_sync( XPTR( local_cxy , &container[511] ) , 4 ); 189 190 // compute container physical address 191 ppn = ppm_base2ppn( XPTR( local_cxy , container ) ); 192 padr = ((uint64_t)ppn << CONFIG_PPM_PAGE_SHIFT) | 193 ((intptr_t)container & CONFIG_PPM_PAGE_MASK); 194 195 // complete chbuf initialisation 196 chbuf->cont_ptr[i] = container; 197 chbuf->cont_pad[i] = padr; 198 } 199 200 // software L2/L3 cache coherence for chbuf descriptor 201 if( chdev_dir.iob ) dev_mmc_sync( XPTR( local_cxy , chbuf ), 202 sizeof(nic_chbuf_t) ); 203 204 // get NIC channel segment base and chbuf depth 205 uint32_t * channel_base = nic_ptr + NIC_CHANNEL_SPAN * channel; 206 uint32_t nbufs = SOCLIB_NIC_CHBUF_DEPTH; 207 208 // compute chbuf physical address 209 ppn = ppm_base2ppn( XPTR( local_cxy , chbuf ) ); 210 padr = ((uint64_t)ppn << CONFIG_PPM_PAGE_SHIFT) | 211 ((intptr_t)chbuf & CONFIG_PPM_PAGE_MASK); 212 213 uint32_t low = (uint32_t)(padr); 214 uint32_t high = (uint32_t)(padr >> 32); 215 216 // initialize the NIC channel registers 217 if( is_rx ) 218 { 219 hal_remote_s32( XPTR( nic_cxy , channel_base + NIC_RX_CHBUF_DESC_LO ) , low ); 220 hal_remote_s32( XPTR( nic_cxy , channel_base + NIC_RX_CHBUF_DESC_HI ) , high ); 221 hal_remote_s32( XPTR( nic_cxy , channel_base + NIC_RX_CHBUF_NBUFS ) , nbufs ); 222 223 hal_fence(); 224 225 hal_remote_s32( XPTR( nic_cxy , channel_base + NIC_RX_CHANNEL_RUN ) , 1 ); 226 } 227 else 228 { 229 hal_remote_s32( XPTR( nic_cxy , channel_base + NIC_TX_CHBUF_DESC_LO ) , low ); 230 hal_remote_s32( XPTR( nic_cxy , channel_base + NIC_TX_CHBUF_DESC_HI ) , high ); 231 hal_remote_s32( XPTR( nic_cxy , channel_base + NIC_TX_CHBUF_NBUFS ) , nbufs ); 232 233 hal_fence(); 234 235 hal_remote_s32( XPTR( nic_cxy , channel_base + NIC_TX_CHANNEL_RUN ) , 1 ); 236 } 237 238 // register chbuf pointer in chdev descriptor extension 239 chdev->ext.nic.queue = chbuf; 85 240 86 chbuf->cont[i] = container; 87 chbuf->full[i] = (paddr_t)XPTR( local_cxy , container ); 88 } 241 #if DEBUG_HAL_NIC_TX || DEBUG_HAL_NIC_RX 242 cycle = (uint32_t)hal_get_cycles(); 243 if( (is_rx == false) && DEBUG_HAL_NIC_RX < cycle ) 244 printk("\n[%s] thread[%x,%x] exit / NIC_TX channel %d / chbuf %x / cycle %d\n", 245 __FUNCTION__, this->process->pid, this->trdid, channel, chbuf, cycle ); 246 if( is_rx && DEBUG_HAL_NIC_RX < cycle ) 247 printk("\n[%s] thread[%x,%x] exit / NIC_RX channel %d / chbuf %x / cycle %d\n", 248 __FUNCTION__, this->process->pid, this->trdid, channel, chbuf, cycle ); 249 soclib_nic_chbuf_display( chbuf , chdev->name ); 250 #endif 251 89 252 } // end soclib_nic_init() 90 91 253 92 254 ////////////////////////////////////////////////////////////////// … … 94 256 { 95 257 uint32_t type; // command type 96 char* buffer; // pointer on command buffer258 uint8_t * buffer; // pointer on command buffer 97 259 uint32_t length; // Ethernet packet length 98 xptr_t dev_xp; // extended pointer on NIC device 260 xptr_t dev_xp; // extended pointer on NIC chdev 261 chdev_t * dev_ptr; // local pointer on NIC chdev 262 cxy_t dev_cxy; // NIC chdev cluster identifier 99 263 nic_chbuf_t * chbuf; // pointer on chbuf descriptor 100 uint32_t cont_id; // index of current container in chbuf 101 uint32_t pkt_id; // index of current packet in container 102 uint32_t word_id; // index of first word of current packet in container 264 uint32_t index; // index of current container in chbuf 103 265 uint32_t * container; // pointer on container (array of uint32_t) 104 uint16_t * header; // pointer on container header (array of uint16_t) 105 uint32_t npackets; // number of packets in current container 106 107 // get local pointer for client thread 108 thread_t * thread_ptr = (thread_t *)GET_PTR( thread_xp ); 109 110 // get command arguments 111 type = thread_ptr->nic_cmd.type; 112 buffer = thread_ptr->nic_cmd.buffer; 113 length = thread_ptr->nic_cmd.length; 114 dev_xp = thread_ptr->nic_cmd.dev_xp; 115 116 // get local pointer for device 117 chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp ); 118 119 // get chbuf descriptor pointer 120 chbuf = (nic_chbuf_t *)dev_ptr->ext.nic.queue; 266 267 thread_t * this = CURRENT_THREAD; 268 269 // check calling thread == client thread 270 assert( (thread_xp == XPTR( local_cxy , this )), "calling thread must be the client thread"); 271 272 // get command type 273 type = this->nic_cmd.type; 274 275 // get chdev pointers for device 276 dev_xp = this->nic_cmd.dev_xp; 277 dev_ptr = GET_PTR( dev_xp ); 278 dev_cxy = GET_CXY( dev_xp ); 121 279 122 280 // analyse command type 123 281 switch( type ) 124 282 { 125 ///////////////////////////////////////////////////////////////////////////// 126 case NIC_CMD_READ: // transfer one packet from RX queue to command buffer 127 { 128 // get current container index 129 cont_id = chbuf->cont_id; 283 ////////////////////////////////////////////////////////////////////////// 284 case NIC_CMD_WRITE: // move one packet from command buffer to TX queue 285 { 286 287 // check chdev is local 288 assert( (dev_cxy == local_cxy), "illegal cluster for a WRITE command"); 130 289 131 assert( chbuf->full[cont_id] == 0 , "Read an empty container\n" ); 132 133 // get pointer on container and header 134 container = chbuf->cont[cont_id]; 135 header = (uint16_t *)container; 136 137 // get expected packet index and first word index in container 138 pkt_id = chbuf->pkt_id; 139 word_id = chbuf->word_id; 140 141 // get packet length and number of packets from container header 142 length = header[pkt_id + 2]; 143 npackets = header[0]; 144 145 assert( pkt_id >= npackets, 146 "Read a non readable container, packet index too large\n"); 147 148 // move the packet from container to buffer 149 memcpy( buffer , container + word_id , length ); 150 151 // update current packet index and first word index 152 chbuf->pkt_id = pkt_id + 1; 153 if( length & 0x3 ) chbuf->word_id = word_id + (length>>2) + 1; 154 else chbuf->word_id = word_id + (length>>2); 290 // get command arguments 291 buffer = this->nic_cmd.buffer; 292 length = this->nic_cmd.length; 293 294 // check packet length 295 assert( (length <= 2040), "packet length too large"); 296 297 // get chbuf descriptor pointer 298 chbuf = (nic_chbuf_t *)dev_ptr->ext.nic.queue; 299 300 // software L2/L3 cache coherence for chbuf WID read 301 if( chdev_dir.iob ) dev_mmc_inval( XPTR ( local_cxy , chbuf ) , 8 ); 302 303 // get container write index 304 index = chbuf->wid; 305 306 // get pointer on container (no L2/L3 cache coherence required) 307 container = chbuf->cont_ptr[index]; 308 309 // software L2/L3 cache coherence for container STS read 310 if( chdev_dir.iob ) dev_mmc_inval( XPTR ( local_cxy , &container[511]) , 4 ); 311 312 #if DEBUG_HAL_NIC_TX 313 uint32_t cycle = (uint32_t)hal_get_cycles(); 314 if( DEBUG_HAL_NIC_TX < cycle ) 315 printk("\n[%s] thread[%x,%x] enter / WRITE / chdev %x / chbuf %x / len %d / cycle %d\n", 316 __FUNCTION__, this->process->pid, this->trdid, dev_ptr, chbuf, length, cycle ); 317 soclib_nic_chbuf_display( chbuf , dev_ptr->name ); 318 #endif 319 // check container STS 320 if( container[511] != 0 ) // container full 321 { 322 // return failure 323 this->nic_cmd.status = 0; 324 this->nic_cmd.error = 0; 325 326 #if DEBUG_HAL_NIC_TX 327 cycle = (uint32_t)hal_get_cycles(); 328 if( DEBUG_HAL_NIC_TX < cycle ) 329 printk("\n[%s] thread[%x,%x] WRITE failure : NIC_TX[%d] queue full / cycle %d\n", 330 __FUNCTION__, this->process->pid , this->trdid , dev_ptr->channel , cycle ); 331 soclib_nic_chbuf_display( chbuf , dev_ptr->name ); 332 #endif 333 } 334 else // container empty 335 { 336 // move the packet from buffer to container 337 memcpy( container , buffer , length ); 338 339 // update packet length in container header 340 container[510] = length; 341 342 hal_fence(); 343 344 // update container STS 345 container[511] = 1; 346 347 // update current container WID 348 chbuf->wid = (index + 1) % SOCLIB_NIC_CHBUF_DEPTH; 349 350 // software L2/L3 cache coherence for container DATA write 351 if( chdev_dir.iob ) dev_mmc_sync( XPTR( local_cxy , container ), length ); 352 353 // software L2/L3 cache coherence for container LENGTH and STS write 354 if( chdev_dir.iob ) dev_mmc_sync( XPTR( local_cxy , &container[510] ) , 8 ); 355 356 // software L2/L3 cache coherence for chbuf WID write 357 if( chdev_dir.iob ) dev_mmc_sync( XPTR( local_cxy , chbuf ) , 8 ); 358 359 // return success 360 this->nic_cmd.status = length; 361 this->nic_cmd.error = 0; 362 363 #if DEBUG_HAL_NIC_TX 364 cycle = (uint32_t)hal_get_cycles(); 365 if( DEBUG_HAL_NIC_TX < cycle ) 366 printk("\n[%s] thread[%x,%x] WRITE success on NIC_TX[%d] / len %d / cycle %d\n", 367 __FUNCTION__, this->process->pid, this->trdid, dev_ptr->channel , length, cycle ); 368 soclib_nic_chbuf_display( chbuf , dev_ptr->name ); 369 #endif 370 } 371 } 372 break; // end WRITE 373 374 ///////////////////////////////////////////////////////////////////////// 375 case NIC_CMD_READ: // move one packet from RX queue to kernel buffer 376 { 377 378 // check chdev is local 379 assert( (dev_cxy == local_cxy), "illegal cluster for a READ command"); 380 381 // get target buffer 382 buffer = this->nic_cmd.buffer; 383 384 // get chbuf descriptor pointer 385 chbuf = (nic_chbuf_t *)dev_ptr->ext.nic.queue; 386 387 // software L2/L3 cache coherence for chbuf WID & RID read 388 if( chdev_dir.iob ) dev_mmc_inval( XPTR ( local_cxy , chbuf ) , 8 ); 389 390 // get container read index 391 index = chbuf->rid; 392 393 // get pointer on container (no L2/L3 cache coherence required) 394 container = chbuf->cont_ptr[index]; 395 396 // software L2/L3 cache coherence for container STS & PLEN read 397 if( chdev_dir.iob ) dev_mmc_inval( XPTR( local_cxy , container + 510 ), 8 ); 398 399 #if DEBUG_HAL_NIC_RX 400 uint32_t cycle = (uint32_t)hal_get_cycles(); 401 if( DEBUG_HAL_NIC_RX < cycle ) 402 printk("\n[%s] thread[%x,%x] enter / READ / chdev %x / chbuf %x / cycle %d\n", 403 __FUNCTION__, this->process->pid, this->trdid, dev_ptr, chbuf, cycle ); 404 soclib_nic_chbuf_display( chbuf , dev_ptr->name ); 405 #endif 406 // check container state 407 if( container[511] == 0 ) // container empty 408 { 409 // return failure 410 this->nic_cmd.status = 0; 411 this->nic_cmd.error = 0; 412 413 #if DEBUG_HAL_NIC_RX 414 cycle = (uint32_t)hal_get_cycles(); 415 if( DEBUG_HAL_NIC_RX < cycle ) 416 printk("\n[%s] thread[%x,%x] READ failure : NIC_RX[%d] queue empty / cycle %d\n", 417 __FUNCTION__, this->process->pid, this->trdid, dev_ptr->channel , cycle ); 418 soclib_nic_chbuf_display( chbuf , dev_ptr->name ); 419 #endif 420 } 421 else // container full 422 { 423 // get packet length from container 424 length = container[510]; 425 426 // software L2/L3 cache coherence for container DATA 427 if( chdev_dir.iob ) dev_mmc_inval( XPTR( local_cxy , container) , length ); 428 429 // move the packet from container to buffer 430 memcpy( buffer , container , length ); 431 432 hal_fence(); 433 434 // update container STS 435 container[511] = 0; 436 437 // update current container WID 438 chbuf->rid = (index + 1) % SOCLIB_NIC_CHBUF_DEPTH; 439 440 // software L2/L3 cache coherence for container STS write 441 if( chdev_dir.iob ) dev_mmc_sync( XPTR( local_cxy , &container[511] ), 4 ); 442 443 // software L2/L3 cache coherence for chbuf RID write 444 if( chdev_dir.iob ) dev_mmc_sync( XPTR ( local_cxy , chbuf ) , 8 ); 445 446 // return success 447 this->nic_cmd.status = length; 448 this->nic_cmd.error = 0; 449 450 #if DEBUG_HAL_NIC_RX 451 uint32_t cycle = (uint32_t)hal_get_cycles(); 452 if( DEBUG_HAL_NIC_RX < cycle ) 453 printk("\n[%s] thread[%x,%x] READ success on NIC_RX[%d] queue / len %d / cycle %d\n", 454 __FUNCTION__, this->process->pid, this->trdid , dev_ptr->channel , length , cycle ); 455 soclib_nic_chbuf_display( chbuf , dev_ptr->name ); 456 #endif 457 } 155 458 } 156 459 break; // end READ 157 460 158 ////////////////////////////////////////////////////////////////////////// 159 case NIC_CMD_WRITE: // move one packet from command buffer to TX queue 160 { 161 // get current TX container indexes 162 cont_id = chbuf->cont_id; 163 pkt_id = chbuf->pkt_id; 164 word_id = chbuf->word_id; 165 166 assert( chbuf->full[cont_id] != 0, "Write to a full container\n" ); 167 168 // get pointer on container and header 169 container = chbuf->cont[cont_id]; 170 header = (uint16_t *)container; 171 172 assert( length > ((1024 - word_id) << 2), 173 "Write to a non writable container, packet length too large\n"); 174 175 // update packet length in container header 176 header[pkt_id + 2] = (uint16_t)length; 177 178 // move the packet from buffer to container 179 memcpy( container + word_id , buffer , length ); 180 181 // update current packet index and first word index 182 chbuf->pkt_id = pkt_id + 1; 183 if( length & 0x3 ) chbuf->word_id = word_id + (length>>2) + 1; 184 else chbuf->word_id = word_id + (length>>2); 185 } 186 break; // end WRITE 187 188 //////////////////////////////////////////////////////////////////////////// 189 case NIC_CMD_WRITABLE: // analyse chbuf status / update status if required 190 { 191 // get current container state 192 cont_id = chbuf->cont_id; 193 word_id = chbuf->word_id; 194 195 // compute current container writable 196 bool_t ok = ( chbuf->full[cont_id] == 0 ) && 197 ( length <= ((1024 - word_id)<<2) ); 198 199 if( ok ) // current container writable 200 { 201 // return chbuf writable 202 thread_ptr->nic_cmd.status = true; 203 } 204 else // current container not writable 205 { 206 // release current container 207 chbuf->full[cont_id] = 1; 208 209 // check next container 210 cont_id = (cont_id + 1) % CONFIG_NIC_CHBUF_DEPTH; 211 212 if( chbuf->full[cont_id] == 0 ) // next container empty 213 { 214 // update chbuf status 215 chbuf->word_id = 34; 216 chbuf->cont_id = cont_id; 217 chbuf->pkt_id = 0; 218 219 // return chbuf writable 220 thread_ptr->nic_cmd.status = true; 221 } 222 else // next container full 223 { 224 // return chbuf non writable 225 thread_ptr->nic_cmd.status = false; 226 } 227 } 228 } 229 break; // end WRITABLE 230 231 ///////////////////////////////////////////////////////////////////////////// 232 case NIC_CMD_READABLE: // analyse chbuf status / update status if required 233 { 234 // get current container state 235 cont_id = chbuf->cont_id; 236 pkt_id = chbuf->pkt_id; 237 npackets = chbuf->cont[cont_id][0] & 0x0000FFFF; 238 239 // compute current container readable 240 bool_t ok = ( chbuf->full[cont_id] == 1 ) && 241 ( pkt_id < npackets ); 242 243 if( ok ) // current container readable 244 { 245 // return chbuf readable 246 thread_ptr->nic_cmd.status = true; 247 } 248 else // current container non readable 249 { 250 // release current container 251 chbuf->full[cont_id] = 0; 252 253 // check next container 254 cont_id = (cont_id + 1) % CONFIG_NIC_CHBUF_DEPTH; 255 256 if( chbuf->full[cont_id] == 1 ) // next container full 257 { 258 // update chbuf status 259 chbuf->word_id = 34; 260 chbuf->cont_id = cont_id; 261 chbuf->pkt_id = 0; 262 263 // return chbuf readable 264 thread_ptr->nic_cmd.status = true; 265 } 266 else // next container empty 267 { 268 // return chbuf non readable 269 thread_ptr->nic_cmd.status = false; 270 } 271 } 272 273 } 274 break; // end READABLE 275 default: { 461 ///////////////////////////////////////////////////////////////////// 462 case NIC_CMD_GET_KEY: // return channel from IP addr & port 463 { 464 // get number of NIC channels 465 uint32_t channels = LOCAL_CLUSTER->nb_nic_channels; 466 467 // get IP address and port from command in thread descriptor 468 uint32_t addr = (intptr_t)this->nic_cmd.buffer; 469 uint16_t port = (uint16_t)this->nic_cmd.length; 470 471 // compute NIC channel index 472 uint32_t key = ( ((addr ) & 0xFF) + 473 ((addr > 8 ) & 0xFF) + 474 ((addr > 16) & 0xFF) + 475 ((addr > 24) & 0xFF) + 476 ((port ) & 0xFF) + 477 ((port > 8 ) & 0xFF) ) % channels; 478 479 // return key in "status" and return "error" 480 this->nic_cmd.status = key; 481 this->nic_cmd.error = 0; 482 } 483 break; // end GET_KEY 484 485 ///////////////////////////////////////////////////////////////////// 486 case NIC_CMD_SET_RUN: // activate/desactivate one NIC channel 487 { 488 // get pointers on NIC peripheral 489 xptr_t base_xp = dev_ptr->base; 490 uint32_t * base_ptr = GET_PTR( base_xp ); 491 cxy_t base_cxy = GET_CXY( base_xp ); 492 493 // get channel and run from the "length" and "status" arguments 494 uint32_t channel = this->nic_cmd.length; 495 uint32_t run = this->nic_cmd.status; 496 497 // build pointers on channel base 498 uint32_t * channel_ptr = base_ptr + NIC_CHANNEL_SPAN * channel; 499 500 // set new value in NIC_RX_CHANNEL_RUN & NIC_TX_CHANNEL_RUN registers 501 hal_remote_s32( XPTR( base_cxy , channel_ptr + NIC_RX_CHANNEL_RUN ) , run ); 502 hal_remote_s32( XPTR( base_cxy , channel_ptr + NIC_TX_CHANNEL_RUN ) , run ); 503 504 // return "error" 505 this->nic_cmd.error = 0; 506 } 507 break; // end SET_RUN 508 509 ///////////////////////////////////////////////////////////////////// 510 case NIC_CMD_GET_INSTRU: // diplay packets counters on TXT0 511 { 512 // get pointers on NIC peripheral 513 xptr_t base_xp = dev_ptr->base; 514 uint32_t * base_ptr = GET_PTR( base_xp ); 515 cxy_t base_cxy = GET_CXY( base_xp ); 516 517 // build pointer on global register base 518 uint32_t * global_ptr = base_ptr + NIC_GLOBAL_OFFSET; 519 520 uint32_t rx_g2s_received = hal_remote_l32( XPTR( base_cxy , 521 global_ptr + NIC_G_NPKT_RX_G2S_RECEIVED )); 522 uint32_t rx_g2s_discarded = hal_remote_l32( XPTR( base_cxy , 523 global_ptr + NIC_G_NPKT_RX_G2S_DISCARDED )); 524 uint32_t rx_des_success = hal_remote_l32( XPTR( base_cxy , 525 global_ptr + NIC_G_NPKT_RX_DES_SUCCESS )); 526 uint32_t rx_des_too_small = hal_remote_l32( XPTR( base_cxy , 527 global_ptr + NIC_G_NPKT_RX_DES_TOO_SMALL )); 528 uint32_t rx_des_too_big = hal_remote_l32( XPTR( base_cxy , 529 global_ptr + NIC_G_NPKT_RX_DES_TOO_BIG )); 530 uint32_t rx_des_mfifo_full = hal_remote_l32( XPTR( base_cxy , 531 global_ptr + NIC_G_NPKT_RX_DES_MFIFO_FULL )); 532 uint32_t rx_des_crc_fail = hal_remote_l32( XPTR( base_cxy , 533 global_ptr + NIC_G_NPKT_RX_DES_CRC_FAIL )); 534 uint32_t rx_disp_received = hal_remote_l32( XPTR( base_cxy , 535 global_ptr + NIC_G_NPKT_RX_DISP_RECEIVED )); 536 uint32_t rx_disp_dst_fail = hal_remote_l32( XPTR( base_cxy , 537 global_ptr + NIC_G_NPKT_RX_DISP_DST_FAIL )); 538 uint32_t rx_disp_ch_full = hal_remote_l32( XPTR( base_cxy , 539 global_ptr + NIC_G_NPKT_RX_DISP_CH_FULL )); 540 541 uint32_t tx_disp_received = hal_remote_l32( XPTR( base_cxy , 542 global_ptr + NIC_G_NPKT_TX_DISP_RECEIVED )); 543 uint32_t tx_disp_too_small = hal_remote_l32( XPTR( base_cxy , 544 global_ptr + NIC_G_NPKT_TX_DISP_TOO_SMALL )); 545 uint32_t tx_disp_too_big = hal_remote_l32( XPTR( base_cxy , 546 global_ptr + NIC_G_NPKT_TX_DISP_TOO_BIG )); 547 uint32_t tx_disp_transmit = hal_remote_l32( XPTR( base_cxy , 548 global_ptr + NIC_G_NPKT_TX_DISP_TRANSMIT )); 549 550 printk("\n*** NIC device Instrumentation ***\n\n" 551 " - rx_g2s_received = %d\n" 552 " - rx_g2s_discarded = %d\n" 553 " - rx_des_success = %d\n" 554 " - rx_des_too_small = %d\n" 555 " - rx_des_too_big = %d\n" 556 " - rx_des_mfifo_full = %d\n" 557 " - rx_des_crc_fail = %d\n" 558 " - rx_disp_received = %d\n" 559 " - rx_disp_dsp_fail = %d\n" 560 " - rx_disp_ch_full = %d\n\n" 561 " - tx_disp_received = %d\n" 562 " - tx_disp_too_small = %d\n" 563 " - tx_disp_too_big = %d\n" 564 " - tx_disp_transmit = %d\n", 565 rx_g2s_received, 566 rx_g2s_discarded, 567 rx_des_success, 568 rx_des_too_small, 569 rx_des_too_big, 570 rx_des_mfifo_full, 571 rx_des_crc_fail, 572 rx_disp_received, 573 rx_disp_dst_fail, 574 rx_disp_ch_full, 575 tx_disp_received, 576 tx_disp_too_small, 577 tx_disp_too_big, 578 tx_disp_transmit ); 579 580 // return "error" 581 this->nic_cmd.error = 0; 582 } 583 break; // end CLEAR_INSTRU 584 585 ///////////////////////////////////////////////////////////////////// 586 case NIC_CMD_CLEAR_INSTRU: // reset instrumentation registers 587 { 588 // get pointers on NIC peripheral 589 xptr_t base_xp = dev_ptr->base; 590 uint32_t * base_ptr = GET_PTR( base_xp ); 591 cxy_t base_cxy = GET_CXY( base_xp ); 592 593 // build pointer on relevant NIC register 594 uint32_t * reset_ptr = base_ptr + NIC_GLOBAL_OFFSET + NIC_G_NPKT_RESET; 595 596 // reset all NIC instrumentation registers 597 hal_remote_s32( XPTR( base_cxy , reset_ptr ) , 0 ); 598 599 // return "error" 600 this->nic_cmd.error = 0; 601 } 602 break; // end GET_INSTRU 603 604 default: 605 { 276 606 assert( false, "Unknown command <%x>\n", type ); 277 607 } … … 284 614 { 285 615 // get base, size, channel, is_rx from NIC channel device NIC 286 xptr_t base 616 xptr_t base_xp = chdev->base; 287 617 uint32_t channel = chdev->channel; 288 618 bool_t is_rx = chdev->is_rx; 289 619 290 620 // get NIC peripheral cluster and local pointer 291 cxy_t cxy_nic = GET_CXY( base);292 uint32_t * ptr_nic = (uint32_t *)GET_PTR( base);293 294 // compute local pointer on stat usregister295 uint32_t * offset;296 if( is_rx ) offset = ptr_nic + (NIC_CHANNEL_SPAN * (channel + 1)) + NIC_RX_STATUS;297 else offset = ptr_nic + (NIC_CHANNEL_SPAN * (channel + 1)) + NIC_TX_STATUS;621 cxy_t nic_cxy = GET_CXY( base_xp ); 622 uint32_t * nic_ptr = GET_PTR( base_xp ); 623 624 // compute local pointer on state register 625 uint32_t * ptr; 626 if( is_rx ) ptr = nic_ptr + (NIC_CHANNEL_SPAN * channel) + NIC_RX_CHANNEL_STATE; 627 else ptr = nic_ptr + (NIC_CHANNEL_SPAN * channel) + NIC_TX_CHANNEL_STATE; 298 628 299 629 // read NIC channel status and acknowledge IRQ 300 uint32_t status = hal_remote_l32( XPTR( cxy_nic , offset ) ); 301 302 assert( status != 0, "Illegal address: \n" ); 630 uint32_t status = hal_remote_l32( XPTR( nic_cxy , ptr ) ); 631 632 // check status value 633 if( is_rx && (status != NIC_CHANNEL_STATUS_IDLE) ) 634 printk("\n[PANIC] in %s : error reported by NIC_RX[%d]\n", __FUNCTION__, channel ); 635 if( (is_rx == false) && (status != NIC_CHANNEL_STATUS_IDLE) ) 636 printk("\n[PANIC] in %s : error reported by NIC_TX[%d]\n", __FUNCTION__, channel ); 303 637 304 638 // unblock server thread 305 639 thread_t * server = chdev->server; 306 thread_unblock( XPTR( local_cxy , server ) , THREAD_BLOCKED_IO ); 640 thread_unblock( XPTR( local_cxy , server ) , THREAD_BLOCKED_ISR ); 641 642 #if (DEBUG_HAL_NIC_RX || DEBUG_HAL_NIC_TX) 643 uint32_t cycle = (uint32_t)hal_get_cycles(); 644 if( is_rx && DEBUG_HAL_NIC_RX < cycle ) 645 printk("\n[%s] ISR unblocks NIC_RX[%d] server thread / cycle %d\n", 646 __FUNCTION__, channel, cycle ); 647 if( (is_rx == false) && DEBUG_HAL_NIC_TX < cycle ) 648 printk("\n[%s] ISR unblocks NIC_TX[%d] server thread / cycle %d\n", 649 __FUNCTION__, channel, cycle ); 650 #endif 307 651 308 652 } // end soclib_nic_isr() 309 653 310 311
Note: See TracChangeset
for help on using the changeset viewer.