Changeset 76 for trunk/hal/x86_64/drivers/soclib_nic.c
- Timestamp:
- Jun 27, 2017, 2:07:55 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/hal/x86_64/drivers/soclib_nic.c
r75 r76 34 34 #include <soclib_nic.h> 35 35 36 ///////////////////////////////////////37 36 void soclib_nic_init( chdev_t * chdev ) 38 37 { 39 uint32_t i;40 kmem_req_t req;41 42 // get hardware device cluster and local pointer43 cxy_t nic_cxy = GET_CXY( chdev->base );44 uint32_t * nic_ptr = (uint32_t *)GET_PTR( chdev->base );45 38 46 // initialize Soclib NIC global registers 47 hal_remote_sw( XPTR( nic_cxy , &nic_ptr + NIC_G_BC_ENABLE ) , 0 ); 48 hal_remote_sw( XPTR( nic_cxy , &nic_ptr + NIC_G_RUN ) , 0 ); 39 } 49 40 50 // allocate memory for chbuf descriptor (one page)51 assert( (sizeof(nic_chbuf_t) <= CONFIG_PPM_PAGE_SIZE ) , __FUNCTION__ ,52 "chbuf descriptor exceeds one page" );53 54 req.type = KMEM_PAGE;55 req.size = 0;56 req.flags = AF_KERNEL;57 58 nic_chbuf_t * chbuf = (nic_chbuf_t *)kmem_alloc( &req );59 60 assert( (chbuf != NULL) , __FUNCTION__ ,61 "cannot allocate chbuf descriptor" );62 63 // initialise chbuf state64 chbuf->cont_id = 0;65 chbuf->pkt_id = 0;66 chbuf->word_id = 34;67 68 // allocate containers (one page per container)69 // and complete chbuf descriptor initialization70 assert( (CONFIG_PPM_PAGE_SIZE == 4096) , __FUNCTION__ ,71 "chbuf container must be 4 Kbytes" );72 73 for( i = 0 ; i < CONFIG_NIC_CHBUF_DEPTH ; i++ )74 {75 uint32_t * container = (uint32_t *)kmem_alloc( &req );76 77 assert( (container != NULL) , __FUNCTION__ ,78 "cannot allocate container" );79 80 chbuf->cont[i] = container;81 chbuf->full[i] = (paddr_t)XPTR( local_cxy , container );82 }83 } // end soclib_nic_init()84 85 86 //////////////////////////////////////////////////////////////////87 41 void __attribute__ ((noinline)) soclib_nic_cmd( xptr_t thread_xp ) 88 42 { 89 uint32_t cmd; // command type90 char * buffer; // pointer on command buffer91 uint32_t length; // Ethernet packet length92 xptr_t dev_xp; // extended pointer on NIC device93 nic_chbuf_t * chbuf; // pointer on chbuf descriptor94 uint32_t cont_id; // index of current container in chbuf95 uint32_t pkt_id; // index of current packet in container96 uint32_t word_id; // index of first word of current packet in container97 uint32_t * container; // pointer on container (array of uint32_t)98 uint16_t * header; // pointer on container header (array of uint16_t)99 uint32_t npackets; // number of packets in current container100 43 101 // get local pointer for client thread 102 thread_t * thread_ptr = (thread_t *)GET_PTR( thread_xp ); 44 } 103 45 104 // get command arguments105 cmd = thread_ptr->command.nic.cmd;106 buffer = thread_ptr->command.nic.buffer;107 length = thread_ptr->command.nic.length;108 dev_xp = thread_ptr->command.nic.dev_xp;109 110 // get local pointer for device111 chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp );112 113 // get chbuf descriptor pointer114 chbuf = (nic_chbuf_t *)dev_ptr->ext.nic.queue;115 116 // analyse command type117 switch( cmd )118 {119 /////////////////////////////////////////////////////////////////////////////120 case NIC_CMD_READ: // transfer one packet from RX queue to command buffer121 {122 // get current container index123 cont_id = chbuf->cont_id;124 125 if( chbuf->full[cont_id] == 0 ) // container empty126 {127 printk("PANIC in %s : read an empty container\n", __FUNCTION__ );128 hal_core_sleep();129 }130 131 // get pointer on container and header132 container = chbuf->cont[cont_id];133 header = (uint16_t *)container;134 135 // get expected packet index and first word index in container136 pkt_id = chbuf->pkt_id;137 word_id = chbuf->word_id;138 139 // get packet length and number of packets from container header140 length = header[pkt_id + 2];141 npackets = header[0];142 143 if( pkt_id >= npackets ) // packet index too large144 {145 printk("PANIC in %s : read a non readable container\n", __FUNCTION__ );146 hal_core_sleep();147 }148 149 // move the packet from container to buffer150 memcpy( buffer , container + word_id , length );151 152 // update current packet index and first word index153 chbuf->pkt_id = pkt_id + 1;154 if( length & 0x3 ) chbuf->word_id = word_id + (length>>2) + 1;155 else chbuf->word_id = word_id + (length>>2);156 }157 break; // end READ158 159 //////////////////////////////////////////////////////////////////////////160 case NIC_CMD_WRITE: // move one packet from command buffer to TX queue161 {162 // get current TX container indexes163 cont_id = chbuf->cont_id;164 pkt_id = chbuf->pkt_id;165 word_id = chbuf->word_id;166 167 if( chbuf->full[cont_id] != 0 ) // container full168 {169 printk("PANIC in %s : write to a full container\n", __FUNCTION__ );170 hal_core_sleep();171 }172 173 // get pointer on container and header174 container = chbuf->cont[cont_id];175 header = (uint16_t *)container;176 177 if( length > ((1024 - word_id)<<2) ) // packet length too large178 {179 printk("PANIC in %s : write to a non writable container\n", __FUNCTION__ );180 hal_core_sleep();181 }182 183 // update packet length in container header184 header[pkt_id + 2] = (uint16_t)length;185 186 // move the packet from buffer to container187 memcpy( container + word_id , buffer , length );188 189 // update current packet index and first word index190 chbuf->pkt_id = pkt_id + 1;191 if( length & 0x3 ) chbuf->word_id = word_id + (length>>2) + 1;192 else chbuf->word_id = word_id + (length>>2);193 }194 break; // end WRITE195 196 ////////////////////////////////////////////////////////////////////////////197 case NIC_CMD_WRITABLE: // analyse chbuf status / update status if required198 {199 // get current container state200 cont_id = chbuf->cont_id;201 word_id = chbuf->word_id;202 203 // compute current container writable204 bool_t ok = ( chbuf->full[cont_id] == 0 ) &&205 ( length <= ((1024 - word_id)<<2) );206 207 if( ok ) // current container writable208 {209 // return chbuf writable210 thread_ptr->command.nic.status = true;211 }212 else // current container not writable213 {214 // release current container215 chbuf->full[cont_id] = 1;216 217 // check next container218 cont_id = (cont_id + 1) % CONFIG_NIC_CHBUF_DEPTH;219 220 if( chbuf->full[cont_id] == 0 ) // next container empty221 {222 // update chbuf status223 chbuf->word_id = 34;224 chbuf->cont_id = cont_id;225 chbuf->pkt_id = 0;226 227 // return chbuf writable228 thread_ptr->command.nic.status = true;229 }230 else // next container full231 {232 // return chbuf non writable233 thread_ptr->command.nic.status = false;234 }235 }236 }237 break; // end WRITABLE238 239 /////////////////////////////////////////////////////////////////////////////240 case NIC_CMD_READABLE: // analyse chbuf status / update status if required241 {242 // get current container state243 cont_id = chbuf->cont_id;244 pkt_id = chbuf->pkt_id;245 npackets = chbuf->cont[cont_id][0] & 0x0000FFFF;246 247 // compute current container readable248 bool_t ok = ( chbuf->full[cont_id] == 1 ) &&249 ( pkt_id < npackets );250 251 if( ok ) // current container readable252 {253 // return chbuf readable254 thread_ptr->command.nic.status = true;255 }256 else // current container non readable257 {258 // release current container259 chbuf->full[cont_id] = 0;260 261 // check next container262 cont_id = (cont_id + 1) % CONFIG_NIC_CHBUF_DEPTH;263 264 if( chbuf->full[cont_id] == 1 ) // next container full265 {266 // update chbuf status267 chbuf->word_id = 34;268 chbuf->cont_id = cont_id;269 chbuf->pkt_id = 0;270 271 // return chbuf readable272 thread_ptr->command.nic.status = true;273 }274 else // next container empty275 {276 // return chbuf non readable277 thread_ptr->command.nic.status = false;278 }279 }280 281 }282 break; // end READABLE283 }284 } // end soclib_nic_cmd()285 286 287 /////////////////////////////////////////////////////////////////288 46 void __attribute__ ((noinline)) soclib_nic_isr( chdev_t * chdev ) 289 47 { 290 // get base, size, channel, is_rx from NIC channel device NIC291 xptr_t base = chdev->base;292 uint32_t channel = chdev->channel;293 bool_t is_rx = chdev->is_rx;294 48 295 // get NIC peripheral cluster and local pointer 296 cxy_t cxy_nic = GET_CXY( base ); 297 uint32_t * ptr_nic = (uint32_t *)GET_PTR( base ); 49 } 298 50 299 // compute local pointer on status register300 uint32_t * offset;301 if( is_rx ) offset = ptr_nic + (NIC_CHANNEL_SPAN * (channel + 1)) + NIC_RX_STATUS;302 else offset = ptr_nic + (NIC_CHANNEL_SPAN * (channel + 1)) + NIC_TX_STATUS;303 304 // read NIC channel status and acknowledge IRQ305 uint32_t status = hal_remote_lw( XPTR( cxy_nic , offset ) );306 307 if( status != 0 ) hal_core_sleep("%s : illegal address\n", __FUNCTION__ );308 309 // unblock server thread310 thread_t * server = chdev->server;311 thread_unblock( XPTR( local_cxy , server ) , THREAD_BLOCKED_IO );312 313 } // end soclib_nic_isr()314 315 316
Note: See TracChangeset
for help on using the changeset viewer.