Changeset 437 for soft/giet_vm/giet_drivers/nic_driver.c
- Timestamp:
- Nov 3, 2014, 10:53:00 AM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
soft/giet_vm/giet_drivers/nic_driver.c
r333 r437 5 5 // Copyright (c) UPMC-LIP6 6 6 /////////////////////////////////////////////////////////////////////////////////// 7 // The nic_driver.c and nic_driver.h files are part ot the GIET-VM nano-kernel.8 // This driver supports the vci_multi_nic component.9 //10 // It can exist only one network controller in the architecture, but this11 // component supports several channels.12 //13 // It can be accessed directly by software with memcpy(),14 // or it can be accessed through the vci_chbuf_dma component:15 //16 // The '_nic_sync_write' and '_nic_sync_read' functions use a memcpy strategy to17 // implement the transfer between a data buffer (user space) and the NIC18 // buffer (kernel space). They are blocking until completion of the transfer.19 //20 // The _nic_cma_*_init() and _nic_cma_stop() functions use the VciChbufDma component21 // to transfer a flow of packets from the NIC RX hard chbuf (two containers)22 // to an user RX chbuf (two containers), and to transfer another flow of packets23 // from an user TX chbuf (two containers) to the NIC TX chbuf (two containers).24 // One NIC channel and two CMA channels must be allocated to the task25 // in the mapping_info data structure.26 //27 // The SEG_NIC_BASE address must be defined in the hard_config.h file.28 //////////////////////////////////////////////////////////////////////////////////29 7 30 8 #include <giet_config.h> 31 9 #include <nic_driver.h> 10 #include <cma_driver.h> 32 11 #include <utils.h> 12 #include <ctx_handler.h> 13 #include <vmem.h> 33 14 34 15 #if !defined(GIET_USE_IOMMU) … … 44 25 #endif 45 26 27 #if !defined(X_IO) 28 # error: You must define X_IO in the hard_config.h file 29 #endif 30 31 #if !defined(Y_IO) 32 # error: You must define Y_IO in the hard_config.h file 33 #endif 34 46 35 #if ( NB_NIC_CHANNELS > 8 ) 47 36 # error: NB_NIC_CHANNELS cannot be larger than 8 … … 60 49 #endif 61 50 51 #if !defined( GIET_CHBUF_NBUFS ) 52 # error: You must define GIET_CHBUF_NBUFS in the giet_config.h file 53 #endif 54 62 55 #define in_unckdata __attribute__((section (".unckdata"))) 63 56 64 57 /////////////////////////////////////////////////////////////////////////////// 65 // This low_level function returns the value contained in register (index).66 /////////////////////////////////////////////////////////////////////////////// 67 unsigned int _nic_get_ register( unsigned int channel,68 unsigned int index )58 // This low_level function returns the value contained in a channel register. 59 /////////////////////////////////////////////////////////////////////////////// 60 unsigned int _nic_get_channel_register( unsigned int channel, 61 unsigned int index ) 69 62 { 70 63 unsigned int* vaddr = (unsigned int*)SEG_NIC_BASE + … … 74 67 75 68 /////////////////////////////////////////////////////////////////////////////// 76 // This low-level function set a new value in register (index).77 /////////////////////////////////////////////////////////////////////////////// 78 void _nic_set_ register( unsigned int channel,79 unsigned int index,80 unsigned int value )69 // This low-level function set a new value in a channel register. 70 /////////////////////////////////////////////////////////////////////////////// 71 void _nic_set_channel_register( unsigned int channel, 72 unsigned int index, 73 unsigned int value ) 81 74 { 82 75 unsigned int* vaddr = (unsigned int*)SEG_NIC_BASE + … … 85 78 } 86 79 87 ////////////////////////////////////////////////////////////////////////////////// 88 // Transfer data from an memory buffer to the NIC device using a memcpy. 89 // - buffer : base address of the memory buffer. 90 // - length : number of bytes to be transfered. 91 ////////////////////////////////////////////////////////////////////////////////// 92 unsigned int _nic_sync_write( const void* buffer, 93 unsigned int length ) 94 { 95 _printf("[GIET ERROR] _nic_sync_write function not implemented / cycle %d\n", 96 _get_proctime() ); 97 _exit(); 98 99 return 0; 100 } 101 ////////////////////////////////////////////////////////////////////////////////// 102 // Transfer data from the NIC device to a memory buffer using a memcpy. 103 // - buffer : base address of the memory buffer. 104 // - length : number of bytes to be transfered. 105 ////////////////////////////////////////////////////////////////////////////////// 106 unsigned int _nic_sync_read( const void* buffer, 107 unsigned int length ) 108 { 109 _printf("[GIET ERROR] _nic_sync_read function not implemented / cycle %d\n", 110 _get_proctime() ); 111 _exit(); 112 113 return 0; 114 } 115 ////////////////////////////////////////////////////////////////////////////////// 116 // Returns 0 if success, > 0 if error. 117 ////////////////////////////////////////////////////////////////////////////////// 118 unsigned int _nic_cma_start( ) 119 { 120 _printf("[GIET ERROR] _nic_cma_start() not implemented / cycle %d\n", 121 _get_proctime() ); 122 _exit(); 123 124 return 0; 125 } 126 ////////////////////////////////////////////////////////////////////////////////// 127 // Returns 0 if success, > 0 if error. 128 ////////////////////////////////////////////////////////////////////////////////// 129 unsigned int _nic_cma_stop() 130 { 131 _printf("[GIET ERROR] _nic_cma_stop() not implemented / cycle %d\n", 132 _get_proctime() ); 133 _exit(); 134 135 return 0; 136 } 137 138 ////////////////////////////////////////////////////////////////////////////////// 139 // This ISR handles IRQx from a NIC RX channeL 140 ////////////////////////////////////////////////////////////////////////////////// 80 /////////////////////////////////////////////////////////////////////////////// 81 // This low_level function returns the value contained in a global register. 82 /////////////////////////////////////////////////////////////////////////////// 83 unsigned int _nic_get_global_register( unsigned int index ) 84 { 85 unsigned int* vaddr = (unsigned int*)SEG_NIC_BASE + 86 NIC_CHANNEL_SPAN * NB_NIC_CHANNELS + index; 87 return _io_extended_read( vaddr ); 88 } 89 90 /////////////////////////////////////////////////////////////////////////////// 91 // This low-level function set a new value in a global register. 92 /////////////////////////////////////////////////////////////////////////////// 93 void _nic_set_global_register( unsigned int index, 94 unsigned int value ) 95 { 96 unsigned int* vaddr = (unsigned int*)SEG_NIC_BASE + 97 NIC_CHANNEL_SPAN * NB_NIC_CHANNELS + index; 98 _io_extended_write( vaddr, value ); 99 } 100 101 //////////////////////////////////////////// 102 int _nic_global_init( unsigned int channels, 103 unsigned int vis, 104 unsigned int bc_enable, 105 unsigned int bypass_enable ) 106 { 107 _nic_set_global_register( NIC_G_VIS , vis ); 108 _nic_set_global_register( NIC_G_NB_CHAN , channels ); 109 _nic_set_global_register( NIC_G_BC_ENABLE , bc_enable ); 110 _nic_set_global_register( NIC_G_BYPASS_ENABLE, bypass_enable ); 111 _nic_set_global_register( NIC_G_ON , 1 ); 112 113 return 0; 114 } 115 116 //////////////////////////////////////////// 117 int _nic_channel_init( unsigned int index, 118 unsigned int mac4, 119 unsigned int mac2 ) 120 { 121 unsigned int base = SEG_NIC_BASE; 122 unsigned int extend = (X_IO << Y_WIDTH) + Y_IO; 123 124 _nic_set_channel_register( index, NIC_RX_DESC_LO_0 + 4096, base ); 125 _nic_set_channel_register( index, NIC_RX_DESC_LO_1 + 4096, base + 0x1000 ); 126 _nic_set_channel_register( index, NIC_TX_DESC_LO_0 + 4096, base + 0x2000 ); 127 _nic_set_channel_register( index, NIC_TX_DESC_LO_1 + 4096, base + 0x3000 ); 128 129 _nic_set_channel_register( index, NIC_RX_DESC_HI_0 , extend ); 130 _nic_set_channel_register( index, NIC_RX_DESC_HI_1 , extend ); 131 _nic_set_channel_register( index, NIC_TX_DESC_HI_0 , extend ); 132 _nic_set_channel_register( index, NIC_TX_DESC_HI_1 , extend ); 133 134 _nic_set_channel_register( index, NIC_MAC_4 , mac4 ); 135 _nic_set_channel_register( index, NIC_MAC_2 , mac2 ); 136 137 _nic_set_channel_register( index, NIC_RX_RUN , 1 ); 138 _nic_set_channel_register( index, NIC_TX_RUN , 1 ); 139 140 return 0; 141 } 142 143 ///////////////////////////////////////////////////////////////////////////////////// 144 // Synchronous access functions 145 ///////////////////////////////////////////////////////////////////////////////////// 146 147 /////////////////////////////////////////////// 148 int _nic_sync_send( unsigned int channel, 149 unsigned long long user_paddr ) 150 { 151 unsigned long long nic_paddr; // nic buffer physical address 152 unsigned int done = 0; 153 unsigned int lsb; 154 unsigned int msb; 155 156 if ( channel >= NB_NIC_CHANNELS ) 157 { 158 _puts("[GIET ERROR] in _timer_sync_send()\n"); 159 return -1; 160 } 161 162 // poll the NIC buffers 163 while ( done == 0 ) 164 { 165 // test availability of NIC TX buffer 0 166 lsb = _nic_get_channel_register( channel, NIC_TX_DESC_LO_0 ); 167 msb = _nic_get_channel_register( channel, NIC_TX_DESC_HI_0 ); 168 if ( (msb & 0x80000000) == 0 ) 169 { 170 msb = msb & 0x0000FFFF; 171 done = 1; 172 continue; 173 } 174 175 // test availability of NIC TX buffer 1 176 lsb = _nic_get_channel_register( channel, NIC_TX_DESC_LO_1 ); 177 msb = _nic_get_channel_register( channel, NIC_TX_DESC_HI_1 ); 178 if ( (msb & 0x80000000) == 0 ) 179 { 180 msb = msb & 0x0000FFFF; 181 done = 1; 182 continue; 183 } 184 185 // random delay (average value: 380 cycle) 186 _random_wait( 8 ); 187 } 188 189 // make the transfer 190 nic_paddr = (unsigned long long)lsb + (((unsigned long long)msb) << 32); 191 192 _physical_memcpy( nic_paddr , user_paddr, 4096 ); 193 194 return 0; 195 } 196 197 /////////////////////////////////////////////////// 198 int _nic_sync_receive( unsigned int channel, 199 unsigned long long user_paddr ) 200 { 201 unsigned long long nic_paddr; // nic buffer physical address 202 unsigned int done = 0; 203 unsigned int lsb; 204 unsigned int msb; 205 206 if ( channel >= NB_NIC_CHANNELS ) 207 { 208 _puts("[GIET ERROR] in _timer_sync_receive()\n"); 209 return -1; 210 } 211 212 // polling the NIC buffers 213 while ( done == 0 ) 214 { 215 // test availability of NIC RX buffer 0 216 lsb = _nic_get_channel_register( channel, NIC_RX_DESC_LO_0 ); 217 msb = _nic_get_channel_register( channel, NIC_RX_DESC_HI_0 ); 218 if ( (msb & 0x80000000) == 1 ) 219 { 220 msb = msb & 0x0000FFFF; 221 done = 1; 222 continue; 223 } 224 225 // test availability of NIC RX buffer 1 226 lsb = _nic_get_channel_register( channel, NIC_RX_DESC_LO_1 ); 227 msb = _nic_get_channel_register( channel, NIC_RX_DESC_HI_1 ); 228 if ( (msb & 0x80000000) == 1 ) 229 { 230 msb = msb & 0x0000FFFF; 231 done = 1; 232 continue; 233 } 234 235 // random delay (average value: 380 cycle) 236 _random_wait( 8 ); 237 } 238 239 // make the transfer 240 nic_paddr = (unsigned long long)lsb + (((unsigned long long)msb) << 32); 241 242 _physical_memcpy( user_paddr, nic_paddr , 4096 ); 243 244 return 0; 245 } 246 247 ///////////////////////////////////////////////////////////////////////////////////// 248 // CMA access functions 249 ///////////////////////////////////////////////////////////////////////////////////// 250 251 ////////////////////////////////////////////////////////////// 252 int _nic_cma_receive( unsigned int nic_channel, 253 unsigned int cma_channel, 254 nic_chbuf_t* kernel_chbuf ) 255 256 { 257 unsigned int nic_chbuf_lsb; // 32 LSB bits of the NIC chbuf physical address 258 unsigned int nic_chbuf_msb; // 16 MSB bits of the NIC chbuf physical address 259 unsigned int mem_chbuf_lsb; // 32 LSB bits of the kernel chbuf physical address 260 unsigned int mem_chbuf_msb; // 16 MSB bits of the kernel chbuf physical address 261 262 unsigned int ppn; 263 unsigned int flags; 264 265 // checking parameters 266 if ( nic_channel >= NB_NIC_CHANNELS ) 267 { 268 _puts("[GIET ERROR] in _nic_cma_start_receive() : nic_channel index too large\n"); 269 return -1; 270 } 271 if ( cma_channel >= NB_CMA_CHANNELS ) 272 { 273 _puts("[GIET ERROR] in _nic_cma_start_receive() : cma_channel index too large\n"); 274 return -1; 275 } 276 277 // get the NIC_RX chbuf descriptor physical address 278 nic_chbuf_lsb = SEG_NIC_BASE + (nic_channel * NIC_CHANNEL_SPAN) + 0x1000; 279 nic_chbuf_msb = (X_IO << Y_WIDTH) + Y_IO; 280 281 // compute the kernel chbuf physical address 282 unsigned int ptab = _get_context_slot(CTX_PTAB_ID); 283 unsigned int vaddr = (unsigned int)kernel_chbuf; 284 unsigned int ko = _v2p_translate( (page_table_t*)ptab, 285 vaddr, 286 &ppn, 287 &flags ); 288 if ( ko ) 289 { 290 _puts("\n[GIET ERROR] in _nic_cma_start_receive() : kernel buffer unmapped\n"); 291 return -1; 292 } 293 294 mem_chbuf_lsb = (ppn << 12) | (vaddr & 0x00000FFF); 295 mem_chbuf_msb = ppn >> 20; 296 297 // initializes CMA registers defining the source chbuf (NIC_RX) 298 _cma_set_register( cma_channel, CHBUF_SRC_DESC , nic_chbuf_lsb ); 299 _cma_set_register( cma_channel, CHBUF_DST_EXT , nic_chbuf_msb ); 300 _cma_set_register( cma_channel, CHBUF_SRC_NBUFS, 2 ); 301 302 // initializes CMA registers defining the destination chbuf (kernel memory) 303 _cma_set_register( cma_channel, CHBUF_DST_DESC , mem_chbuf_lsb ); 304 _cma_set_register( cma_channel, CHBUF_DST_EXT , mem_chbuf_msb ); 305 _cma_set_register( cma_channel, CHBUF_DST_NBUFS, GIET_CHBUF_NBUFS ); 306 307 // set buffer size, polling period, and start 308 _cma_set_register( cma_channel, CHBUF_BUF_SIZE , 4096 ); 309 _cma_set_register( cma_channel, CHBUF_PERIOD , 300 ); 310 _cma_set_register( cma_channel, CHBUF_RUN , 1 ); 311 312 return 0; 313 } 314 315 ////////////////////////////////////////////////////////// 316 int _nic_cma_send( unsigned int nic_channel, 317 unsigned int cma_channel, 318 nic_chbuf_t* kernel_chbuf ) 319 { 320 unsigned int nic_chbuf_lsb; // 32 LSB bits of the NIC chbuf physical address 321 unsigned int nic_chbuf_msb; // 16 MSB bits of the NIC chbuf physical address 322 unsigned int mem_chbuf_lsb; // 32 LSB bits of the kernel chbuf physical address 323 unsigned int mem_chbuf_msb; // 16 MSB bits of the kernel chbuf physical address 324 325 unsigned int ppn; 326 unsigned int flags; 327 328 // checking parameters 329 if ( nic_channel >= NB_NIC_CHANNELS ) 330 { 331 _puts("[GIET ERROR] in _nic_cma_start_send() : nic_channel index too large\n"); 332 return -1; 333 } 334 if ( cma_channel >= NB_CMA_CHANNELS ) 335 { 336 _puts("[GIET ERROR] in _nic_cma_start_send() : cma_channel index too large\n"); 337 return -1; 338 } 339 340 // get the NIC_TX chbuf descriptor physical address 341 nic_chbuf_lsb = SEG_NIC_BASE + (nic_channel * NIC_CHANNEL_SPAN) + 0x1010; 342 nic_chbuf_msb = (X_IO << Y_WIDTH) + Y_IO; 343 344 // compute the kernel chbuf physical address 345 unsigned int ptab = _get_context_slot(CTX_PTAB_ID); 346 unsigned int vaddr = (unsigned int)kernel_chbuf; 347 unsigned int ko = _v2p_translate( (page_table_t*)ptab, 348 vaddr, 349 &ppn, 350 &flags ); 351 if ( ko ) 352 { 353 _puts("\n[GIET ERROR] in _nic_cma_start_send() : kernel buffer unmapped\n"); 354 return -1; 355 } 356 357 mem_chbuf_lsb = (ppn << 12) | (vaddr & 0x00000FFF); 358 mem_chbuf_msb = ppn >> 20; 359 360 // initializes CMA registers defining the source chbuf (kernel memory) 361 _cma_set_register( cma_channel, CHBUF_SRC_DESC , mem_chbuf_lsb ); 362 _cma_set_register( cma_channel, CHBUF_DST_EXT , mem_chbuf_msb ); 363 _cma_set_register( cma_channel, CHBUF_SRC_NBUFS, GIET_CHBUF_NBUFS ); 364 365 // initializes CMA registers defining the destination chbuf (NIC_TX) 366 _cma_set_register( cma_channel, CHBUF_DST_DESC , nic_chbuf_lsb ); 367 _cma_set_register( cma_channel, CHBUF_DST_EXT , nic_chbuf_msb ); 368 _cma_set_register( cma_channel, CHBUF_DST_NBUFS, 2 ); 369 370 // set buffer size, polling period, and start 371 _cma_set_register( cma_channel, CHBUF_BUF_SIZE , 4096 ); 372 _cma_set_register( cma_channel, CHBUF_PERIOD , 300 ); 373 _cma_set_register( cma_channel, CHBUF_RUN , 1 ); 374 375 return 0; 376 } 377 378 //////////////////////////////////////////////////////////////////////////////////////////// 379 // Interrupt Service Routines 380 //////////////////////////////////////////////////////////////////////////////////////////// 381 382 //////////////////////////////////////// 141 383 void _nic_rx_isr( unsigned int irq_type, 142 384 unsigned int irq_id, 143 385 unsigned int channel ) 144 386 { 145 _printf("[GIET ERROR] _nic_rx_isr() not implemented / cycle %d\n", 146 _get_proctime() ); 147 _exit(); 148 } 149 150 ////////////////////////////////////////////////////////////////////////////////// 151 // This ISR handles IRQx from a NIC RX channeL 152 ////////////////////////////////////////////////////////////////////////////////// 387 _puts("[NIC WARNING] RX buffers are full for NIC channel "); 388 _putd( channel ); 389 _puts("\n"); 390 } 391 392 //////////////////////////////////////// 153 393 void _nic_tx_isr( unsigned int irq_type, 154 394 unsigned int irq_id, 155 395 unsigned int channel ) 156 396 { 157 _p rintf("[GIET ERROR] _nic_tx_isr() not implemented / cycle %d\n",158 _get_proctime());159 _ exit();397 _puts("[NIC WARNING] TX buffers are full for NIC channel "); 398 _putd( channel ); 399 _puts("\n"); 160 400 } 161 401
Note: See TracChangeset
for help on using the changeset viewer.