source: trunk/hal/tsar_mips32/drivers/soclib_nic.c @ 686

Last change on this file since 686 was 686, checked in by alain, 3 years ago

cosmetic

File size: 26.6 KB
Line 
1/*
2 * soclib_nic.c - VCI_MASTER_NIC (Network Interface Controler) driver implementation.
3 *
4 * Author     Alain Greiner (2016,2017,2018,2019,2020)
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_kernel_types.h>
25#include <hal_remote.h>
26#include <hal_special.h>
27#include <chdev.h>
28#include <dev_nic.h>
29#include <kmem.h>
30#include <printk.h>
31#include <memcpy.h>
32#include <thread.h>
33#include <soclib_nic.h>
34
35
36////////////////////////////////////////////////////////////////////////////////////////
37// Extern global variables
38////////////////////////////////////////////////////////////////////////////////////////
39
40extern 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////////////////////////////////////////////////////////////////////////////////////////
47static 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 : cxy %x / ptr %x / wid %d / rid %d *****\n",
67    name, local_cxy , chbuf, chbuf->wid, chbuf->rid );
68
69    for( i = 0 ; i < CONFIG_SOCK_QUEUES_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 / plen %d\n",
79            i, chbuf->cont_ptr[i], container[510] );
80        }
81        else
82        {
83            nolock_printk(" - %d : EMPTY / cont_ptr %x\n",
84            i, chbuf->cont_ptr[i] ); 
85        }
86    }
87
88    // release TXT0 lock
89    remote_busylock_release( lock_xp );
90
91}  // end soclib_nic_chbuf_display()
92
93#endif
94
95///////////////////////////////////////
96void soclib_nic_init( chdev_t * chdev )
97{
98    uint32_t * container;       // local pointer on one container
99    uint32_t   cont_per_page;   // number of containers per page
100    uint32_t   cont_gid;        // container global index (in chbuf)
101    bool_t     cont_error;      // not enough memory for chbuf containers
102
103    ppn_t      ppn;             // used for both the chbuf descriptor and the containers
104    uint64_t   padr;            // used for both the chbuf descriptor and the containers
105
106assert( __FUNCTION__ , (chdev->func == DEV_FUNC_NIC),
107"bad func argument" );
108
109assert( __FUNCTION__ , (sizeof(nic_cont_t) == 2048),
110"container size must be 2048 bytes" );
111
112assert( __FUNCTION__ , (CONFIG_PPM_PAGE_ORDER >= 11 ),
113"page size cannot be smaller than container size" );
114
115    // set driver specific fields in chdev descriptor
116    chdev->cmd = &soclib_nic_cmd;
117    chdev->isr = &soclib_nic_isr;
118
119    // get chdev channel & direction
120    bool_t   is_rx   = chdev->is_rx;
121    uint32_t channel = chdev->channel;
122   
123    // get NIC device cluster and local pointer
124    cxy_t      nic_cxy  = GET_CXY( chdev->base );
125    uint32_t * nic_ptr  = GET_PTR( chdev->base );
126
127#if DEBUG_HAL_NIC_TX || DEBUG_HAL_NIC_RX
128thread_t * this  = CURRENT_THREAD;
129uint32_t   cycle = (uint32_t)hal_get_cycles();
130if( (is_rx == false) && DEBUG_HAL_NIC_RX < cycle )
131printk("\n[%s] thread[%x,%x] enter : NIC_TX channel %d / chdev %x / cycle %d\n",
132__FUNCTION__, this->process->pid, this->trdid, channel, chdev, cycle );
133if( is_rx && DEBUG_HAL_NIC_RX < cycle )
134printk("\n[%s] thread[%x,%x] enter : NIC_RX channel %d / chdev %x / cycle %d\n",
135__FUNCTION__, this->process->pid, this->trdid, channel, chdev, cycle );
136#endif
137
138    // get number of channels from NIC hardware register
139    uint32_t channels = hal_remote_l32( XPTR( nic_cxy,
140                        nic_ptr + NIC_GLOBAL_OFFSET + NIC_G_CHANNELS )); 
141
142    // check value registered in cluster descriptor
143    if( LOCAL_CLUSTER->nb_nic_channels != channels )
144    {
145        printk("\n[PANIC] in %s : channels[soft] (%d) != channels[hard] (%d)\n",
146        __FUNCTION__, LOCAL_CLUSTER->nb_nic_channels, channels );
147        return;
148    }
149
150    // check channel index
151    if( channel >= channels ) 
152    {
153        printk("\n[ERROR] in %s illegal channel index\n", __FUNCTION__ );
154        return;
155    }
156
157    // allocate memory for chbuf descriptor
158    nic_chbuf_t * chbuf = kmem_alloc( bits_log2( sizeof(nic_chbuf_t) ) , AF_KERNEL );
159
160    if( chbuf == NULL )
161    {
162        printk("\n[ERROR] in %s : cannot allocate chbuf descriptor\n", __FUNCTION__ );
163        return;
164    }
165
166    // initialise chbuf indexes
167    chbuf->wid  = 0;
168    chbuf->rid  = 0;
169     
170    // software L2/L3 cache coherence for chbuf WID & RID     
171    if( chdev_dir.iob ) dev_mmc_sync( XPTR( local_cxy , chbuf ) , 8 );
172
173    cont_error    = false;
174    cont_gid      = 0;
175    cont_per_page = 1 << (CONFIG_PPM_PAGE_ORDER - 11);
176
177    // allocate containers & complete chbuf initialisation
178    // depending on the PPM page size, we pack several
179    // 248 bytes containers in one single page.
180
181    // lopp on containers
182    while( cont_gid < CONFIG_SOCK_QUEUES_DEPTH ) 
183    {
184        if( (cont_gid & (cont_per_page - 1)) == 0 )  // allocate one PPM page
185        {
186            container = kmem_alloc( CONFIG_PPM_PAGE_ORDER , AF_KERNEL );
187
188            if( container == NULL )
189            {
190                cont_error = true;
191                break;
192            }
193        }
194        else           // increment container base address
195        { 
196            container = container + 512;
197        }
198
199        // initialize container as empty
200        container[511] = 0;
201
202        // software L2/L3 cache coherence for container STS       
203        if( chdev_dir.iob ) dev_mmc_sync( XPTR( local_cxy , &container[511] ) , 4 );
204
205        // compute container physical address
206        ppn  = ppm_base2ppn( XPTR( local_cxy , container ) );
207        padr = ((uint64_t)ppn << CONFIG_PPM_PAGE_ORDER) |
208               ((intptr_t)container & CONFIG_PPM_PAGE_MASK);
209
210        // complete chbuf initialisation       
211        chbuf->cont_ptr[cont_gid] = container;
212        chbuf->cont_pad[cont_gid] = padr;
213
214        // increment container index
215        cont_gid++;
216    }
217
218    // release allocated containers and chbuf if not enough memory
219    if( cont_error )
220    {
221        // loop on allocated containers
222        while( cont_gid )
223        {
224            // release container when required
225            if( (cont_gid & (cont_per_page - 1)) == 0 )
226            kmem_free( chbuf->cont_ptr[cont_gid] , CONFIG_PPM_PAGE_ORDER );
227
228            // decrement container index
229            cont_gid--;
230        }
231
232        // release chbuf descriptor
233        kmem_free( chbuf , bits_log2(sizeof(nic_chbuf_t)) );
234
235        return;
236    }
237
238    // software L2/L3 cache coherence for chbuf descriptor
239    if( chdev_dir.iob ) dev_mmc_sync( XPTR( local_cxy , chbuf ),
240                                      sizeof(nic_chbuf_t) );
241
242    // get NIC channel segment base and chbuf depth
243    uint32_t * channel_base = nic_ptr + NIC_CHANNEL_SPAN * channel;
244    uint32_t   nbufs        = CONFIG_SOCK_QUEUES_DEPTH;
245   
246    // compute chbuf physical address
247    ppn  = ppm_base2ppn( XPTR( local_cxy , chbuf ) );
248    padr = ((uint64_t)ppn  << CONFIG_PPM_PAGE_ORDER) |
249           ((intptr_t)chbuf & CONFIG_PPM_PAGE_MASK);
250
251    uint32_t low  = (uint32_t)(padr); 
252    uint32_t high = (uint32_t)(padr >> 32); 
253
254    // initialize the NIC channel registers
255    if( is_rx ) 
256    {
257        hal_remote_s32( XPTR( nic_cxy , channel_base + NIC_RX_CHBUF_DESC_LO ) , low );
258        hal_remote_s32( XPTR( nic_cxy , channel_base + NIC_RX_CHBUF_DESC_HI ) , high );
259        hal_remote_s32( XPTR( nic_cxy , channel_base + NIC_RX_CHBUF_NBUFS   ) , nbufs );
260
261        hal_fence();
262
263        hal_remote_s32( XPTR( nic_cxy , channel_base + NIC_RX_CHANNEL_RUN   ) , 1 );
264    }
265    else
266    {
267        hal_remote_s32( XPTR( nic_cxy , channel_base + NIC_TX_CHBUF_DESC_LO ) , low );
268        hal_remote_s32( XPTR( nic_cxy , channel_base + NIC_TX_CHBUF_DESC_HI ) , high );
269        hal_remote_s32( XPTR( nic_cxy , channel_base + NIC_TX_CHBUF_NBUFS   ) , nbufs );
270
271        hal_fence();
272
273        hal_remote_s32( XPTR( nic_cxy , channel_base + NIC_TX_CHANNEL_RUN   ) , 1 );
274    }
275
276    // register chbuf pointer in chdev descriptor extension
277    chdev->ext.nic.queue = chbuf;
278       
279#if DEBUG_HAL_NIC_TX || DEBUG_HAL_NIC_RX
280cycle = (uint32_t)hal_get_cycles();
281if( (is_rx == false) && DEBUG_HAL_NIC_RX < cycle )
282printk("\n[%s] thread[%x,%x] exit / NIC_TX channel %d / chbuf %x / cycle %d\n",
283__FUNCTION__, this->process->pid, this->trdid, channel, chbuf, cycle );
284if( is_rx && DEBUG_HAL_NIC_RX < cycle )
285printk("\n[%s] thread[%x,%x] exit / NIC_RX channel %d / chbuf %x / cycle %d\n",
286__FUNCTION__, this->process->pid, this->trdid, channel, chbuf, cycle );
287soclib_nic_chbuf_display( chbuf , chdev->name );
288#endif
289
290} // end soclib_nic_init()
291
292//////////////////////////////////////////////////////////////////
293void __attribute__ ((noinline)) soclib_nic_cmd( xptr_t thread_xp )
294{
295    uint32_t       type;         // command type   
296    uint8_t      * buffer;       // pointer on command buffer   
297    uint32_t       length;       // Ethernet packet length
298    xptr_t         dev_xp;       // extended pointer on NIC chdev
299    chdev_t      * dev_ptr;      // local pointer on NIC chdev
300    cxy_t          dev_cxy;      // NIC chdev cluster identifier
301    nic_chbuf_t  * chbuf;        // pointer on chbuf descriptor
302    uint32_t       index;        // index of current container in chbuf
303    uint32_t     * container;    // pointer on container (array of uint32_t)
304
305    thread_t * this = CURRENT_THREAD;
306
307assert( __FUNCTION__, (thread_xp == XPTR( local_cxy , this )), 
308"calling thread must be the client thread");
309 
310    // get command type
311    type    = this->nic_cmd.type;
312
313    // get chdev pointers for device
314    dev_xp  = this->nic_cmd.dev_xp;
315    dev_ptr = GET_PTR( dev_xp );
316    dev_cxy = GET_CXY( dev_xp );
317
318    // analyse command type
319    switch( type )
320    {
321        //////////////////////////////////////////////////////////////////////////
322        case NIC_CMD_WRITE:  // move one packet from command buffer to TX queue
323        {
324
325// check chdev is local
326assert( __FUNCTION__, (dev_cxy == local_cxy),
327"illegal cluster for a WRITE command");
328           
329            // get command arguments
330            buffer = this->nic_cmd.buffer;
331            length = this->nic_cmd.length;
332
333// check packet length
334assert( __FUNCTION__, (length <= 2040),
335"packet length too large");
336
337            // get chbuf descriptor pointer
338            chbuf = (nic_chbuf_t *)dev_ptr->ext.nic.queue;
339
340            // software L2/L3 cache coherence for chbuf WID read
341            if( chdev_dir.iob )  dev_mmc_inval( XPTR ( local_cxy , chbuf ) , 8 );
342
343            // get container write index
344            index = chbuf->wid;
345
346            // get pointer on container (no L2/L3 cache coherence required)
347            container = chbuf->cont_ptr[index];
348
349            // software L2/L3 cache coherence for container STS read
350            if( chdev_dir.iob )  dev_mmc_inval( XPTR ( local_cxy , &container[511]) , 4 );
351
352#if DEBUG_HAL_NIC_TX
353uint32_t   cycle = (uint32_t)hal_get_cycles();
354if( DEBUG_HAL_NIC_TX < cycle )
355printk("\n[%s] thread[%x,%x] enter / WRITE / %s / chbuf (%x,%x) / len %d / cycle %d\n",
356__FUNCTION__, this->process->pid, this->trdid, dev_ptr->name, local_cxy, chbuf, length, cycle );
357#endif
358            // check container STS
359            if( container[511] != 0 )   // container full
360            {
361                // return failure
362                this->nic_cmd.status = 0;
363                this->nic_cmd.error  = 0;
364
365#if DEBUG_HAL_NIC_TX
366cycle = (uint32_t)hal_get_cycles();
367if( DEBUG_HAL_NIC_TX < cycle )
368printk("\n[%s] thread[%x,%x] exit / WRITE failure : NIC_TX[%d] queue full / cycle %d\n",
369__FUNCTION__, this->process->pid , this->trdid , dev_ptr->channel , cycle );
370#endif
371            }
372            else                                       // container empty
373            {
374                // move the packet from buffer to container
375                memcpy( container , buffer , length );
376
377                // update packet length in container header
378                container[510] = length;
379
380                hal_fence();
381
382                // update container STS
383                container[511] = 1;
384
385                // update current container WID
386                chbuf->wid = (index + 1) % CONFIG_SOCK_QUEUES_DEPTH;
387
388                // software L2/L3 cache coherence for container DATA write
389                if( chdev_dir.iob ) dev_mmc_sync( XPTR( local_cxy , container ), length );
390
391                // software L2/L3 cache coherence for container LENGTH and STS write
392                if( chdev_dir.iob ) dev_mmc_sync( XPTR( local_cxy , &container[510] ) , 8 );
393               
394                // software L2/L3 cache coherence for chbuf WID write
395                if( chdev_dir.iob ) dev_mmc_sync( XPTR( local_cxy , chbuf ) , 8 );
396
397                // return success
398                this->nic_cmd.status = length;
399                this->nic_cmd.error  = 0;
400
401#if DEBUG_HAL_NIC_TX
402cycle = (uint32_t)hal_get_cycles();
403if( DEBUG_HAL_NIC_TX < cycle )
404printk("\n[%s] thread[%x,%x] exit / WRITE success on NIC_TX[%d] / len %d / cycle %d\n",
405__FUNCTION__, this->process->pid, this->trdid, dev_ptr->channel , length, cycle );
406if((DEBUG_HAL_NIC_TX < cycle) && (DEBUG_HAL_NIC_TX & 1))
407putb( "64 first bytes moved to TX queue by NIC driver" , buffer , 64 );
408#endif
409            }
410        }
411        break;  // end WRITE
412
413        /////////////////////////////////////////////////////////////////////////
414        case NIC_CMD_READ:   // move one packet from RX queue to kernel buffer
415        {
416
417// check chdev is local
418assert( __FUNCTION__, (dev_cxy == local_cxy), 
419"illegal cluster for a READ command");
420           
421            // get target buffer
422            buffer = this->nic_cmd.buffer;
423
424            // get chbuf descriptor pointer
425            chbuf = (nic_chbuf_t *)dev_ptr->ext.nic.queue;
426
427            // software L2/L3 cache coherence for chbuf WID & RID read
428            if( chdev_dir.iob )  dev_mmc_inval( XPTR ( local_cxy , chbuf ) , 8 );
429
430            // get container read index
431            index = chbuf->rid;
432           
433            // get pointer on container (no L2/L3 cache coherence required)
434            container = chbuf->cont_ptr[index];
435
436            // software L2/L3 cache coherence for container STS & PLEN read
437            if( chdev_dir.iob ) dev_mmc_inval( XPTR( local_cxy , container + 510 ), 8 );
438
439#if DEBUG_HAL_NIC_RX
440uint32_t   cycle = (uint32_t)hal_get_cycles();
441if( DEBUG_HAL_NIC_RX < cycle )
442printk("\n[%s] thread[%x,%x] enter / READ / %s / chbuf (%x,%x) / cycle %d\n",
443__FUNCTION__, this->process->pid, this->trdid, dev_ptr->name, local_cxy, chbuf, cycle );
444#endif
445            // check container state
446            if( container[511] == 0 )   // container empty
447            {
448                // return failure
449                this->nic_cmd.status = 0;
450                this->nic_cmd.error  = 0;
451
452#if DEBUG_HAL_NIC_RX
453cycle = (uint32_t)hal_get_cycles();
454if( DEBUG_HAL_NIC_RX < cycle )
455printk("\n[%s] thread[%x,%x] exit / READ failure : NIC_RX[%d] queue empty / cycle %d\n",
456__FUNCTION__, this->process->pid, this->trdid, dev_ptr->channel , cycle );
457#endif
458            }
459            else                      // container full
460            {
461                // get packet length from container
462                length = container[510];
463
464                // software L2/L3 cache coherence for container DATA
465                if( chdev_dir.iob ) dev_mmc_inval( XPTR( local_cxy , container) , length );
466
467                // move the packet from container to buffer
468                memcpy( buffer , container , length );
469
470                hal_fence();
471
472                // update container STS
473                container[511] = 0;
474
475                // update current container WID
476                chbuf->rid = (index + 1) % CONFIG_SOCK_QUEUES_DEPTH;
477
478                // software L2/L3 cache coherence for container STS write
479                if( chdev_dir.iob ) dev_mmc_sync( XPTR( local_cxy , &container[511] ), 4 );
480
481                // software L2/L3 cache coherence for chbuf RID write
482                if( chdev_dir.iob )  dev_mmc_sync( XPTR ( local_cxy , chbuf ) , 8 );
483
484                // return success
485                this->nic_cmd.status = length;
486                this->nic_cmd.error  = 0;
487
488#if DEBUG_HAL_NIC_RX
489uint32_t   cycle = (uint32_t)hal_get_cycles();
490if( DEBUG_HAL_NIC_RX < cycle )
491printk("\n[%s] thread[%x,%x] exit / READ success on NIC_RX[%d] queue / len %d / cycle %d\n",
492__FUNCTION__, this->process->pid, this->trdid , dev_ptr->channel , length , cycle );
493if((DEBUG_HAL_NIC_RX < cycle) && (DEBUG_HAL_NIC_RX & 1))
494putb("64 first bytes moved from RX queue by NIC driver" , buffer , 64 );
495#endif
496            }
497        }
498        break;    // end READ
499           
500        /////////////////////////////////////////////////////////////////////
501        case NIC_CMD_GET_KEY:      // return channel from IP addr & port
502        {
503            // get number of NIC channels
504            uint32_t channels = LOCAL_CLUSTER->nb_nic_channels;
505 
506            // get IP address and port from command in thread descriptor
507            uint32_t addr = (intptr_t)this->nic_cmd.buffer;
508            uint16_t port = (uint16_t)this->nic_cmd.length;
509 
510            // compute NIC channel index
511            uint32_t key = ( ((addr     ) & 0xFF) +
512                             ((addr > 8 ) & 0xFF) +
513                             ((addr > 16) & 0xFF) +
514                             ((addr > 24) & 0xFF) +
515                             ((port     ) & 0xFF) +
516                             ((port > 8 ) & 0xFF) ) % channels;
517
518            // return key in "status" and return "error"
519            this->nic_cmd.status = key;
520            this->nic_cmd.error  = 0;
521        }
522        break;  // end GET_KEY
523
524        /////////////////////////////////////////////////////////////////////
525        case NIC_CMD_SET_RUN:       // activate/desactivate one NIC channel
526        {
527            // get pointers on NIC peripheral
528            xptr_t     base_xp  = dev_ptr->base;
529            uint32_t * base_ptr = GET_PTR( base_xp );
530            cxy_t      base_cxy = GET_CXY( base_xp );
531
532            // get "channel" and "run" arguments from the "length" and "status" arguments
533            uint32_t channel = this->nic_cmd.length;
534            uint32_t run     = this->nic_cmd.status;
535
536            // build pointers on channel base
537            uint32_t * channel_ptr = base_ptr + NIC_CHANNEL_SPAN * channel;
538
539            // set new value in NIC_RX_CHANNEL_RUN & NIC_TX_CHANNEL_RUN registers
540            hal_remote_s32( XPTR( base_cxy , channel_ptr + NIC_RX_CHANNEL_RUN ) , run );
541            hal_remote_s32( XPTR( base_cxy , channel_ptr + NIC_TX_CHANNEL_RUN ) , run );
542
543            // return "error"
544            this->nic_cmd.error  = 0;
545        }
546        break;  // end SET_RUN
547
548        /////////////////////////////////////////////////////////////////////
549        case NIC_CMD_GET_INSTRU:     // diplay packets counters on TXT0
550        {
551            // get pointers on NIC peripheral
552            xptr_t     base_xp  = dev_ptr->base;
553            uint32_t * base_ptr = GET_PTR( base_xp );
554            cxy_t      base_cxy = GET_CXY( base_xp );
555
556            // build pointer on global register base
557            uint32_t * global_ptr = base_ptr + NIC_GLOBAL_OFFSET;
558
559            uint32_t rx_g2s_received      = hal_remote_l32( XPTR( base_cxy , 
560                                            global_ptr + NIC_G_NPKT_RX_G2S_RECEIVED ));
561            uint32_t rx_g2s_discarded     = hal_remote_l32( XPTR( base_cxy , 
562                                            global_ptr + NIC_G_NPKT_RX_G2S_DISCARDED ));
563            uint32_t rx_des_success       = hal_remote_l32( XPTR( base_cxy , 
564                                            global_ptr + NIC_G_NPKT_RX_DES_SUCCESS ));
565            uint32_t rx_des_too_small     = hal_remote_l32( XPTR( base_cxy , 
566                                            global_ptr + NIC_G_NPKT_RX_DES_TOO_SMALL ));
567            uint32_t rx_des_too_big       = hal_remote_l32( XPTR( base_cxy , 
568                                            global_ptr + NIC_G_NPKT_RX_DES_TOO_BIG ));
569            uint32_t rx_des_mfifo_full    = hal_remote_l32( XPTR( base_cxy , 
570                                            global_ptr + NIC_G_NPKT_RX_DES_MFIFO_FULL ));
571            uint32_t rx_des_crc_fail      = hal_remote_l32( XPTR( base_cxy , 
572                                            global_ptr + NIC_G_NPKT_RX_DES_CRC_FAIL ));
573            uint32_t rx_disp_received     = hal_remote_l32( XPTR( base_cxy , 
574                                            global_ptr + NIC_G_NPKT_RX_DISP_RECEIVED ));
575            uint32_t rx_disp_dst_fail     = hal_remote_l32( XPTR( base_cxy , 
576                                            global_ptr + NIC_G_NPKT_RX_DISP_DST_FAIL ));
577            uint32_t rx_disp_ch_full      = hal_remote_l32( XPTR( base_cxy , 
578                                            global_ptr + NIC_G_NPKT_RX_DISP_CH_FULL ));
579
580            uint32_t tx_disp_received     = hal_remote_l32( XPTR( base_cxy , 
581                                            global_ptr + NIC_G_NPKT_TX_DISP_RECEIVED ));
582            uint32_t tx_disp_too_small    = hal_remote_l32( XPTR( base_cxy , 
583                                            global_ptr + NIC_G_NPKT_TX_DISP_TOO_SMALL ));
584            uint32_t tx_disp_too_big      = hal_remote_l32( XPTR( base_cxy , 
585                                            global_ptr + NIC_G_NPKT_TX_DISP_TOO_BIG ));
586            uint32_t tx_disp_transmit     = hal_remote_l32( XPTR( base_cxy , 
587                                            global_ptr + NIC_G_NPKT_TX_DISP_TRANSMIT ));
588
589            printk("\n*** NIC device Instrumentation ***\n\n"
590                   " - rx_g2s_received   = %d\n"
591                   " - rx_g2s_discarded  = %d\n"
592                   " - rx_des_success    = %d\n"
593                   " - rx_des_too_small  = %d\n"
594                   " - rx_des_too_big    = %d\n"
595                   " - rx_des_mfifo_full = %d\n"
596                   " - rx_des_crc_fail   = %d\n"
597                   " - rx_disp_received  = %d\n"
598                   " - rx_disp_dsp_fail  = %d\n"
599                   " - rx_disp_ch_full   = %d\n\n"
600                   " - tx_disp_received  = %d\n"
601                   " - tx_disp_too_small = %d\n"
602                   " - tx_disp_too_big   = %d\n"
603                   " - tx_disp_transmit  = %d\n",
604                   rx_g2s_received,
605                   rx_g2s_discarded,
606                   rx_des_success,
607                   rx_des_too_small,
608                   rx_des_too_big,
609                   rx_des_mfifo_full,
610                   rx_des_crc_fail,
611                   rx_disp_received,
612                   rx_disp_dst_fail, 
613                   rx_disp_ch_full,
614                   tx_disp_received,
615                   tx_disp_too_small,
616                   tx_disp_too_big, 
617                   tx_disp_transmit );
618
619            // return "error"
620            this->nic_cmd.error  = 0;
621        }
622        break;  // end CLEAR_INSTRU
623
624        /////////////////////////////////////////////////////////////////////
625        case NIC_CMD_CLEAR_INSTRU:  // reset instrumentation registers
626        {
627            // get pointers on NIC peripheral
628            xptr_t     base_xp  = dev_ptr->base;
629            uint32_t * base_ptr = GET_PTR( base_xp );
630            cxy_t      base_cxy = GET_CXY( base_xp );
631
632            // build pointer on relevant NIC register
633            uint32_t * reset_ptr = base_ptr + NIC_GLOBAL_OFFSET + NIC_G_NPKT_RESET;
634
635            // reset all NIC instrumentation registers
636            hal_remote_s32( XPTR( base_cxy , reset_ptr ) , 0 );
637
638            // return "error"
639            this->nic_cmd.error  = 0;
640        }
641        break;  // end GET_INSTRU
642
643        default:
644        {
645            assert( __FUNCTION__, false, "Unknown command <%x>\n", type );
646        }
647    }
648} // end soclib_nic_cmd()
649
650
651/////////////////////////////////////////////////////////////////
652void __attribute__ ((noinline)) soclib_nic_isr( chdev_t * chdev )
653{
654    // get base, size, channel, is_rx, name, and server from NIC chdev
655    xptr_t     base_xp = chdev->base;
656    uint32_t   channel = chdev->channel;
657    bool_t     is_rx   = chdev->is_rx;
658    thread_t * server  = chdev->server;
659
660    // get NIC peripheral cluster and local pointer
661    cxy_t      nic_cxy = GET_CXY( base_xp );
662    uint32_t * nic_ptr = GET_PTR( base_xp );
663
664    // compute local pointer on state register
665    uint32_t  * ptr;
666    if( is_rx ) ptr = nic_ptr + (NIC_CHANNEL_SPAN * channel) + NIC_RX_CHANNEL_STATE;
667    else        ptr = nic_ptr + (NIC_CHANNEL_SPAN * channel) + NIC_TX_CHANNEL_STATE;
668
669    // read NIC channel status and acknowledge IRQ
670    uint32_t status = hal_remote_l32( XPTR( nic_cxy , ptr ) );
671
672    // check status value
673    if( status == NIC_CHANNEL_STATUS_ERROR )    // error reported
674    {
675
676#if (DEBUG_HAL_NIC_RX || DEBUG_HAL_NIC_TX)
677uint32_t   cycle = (uint32_t)hal_get_cycles();
678printk("\n[%s] error reported for %s / status %d / cycle %d\n",
679 __FUNCTION__ , chdev->name , status , cycle );
680#endif
681        server->nic_cmd.error  = 1;
682    }
683    else if( status != NIC_CHANNEL_STATUS_IDLE)   // no error but DMA BUSY
684    {
685
686#if (DEBUG_HAL_NIC_RX || DEBUG_HAL_NIC_TX)
687uint32_t   cycle = (uint32_t)hal_get_cycles();
688printk("\n[%s] warning reported for %s / status %d / cycle %d\n",
689 __FUNCTION__ , chdev->name , status , cycle );
690#endif
691        server->nic_cmd.error  = 0;
692    }
693    else
694    {
695
696#if (DEBUG_HAL_NIC_RX || DEBUG_HAL_NIC_TX)
697uint32_t   cycle = (uint32_t)hal_get_cycles();
698printk("\n[%s] irq reported for %s / status %d / cycle %d\n",
699 __FUNCTION__ , chdev->name , status , cycle );
700#endif
701        server->nic_cmd.error  = 0;
702    }
703
704    // unblock server thread
705    server->nic_cmd.status = status;
706    thread_unblock( XPTR( local_cxy , server ) , THREAD_BLOCKED_ISR );
707
708} // end soclib_nic_isr()
709
Note: See TracBrowser for help on using the repository browser.