Changeset 76 for trunk/hal/x86_64/drivers/soclib_cma.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_cma.c
r75 r76 27 27 #include <spinlock.h> 28 28 29 30 /////////////////////////////////////31 29 void soclib_nic_init( xptr_t xp_dev ) 32 30 { 33 uint32_t i;34 kmem_req_t req;35 36 // get NIC device descriptor cluster and local pointer37 cxy_t dev_cxy = GET_CXY( dev );38 device_t * dev_ptr = (device_t *)GET_PTR( dev );39 40 // get hardware device base address41 xptr_t base = hal_remote_lwd( XPTR( dev_cxy , &dev_ptr->base ) );42 31 43 // get hardware device cluster and local pointer 44 cxy_t nic_cxy = GET_CXY( base ); 45 uint32_t * nic_ptr = (uint32_t *)GET_PTR( base ); 32 } 46 33 47 // initialize Soclib NIC global registers48 hal_remote_sw( XPTR( nic_cxy , &nic_ptr + NIC_G_BC_ENABLE ) , 0 );49 hal_remote_sw( XPTR( nic_cxy , &nic_ptr + NIC_G_ON ) , 0 );50 51 // allocate memory for chbuf descriptor (one page)52 if( sizeof(nic_chbuf_t) > CONFIG_PPM_PAGE_SIZE )53 {54 printk("PANIC in %s : chbuf descriptor exceeds one page\n", __FUNCTION__ );55 hal_core_sleep;56 }57 58 req->type = KMEM_PAGE;59 req->size = 0;60 req_flags = AF_KERNEL;61 62 nic_chbuf_t * chbuf = (nic_chbuf_t *)kmem_alloc( &req );63 64 if( chbuf == NULL )65 {66 printk("PANIC in %s : no more memory for chbuf desccriptor\n", __FUNCTION__ );67 hal_core_sleep;68 }69 70 // initialise chbuf state71 chbuf->cont_id = 0;72 chbuf->pkt_id = 0;73 chbuf->word_id = 34;74 75 // allocate containers (one page per container)76 // and complete chbuf descriptor initialization77 if( CONFIG_PPM_PAGE_SIZE != 4096 )78 {79 printk("PANIC in %s : chbuf container must be 4 Kbytes\n", __FUNCTION__ );80 hal_core_sleep;81 }82 83 for( i = 0 ; i < CONFIG_NIC_CHBUF_DEPTH ; i++ )84 {85 uint32_t * container = (uint32_t *)kmem_alloc( req );86 87 if( container == NULL )88 {89 printk("PANIC in %s : no more memory for container\n", __FUNCTION__ );90 hal_core_sleep;91 }92 93 chbuf->cont[i] = container;94 chbuf->full[i] = (paddr_t)XPTR( local_cxy , container );95 }96 97 // get a free WTI mailbox98 uint32_t wti_id = dev_icu_wti_alloc();99 if( wti_id == -1 )100 {101 printk("PANIC in %s : cannot allocate WTI mailbox\n", __FUNCTION__ );102 hal_core_sleep;103 }104 105 // enable WTI IRQ in local ICU and update WTI interrupt vector106 dev_icu_enable_irq( WTI_TYPE , wti_id , xp_dev );107 108 // link NIC IRQ to WTI mailbox in PIC component109 uint32_t irq_id;110 if( is_rx ) irq_id = devices_irq.nic_rx[channel];111 else irq_id = devices_irq.nic_tx[channel];112 dev_pic_bind_irq( irq_id , local_cxy , wti_id );113 114 } // end soclib_nic_init()115 116 117 ////////////////////////////////////////////////118 34 void __attribute__ ((noinline)) soclib_nic_cmd() 119 35 { 120 uint32_t cmd; // command type121 char * buffer; // pointer on command buffer122 uint32_t length; // Ethernet packet length123 uint32_t offset; // offset in buffer124 nic_chbuf_t * chbuf; // pointer on chbuf descriptor125 uint32_t cont_id; // index of current container in chbuf126 uint32_t pkt_id; // index of current packet in container127 uint32_t word_id; // index of first word of current packet in container128 uint32_t * container; // pointer on container (array of uint32_t)129 uint16_t * header; // pointer on container header (array of uint16_t)130 uint32_t npackets; // number of packets in current container131 36 132 volatile uint64_t sts; // container descriptor (containing status) 37 } 133 38 134 thread_t * this = CURRENT_THREAD;135 136 // get command arguments137 cmd = this->dev.nic.cmd;138 buffer = this->dev.nic.buffer;139 length = this->dev.nic.length;140 141 // get chbuf descriptor pointer142 chbuf = (nic_chbuf_t *)dev->ext.nic.queue;143 144 // analyse command type145 switch( cmd )146 {147 /////////////////////////////////////////////////////////////////////////////148 case NIC_CMD_READ: // transfer one packet from RX queue to command buffer149 {150 // get current container index151 cont_id = chbuf->cont_id;152 153 if( chbuf->full[cont_id] == 0 ) // container empty154 {155 printk("PANIC in %s : read an empty container\n", __FUNCTION__ );156 hal_core_sleep();157 }158 159 // get pointer on container and header160 container = chbuf->cont[cont_id];161 header = (uint16_t *)header;162 163 // get expected packet index and first word index in container164 pkt_id = chbuf->pkt_id;165 word_id = chbuf->word_id;166 167 // get packet length and number of packets from container header168 length = header[pkt_id + 2];169 npackets = header[0];170 171 if( pkt_id >= npackets ) // packet index too large172 {173 printk("PANIC in %s : read a non readable container\n", __FUNCTION__ );174 hal_core_sleep();175 }176 177 // move the packet from container to buffer178 memcpy( buffer , container + word_id , length );179 180 // update current packet index and first word index181 chbuf->pkt_id = pkt_id + 1;182 if( length & 0x3 ) chbuf->word_id = word_id + (length>>2) + 1;183 else chbuf->word_id = word_id + (length>>2);184 }185 break; // end READ186 187 //////////////////////////////////////////////////////////////////////////188 case NIC_CMD_WRITE: // move one packet from command buffer to TX queue189 {190 // get current TX container indexes191 cont_id = chbuf->cont_id;192 pkt_id = chbuf->pkt_id;193 word_id = chbuf->word_id;194 195 if( chbuf->full[cont_id] != 0 ) // container full196 {197 printk("PANIC in %s : write to a full container\n", __FUNCTION__ );198 hal_core_sleep();199 }200 201 // get pointer on container and header202 container = chbuf->cont[cont_id];203 header = (uint16_t *)container;204 205 if( length > ((1024 - word_id)<<2) ) // packet length too large206 {207 printk("PANIC in %s : write to a non writable container\n", __FUNCTION__ );208 hal_core_sleep();209 }210 211 // update packet length in container header212 header[pkt_id + 2] = (uint16_t)length;213 214 // move the packet from buffer to container215 memcpy( container + word_id , buffer , length );216 217 // update current packet index and first word index218 chbuf->pkt_id = pkt_id + 1;219 if( length & 0x3 ) chbuf->word_id = word_id + (length>>2) + 1;220 else chbuf->word_id = word_id + (length>>2);221 }222 break; // end WRITE223 224 ////////////////////////////////////////////////////////////////////////////225 case NIC_CMD_WRITABLE: // analyse chbuf status / update status if required226 {227 // get current container state228 cont_id = chbuf->cont_id;229 word_id = chbuf->word_id;230 231 // compute current container writable232 bool_t ok = ( chbuf->full[cont_id] == 0 ) &&233 ( length <= ((1024 - word_id)<<2) );234 235 if( ok ) // current container writable236 {237 // return chbuf writable238 this->dev.nic.status = true;239 }240 else // current container not writable241 {242 // release current container243 chbuf->full[cont_id] = 1;244 245 // check next container246 cont_id = (cont_id + 1) % CONFIG_NIC_CHBUF_DEPTH;247 248 if( chbuf->full[cont_id] == 0 ) // next container empty249 {250 // update chbuf status251 chbuf->word_id = 34;252 chbuf->cont_id = cont-id;253 chbuf->pkt_id = 0;254 255 // return chbuf writable256 this->dev.nic.status = true;257 }258 else // next container full259 {260 // return chbuf non writable261 this->dev.nic.status = false;262 }263 }264 }265 break; // end WRITABLE266 267 /////////////////////////////////////////////////////////////////////////////268 case NIC_CMD_READABLE: // analyse chbuf status / update status if required269 {270 // get current container state271 cont_id = chbuf->cont_id;272 pkt_id = chbuf->pkt_id;273 npackets = chbuf->cont[cont_id][0] & 0x0000FFFF;274 275 // compute current container readable276 bool_t ok = ( chbuf->full[cont_id] == 1 ) &&277 ( pkt_id < npackets );278 279 if( ok ) // current container readable280 {281 // return chbuf readable282 this->dev.nic.status = true;283 }284 else // current container non readable285 {286 // release current container287 chbuf->full[cont_id] = 0;288 289 // check next container290 cont_id = (cont_id + 1) % CONFIG_NIC_CHBUF_DEPTH;291 292 if( chbuf->full[cont_id] == 1 ) // next container full293 {294 // update chbuf status295 chbuf->word_id = 34;296 chbuf->cont_id = cont-id;297 chbuf->pkt_id = 0;298 299 // return chbuf readable300 this->dev.nic.status = true;301 }302 else // next container empty303 {304 // return chbuf non readable305 this->dev.nic.status = false;306 }307 }308 309 }310 break; // end READABLE311 }312 } // end soclib_nic_cmd()313 314 315 ////////////////////////////////////////////////////////////////316 39 void __attribute__ ((noinline)) soclib_nic_isr( device_t * dev ) 317 40 { 318 cxy_t local_cxy = LOCAL_CUSTER->cxy;319 41 320 // acknowledge WTI IRQ TODO 42 } 321 43 322 // unblock server thread323 thread_t * server = dev->server;324 thread_unblock( XPTR( local_cxy , server ) , THREAD_BLOCKED_IO );325 326 } // end soclib_nic_isr()327 328 329
Note: See TracChangeset
for help on using the changeset viewer.