Changeset 76
- Timestamp:
- Jun 27, 2017, 2:07:55 PM (7 years ago)
- Location:
- trunk/hal/x86_64/drivers
- Files:
-
- 4 deleted
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/hal/x86_64/drivers/soclib_bdv.c
r75 r76 28 28 #include <spinlock.h> 29 29 30 31 ///////////////////////////////////////32 30 void soclib_bdv_init( chdev_t * chdev ) 33 31 { 34 // get extended pointer on SOCLIB_BDV peripheral base address35 xptr_t bdv_xp = chdev->base;36 32 37 // get hardware device cluster and local pointer 38 cxy_t bdv_cxy = GET_CXY( bdv_xp ); 39 uint32_t * bdv_ptr = (uint32_t *)GET_PTR( bdv_xp ); 33 } 40 34 41 // get block_size and block_count42 uint32_t block_size = hal_remote_lw( XPTR( bdv_cxy , bdv_ptr + BDV_BLOCK_SIZE_REG ) );43 uint32_t block_count = hal_remote_lw( XPTR( bdv_cxy , bdv_ptr + BDV_SIZE_REG ) );44 45 // set IOC device descriptor extension46 chdev->ext.ioc.size = block_size;47 chdev->ext.ioc.count = block_count;48 49 } // end soclib_bdv_init()50 51 52 //////////////////////////////////////////////////////////////53 35 void __attribute__ ((noinline)) soclib_bdv_cmd( xptr_t th_xp ) 54 36 { 55 uint32_t cmd_type; // IOC_READ / IOC_WRITE / IOC_SYNC_READ56 uint32_t lba; // command argument57 uint32_t count; // command argument58 xptr_t buf_xp; // command argument59 xptr_t dev_xp; // command argument60 37 61 // get client thread cluster and local pointer 62 cxy_t th_cxy = GET_CXY( th_xp ); 63 thread_t * th_ptr = (thread_t *)GET_PTR( th_xp ); 38 } 64 39 65 // get command arguments and extended pointer on IOC device66 cmd_type = hal_remote_lw ( XPTR( th_cxy , &th_ptr->command.ioc.type ) );67 lba = hal_remote_lw ( XPTR( th_cxy , &th_ptr->command.ioc.lba ) );68 count = hal_remote_lw ( XPTR( th_cxy , &th_ptr->command.ioc.count ) );69 buf_xp = (xptr_t)hal_remote_lwd( XPTR( th_cxy , &th_ptr->command.ioc.buf_xp ) );70 dev_xp = (xptr_t)hal_remote_lwd( XPTR( th_cxy , &th_ptr->command.ioc.dev_xp ) );71 72 // get IOC device cluster and local pointer73 cxy_t dev_cxy = GET_CXY( dev_xp );74 chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp );75 76 // get extended pointer on SOCLIB-BDV peripheral77 xptr_t bdv_xp = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->base ) );78 79 // get SOCLIB_BDV device cluster and local pointer80 cxy_t bdv_cxy = GET_CXY( bdv_xp );81 uint32_t * bdv_ptr = (uint32_t *)GET_PTR( bdv_xp );82 83 // split buffer address in two 32 bits words84 uint32_t buf_lsb = (uint32_t)(buf_xp);85 uint32_t buf_msb = (uint32_t)(buf_xp>>32);86 87 // set operation88 uint32_t op;89 if( cmd_type == IOC_WRITE ) op = BDV_OP_WRITE;90 else op = BDV_OP_READ;91 92 // set SOCLIB_BDV registers to start one I/O operation93 hal_remote_sw( XPTR( bdv_cxy , bdv_ptr + BDV_IRQ_ENABLE_REG ) , 1 );94 hal_remote_sw( XPTR( bdv_cxy , bdv_ptr + BDV_BUFFER_REG ) , buf_lsb );95 hal_remote_sw( XPTR( bdv_cxy , bdv_ptr + BDV_BUFFER_EXT_REG ) , buf_msb );96 hal_remote_sw( XPTR( bdv_cxy , bdv_ptr + BDV_LBA_REG ) , lba );97 hal_remote_sw( XPTR( bdv_cxy , bdv_ptr + BDV_COUNT_REG ) , count );98 hal_remote_sw( XPTR( bdv_cxy , bdv_ptr + BDV_OP_REG ) , op );99 100 // waiting policy depends on the command type101 102 if( cmd_type == IOC_SYNC_READ ) // polling policy103 {104 uint32_t status;105 while (1)106 {107 status = hal_remote_lw( XPTR( bdv_cxy , bdv_ptr + BDV_STATUS_REG ) );108 109 if( status == BDV_READ_SUCCESS ) // successfully completed110 {111 hal_remote_sw( XPTR( th_cxy , &th_ptr->command.ioc.error ) , 0 );112 break;113 }114 else if( status == BDV_BUSY ) // non completed115 {116 continue;117 }118 else // error reported119 {120 hal_remote_sw( XPTR( th_cxy , &th_ptr->command.ioc.error ) , 1 );121 break;122 }123 }124 }125 else // descheduling + IRQ policy126 {127 thread_block( CURRENT_THREAD , THREAD_BLOCKED_DEV_ISR );128 sched_yield();129 }130 131 } // end soclib_bdv_cmd()132 133 134 /////////////////////////////////////////////////////////////////135 40 void __attribute__ ((noinline)) soclib_bdv_isr( chdev_t * chdev ) 136 41 { 137 // get extended pointer on client thread138 xptr_t root = XPTR( local_cxy , &chdev->wait_root );139 xptr_t client_xp = XLIST_FIRST_ELEMENT( root , thread_t , wait_list );140 42 141 // get extended pointer on server thread 142 xptr_t server_xp = XPTR( local_cxy , &chdev->server ); 43 } 143 44 144 // get client thread cluster and local pointer145 cxy_t client_cxy = GET_CXY( client_xp );146 thread_t * client_ptr = (thread_t *)GET_PTR( client_xp );147 148 // get SOCLIB_BDV device cluster and local pointer149 cxy_t bdv_cxy = GET_CXY( chdev->base );150 uint32_t * bdv_ptr = (uint32_t *)GET_PTR( chdev->base );151 152 // get BDV status register and acknowledge IRQ153 uint32_t status = hal_remote_lw( XPTR( bdv_cxy , bdv_ptr + BDV_STATUS_REG ) );154 155 // set operation status in command156 if((status != BDV_READ_SUCCESS) && (status != BDV_WRITE_SUCCESS))157 {158 hal_remote_sw( XPTR( client_cxy , &client_ptr->command.ioc.error ) , 1 );159 }160 else161 {162 hal_remote_sw( XPTR( client_cxy , &client_ptr->command.ioc.error ) , 0 );163 }164 165 // unblock server thread166 thread_unblock( server_xp , THREAD_BLOCKED_DEV_ISR );167 168 // unblock client thread169 thread_unblock( client_xp , THREAD_BLOCKED_IO );170 171 } // end soclib_bdv_isr()172 173 174 -
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 -
trunk/hal/x86_64/drivers/soclib_dma.c
r75 r76 28 28 #include <soclib_dma.h> 29 29 30 ///////////////////////////////////////31 30 void soclib_dma_init( chdev_t * chdev ) 32 31 { 33 // get hardware device cluster and local pointer34 cxy_t dma_cxy = GET_CXY( chdev->base );35 uint32_t * dma_ptr = (uint32_t *)GET_PTR( chdev->base );36 32 37 // enable interrupts 38 hal_remote_sw( XPTR( dma_cxy , dma_ptr + DMA_IRQ_DISABLED ) , 0 ); 33 } 39 34 40 } // soclib_dma_init()41 42 //////////////////////////////////////////////////////////////////43 35 void __attribute__ ((noinline)) soclib_dma_cmd( xptr_t thread_xp ) 44 36 { 45 xptr_t dev_xp; // extended pointer on DMA devive46 xptr_t dst_xp; // extended pointer on destination buffer47 xptr_t src_xp; // extended pointer on source buffer48 uint32_t size; // buffer size49 37 50 // get client thread cluster and local pointer 51 cxy_t thread_cxy = GET_CXY( thread_xp ); 52 thread_t * thread_ptr = (thread_t *)GET_PTR( thread_xp ); 38 } 53 39 54 // get command arguments and extended pointer on DMA device55 dev_xp = (xptr_t)hal_remote_lwd( XPTR( thread_cxy , &thread_ptr->command.dma.dev_xp ) );56 dst_xp = (xptr_t)hal_remote_lwd( XPTR( thread_cxy , &thread_ptr->command.dma.dst_xp ) );57 src_xp = (xptr_t)hal_remote_lwd( XPTR( thread_cxy , &thread_ptr->command.dma.src_xp ) );58 size = hal_remote_lw ( XPTR( thread_cxy , &thread_ptr->command.dma.size ) );59 60 // get DMA device cluster and local pointer61 cxy_t dev_cxy = GET_CXY( dev_xp );62 chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp );63 64 // get extended pointer on SOCLIB-DMA peripheral65 xptr_t dma_xp = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->base ) );66 67 // get SOCLIB_DMA device cluster and local pointer68 cxy_t dma_cxy = GET_CXY( dma_xp );69 uint32_t * dma_ptr = (uint32_t *)GET_PTR( dma_xp );70 71 // get DMA channel index and channel base address72 uint32_t * base = dma_ptr + DMA_SPAN * dev_ptr->channel;73 74 // split dst and src buffers addresses in two 32 bits words75 uint32_t dst_lsb = (uint32_t)(dst_xp);76 uint32_t dst_msb = (uint32_t)(dst_xp>>32);77 uint32_t src_lsb = (uint32_t)(src_xp);78 uint32_t src_msb = (uint32_t)(src_xp>>32);79 80 // set SOCLIB_DMA registers to start tranfer operation81 hal_remote_sw( XPTR( dma_cxy , base + DMA_SRC ) , src_lsb );82 hal_remote_sw( XPTR( dma_cxy , base + DMA_SRC_EXT ) , src_msb );83 hal_remote_sw( XPTR( dma_cxy , base + DMA_DST ) , dst_lsb );84 hal_remote_sw( XPTR( dma_cxy , base + DMA_DST_EXT ) , dst_msb );85 hal_remote_sw( XPTR( dma_cxy , base + DMA_LEN ) , size );86 87 // Block and deschedule server thread88 thread_block( CURRENT_THREAD , THREAD_BLOCKED_DEV_ISR );89 sched_yield();90 91 } // soclib_dma_cmd()92 93 /////////////////////////////////////////////////////////////////94 40 void __attribute__ ((noinline)) soclib_dma_isr( chdev_t * chdev ) 95 41 { 96 // get extended pointer on client thread97 xptr_t root = XPTR( local_cxy , &chdev->wait_root );98 xptr_t client_xp = XLIST_FIRST_ELEMENT( root , thread_t , wait_list );99 42 100 // get extended pointer on server thread 101 xptr_t server_xp = XPTR( local_cxy , &chdev->server ); 43 } 102 44 103 // get client thread cluster and local pointer104 cxy_t client_cxy = GET_CXY( client_xp );105 thread_t * client_ptr = (thread_t *)GET_PTR( client_xp );106 107 // get SOCLIB_DMA peripheral cluster and local pointer108 cxy_t dma_cxy = GET_CXY( chdev->base );109 uint32_t * dma_ptr = (uint32_t *)GET_PTR( chdev->base );110 111 // get DMA channel base address112 uint32_t * base = dma_ptr + (DMA_SPAN * chdev->channel);113 114 // get DMA status register115 uint32_t status = hal_remote_lw( XPTR( dma_cxy , base + DMA_LEN ) );116 117 // acknowledge IRQ118 hal_remote_sw( XPTR( dma_cxy , base + DMA_RESET ) , 0 );119 120 // set operation status in command121 error_t error = ( status != DMA_SUCCESS );122 hal_remote_sw( XPTR( client_cxy , &client_ptr->command.dma.error ) , error );123 124 // unblock server thread125 thread_unblock( server_xp , THREAD_BLOCKED_DEV_ISR );126 127 // unblock client thread128 thread_unblock( client_xp , THREAD_BLOCKED_IO );129 130 } // soclib_dma_isr()131 132 133 -
trunk/hal/x86_64/drivers/soclib_hba.c
r75 r76 30 30 #include <thread.h> 31 31 32 //////////////////////////////////////////////////////////////////////////////////33 // SOCLIB_HBA specific global variables34 //////////////////////////////////////////////////////////////////////////////////35 36 // command list : up to 32 commands37 __attribute__((section(".kdata")))38 hba_cmd_desc_t hba_cmd_list[32] __attribute__((aligned(0x40)));39 40 // command tables array : one command table per entry in command list41 __attribute__((section(".kdata")))42 hba_cmd_table_t hba_cmd_table[32] __attribute__((aligned(0x40)));43 44 // extended pointer on the owner thread, for each slot45 __attribute__((section(".kdata")))46 xptr_t hba_owner_thread[32];47 48 // bit vector of active slots49 __attribute__((section(".kdata")))50 uint32_t hba_active_slots;51 52 // spinlock protecting the command slot allocator53 __attribute__((section(".kdata")))54 spinlock_t hba_lock;55 56 ///////////////////////////////////////57 32 void soclib_hba_init( chdev_t * chdev ) 58 33 { 59 // get hardware device base address60 xptr_t hba_xp = chdev->base;61 34 62 // get hardware device cluster and local pointer 63 cxy_t hba_cxy = GET_CXY( hba_xp ); 64 uint32_t * hba_ptr = (uint32_t *)GET_PTR( hba_xp ); 35 } 65 36 66 // get block_size and block_count67 uint32_t block_size = hal_remote_lw( XPTR( hba_cxy , hba_ptr + HBA_BLOCK_SIZE_REG ) );68 uint32_t block_count = hal_remote_lw( XPTR( hba_cxy , hba_ptr + HBA_BLOCK_COUNT_REG ) );69 70 // set device descriptor extension71 chdev->ext.ioc.size = block_size;72 chdev->ext.ioc.count = block_count;73 74 // activate HBA interrupts75 hal_remote_sw( XPTR( hba_cxy , hba_ptr + HBA_PXIE_REG ) , 0x1 );76 77 // reset SOCLIB_HBA driver global variable78 hba_active_slots = 0;79 80 } // end soclib_hba_init()81 82 83 //////////////////////////////////////////////////////////////84 37 void __attribute__ ((noinline)) soclib_hba_cmd( xptr_t th_xp ) 85 38 { 86 39 87 uint32_t cmd_type; // IOC_READ / IOC_WRITE / IOC_SYNC_READ 88 uint32_t lba; // lba : command argument 89 uint32_t count; // count : command argument 90 xptr_t buf_xp; // buffer : command argument 91 xptr_t dev_xp; // device : command argument 40 } 92 41 93 uint32_t cmd_id; // current slot index in command bit_vector94 hba_cmd_desc_t * cmd_desc; // command descriptor pointer95 hba_cmd_table_t * cmd_table; // command table pointer96 97 bool_t found;98 uint32_t iter;99 100 // get client thread cluster and local pointer101 cxy_t th_cxy = GET_CXY( th_xp );102 thread_t * th_ptr = (thread_t *)GET_PTR( th_xp );103 104 // get command arguments and extended pointer on IOC device105 cmd_type = hal_remote_lw ( XPTR( th_cxy , &th_ptr->command.ioc.type ) );106 lba = hal_remote_lw ( XPTR( th_cxy , &th_ptr->command.ioc.lba ) );107 count = hal_remote_lw ( XPTR( th_cxy , &th_ptr->command.ioc.count ) );108 buf_xp = (xptr_t)hal_remote_lwd( XPTR( th_cxy , &th_ptr->command.ioc.buf_xp ) );109 dev_xp = (xptr_t)hal_remote_lwd( XPTR( th_cxy , &th_ptr->command.ioc.dev_xp ) );110 111 // get IOC device cluster and local pointer112 cxy_t dev_cxy = GET_CXY( dev_xp );113 chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp );114 115 // get extended pointer on SOCLIB-HBA peripheral116 xptr_t hba_xp = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->base ) );117 118 // get SOCLIB_HBA device cluster and local pointer119 cxy_t hba_cxy = GET_CXY( hba_xp );120 uint32_t * hba_ptr = (uint32_t *)GET_PTR( hba_xp );121 122 // try to register the I/O operation in a free slot123 // returns if success, deschedule if no slot available124 // we do not need a lock to access the slot allocator,125 // because the driver is only called by the server thread.126 while( 1 )127 {128 // try to find a free slot in the 32 slots command list129 cmd_id = 0;130 found = false;131 for ( iter = 0 ; iter < 32 ; iter++ )132 {133 if( (hba_active_slots & (1<<iter) ) == 0 )134 {135 found = true;136 cmd_id = iter;137 hba_active_slots |= (1<<iter);138 break;139 }140 }141 142 if( found ) // slot available in SOCLIB_HBA143 {144 // compute pointers on command descriptor and command table145 cmd_desc = &hba_cmd_list[cmd_id];146 cmd_table = &hba_cmd_table[cmd_id];147 148 // set buffer descriptor in command table149 cmd_table->buffer.dba = (uint32_t)(buf_xp);150 cmd_table->buffer.dbau = (uint32_t)(buf_xp >> 32);151 cmd_table->buffer.dbc = count * 512;152 153 // initialize command table header154 cmd_table->header.lba0 = (char)lba;155 cmd_table->header.lba1 = (char)(lba>>8);156 cmd_table->header.lba2 = (char)(lba>>16);157 cmd_table->header.lba3 = (char)(lba>>24);158 cmd_table->header.lba4 = 0;159 cmd_table->header.lba5 = 0;160 161 // initialise command descriptor162 cmd_desc->prdtl[0] = 1;163 cmd_desc->prdtl[1] = 0;164 if( cmd_type == IOC_WRITE ) cmd_desc->flag[0] = 0x40;165 else cmd_desc->flag[0] = 0x00;166 167 #if USE_IOB // software L2/L3 cache coherence168 169 dev_mmc_sync( cmd_table , sizeof(hba_cmd_table_t) );170 dev_mmc_sync( cmd_desc , sizeof(hba_cmd_desc_t) );171 172 #endif // end software L2/L3 cache coherence173 174 // set hba_owner_thread[slot]175 hba_owner_thread[cmd_id] = th_xp;176 177 // register slot in bit_vector178 hba_active_slots |= 1<<cmd_id;179 180 // set HBA_PXCI_REG to start transfer181 hal_remote_sw( XPTR( hba_cxy , hba_ptr + HBA_PXCI_REG ) , 1<<cmd_id );182 183 // exit the while184 break;185 }186 else // no slot available in SOCLIB_HBA187 {188 if( cmd_type == IOC_SYNC_READ ) // fatal if synchronous access189 {190 printk("\n[PANIC] in %s : no slot available for a SYNC_READ\n", __FUNCTION__ );191 hal_core_sleep();192 }193 else // retry if asynchronous access.194 {195 sched_yield();196 }197 }198 } // end while to get a slot199 200 // waiting policy depends on the command type201 202 if( cmd_type == IOC_SYNC_READ ) // polling, busy waiting203 {204 uint32_t pxis;205 uint32_t pxci;206 uint32_t error;207 uint32_t fault_id;208 while(1)209 {210 pxis = hal_remote_lw( XPTR( hba_cxy , hba_ptr + HBA_PXIS_REG ) );211 pxci = hal_remote_lw( XPTR( hba_cxy , hba_ptr + HBA_PXCI_REG ) );212 error = (pxis & 0x40000000) >> 30;213 fault_id = (pxis & 0x1F000000) >> 24;214 215 if( (pxci & (1<<cmd_id)) == 0 ) // completed216 {217 // release slot218 hba_active_slots &= ~(1<<cmd_id);219 220 // set operation status in client thread command221 if( error && (fault_id == cmd_id) )222 {223 hal_remote_sw( XPTR( th_cxy , &th_ptr->command.ioc.error ) , 1 );224 }225 else226 {227 hal_remote_sw( XPTR( th_cxy , &th_ptr->command.ioc.error ) , 0 );228 }229 230 // exit while231 break;232 }233 }234 }235 else // descheduling + IRQ236 {237 thread_block( CURRENT_THREAD , THREAD_BLOCKED_DEV_ISR );238 sched_yield();239 }240 241 } // end soclib_hba_cmd()242 243 244 /////////////////////////////////////////////////////////////////245 42 void __attribute__ ((noinline)) soclib_hba_isr( chdev_t * chdev ) 246 43 { 247 // get extended pointer on client thread248 xptr_t root = XPTR( local_cxy , &chdev->wait_root );249 xptr_t client_xp = XLIST_FIRST_ELEMENT( root , thread_t , wait_list );250 44 251 // get client thread cluster and local pointer 252 cxy_t client_cxy = GET_CXY( client_xp ); 253 thread_t * client_ptr = (thread_t *)GET_PTR( client_xp ); 45 } 254 46 255 // get SOCLIB_HBA device cluster and local pointer256 cxy_t hba_cxy = GET_CXY( chdev->base );257 uint32_t * hba_ptr = (uint32_t *)GET_PTR( chdev->base );258 259 // get HBA_PXIS_REG and HBA_PXCI_REG current values260 uint32_t current_pxis = hal_remote_lw( XPTR( hba_cxy , hba_ptr + HBA_PXIS_REG ) );261 uint32_t current_pxci = hal_remote_lw( XPTR( hba_cxy , hba_ptr + HBA_PXCI_REG ) );262 263 uint32_t error = (current_pxis & 0x40000000) >> 30;264 uint32_t fault_id = (current_pxis & 0x1F000000) >> 24;265 uint32_t iter;266 267 // loop on active commands to signal one or several completed I/O operations268 for( iter = 0 ; iter < 32 ; iter++ )269 {270 if ( ( (hba_active_slots & (1<<iter)) != 0 ) && // active command271 ( (current_pxci & (1<<iter)) == 0 ) ) // completed command272 {273 // release the slot274 hba_active_slots &= ~(1<<iter);275 276 // set operation status in client thread command277 if( error && (iter == fault_id ) )278 {279 hal_remote_sw( XPTR( client_cxy , &client_ptr->command.ioc.error ) , 1 );280 }281 else282 {283 hal_remote_sw( XPTR( client_cxy , &client_ptr->command.ioc.error ) , 0 );284 }285 286 // unblock client thread287 thread_unblock( client_xp , THREAD_BLOCKED_IO );288 289 ioc_dmsg("INFO in %s : thread %x at cycle %d\n",290 __FUNCTION__ , hal_remote_lw( XPTR( client_cxy , &client_ptr->trdid ) ) ,291 hal_time_stamp() );292 }293 }294 295 // reset HBA_PXIS_REG296 hal_remote_sw( XPTR( hba_cxy , hba_ptr + HBA_PXIS_REG ) , 0 );297 298 } // end soclib_hba_isr()299 300 301 -
trunk/hal/x86_64/drivers/soclib_iob.c
r75 r76 27 27 #include <soclib_iob.h> 28 28 29 ///////////////////////////////////////30 29 void soclib_iob_init( chdev_t * chdev ) 31 30 { 32 // desactivate IOMMU 33 hal_remote_sw( chdev->base + (IOB_IOMMU_ACTIVE<<2) , 0 ); 31 34 32 } 35 33 36 ////////////////////////////////////////////37 34 void soclib_iob_set_active( xptr_t iob_xp, 38 35 uint32_t value ) 39 36 { 40 // get IOX device cluster and local pointer41 cxy_t iob_cxy = GET_CXY( iob_xp );42 chdev_t * iob_ptr = (chdev_t *)GET_PTR( iob_xp );43 37 44 // get extended pointer on SOCLIB_IOB base_xp segment45 xptr_t base_xp = (xptr_t)hal_remote_lwd( XPTR( iob_cxy , &iob_ptr->base ) );46 47 // set ACTIVE register48 hal_remote_sw( base_xp + (IOB_IOMMU_ACTIVE<<2) , value );49 38 } 50 39 51 //////////////////////////////////////////52 40 void soclib_iob_set_ptpr( xptr_t iob_xp, 53 41 uint32_t value ) 54 42 { 55 // get IOX device cluster and local pointer56 cxy_t iob_cxy = GET_CXY( iob_xp );57 chdev_t * iob_ptr = (chdev_t *)GET_PTR( iob_xp );58 43 59 // get extended pointer on SOCLIB_IOB base_xp segment60 xptr_t base_xp = (xptr_t)hal_remote_lwd( XPTR( iob_cxy , &iob_ptr->base ) );61 62 // set PTPR register63 hal_remote_sw( base_xp + (IOB_IOMMU_PTPR<<2) , value );64 44 } 65 45 66 ///////////////////////////////////////////67 46 void soclib_iob_inval_page( xptr_t iob_xp, 68 47 vpn_t vpn ) 69 48 { 70 // get IOX device cluster and local pointer71 cxy_t iob_cxy = GET_CXY( iob_xp );72 chdev_t * iob_ptr = (chdev_t *)GET_PTR( iob_xp );73 49 74 // get extended pointer on SOCLIB_IOB base_xp segment75 xptr_t base_xp = (xptr_t)hal_remote_lwd( XPTR( iob_cxy , &iob_ptr->base ) );76 77 // invalidate TLB entry78 hal_remote_sw( base_xp + (IOB_INVAL_PTE<<2) , vpn );79 50 } 80 51 81 //////////////////////////////////////////////82 52 uint32_t soclib_iob_get_bvar( xptr_t iob_xp ) 83 53 { 84 // get IOX device cluster and local pointer 85 cxy_t iob_cxy = GET_CXY( iob_xp ); 86 chdev_t * iob_ptr = (chdev_t *)GET_PTR( iob_xp ); 87 88 // get extended pointer on SOCLIB_IOB base_xp segment 89 xptr_t base_xp = (xptr_t)hal_remote_lwd( XPTR( iob_cxy , &iob_ptr->base ) ); 90 91 // get BVAR register 92 return hal_remote_lw( base_xp + (IOB_IOMMU_BVAR<<2) ); 54 return 0; 93 55 } 94 56 95 ///////////////////////////////////////////////96 57 uint32_t soclib_iob_get_srcid( xptr_t iob_xp ) 97 58 { 98 // get IOX device cluster and local pointer 99 cxy_t iob_cxy = GET_CXY( iob_xp ); 100 chdev_t * iob_ptr = (chdev_t *)GET_PTR( iob_xp ); 101 102 // get extended pointer on SOCLIB_IOB base_xp segment 103 xptr_t base_xp = (xptr_t)hal_remote_lwd( XPTR( iob_cxy , &iob_ptr->base ) ); 104 105 // get BVAR register 106 return hal_remote_lw( base_xp + (IOB_IOMMU_SRCID<<2) ); 59 return 0; 107 60 } 108 61 109 ///////////////////////////////////////////////110 62 uint32_t soclib_iob_get_error( xptr_t iob_xp ) 111 63 { 112 // get IOX device cluster and local pointer 113 cxy_t iob_cxy = GET_CXY( iob_xp ); 114 chdev_t * iob_ptr = (chdev_t *)GET_PTR( iob_xp ); 115 116 // get extended pointer on SOCLIB_IOB base_xp segment 117 xptr_t base_xp = (xptr_t)hal_remote_lwd( XPTR( iob_cxy , &iob_ptr->base ) ); 118 119 // get BVAR register 120 return hal_remote_lw( base_xp + (IOB_IOMMU_ERROR<<2) ); 64 return 0; 121 65 } 122 66 123 124 // Local Variables:125 // tab-width: 4126 // c-basic-offset: 4127 // c-file-offsets:((innamespace . 0)(inline-open . 0))128 // indent-tabs-mode: nil129 // End:130 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4131 -
trunk/hal/x86_64/drivers/soclib_mmc.c
r75 r76 31 31 #include <printk.h> 32 32 33 34 ///////////////////////////////////////35 33 void soclib_mmc_init( chdev_t * chdev ) 36 34 { 37 // get pointer on MMC segment base38 uint32_t * base = (uint32_t *)GET_PTR( chdev->base );39 35 40 // enable MMC IRQ41 *(base + (SOCLIB_MMC_ERROR_FUNC << 7) + SOCLIB_MMC_ERROR_IRQ_ENABLE) = 1;42 36 } 43 37 44 45 //////////////////////////////////////////////////////////////46 38 void __attribute__ ((noinline)) soclib_mmc_cmd( xptr_t th_xp ) 47 39 { 48 xptr_t dev_xp; // extended pointer on MMC device49 uint32_t type; // MMC command : type50 uint64_t buf_paddr; // MMC command : buffer physical address51 uint32_t buf_size; // MMC command : buffer size52 uint32_t reg_index; // MMC command : register index in MMC peripheral53 uint32_t * reg_ptr; // MMC command : pointer on dst/src buffer in client cluster54 40 55 // get client thread cluster and local pointer 56 cxy_t th_cxy = GET_CXY( th_xp ); 57 thread_t * th_ptr = (thread_t *)GET_PTR( th_xp ); 41 } 58 42 59 // get command type and extended pointer on MMC device60 type = hal_remote_lw ( XPTR( th_cxy , &th_ptr->command.mmc.type ) );61 dev_xp = (xptr_t)hal_remote_lwd( XPTR( th_cxy , &th_ptr->command.mmc.dev_xp ) );62 63 // get MMC device cluster and local pointer64 cxy_t dev_cxy = GET_CXY( dev_xp );65 chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp );66 67 // get extended pointer on SOCLIB-MMC peripheral68 xptr_t mmc_xp = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->base ) );69 70 // get SOCLIB_MMC peripheral cluster and local pointer71 cxy_t mmc_cxy = GET_CXY( mmc_xp );72 uint32_t * mmc_ptr = (uint32_t *)GET_PTR( mmc_xp );73 74 if( (type == MMC_CC_INVAL) || (type == MMC_CC_SYNC) )75 {76 // get buffer paddr77 buf_paddr = hal_remote_lwd( XPTR( th_cxy , &th_ptr->command.mmc.buf_paddr ) );78 79 // split buffer paddr in two 32 bits words80 uint32_t buf_lo = (uint32_t)( buf_paddr );81 uint32_t buf_hi = (uint32_t)( buf_paddr>>32 );82 83 // get buffer size84 buf_size = hal_remote_lw( XPTR( th_cxy , &th_ptr->command.mmc.buf_size ) );85 86 // get command type87 uint32_t cc_cmd;88 if( type == MMC_CC_INVAL ) cc_cmd = SOCLIB_MMC_CC_INVAL;89 else cc_cmd = SOCLIB_MMC_CC_SYNC;90 91 // set SOCLIB_MMC registers to start INVAL/SYNC operation92 hal_remote_sw( XPTR( mmc_cxy , mmc_ptr + SOCLIB_MMC_ADDR_LO ) , buf_lo );93 hal_remote_sw( XPTR( mmc_cxy , mmc_ptr + SOCLIB_MMC_ADDR_HI ) , buf_hi );94 hal_remote_sw( XPTR( mmc_cxy , mmc_ptr + SOCLIB_MMC_BUF_LENGTH ) , buf_size );95 hal_remote_sw( XPTR( mmc_cxy , mmc_ptr + SOCLIB_MMC_CMD_TYPE ) , cc_cmd );96 }97 else // (type == MMC_GET_ERROR) or (type == MMC_GET_ERROR) pr (type == MMC_GET_INSTRU )98 {99 // get src/dst buffer local pointer and register index100 reg_ptr = (uint32_t *)hal_remote_lpt( XPTR( th_cxy , &th_ptr->command.mmc.reg_ptr ) );101 reg_index = hal_remote_lw( XPTR( th_cxy , &th_ptr->command.mmc.reg_index ) );102 103 // move register to/from local buffer104 if( (type == MMC_GET_ERROR) || (type == MMC_GET_INSTRU) )105 {106 *reg_ptr = hal_remote_lw( XPTR( mmc_cxy , mmc_ptr + reg_index ) );107 }108 else // type == MMC_SET_ERROR109 {110 hal_remote_sw( XPTR( mmc_cxy , mmc_ptr + reg_index ) , *reg_ptr );111 }112 }113 } // end soclib_mmc_cmd()114 115 116 ////////////////////////////////////////////////////////////////117 43 void __attribute__ ((noinline)) soclib_mmc_isr( chdev_t * chdev ) 118 44 { 119 // get pointer on MMC segment base120 uint32_t * base = (uint32_t *)GET_PTR( chdev->base );121 45 122 // get faulty ADDRESS and SRCID from MMC registers 123 uint32_t paddr_lo = *(base + (SOCLIB_MMC_ERROR_FUNC << 7) + SOCLIB_MMC_ERROR_ADDR_LO); 124 uint32_t paddr_hi = *(base + (SOCLIB_MMC_ERROR_FUNC << 7) + SOCLIB_MMC_ERROR_ADDR_HI); 125 uint32_t srcid = *(base + (SOCLIB_MMC_ERROR_FUNC << 7) + SOCLIB_MMC_ERROR_SRCID); 46 } 126 47 127 paddr_t paddr = (((paddr_t)paddr_hi)<<32) + ((paddr_t)paddr_lo);128 129 // reset MMC IRQ130 *(base + (SOCLIB_MMC_ERROR_FUNC << 7) + SOCLIB_MMC_ERROR_IRQ_RESET) = 0;131 132 // print an error message on kernel terminal TODO : should be improved133 printk("\n[ERROR] reported from MMC in cluster %x : faulty address = %l / srcid = %x\n",134 paddr , srcid );135 136 } // end soclib_mmc_isr()137 138 139 -
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 -
trunk/hal/x86_64/drivers/soclib_pic.c
r75 r76 30 30 #include <vfs.h> 31 31 32 33 ////////////////////////////////////////34 32 void soclib_pic_init( chdev_t * chdev ) 35 33 { 36 // get PIC controller segment cluster and local pointer37 cxy_t seg_cxy = (cxy_t)GET_CXY( chdev->base );38 uint32_t * seg_ptr = (uint32_t *)GET_PTR( chdev->base );39 uint32_t i;40 34 41 // reset the MASK registers for all input IRQs42 for( i = 0 ; i < CONFIG_MAX_IRQS_PER_PIC ; i++ )43 {44 hal_remote_sw( XPTR( seg_cxy , seg_ptr + i*IOPIC_SPAN + IOPIC_MASK ) , 0 );45 }46 35 } 47 36 48 ////////////////////////////////////////////49 37 void soclib_pic_bind_irq( xptr_t dev_xp, 50 38 uint32_t irq_id, 51 39 xptr_t xp_wti ) 52 40 { 53 // get PIC device descriptor cluster and local pointer54 cxy_t dev_cxy = GET_CXY( dev_xp );55 chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp );56 57 // get extended pointer on PIC segment base from PIC device descriptor58 xptr_t seg_xp = (xptr_t)hal_remote_lwd( XPTR( dev_cxy , &dev_ptr->base ) );59 60 // get PIC controller segment cluster and local pointer61 cxy_t seg_cxy = (cxy_t)GET_CXY( seg_xp);62 uint32_t * seg_ptr = (uint32_t *)GET_PTR( seg_xp );63 41 64 uint32_t lsb = (uint32_t)xp_wti;65 uint32_t msb = (uint32_t)(xp_wti>>32);66 67 // set the IOPIC_ADDRESS and IOPIC_EXTEND registers68 hal_remote_sw( XPTR( seg_cxy , seg_ptr+irq_id*IOPIC_SPAN+IOPIC_ADDRESS ) , lsb );69 hal_remote_sw( XPTR( seg_cxy , seg_ptr+irq_id*IOPIC_SPAN+IOPIC_EXTEND ) , msb );70 71 // set IOPIC_MASK register72 hal_remote_sw( XPTR( seg_cxy , seg_ptr+irq_id*IOPIC_SPAN+IOPIC_MASK ) , 1 );73 42 } 74 43 75 //////////////////////////////////////////////76 44 void soclib_pic_unbind_irq( xptr_t dev_xp, 77 45 uint32_t irq_id ) 78 46 { 79 // get PIC device descriptor cluster and local pointer80 cxy_t dev_cxy = GET_CXY( dev_xp );81 chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp );82 83 // get extended pointer on PIC segment base from PIC device descriptor84 xptr_t seg_xp = (xptr_t)hal_remote_lwd( XPTR( dev_cxy , &dev_ptr->base ) );85 86 // get PIC controller segment cluster and local pointer87 cxy_t seg_cxy = (cxy_t)GET_CXY( seg_xp);88 uint32_t * seg_ptr = (uint32_t *)GET_PTR( seg_xp );89 47 90 // set IOPIC_MASK register91 hal_remote_sw( XPTR( seg_cxy , seg_ptr+irq_id*IOPIC_SPAN+IOPIC_MASK ) , 0 );92 48 } 93 49 94 //////////////////////////////////////////////95 50 void soclib_pic_get_status( xptr_t dev_xp, 96 51 uint32_t irq_id, 97 52 uint32_t * status) 98 53 { 99 // get PIC device descriptor cluster and local pointer100 cxy_t dev_cxy = GET_CXY( dev_xp );101 chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp );102 103 // get extended pointer on PIC segment base from PIC device descriptor104 xptr_t seg_xp = (xptr_t)hal_remote_lwd( XPTR( dev_cxy , &dev_ptr->base ) );105 106 // get PIC controller segment cluster and local pointer107 cxy_t seg_cxy = (cxy_t)GET_CXY( seg_xp);108 uint32_t * seg_ptr = (uint32_t *)GET_PTR( seg_xp );109 54 110 // return status111 *status = hal_remote_lw( XPTR( seg_cxy , seg_ptr+irq_id*IOPIC_SPAN+IOPIC_STATUS ) );112 55 } 113 56 -
trunk/hal/x86_64/drivers/soclib_tty.c
r75 r76 29 29 #include <hal_special.h> 30 30 31 ///////////////////////////////////////32 31 void soclib_tty_init( chdev_t * chdev ) 33 32 { 34 // get extended pointer on TTY-SOCLIB peripheral base address35 xptr_t tty_xp = chdev->base;36 33 37 // get SOCLIB_TTY device cluster and local pointer38 cxy_t tty_cxy = GET_CXY( tty_xp );39 uint32_t * tty_ptr = (uint32_t *)GET_PTR( tty_xp );40 41 // mask both TTY_RX_IRQ and TTY_TX_IRQ42 hal_remote_sw( XPTR( tty_cxy , tty_ptr + TTY_CONFIG_REG ) , 0 );43 34 } 44 35 45 //////////////////////////////////////////////////////////////46 36 void __attribute__ ((noinline)) soclib_tty_cmd( xptr_t th_xp ) 47 37 { 48 // get client thread cluster and local pointer49 cxy_t th_cxy = GET_CXY( th_xp );50 thread_t * th_ptr = (thread_t *)GET_PTR( th_xp );51 38 52 // get command type and extended pointer on TXT device53 uint32_t type = hal_remote_lw ( XPTR( th_cxy , &th_ptr->command.txt.type ) );54 xptr_t dev_xp = (xptr_t)hal_remote_lwd( XPTR( th_cxy , &th_ptr->command.txt.dev_xp ) );55 56 // get TXT device cluster and local pointer57 cxy_t dev_cxy = GET_CXY( dev_xp );58 chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp );59 60 // get extended pointer on SOCLIB_TTY base segment61 xptr_t tty_xp = (xptr_t)hal_remote_lwd( XPTR( dev_cxy , &dev_ptr->base ) );62 63 // get SOCLIB_TTY base segment cluster and local pointer64 cxy_t tty_cxy = GET_CXY( tty_xp );65 uint32_t * tty_ptr = (uint32_t *)GET_PTR( tty_xp );66 67 // get TTY channel index and channel base address68 uint32_t channel = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->channel ) );69 uint32_t * base = tty_ptr + TTY_SPAN * channel;70 71 if( type == TXT_READ ) // descheduling strategy for calling thread72 {73 // unmask RX_IRQ (data transfer will be done by the TTY_RX ISR)74 xptr_t config_xp = XPTR( tty_cxy , base + TTY_CONFIG_REG );75 uint32_t old = hal_remote_lw( config_xp );76 uint32_t new = old | TTY_CONFIG_RX_ENABLE;77 hal_remote_atomic_cas( config_xp , old , new );78 79 // Block and deschedule server thread80 thread_block( CURRENT_THREAD , THREAD_BLOCKED_DEV_ISR );81 sched_yield();82 }83 else if( type == TXT_WRITE ) // descheduling strategy for calling thread84 {85 // unmask TX_IRQ (data transfer will be done by the TTY_TX ISR)86 xptr_t config_xp = XPTR( tty_cxy , base + TTY_CONFIG_REG );87 uint32_t old = hal_remote_lw( config_xp );88 uint32_t new = old | TTY_CONFIG_TX_ENABLE;89 hal_remote_atomic_cas( config_xp , old , new );90 91 // Block and deschedule server thread92 thread_block( CURRENT_THREAD , THREAD_BLOCKED_DEV_ISR );93 sched_yield();94 }95 else if( type == TXT_SYNC_WRITE ) // busy waiting strategy for calling thread96 {97 uint32_t status;98 bool_t empty;99 uint32_t i;100 101 // get source buffer extended pointer & bytes count102 uint32_t count = hal_remote_lw ( XPTR( th_cxy , &th_ptr->command.txt.count ) );103 xptr_t buf_xp = hal_remote_lwd( XPTR( th_cxy , &th_ptr->command.txt.buf_xp ) );104 105 // loop on characters106 for( i = 0 ; i < count ; i++ )107 {108 do109 {110 // get TTY_STATUS_REG111 status = hal_remote_lw( XPTR( tty_cxy , base + TTY_STATUS_REG ) );112 empty = ( (status & TTY_STATUS_TX_FULL) == 0 );113 114 if ( empty ) // TTY_TX empty => transfer one byte115 {116 // get one byte from command buffer in client cluster117 char byte = (char)hal_remote_lb( buf_xp + i );118 119 // write byte to TTY_WRITE_REG in TTY cluster120 hal_remote_sb( XPTR( tty_cxy , base + TTY_WRITE_REG ) , byte );121 }122 }123 while ( empty == false );124 }125 }126 39 } 127 40 128 /////////////////////////////////////////////////////////////////129 41 void __attribute__ ((noinline)) soclib_tty_isr( chdev_t * chdev ) 130 42 { 131 uint32_t type; // command type132 uint32_t count; // number of bytes in buffer133 xptr_t buf_xp; // Rextended pointer on buffer134 uint32_t status; // TTY terminal status135 char byte; // read byte136 uint32_t i;137 43 138 // get extended pointer on client thread139 xptr_t root = XPTR( local_cxy , &chdev->wait_root );140 xptr_t client_xp = XLIST_FIRST_ELEMENT( root , thread_t , wait_list );141 142 // get client thread cluster and local pointer143 cxy_t client_cxy = GET_CXY( client_xp );144 thread_t * client_ptr = (thread_t *)GET_PTR( client_xp );145 146 // get command arguments147 type = hal_remote_lw ( XPTR( client_cxy , &client_ptr->command.txt.type ) );148 count = hal_remote_lw ( XPTR( client_cxy , &client_ptr->command.txt.count ) );149 buf_xp = hal_remote_lwd( XPTR( client_cxy , &client_ptr->command.txt.buf_xp ) );150 151 // get SOCLIB_TTY peripheral cluster and local pointer152 cxy_t tty_cxy = GET_CXY( chdev->base );153 uint32_t * tty_ptr = (uint32_t *)GET_PTR( chdev->base );154 155 // get channel base address156 uint32_t * base = tty_ptr + TTY_SPAN * chdev->channel;157 158 if( type == TXT_READ ) // read one single character159 {160 // get TTY_STATUS_REG161 status = hal_remote_lw( XPTR( tty_cxy , base + TTY_STATUS_REG ) );162 163 if( status & TTY_STATUS_RX_FULL ) // TTY_RX full => transfer one byte164 {165 // get a byte from TTY_READ_REG, and acknowledge RX_IRQ166 byte = (char)hal_remote_lb( XPTR( tty_cxy , base + TTY_READ_REG ) );167 168 // write it to command buffer169 hal_remote_sb( buf_xp , byte );170 171 // update TTY_WRITE_REG if echo mode172 if( CONFIG_TXT_ECHO_MODE )173 {174 if( (byte == '\b') || (byte == 0x7F) )175 {176 hal_remote_sb( XPTR( tty_cxy , base + TTY_WRITE_REG ) , '\b' );177 hal_remote_sb( XPTR( tty_cxy , base + TTY_WRITE_REG ) , ' ' );178 hal_remote_sb( XPTR( tty_cxy , base + TTY_WRITE_REG ) , '\b' );179 }180 else181 {182 hal_remote_sw( XPTR( tty_cxy , base + TTY_WRITE_REG ) , byte );183 }184 }185 }186 else // buffer empty => exit ISR for retry187 {188 return;189 }190 }191 else if( type == TXT_WRITE ) // write a string192 {193 // loop on characters194 for( i = 0 ; i < count ; i++ )195 {196 // get TTY_STATUS_REG197 status = hal_remote_lw( XPTR( tty_cxy , base + TTY_STATUS_REG ) );198 199 if( (status & TTY_STATUS_TX_FULL) == 0 ) // TTY_TX empty => transfer one byte200 {201 // get one byte from command buffer202 byte = (char)hal_remote_lb( buf_xp + i );203 204 // write byte to TTY_WRITE_REG, and acknowledge TX_IRQ205 hal_remote_sb( XPTR( tty_cxy , base + TTY_STATUS_REG ) , byte );206 }207 else // TTY_TX full => update command arguments and exit ISR for retry208 {209 hal_remote_sw ( XPTR( client_cxy , &client_ptr->command.txt.count ), count-i );210 hal_remote_swd( XPTR( client_cxy , &client_ptr->command.txt.buf_xp ), buf_xp+i );211 return;212 }213 }214 }215 216 // The I/O operation completed when we reach this point217 218 // mask both TTY_RX_IRQ and TTY_TX_IRQ219 hal_remote_sw( XPTR( tty_cxy , base + TTY_CONFIG_REG ) , 0 );220 221 // set I/O operation status in command222 hal_remote_sw( XPTR( client_cxy , &client_ptr->command.txt.error ) , 0 );223 224 // unblock server thread225 thread_unblock( XPTR( local_cxy , &chdev->server ) , THREAD_BLOCKED_DEV_ISR );226 227 // unblock client thread228 thread_unblock( client_xp , THREAD_BLOCKED_IO );229 44 } 230 45 -
trunk/hal/x86_64/drivers/soclib_xcu.c
r75 r76 27 27 #include <chdev.h> 28 28 29 30 31 ////////////////////////////////////32 29 void soclib_xcu_init( chdev_t * icu, 33 30 lid_t lid ) 34 31 { 35 // get local ICU segment base address36 uint32_t * base = (uint32_t *)GET_PTR( icu->base );37 32 38 // disable all IRQs39 base[XCU_MSK_HWI_DISABLE << 5 | lid] = 0xFFFFFFFF;40 base[XCU_MSK_WTI_DISABLE << 5 | lid] = 0xFFFFFFFF;41 base[XCU_MSK_PTI_DISABLE << 5 | lid] = 0xFFFFFFFF;42 33 } 43 34 44 ////////////////////////////////////////////45 35 void soclib_xcu_disable_irq( chdev_t * icu, 46 36 uint32_t mask, … … 48 38 lid_t lid ) 49 39 { 50 // get XCU segment base address51 uint32_t * base = (uint32_t *)GET_PTR( icu->base );52 40 53 // write into register54 if ( type == WTI_TYPE ) base[XCU_MSK_WTI_DISABLE << 5 | lid] = mask;55 else if( type == HWI_TYPE ) base[XCU_MSK_HWI_DISABLE << 5 | lid] = mask;56 else base[XCU_MSK_PTI_DISABLE << 5 | lid] = mask;57 41 } 58 42 59 ///////////////////////////////////////////60 43 void soclib_xcu_enable_irq( chdev_t * icu, 61 44 uint32_t mask, … … 63 46 lid_t lid ) 64 47 { 65 // get XCU segment base address66 uint32_t * base = (uint32_t *)GET_PTR( icu->base );67 48 68 // write into register69 if ( type == WTI_TYPE ) base[XCU_MSK_WTI_ENABLE << 5 | lid] = mask;70 else if( type == HWI_TYPE ) base[XCU_MSK_HWI_ENABLE << 5 | lid] = mask;71 else base[XCU_MSK_PTI_ENABLE << 5 | lid] = mask;72 49 } 73 50 74 ///////////////////////////////////////////75 51 void soclib_xcu_get_masks( chdev_t * icu, 76 52 lid_t lid, … … 79 55 uint32_t * pti_mask ) 80 56 { 81 // get XCU segment base address 82 uint32_t * base = (uint32_t *)GET_PTR( icu->base ); 83 84 // get values from registers 85 *hwi_mask = base[XCU_MSK_HWI << 5 | lid]; 86 *wti_mask = base[XCU_MSK_WTI << 5 | lid]; 87 *pti_mask = base[XCU_MSK_PTI << 5 | lid]; 57 88 58 } 89 59 90 //////////////////////////////////////////91 60 void soclib_xcu_set_period( chdev_t * icu, 92 61 uint32_t index, 93 62 uint32_t period ) 94 63 { 95 // get local ICU segment base address96 uint32_t * base = (uint32_t *)GET_PTR( icu->base );97 64 98 // write into register99 base[XCU_PTI_PER << 5 | index] = period;100 65 } 101 66 102 /////////////////////////////////////////////103 67 uint32_t soclib_xcu_ack_timer( chdev_t * icu, 104 68 uint32_t index ) 105 69 { 106 // get local ICU segment base address107 uint32_t * base = (uint32_t *)GET_PTR( icu->base );108 70 109 // read from register110 return base[XCU_PTI_ACK << 5 | index];111 71 } 112 72 113 ///////////////////////////////////////////114 73 void soclib_xcu_get_status( chdev_t * icu, 115 74 lid_t lid, … … 118 77 uint32_t * pti_status ) 119 78 { 120 // get local ICU segment base address121 uint32_t * base = (uint32_t *)GET_PTR( icu->base );122 79 123 // read PRIO register124 uint32_t prio = base[XCU_PRIO << 5 | lid];125 126 *wti_status = (prio & 0x4) ? (((prio >> 24) & 0x1F) + 1) : 0;127 *hwi_status = (prio & 0x2) ? (((prio >> 16) & 0x1F) + 1) : 0;128 *pti_status = (prio & 0x1) ? (((prio >> 8) & 0x1F) + 1) : 0;129 80 } 130 81 131 /////////////////////////////////////////132 82 void soclib_xcu_send_ipi( xptr_t icu_xp, 133 83 lid_t lid ) 134 84 { 135 // get target ICU device cluster and local pointer136 cxy_t cxy_icu = GET_CXY( icu_xp );137 chdev_t * ptr_icu = (chdev_t *)GET_PTR( icu_xp );138 85 139 // get extended pointer on target ICU segment base140 xptr_t xp_base = (xptr_t)hal_remote_lwd( XPTR( cxy_icu , &ptr_icu->base ) );141 142 // get remote ICU segment local pointer143 uint32_t * base = (uint32_t *)GET_PTR( xp_base );144 145 // send IPI to remote core146 hal_remote_sw( XPTR( cxy_icu , &base[XCU_WTI_REG << 5 | lid] ) , 0 );147 86 } 148 87 149 //////////////////////////////////////////////150 88 uint32_t * soclib_xcu_wti_ptr( chdev_t * icu, 151 89 uint32_t index ) 152 90 { 153 uint32_t * base = (uint32_t *)GET_PTR( icu->base );154 91 155 return &base[XCU_WTI_REG << 5 | index];156 92 }
Note: See TracChangeset
for help on using the changeset viewer.