| [75] | 1 | /* | 
|---|
| [686] | 2 |  * soclib_nic.c - VCI_MASTER_NIC (Network Interface Controler) driver implementation. | 
|---|
| [75] | 3 |  * | 
|---|
| [658] | 4 |  * Author     Alain Greiner (2016,2017,2018,2019,2020) | 
|---|
| [75] | 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 |  | 
|---|
| [451] | 24 | #include <hal_kernel_types.h> | 
|---|
| [75] | 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 |  | 
|---|
| [658] | 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 |  | 
|---|
| [686] | 66 |     nolock_printk("\n***** chbuf %s : cxy %x / ptr %x / wid %d / rid %d *****\n", | 
|---|
 | 67 |     name, local_cxy , chbuf, chbuf->wid, chbuf->rid ); | 
|---|
| [658] | 68 |  | 
|---|
| [686] | 69 |     for( i = 0 ; i < CONFIG_SOCK_QUEUES_DEPTH ; i++ ) | 
|---|
| [658] | 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 |         { | 
|---|
| [686] | 78 |             nolock_printk(" - %d : FULL  / cont_ptr %x / plen %d\n", | 
|---|
 | 79 |             i, chbuf->cont_ptr[i], container[510] ); | 
|---|
| [658] | 80 |         } | 
|---|
 | 81 |         else | 
|---|
 | 82 |         { | 
|---|
| [686] | 83 |             nolock_printk(" - %d : EMPTY / cont_ptr %x\n", | 
|---|
 | 84 |             i, chbuf->cont_ptr[i] );  | 
|---|
| [658] | 85 |         } | 
|---|
 | 86 |     } | 
|---|
 | 87 |  | 
|---|
 | 88 |     // release TXT0 lock  | 
|---|
 | 89 |     remote_busylock_release( lock_xp ); | 
|---|
 | 90 |  | 
|---|
 | 91 | }  // end soclib_nic_chbuf_display() | 
|---|
 | 92 |  | 
|---|
 | 93 | #endif | 
|---|
 | 94 |  | 
|---|
| [75] | 95 | /////////////////////////////////////// | 
|---|
 | 96 | void soclib_nic_init( chdev_t * chdev ) | 
|---|
 | 97 | { | 
|---|
| [686] | 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 | 
|---|
| [259] | 102 |  | 
|---|
| [686] | 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 |  | 
|---|
 | 106 | assert( __FUNCTION__ , (chdev->func == DEV_FUNC_NIC), | 
|---|
 | 107 | "bad func argument" ); | 
|---|
 | 108 |  | 
|---|
 | 109 | assert( __FUNCTION__ , (sizeof(nic_cont_t) == 2048), | 
|---|
 | 110 | "container size must be 2048 bytes" ); | 
|---|
 | 111 |  | 
|---|
 | 112 | assert( __FUNCTION__ , (CONFIG_PPM_PAGE_ORDER >= 11 ), | 
|---|
 | 113 | "page size cannot be smaller than container size" ); | 
|---|
 | 114 |  | 
|---|
| [259] | 115 |     // set driver specific fields in chdev descriptor | 
|---|
 | 116 |     chdev->cmd = &soclib_nic_cmd; | 
|---|
 | 117 |     chdev->isr = &soclib_nic_isr; | 
|---|
| [658] | 118 |  | 
|---|
 | 119 |     // get chdev channel & direction | 
|---|
 | 120 |     bool_t   is_rx   = chdev->is_rx; | 
|---|
 | 121 |     uint32_t channel = chdev->channel; | 
|---|
| [75] | 122 |      | 
|---|
| [658] | 123 |     // get NIC device cluster and local pointer | 
|---|
| [75] | 124 |     cxy_t      nic_cxy  = GET_CXY( chdev->base ); | 
|---|
| [658] | 125 |     uint32_t * nic_ptr  = GET_PTR( chdev->base ); | 
|---|
| [75] | 126 |  | 
|---|
| [658] | 127 | #if DEBUG_HAL_NIC_TX || DEBUG_HAL_NIC_RX | 
|---|
 | 128 | thread_t * this  = CURRENT_THREAD; | 
|---|
 | 129 | uint32_t   cycle = (uint32_t)hal_get_cycles(); | 
|---|
 | 130 | if( (is_rx == false) && DEBUG_HAL_NIC_RX < cycle ) | 
|---|
| [686] | 131 | printk("\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 ); | 
|---|
| [658] | 133 | if( is_rx && DEBUG_HAL_NIC_RX < cycle ) | 
|---|
| [686] | 134 | printk("\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 ); | 
|---|
| [658] | 136 | #endif | 
|---|
| [75] | 137 |  | 
|---|
| [686] | 138 |     // get number of channels from NIC hardware register | 
|---|
| [658] | 139 |     uint32_t channels = hal_remote_l32( XPTR( nic_cxy, | 
|---|
 | 140 |                         nic_ptr + NIC_GLOBAL_OFFSET + NIC_G_CHANNELS ));  | 
|---|
| [75] | 141 |  | 
|---|
| [658] | 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 |     { | 
|---|
| [686] | 153 |         printk("\n[ERROR] in %s illegal channel index\n", __FUNCTION__ ); | 
|---|
| [658] | 154 |         return; | 
|---|
 | 155 |     } | 
|---|
 | 156 |  | 
|---|
 | 157 |     // allocate memory for chbuf descriptor | 
|---|
| [686] | 158 |     nic_chbuf_t * chbuf = kmem_alloc( bits_log2( sizeof(nic_chbuf_t) ) , AF_KERNEL ); | 
|---|
| [75] | 159 |  | 
|---|
| [635] | 160 |     if( chbuf == NULL ) | 
|---|
 | 161 |     { | 
|---|
| [686] | 162 |         printk("\n[ERROR] in %s : cannot allocate chbuf descriptor\n", __FUNCTION__ ); | 
|---|
| [658] | 163 |         return; | 
|---|
| [635] | 164 |     } | 
|---|
| [75] | 165 |  | 
|---|
| [658] | 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 ); | 
|---|
| [686] | 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 )   | 
|---|
| [658] | 183 |     { | 
|---|
| [686] | 184 |         if( (cont_gid & (cont_per_page - 1)) == 0 )  // allocate one PPM page | 
|---|
 | 185 |         { | 
|---|
 | 186 |             container = kmem_alloc( CONFIG_PPM_PAGE_ORDER , AF_KERNEL ); | 
|---|
| [75] | 187 |  | 
|---|
| [686] | 188 |             if( container == NULL ) | 
|---|
 | 189 |             { | 
|---|
 | 190 |                 cont_error = true; | 
|---|
 | 191 |                 break; | 
|---|
 | 192 |             } | 
|---|
| [658] | 193 |         } | 
|---|
| [686] | 194 |         else           // increment container base address  | 
|---|
 | 195 |         {  | 
|---|
 | 196 |             container = container + 512; | 
|---|
 | 197 |         } | 
|---|
| [658] | 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 ) ); | 
|---|
| [686] | 207 |         padr = ((uint64_t)ppn << CONFIG_PPM_PAGE_ORDER) | | 
|---|
| [658] | 208 |                ((intptr_t)container & CONFIG_PPM_PAGE_MASK); | 
|---|
 | 209 |  | 
|---|
 | 210 |         // complete chbuf initialisation         | 
|---|
| [686] | 211 |         chbuf->cont_ptr[cont_gid] = container; | 
|---|
 | 212 |         chbuf->cont_pad[cont_gid] = padr; | 
|---|
 | 213 |  | 
|---|
 | 214 |         // increment container index | 
|---|
 | 215 |         cont_gid++; | 
|---|
| [658] | 216 |     } | 
|---|
 | 217 |  | 
|---|
| [686] | 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 |  | 
|---|
| [658] | 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; | 
|---|
| [686] | 244 |     uint32_t   nbufs        = CONFIG_SOCK_QUEUES_DEPTH; | 
|---|
| [658] | 245 |      | 
|---|
 | 246 |     // compute chbuf physical address  | 
|---|
 | 247 |     ppn  = ppm_base2ppn( XPTR( local_cxy , chbuf ) ); | 
|---|
| [686] | 248 |     padr = ((uint64_t)ppn  << CONFIG_PPM_PAGE_ORDER) | | 
|---|
| [658] | 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 )  | 
|---|
| [75] | 256 |     { | 
|---|
| [658] | 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 ); | 
|---|
| [75] | 260 |  | 
|---|
| [658] | 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; | 
|---|
| [75] | 278 |          | 
|---|
| [658] | 279 | #if DEBUG_HAL_NIC_TX || DEBUG_HAL_NIC_RX | 
|---|
 | 280 | cycle = (uint32_t)hal_get_cycles(); | 
|---|
 | 281 | if( (is_rx == false) && DEBUG_HAL_NIC_RX < cycle ) | 
|---|
 | 282 | printk("\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 ); | 
|---|
 | 284 | if( is_rx && DEBUG_HAL_NIC_RX < cycle ) | 
|---|
 | 285 | printk("\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 ); | 
|---|
 | 287 | soclib_nic_chbuf_display( chbuf , chdev->name ); | 
|---|
 | 288 | #endif | 
|---|
 | 289 |  | 
|---|
| [75] | 290 | } // end soclib_nic_init() | 
|---|
 | 291 |  | 
|---|
 | 292 | ////////////////////////////////////////////////////////////////// | 
|---|
 | 293 | void __attribute__ ((noinline)) soclib_nic_cmd( xptr_t thread_xp ) | 
|---|
 | 294 | { | 
|---|
| [657] | 295 |     uint32_t       type;         // command type     | 
|---|
| [658] | 296 |     uint8_t      * buffer;       // pointer on command buffer    | 
|---|
| [75] | 297 |     uint32_t       length;       // Ethernet packet length | 
|---|
| [658] | 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 | 
|---|
| [75] | 301 |     nic_chbuf_t  * chbuf;        // pointer on chbuf descriptor | 
|---|
| [658] | 302 |     uint32_t       index;        // index of current container in chbuf | 
|---|
| [75] | 303 |     uint32_t     * container;    // pointer on container (array of uint32_t) | 
|---|
 | 304 |  | 
|---|
| [658] | 305 |     thread_t * this = CURRENT_THREAD; | 
|---|
| [75] | 306 |  | 
|---|
| [686] | 307 | assert( __FUNCTION__, (thread_xp == XPTR( local_cxy , this )),  | 
|---|
 | 308 | "calling thread must be the client thread"); | 
|---|
| [658] | 309 |   | 
|---|
 | 310 |     // get command type | 
|---|
 | 311 |     type    = this->nic_cmd.type; | 
|---|
| [75] | 312 |  | 
|---|
| [658] | 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 ); | 
|---|
| [75] | 317 |  | 
|---|
 | 318 |     // analyse command type | 
|---|
| [657] | 319 |     switch( type ) | 
|---|
| [75] | 320 |     { | 
|---|
| [658] | 321 |         ////////////////////////////////////////////////////////////////////////// | 
|---|
 | 322 |         case NIC_CMD_WRITE:  // move one packet from command buffer to TX queue | 
|---|
| [75] | 323 |         { | 
|---|
| [658] | 324 |  | 
|---|
 | 325 | // check chdev is local | 
|---|
| [686] | 326 | assert( __FUNCTION__, (dev_cxy == local_cxy), | 
|---|
 | 327 | "illegal cluster for a WRITE command"); | 
|---|
| [75] | 328 |              | 
|---|
| [658] | 329 |             // get command arguments | 
|---|
 | 330 |             buffer = this->nic_cmd.buffer; | 
|---|
 | 331 |             length = this->nic_cmd.length; | 
|---|
| [75] | 332 |  | 
|---|
| [658] | 333 | // check packet length | 
|---|
| [686] | 334 | assert( __FUNCTION__, (length <= 2040), | 
|---|
 | 335 | "packet length too large"); | 
|---|
| [75] | 336 |  | 
|---|
| [658] | 337 |             // get chbuf descriptor pointer | 
|---|
 | 338 |             chbuf = (nic_chbuf_t *)dev_ptr->ext.nic.queue; | 
|---|
| [75] | 339 |  | 
|---|
| [658] | 340 |             // software L2/L3 cache coherence for chbuf WID read | 
|---|
 | 341 |             if( chdev_dir.iob )  dev_mmc_inval( XPTR ( local_cxy , chbuf ) , 8 ); | 
|---|
| [75] | 342 |  | 
|---|
| [658] | 343 |             // get container write index | 
|---|
 | 344 |             index = chbuf->wid; | 
|---|
| [75] | 345 |  | 
|---|
| [658] | 346 |             // get pointer on container (no L2/L3 cache coherence required) | 
|---|
 | 347 |             container = chbuf->cont_ptr[index]; | 
|---|
| [75] | 348 |  | 
|---|
| [658] | 349 |             // software L2/L3 cache coherence for container STS read | 
|---|
 | 350 |             if( chdev_dir.iob )  dev_mmc_inval( XPTR ( local_cxy , &container[511]) , 4 ); | 
|---|
| [75] | 351 |  | 
|---|
| [658] | 352 | #if DEBUG_HAL_NIC_TX | 
|---|
 | 353 | uint32_t   cycle = (uint32_t)hal_get_cycles(); | 
|---|
 | 354 | if( DEBUG_HAL_NIC_TX < cycle ) | 
|---|
| [686] | 355 | printk("\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 ); | 
|---|
| [658] | 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; | 
|---|
| [75] | 364 |  | 
|---|
| [658] | 365 | #if DEBUG_HAL_NIC_TX | 
|---|
 | 366 | cycle = (uint32_t)hal_get_cycles(); | 
|---|
 | 367 | if( DEBUG_HAL_NIC_TX < cycle ) | 
|---|
| [686] | 368 | printk("\n[%s] thread[%x,%x] exit / WRITE failure : NIC_TX[%d] queue full / cycle %d\n", | 
|---|
| [658] | 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 ); | 
|---|
| [75] | 376 |  | 
|---|
| [658] | 377 |                 // update packet length in container header | 
|---|
 | 378 |                 container[510] = length; | 
|---|
| [75] | 379 |  | 
|---|
| [658] | 380 |                 hal_fence(); | 
|---|
| [75] | 381 |  | 
|---|
| [658] | 382 |                 // update container STS | 
|---|
 | 383 |                 container[511] = 1; | 
|---|
| [75] | 384 |  | 
|---|
| [658] | 385 |                 // update current container WID | 
|---|
| [686] | 386 |                 chbuf->wid = (index + 1) % CONFIG_SOCK_QUEUES_DEPTH; | 
|---|
| [658] | 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 | 
|---|
 | 402 | cycle = (uint32_t)hal_get_cycles(); | 
|---|
 | 403 | if( DEBUG_HAL_NIC_TX < cycle ) | 
|---|
| [686] | 404 | printk("\n[%s] thread[%x,%x] exit / WRITE success on NIC_TX[%d] / len %d / cycle %d\n", | 
|---|
| [658] | 405 | __FUNCTION__, this->process->pid, this->trdid, dev_ptr->channel , length, cycle ); | 
|---|
| [686] | 406 | if((DEBUG_HAL_NIC_TX < cycle) && (DEBUG_HAL_NIC_TX & 1)) | 
|---|
 | 407 | putb( "64 first bytes moved to TX queue by NIC driver" , buffer , 64 ); | 
|---|
| [658] | 408 | #endif | 
|---|
 | 409 |             } | 
|---|
| [75] | 410 |         } | 
|---|
 | 411 |         break;  // end WRITE | 
|---|
 | 412 |  | 
|---|
| [658] | 413 |         ///////////////////////////////////////////////////////////////////////// | 
|---|
 | 414 |         case NIC_CMD_READ:   // move one packet from RX queue to kernel buffer | 
|---|
| [75] | 415 |         { | 
|---|
 | 416 |  | 
|---|
| [658] | 417 | // check chdev is local | 
|---|
| [686] | 418 | assert( __FUNCTION__, (dev_cxy == local_cxy),  | 
|---|
 | 419 | "illegal cluster for a READ command"); | 
|---|
| [658] | 420 |              | 
|---|
 | 421 |             // get target buffer | 
|---|
 | 422 |             buffer = this->nic_cmd.buffer; | 
|---|
| [75] | 423 |  | 
|---|
| [658] | 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  | 
|---|
 | 440 | uint32_t   cycle = (uint32_t)hal_get_cycles(); | 
|---|
 | 441 | if( DEBUG_HAL_NIC_RX < cycle ) | 
|---|
| [686] | 442 | printk("\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 ); | 
|---|
| [658] | 444 | #endif | 
|---|
 | 445 |             // check container state | 
|---|
 | 446 |             if( container[511] == 0 )   // container empty | 
|---|
| [75] | 447 |             { | 
|---|
| [658] | 448 |                 // return failure | 
|---|
 | 449 |                 this->nic_cmd.status = 0; | 
|---|
 | 450 |                 this->nic_cmd.error  = 0; | 
|---|
 | 451 |  | 
|---|
 | 452 | #if DEBUG_HAL_NIC_RX | 
|---|
 | 453 | cycle = (uint32_t)hal_get_cycles(); | 
|---|
 | 454 | if( DEBUG_HAL_NIC_RX < cycle ) | 
|---|
| [686] | 455 | printk("\n[%s] thread[%x,%x] exit / READ failure : NIC_RX[%d] queue empty / cycle %d\n", | 
|---|
| [658] | 456 | __FUNCTION__, this->process->pid, this->trdid, dev_ptr->channel , cycle ); | 
|---|
 | 457 | #endif | 
|---|
| [75] | 458 |             } | 
|---|
| [658] | 459 |             else                      // container full | 
|---|
| [75] | 460 |             { | 
|---|
| [658] | 461 |                 // get packet length from container | 
|---|
 | 462 |                 length = container[510]; | 
|---|
| [75] | 463 |  | 
|---|
| [658] | 464 |                 // software L2/L3 cache coherence for container DATA | 
|---|
 | 465 |                 if( chdev_dir.iob ) dev_mmc_inval( XPTR( local_cxy , container) , length ); | 
|---|
| [75] | 466 |  | 
|---|
| [658] | 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  | 
|---|
| [686] | 476 |                 chbuf->rid = (index + 1) % CONFIG_SOCK_QUEUES_DEPTH; | 
|---|
| [658] | 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  | 
|---|
 | 489 | uint32_t   cycle = (uint32_t)hal_get_cycles(); | 
|---|
 | 490 | if( DEBUG_HAL_NIC_RX < cycle ) | 
|---|
| [686] | 491 | printk("\n[%s] thread[%x,%x] exit / READ success on NIC_RX[%d] queue / len %d / cycle %d\n", | 
|---|
| [658] | 492 | __FUNCTION__, this->process->pid, this->trdid , dev_ptr->channel , length , cycle ); | 
|---|
| [686] | 493 | if((DEBUG_HAL_NIC_RX < cycle) && (DEBUG_HAL_NIC_RX & 1)) | 
|---|
 | 494 | putb("64 first bytes moved from RX queue by NIC driver" , buffer , 64 ); | 
|---|
| [658] | 495 | #endif | 
|---|
| [75] | 496 |             } | 
|---|
 | 497 |         } | 
|---|
| [658] | 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; | 
|---|
| [75] | 517 |  | 
|---|
| [658] | 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 | 
|---|
| [75] | 526 |         { | 
|---|
| [658] | 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 ); | 
|---|
| [75] | 531 |  | 
|---|
| [686] | 532 |             // get "channel" and "run" arguments from the "length" and "status" arguments | 
|---|
| [658] | 533 |             uint32_t channel = this->nic_cmd.length; | 
|---|
 | 534 |             uint32_t run     = this->nic_cmd.status; | 
|---|
| [75] | 535 |  | 
|---|
| [658] | 536 |             // build pointers on channel base | 
|---|
 | 537 |             uint32_t * channel_ptr = base_ptr + NIC_CHANNEL_SPAN * channel; | 
|---|
| [75] | 538 |  | 
|---|
| [658] | 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; | 
|---|
| [75] | 545 |         } | 
|---|
| [658] | 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 |         { | 
|---|
| [679] | 645 |             assert( __FUNCTION__, false, "Unknown command <%x>\n", type ); | 
|---|
| [507] | 646 |         } | 
|---|
| [506] | 647 |     } | 
|---|
| [75] | 648 | } // end soclib_nic_cmd() | 
|---|
 | 649 |  | 
|---|
 | 650 |  | 
|---|
 | 651 | ///////////////////////////////////////////////////////////////// | 
|---|
 | 652 | void __attribute__ ((noinline)) soclib_nic_isr( chdev_t * chdev ) | 
|---|
 | 653 | { | 
|---|
| [686] | 654 |     // get base, size, channel, is_rx, name, and server from NIC chdev | 
|---|
| [658] | 655 |     xptr_t     base_xp = chdev->base; | 
|---|
| [75] | 656 |     uint32_t   channel = chdev->channel; | 
|---|
 | 657 |     bool_t     is_rx   = chdev->is_rx; | 
|---|
| [686] | 658 |     thread_t * server  = chdev->server; | 
|---|
| [75] | 659 |  | 
|---|
 | 660 |     // get NIC peripheral cluster and local pointer | 
|---|
| [658] | 661 |     cxy_t      nic_cxy = GET_CXY( base_xp ); | 
|---|
 | 662 |     uint32_t * nic_ptr = GET_PTR( base_xp ); | 
|---|
| [75] | 663 |  | 
|---|
| [658] | 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; | 
|---|
| [75] | 668 |  | 
|---|
 | 669 |     // read NIC channel status and acknowledge IRQ | 
|---|
| [658] | 670 |     uint32_t status = hal_remote_l32( XPTR( nic_cxy , ptr ) ); | 
|---|
| [75] | 671 |  | 
|---|
| [686] | 672 |     // check status value | 
|---|
 | 673 |     if( status == NIC_CHANNEL_STATUS_ERROR )    // error reported  | 
|---|
 | 674 |     { | 
|---|
| [493] | 675 |  | 
|---|
| [686] | 676 | #if (DEBUG_HAL_NIC_RX || DEBUG_HAL_NIC_TX)  | 
|---|
 | 677 | uint32_t   cycle = (uint32_t)hal_get_cycles(); | 
|---|
 | 678 | printk("\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 |     { | 
|---|
| [75] | 685 |  | 
|---|
| [658] | 686 | #if (DEBUG_HAL_NIC_RX || DEBUG_HAL_NIC_TX)  | 
|---|
 | 687 | uint32_t   cycle = (uint32_t)hal_get_cycles(); | 
|---|
| [686] | 688 | printk("\n[%s] warning reported for %s / status %d / cycle %d\n", | 
|---|
 | 689 |  __FUNCTION__ , chdev->name , status , cycle ); | 
|---|
| [658] | 690 | #endif | 
|---|
| [686] | 691 |         server->nic_cmd.error  = 0; | 
|---|
 | 692 |     } | 
|---|
 | 693 |     else | 
|---|
 | 694 |     { | 
|---|
| [658] | 695 |  | 
|---|
| [686] | 696 | #if (DEBUG_HAL_NIC_RX || DEBUG_HAL_NIC_TX)  | 
|---|
 | 697 | uint32_t   cycle = (uint32_t)hal_get_cycles(); | 
|---|
 | 698 | printk("\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 |  | 
|---|
| [75] | 708 | } // end soclib_nic_isr() | 
|---|
 | 709 |  | 
|---|