- Timestamp:
- Oct 10, 2020, 3:48:50 PM (4 years ago)
- Location:
- trunk/hal
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/hal/generic/hal_uspace.h
r657 r658 30 30 // User space access API (implementation in hal_uspace.c) 31 31 // 32 // For sake of portability, user/kernel data transfers must use the following API. 33 // 32 34 // When moving data between user space and kernel space, the user address is always 33 // a virtual address, but the kernel address is an extended pointer. 34 // For sake of portability, user/kernel data transfers must use the following API. 35 // a virtual address, and the kernel address is an extended pointer. 36 // Therefore, each of these buffers can be located in any cluster. 37 // 38 // WARNING: these function must be executed by an user thread (i.e. PID > 0), 39 // to handle a possible page fault when accessing the user buffer. 35 40 ////////////////////////////////////////////////////////////////////////////////////////// 36 41 37 42 38 43 /***************************************************************************************** 39 * This function tranfers a data buffer in user space to a kernel buffer 40 * that can be located in any cluster. 44 * This function moves <size> bytes from a source buffer in user virtual space, 45 * defined by the <u_src_ptr> argument, to a destination kernel buffer, defined by the 46 * <k_dst_xp> argument. 41 47 ***************************************************************************************** 42 48 * @ k_dst_xp : extended pointer on kernel destination buffer. … … 49 55 50 56 /***************************************************************************************** 51 * This function tranfers a kernel buffer that can be located in any cluster 52 * to a data buffer in the user space. 57 * This function moves <size> bytes from a source kernel buffer, defined by the 58 * <k_src_xp> argument, to a destination buffer in user virtual space, defined by 59 * the <u_dst_ptr> argument. 53 60 ***************************************************************************************** 54 61 * @ u_dst_ptr : destination buffer address in user space. … … 87 94 88 95 /***************************************************************************************** 89 * This function computes the length of a stringin user space.96 * This function returns the length of a string located in user space. 90 97 ***************************************************************************************** 91 98 * @ string : string in user space. -
trunk/hal/tsar_mips32/core/hal_gpt.c
r647 r658 1187 1187 1188 1188 1189 1190 1191 -
trunk/hal/tsar_mips32/core/hal_special.c
r625 r658 292 292 } 293 293 294 -
trunk/hal/tsar_mips32/core/hal_uspace.c
r657 r658 31 31 32 32 /////////////////////////////////////////////////////////////////////////////////////// 33 // This function moves <size> bytes from a source buffer in user virtual space, 34 // defined by the <u_src_ptr> argument, to a destination kernel buffer, defined by the 35 // <k_dst_xp> argument. 33 // Implementation note 36 34 // It works in a critical section, as it modifies two CP2 registers: 37 35 // It activates briefly the DATA_MMU by writing into the CP2_MODE register to access the … … 41 39 // If the buffers are not aligned, it moves all data byte per byte. 42 40 /////////////////////////////////////////////////////////////////////////////////////// 43 // @ k_dst_xp : extended pointer on destination kernel buffer44 // @ u_src_ptr : pointer on source user buffer45 // @ size : number of bytes to move46 ///////////////////////////////////////////////////////////////////////////////////////47 41 void hal_copy_from_uspace( xptr_t k_dst_xp, 48 42 void * u_src_ptr, … … 55 49 uint32_t cxy = (uint32_t)GET_CXY( k_dst_xp ); 56 50 51 assert( (CURRENT_THREAD->process->pid > 0), "must be called by an user thread" ); 52 57 53 #if DEBUG_HAL_USPACE 58 54 thread_t * this = CURRENT_THREAD; … … 133 129 134 130 /////////////////////////////////////////////////////////////////////////////////////// 135 // This function moves <size> bytes from a source kernel buffer, defined by the 136 // <k_src_xp> argument, to a destination buffer in user virtual space, defined by 137 // the <u_dst_ptr> argument. 131 // Implementation note 138 132 // It works in a critical section, as it modifies two CP2 registers: 139 133 // It activates briefly the DATA_MMU by writing into the CP2_MODE register to access the … … 143 137 // If the buffers are not word aligned, it moves all data byte per byte. 144 138 /////////////////////////////////////////////////////////////////////////////////////// 145 // @ u_dst_ptr : pointer on destination user buffer146 // @ k_src_xp : extended pointer on source kernel buffer147 // @ size : number of bytes to move148 ///////////////////////////////////////////////////////////////////////////////////////149 139 void hal_copy_to_uspace( void * u_dst_ptr, 150 140 xptr_t k_src_xp, … … 156 146 uint32_t src = (uint32_t)GET_PTR( k_src_xp ); 157 147 uint32_t cxy = (uint32_t)GET_CXY( k_src_xp ); 148 149 assert( (CURRENT_THREAD->process->pid > 0), "must be called by an user thread" ); 158 150 159 151 #if DEBUG_HAL_USPACE … … 244 236 uint32_t cxy = (uint32_t)GET_CXY( k_dst_xp ); 245 237 238 assert( (CURRENT_THREAD->process->pid > 0), "must be called by an user thread" ); 239 246 240 hal_disable_irq( &save_sr ); 247 241 … … 297 291 uint32_t cxy = (uint32_t)GET_CXY( k_src_xp ); 298 292 293 assert( (CURRENT_THREAD->process->pid > 0), "must be called by an user thread" ); 294 299 295 hal_disable_irq( &save_sr ); 300 296 … … 346 342 uint32_t count = 0; 347 343 uint32_t str = (uint32_t)u_str; 344 345 assert( (CURRENT_THREAD->process->pid > 0), "must be called by an user thread" ); 348 346 349 347 hal_disable_irq( &save_sr ); -
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 -
trunk/hal/tsar_mips32/drivers/soclib_nic.h
r451 r658 2 2 * soclib_nic.h - SOCLIB_NIC (Network Interface Controler) driver definition. 3 3 * 4 * Author Alain Greiner (2016 )4 * Author Alain Greiner (2016,2017,2018,2019,2020) 5 5 * 6 6 * Copyright (c) UPMC Sorbonne Universites … … 30 30 /******************************************************************************************** 31 31 * This driver supports the Soclib VciMasterNic component, that is a GMII compliant 32 * multi-channels Gigabit Ethernet controler. 33 * 34 * The VciMasterNic component supports up to 4 channels, indexed by the source IP address 35 * for the RX packets, and by the destination IP address for the TX packets. 32 * multi-channels Gigabit Ethernet controler with a DMA capability. 33 * 34 * To improve the throughput, this component supports several channels. 35 * The channel index is derived from the (source) remote IP address and port 36 * for the received (RX) packets, and from the (destination) remote IP address 37 * and port for the sent (TX) packets. The actual number of channels is an 38 * hardware parameter that cannot be larger than 8. 39 * 40 * The Ethernet packet length can have any value, in range [42,1538] bytes. 36 41 * 37 * The Ethernet packet length can have any value, between 64 to 1538 bytes. 38 * The data transfer unit between software and the NIC is a 4 Kbytes "container", 39 * containing an integer number of variable size packets. 40 * 41 * The max number of packets in a container is 66 packets. 42 * The first 34 words of a container are the container header : 43 * 44 * word0 | NB_WORDS | NB_PACKETS | 45 * word1 | PLEN[0] | PLEN[1] | 46 * ... | ....... | ........ | 47 * word33 | PLEN[64] | PLEN[65] | 48 * 49 * - NB_PACKETS is the actual number of packets in the container. 50 * - NB_WORDS is the number of useful words in the container. 51 * - PLEN[i] is the number of bytes for the packet[i]. 52 * 53 * Packets are stored in the (1024 - 34) following words, and the packets are word-aligned. 54 * 55 * The TX and RX queues are implemented as chained buffers, where each buffer is a 4 Kbytes 56 * container. Each container is protected by a SET/RESET synchronisation variable. 57 * The structure implementing the chbuf descriptor is described below. 58 * 59 * To access both the container status, and the data contained in the container, the NIC 60 * uses two physical addresses, that are packed in a 64 bits "container descriptor". 61 * - desc[25:0] contain bits[31:6] of the status physical address. 62 * - desc[51:26] contain bits[31:6] of the buffer physical address. 63 * - desc[63:52] contain the common 12 physical address extension bits. 64 *******************************************************************************************/ 65 66 /******************************************************************************************** 67 * Addressable registers offsets 42 * For each channel, the received packets (RX) and the sent packets (TX) are stored 43 * in two memory mapped software FIFOs, called NIC_TX_QUEUE and NIC_RX_QUEUE, implemented 44 * as chained buffers (chbuf). Each slot in these FIFOs is a container, containing one 45 * single packet. The number of containers, defining the queue depth, is a software defined 46 * parameter. The data transfer unit between is a container (one single packet). 47 * 48 * - The "container" structure contains a 2040 bytes data buffer, the packet length, and 49 * the container state : full (owned by the reader) / empty (owned by the writer). 50 * For each container, the state variable is used as a SET/RESET flip-flop to synchronize 51 * the software server thread, and the hardware NIC DMA engines. 52 * 53 * - The "chbuf" descriptor contains an array of local pointers on the containers, used 54 * by the software driver, an array of physical addresses, used by the DMA engines and 55 * two "pointers", defining the current container to be written (wid) by the writer, 56 * and the current container to be read (rid) by the reader. 57 * 58 * WARNING : Both the chbuf descriptor (containing the <rid> and wid> indexes), and the 59 * containers themselve containing the <data> and the <sts> are shared variables 60 * accessed by the server threads (accessing the L2 caches), and by the NIC_DMA 61 * engines (accessing directly the L3 caches). 62 * Therefore, the L2/L3 cache coherence must be handled by this NIC driver for 63 * the INIT, READ & WRITE commands, using the MMC SYNC & INVAL commands. 64 *******************************************************************************************/ 65 66 /******************************************************************************************** 67 * This section defines the NIC device addressable registers offsets: 68 * - The 8 channels registers are stored in the first 512 bytes (8 * 64 bytes). 69 * - The global registers are stored in the next 256 bytes (global offset is 512 bytes). 70 * All values defined below are number of words (one word = 4 bytes). 68 71 *******************************************************************************************/ 69 72 70 73 enum SoclibMasterNicGlobalRegisters 71 74 { 72 NIC_G_RUN = 0, /*! read_write : NIC component activated */ 73 NIC_G_NB_CHANNELS = 1, /*! read_only : number of channels */ 74 NIC_G_BC_ENABLE = 2, /*! read_write : broadcast enabled if non zero */ 75 NIC_G_PERIOD = 3, /*! read-write : container status poll period */ 76 NIC_G_MAC_4 = 4, /*! read-write : mac address 32 LSB bits */ 77 NIC_G_MAC_2 = 5, /*! read-write : mac address 16 MSB bits */ 75 NIC_G_CHANNELS = 1, /*! read_only : number of channels */ 76 NIC_G_NPKT_RESET = 2, /*! write-only : reset packets counters */ 78 77 79 78 NIC_G_NPKT_RX_G2S_RECEIVED = 10, /*! number of packets received */ 80 79 NIC_G_NPKT_RX_G2S_DISCARDED = 11, /*! number of RX packets discarded by RX_G2S */ 80 81 81 NIC_G_NPKT_RX_DES_SUCCESS = 12, /*! number of RX packets transmited by RX_DES */ 82 82 NIC_G_NPKT_RX_DES_TOO_SMALL = 13, /*! number of discarded too small RX packets */ … … 84 84 NIC_G_NPKT_RX_DES_MFIFO_FULL = 15, /*! number of discarded RX packets fifo full */ 85 85 NIC_G_NPKT_RX_DES_CRC_FAIL = 16, /*! number of discarded RX packets CRC32 */ 86 NIC_G_NPKT_RX_DISPATCH_RECEIVED = 17, /*! number of packets received by RX_DISPATCH */ 87 NIC_G_NPKT_RX_DISPATCH_BROADCAST = 18, /*! number of broadcast RX packets received */ 88 NIC_G_NPKT_RX_DISPATCH_DST_FAIL = 19, /*! number of discarded RX packets for DST MAC */ 89 NIC_G_NPKT_RX_DISPATCH_CH_FULL = 20, /*! number of discarded RX packets cont full */ 90 91 NIC_G_NPKT_TX_DISPATCH_RECEIVED = 41, /*! number of packets received by TX_DISPATCH */ 92 NIC_G_NPKT_TX_DISPATCH_TOO_SMALL = 42, /*! number of discarded too small TX packets */ 93 NIC_G_NPKT_TX_DISPATCH_TOO_BIG = 43, /*! number of discarded too big TX packets */ 94 NIC_G_NPKT_TX_DISPATCH_SRC_FAIL = 44, /*! number of discarded TX packets for SRC MAC */ 95 NIC_G_NPKT_TX_DISPATCH_BROADCAST = 45, /*! number of broadcast TX packets received */ 96 NIC_G_NPKT_TX_DISPATCH_TRANSMIT = 46, /*! number of transmit TX packets */ 97 98 NIC_GLOBAL_SPAN = 64 /*! 256 bytes for global registers */ 86 87 NIC_G_NPKT_RX_DISP_RECEIVED = 17, /*! number of packets received by RX_DISPATCH */ 88 NIC_G_NPKT_RX_DISP_DST_FAIL = 18, /*! number of discarded RX packets for DST MAC */ 89 NIC_G_NPKT_RX_DISP_CH_FULL = 19, /*! number of discarded RX packets cont full */ 90 91 NIC_G_NPKT_TX_DISP_RECEIVED = 41, /*! number of packets received by TX_DISPATCH */ 92 NIC_G_NPKT_TX_DISP_TOO_SMALL = 42, /*! number of discarded too small TX packets */ 93 NIC_G_NPKT_TX_DISP_TOO_BIG = 43, /*! number of discarded too big TX packets */ 94 NIC_G_NPKT_TX_DISP_TRANSMIT = 44, /*! number of discarded TX packets for SRC MAC */ 95 96 NIC_GLOBAL_OFFSET = 128, /*! 512 bytes reserved for channel registers */ 99 97 }; 100 98 101 99 enum SoclibMasterNicChannelRegisters 102 100 { 103 NIC_RX_ STATUS = 0, /*! read-only : RX channel status*/104 NIC_RX_CHBUF_DESC_L 0 = 1, /*! read-write : RX chbuf descriptor 32 LSB bits */105 NIC_RX_CHBUF_DESC_HI = 2, /*! read-write : RX chbuf descriptor 32 MSB bits */ 101 NIC_RX_CHANNEL_RUN = 0, /*! write-only : RX channel activation/desactivation */ 102 NIC_RX_CHBUF_DESC_LO = 1, /*! read-write : RX chbuf descriptor 32 LSB bits */ 103 NIC_RX_CHBUF_DESC_HI = 2, /*! read-write : RX chbuf descriptor 32 MSB bits */ 106 104 NIC_RX_CHBUF_NBUFS = 3, /*! read-write : RX chbuf depth (number of buffers) */ 107 108 NIC_TX_STATUS = 8, /*! read-only : TX channel status */ 109 NIC_TX_CHBUF_DESC_L0 = 9, /*! read-write : TX chbuf descriptor 32 LSB bits */ 110 NIC_TX_CHBUF_DESC_HI = 10, /*! read-write : TX chbuf descriptor 32 MSB bits */ 105 NIC_RX_CHANNEL_STATE = 4, /*! read-only : RX channel status */ 106 107 NIC_TX_CHANNEL_RUN = 8, /*! write-only : TX channel activation */ 108 NIC_TX_CHBUF_DESC_LO = 9, /*! read-write : TX chbuf descriptor 32 LSB bits */ 109 NIC_TX_CHBUF_DESC_HI = 10, /*! read-write : TX chbuf descriptor 32 MSB bits */ 111 110 NIC_TX_CHBUF_NBUFS = 11, /*! read-write : TX chbuf depth (number of buffers) */ 111 NIC_TX_CHANNEL_STATE = 12, /*! read-only : TX channel status */ 112 112 113 113 NIC_CHANNEL_SPAN = 16 /*! 64 bytes per channel */ 114 114 }; 115 116 117 118 /******************************************************************************************** 119 * This structure defines the chained buffer descriptor, used to implement both 120 * the RX and TX packets queues. Each buffer in a chbuf is a 4 Kbytes container 121 * containing a variable number of packets. All containers are allocated in 122 * the same cluster as the associated NIC device descriptor. The chbuf descriptor contains: 123 * - an array of container pointers cont[], used by the kernet threads to access the 124 * packets contained in the containers. 125 * - an array of set/reset Boolean full[] used by both the software threads and 126 * by the hardware FSMs for lock-less synchronisation. 127 * - an array of containers descriptors containing the physical addresses of the 128 * "full[i]" and "cont[i]" variables, used by the DMA FSMs. 129 * Moreover, It contains three pointers (cont_id, pkt_id, and word_id) that are private 130 * variables used by the software thread to scan the chbuf. 131 *******************************************************************************************/ 115 116 /******************************************************************************************** 117 * Return values for the RX/TX channel master FSM status 118 *******************************************************************************************/ 119 120 enum SoclibMasterNicStatusValues 121 { 122 NIC_CHANNEL_STATUS_IDLE = 0, 123 NIC_CHANNEL_STATUS_ERROR = 1, 124 NIC_CHANNEL_STATUS_BUSY = 2, // busy for any value >= 2 125 }; 126 127 /******************************************************************************************** 128 * This structure defines the chbuf descriptor, used to implement both the RX and TX packets 129 * queues. Each container contains one single packet, and has only two states (full/empty). 130 * All containers are allocated in the same cluster as the associated NIC chdev descriptor. 131 * The chbuf descriptor contains: 132 * - an array of containers physical addresses cont_pad[], used by the DMA engines. 133 * - an array of container pointers cont_ptr[], used by the kernel threads. 134 * - two indexes rid and wid, defining the next container for read & write respectively. 135 * WARNING : dont modify this structure, used by the DMA engines. 136 *******************************************************************************************/ 137 138 #define SOCLIB_NIC_CHBUF_DEPTH 8 132 139 133 140 typedef struct nic_chbuf_s 134 141 { 135 uint32_t * cont[CONFIG_NIC_CHBUF_DEPTH]; /*! container virtual base address */ 136 uint32_t full[CONFIG_NIC_CHBUF_DEPTH]; /*! Boolean : container full if non zero */ 137 uint64_t desc[CONFIG_NIC_CHBUF_DEPTH]; /*! container & status physical addresses */ 138 uint32_t cont_id; /*! current container index */ 139 uint32_t pkt_id; /*! current packet index in container */ 140 uint32_t word_id; /*! first word of current packet */ 142 uint32_t wid; /*! current container write index */ 143 uint32_t rid; /*! current container read index */ 144 uint64_t cont_pad[SOCLIB_NIC_CHBUF_DEPTH]; /*! containers physical base addresses */ 145 uint32_t * cont_ptr[SOCLIB_NIC_CHBUF_DEPTH]; /*! containers virtual base addresses */ 141 146 } 142 147 nic_chbuf_t; 143 148 144 149 /******************************************************************************************** 145 * SOCLIB_NIC driver access functions 146 *******************************************************************************************/ 147 148 /******************************************************************************************** 149 * This function initializes the SOCLIB_NIC hardware registers, allocates memory for 150 * the RX and TX containers, allocates and initializes the RX and TX chbuf descriptors. 150 * This structure defines the container descriptor format. 151 *******************************************************************************************/ 152 153 typedef struct nic_cont_s 154 { 155 uint8_t buf[2040]; /*! Ethernet packet (42 to 1538 bytes */ 156 uint32_t length; /*! actual packet length in bytes */ 157 uint32_t state; /*! zero == empty / non zero == full */ 158 } 159 nic_cont_t; 160 161 /******************************************************************************************** 162 * Driver access functions 163 *******************************************************************************************/ 164 165 /******************************************************************************************** 166 * This function initializes the SOCLIB_NIC hardware registers, for one NIC chdev 167 * (one direction of one channel). It allocates memory for the RX and TX containers, 168 * it allocates and initializes the RX and TX chbuf descriptors. 151 169 * It allocates one WTI mailbox for the IRQ signaling availability of an RX full container, 152 170 * or a TX empty container, and route the WTI IRQ to the core running the server thread. 171 * It activates the TX and RX DMA engines. 153 172 ******************************************************************************************** 154 173 * @ chdev : pointer on NIC chdev descriptor. … … 157 176 158 177 /******************************************************************************************** 159 * This function implement the READ / WRITE / READABLE / WRITABLE commands for TX/RX queues. 160 * These command don't access the NIC peripheral but only the TX and TX chbufs. 161 * It must be executed by a dedicated kernel thread running in the cluster containing 162 * the CHBUF implementing the TX/RX queues. 163 * It implements also the SET_MAC, SET_BC, SET_RUN configuration commands, that directly 164 * access the NIC peripheral registers. 165 * - READABLE 166 * Returns in the command "status" a non zero value if a packet is available in RX queue. 167 * Update the RX queue read pointer if required. 168 * - READ 169 * Move a packet from the RX queue to the command "buffer", and returns the packet 170 * "length" in the command. The READABLE command must be called before the READ command. 171 * - WRITABLE 172 * Returns in the command "status" a non zero value if a packet with a given "length" 173 * can be written in the TX queue. Update the RX queue read pointer if required. 174 * - WRITE 178 * 1) This function implement the READ & WRITE commands, used by the local server threads 179 * to access the NIC_TX & NIC_RX packets queues. These commands don't access the NIC 180 * registers but only the TX and RX chbufs implementing the queues: 181 * 182 * <READ> 183 * Move a packet from the NIC_RX queue to the command "buffer". 184 * Return 0 in "status" if queue empty / return length in "status" if success. 185 * 186 * <WRITE> 175 187 * Move a packet of a given "length" from the command "buffer" to the TX queue. 176 * The WRITABLE command must be called before the WRITE command. 177 * - SET_MAC 178 * Set the values defined in the "length" and "status" command arguments, 179 * into the NIC_C_MAC4 and NIG_G_MAC2 registers. 180 * - SET_BC 181 * Enable/disable broadcast packets, as defined in the "status" command argument, 182 * into the NIC_G_BC_ENABLE register. 183 * - SET_RUN 184 * Enable/disable NIC, as defined in the "status" command argument, 185 * into the NIC_G_RUN register. 186 * @ dev_xp : extended pointer on the generic NIC device descriptor. 187 ******************************************************************************************** 188 $ @ thread_xp : extended pointer on client thread (containing the command arguments). 188 * Return 0 in "status" if queue full / return length in "status" if success. 189 * 190 * 2) It implements the GET_KEY / SET_RUN / GET_INSTRU / CLEAR_INSTRU commands, 191 * directly called by any thread running in any cluster to access the NIC registers : 192 * 193 * <GET_KEY> 194 * Return in "status" argument the channel index (key) computed from the IP address 195 * defined in the "buffer" argument, and from the port defined by the "length" argument. 196 * 197 * <SET_RUN> 198 * Enable/disable the NIC_TX_CHANNEL_RUN & NIC_RX_CHANNEL_RUN registers.The channel 199 * is defined in the "length" argument / run value defined in the "status" argument. 200 * 201 * <GET_INSTRU> 202 * Display on kernel TXT0 the contaent of all NIC instrumentation registers. 203 * 204 * <CLEAR_INSTRU> 205 * Reset all NIC instrumentation registers. 206 * 207 * Note (i) For the NIC device, the command arguments are always registered in the calling 208 * thread descriptor (i.e. the calling thread is always the client thread). 209 * Note (ii) The actual command mnemonics are defined in the <dev_nic.h> file. 189 210 *******************************************************************************************/ 190 211 extern void soclib_nic_cmd( xptr_t thread_xp ); 191 212 192 213 /******************************************************************************************** 193 * This ISR acknowledge the NIC_RX or NIC_TX channel ISR signaling that a new container 194 * has beeen moved, and reactivate the corresponding server thread. 195 * In case of address error reported by the NIC controler in accessing the kernel chbuf, 196 * it goes to kernel panic. 214 * This ISR is executed when a new RX container has been moved to an empty TX queue, 215 * or when a TX container has been removed from a full TX queue. In both cases, it 216 * reactivate the corresponding server thread from the BLOCKED_ISR condition. 217 * It is also executed in case of error reported by the DMA engines accessing the TX or RX 218 * queues. It simply print an error message on the kernel terminal. 219 * TODO improve this error handling... 197 220 ******************************************************************************************** 198 221 * @ chdev : local pointer on NIC chdev descriptor. -
trunk/hal/tsar_mips32/drivers/soclib_tty.c
r625 r658 2 2 * soclib_tty.c - soclib tty driver implementation. 3 3 * 4 * Author Alain Greiner (2016,2017,2018 )4 * Author Alain Greiner (2016,2017,2018,2019,2020) 5 5 * 6 6 * Copyright (c) UPMC Sorbonne Universites … … 418 418 419 419 // remove process from TXT list 420 // process_txt_detach( owner_xp ); 420 process_txt_detach( owner_xp ); 421 422 // close all open files 423 process_fd_clean_all( owner_xp ); 421 424 422 425 // mark for delete all thread in all clusters, but the main
Note: See TracChangeset
for help on using the changeset viewer.