Changeset 76 for trunk/hal/x86_64/drivers/soclib_hba.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_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
Note: See TracChangeset
for help on using the changeset viewer.