Changeset 529 for soft/giet_vm/giet_drivers/hba_driver.c
- Timestamp:
- Mar 27, 2015, 11:51:33 AM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
soft/giet_vm/giet_drivers/hba_driver.c
r481 r529 1 ////////////////////////////////////////////////////////////////////////////////// /1 ////////////////////////////////////////////////////////////////////////////////// 2 2 // File : hba_driver.c 3 3 // Date : 23/11/2013 … … 6 6 /////////////////////////////////////////////////////////////////////////////////// 7 7 // Implementation notes: 8 // 1. In order to share code, the two _hba_read() and _hba_write() functions 9 // call the same _hba_set_cmd() function. 10 // 2. All accesses to HBA registers are done by the two 11 // _hba_set_register() and _hba_get_register() low-level functions, 12 // that are handling virtual / physical extended addressing. 8 // All accesses to HBA registers are done by the two 9 // _hba_set_register() and _hba_get_register() low-level functions, 10 // that are handling virtual / physical extended addressing. 13 11 /////////////////////////////////////////////////////////////////////////////////// 14 12 15 13 #include <giet_config.h> 16 #include <ioc_driver.h> 14 #include <hard_config.h> 15 #include <hba_driver.h> 16 #include <xcu_driver.h> 17 #include <kernel_locks.h> 17 18 #include <utils.h> 18 19 #include <tty0.h> 19 #include <iob_driver.h>20 20 #include <ctx_handler.h> 21 #include <mmc_driver.h> 22 #include <hba_driver.h> 21 #include <irq_handler.h> 23 22 #include <vmem.h> 24 23 25 #if !defined( NB_IOC_CHANNELS ) 26 # error: You must define NB_IOC_CHANNELS in the hard_config.h file 27 #endif 28 29 #if ( NB_IOC_CHANNELS > 8 ) 30 # error: NB_IOC_CHANNELS cannot be larger than 8 31 #endif 32 33 #define in_unckdata __attribute__((section (".unckdata"))) 34 35 ////////////////////////////////////////////////////////////////// 24 /////////////////////////////////////////////////////////////////////////////////// 36 25 // Global variables 37 ////////////////////////////////////////////////////////////////// 38 39 // command list array (one per channel) 40 hba_cmd_list_t hba_cmd_list[NB_IOC_CHANNELS] __attribute__((aligned(0x1000))); 41 42 // command tables array (32 command tables per channel) 43 hba_cmd_table_t hba_cmd_table[NB_IOC_CHANNELS][32] __attribute__((aligned(0x1000))); 44 45 // command list physical addresses array (one per channel) 46 paddr_t hba_cmd_list_paddr[NB_IOC_CHANNELS]; 47 48 // command tables physical addresses array (32 command tables per channel) 49 paddr_t hba_cmd_table_paddr[NB_IOC_CHANNELS][32]; 50 51 // command list pointer array (one per channel) 52 unsigned int hba_cmd_slot[NB_IOC_CHANNELS]; 26 /////////////////////////////////////////////////////////////////////////////////// 27 28 // global index ot the task, for each entry in the command list 29 __attribute__((section(".kdata"))) 30 unsigned int _hba_gtid[32]; 31 32 // status of the command, for each entry in the command list 33 __attribute__((section(".kdata"))) 34 unsigned int _hba_status[32]; 35 36 // command list : up to 32 commands 37 __attribute__((section(".kdata"))) 38 hba_cmd_desc_t _hba_cmd_list[32] __attribute__((aligned(0x1000))); 39 40 // command tables array : one command table per entry in command list 41 __attribute__((section(".kdata"))) 42 hba_cmd_table_t _hba_cmd_table[32] __attribute__((aligned(0x1000))); 43 44 // command list write index : next slot to register a command 45 __attribute__((section(".kdata"))) 46 unsigned int _hba_cmd_ptw; 47 48 // command list read index : next slot to poll a completed command 49 __attribute__((section(".kdata"))) 50 unsigned int _hba_cmd_ptr; 53 51 54 52 ////////////////////////////////////////////////////////////////////////////// 55 // This low level function returns the value of register ( channel /index)53 // This low level function returns the value of register (index) 56 54 ////////////////////////////////////////////////////////////////////////////// 57 unsigned int _hba_get_register( unsigned int channel, 58 unsigned int index ) 59 { 60 unsigned int* vaddr = (unsigned int*)SEG_IOC_BASE + channel*HBA_SPAN + index; 55 unsigned int _hba_get_register( unsigned int index ) 56 { 57 unsigned int* vaddr = (unsigned int*)SEG_IOC_BASE + index; 61 58 return _io_extended_read( vaddr ); 62 59 } 63 60 64 61 ////////////////////////////////////////////////////////////////////////////// 65 // This low level function set a new value in register ( channel /index)62 // This low level function set a new value in register (index) 66 63 ////////////////////////////////////////////////////////////////////////////// 67 void _hba_set_register( unsigned int channel, 68 unsigned int index, 64 void _hba_set_register( unsigned int index, 69 65 unsigned int value ) 70 66 { 71 unsigned int* vaddr = (unsigned int*)SEG_IOC_BASE + channel*HBA_SPAN +index;67 unsigned int* vaddr = (unsigned int*)SEG_IOC_BASE + index; 72 68 _io_extended_write( vaddr, value ); 73 69 } 74 70 71 /////////////////////////////////////////////////////////////////////////////// 72 // Extern functions 73 /////////////////////////////////////////////////////////////////////////////// 75 74 76 75 /////////////////////////////////////////////////////////////////////////////// 77 76 // This function register a command in both the command list 78 77 // and the command table, and updates the HBA_PXCI register. 79 // It uses the AHCI Scatter/Gather mechanisme to split the user80 // buffer in several physical buffers, with the constraint that each physical81 // buffer must be an integer number of blocks entirely contained in a single82 // page frame.83 78 // return 0 if success, -1 if error 84 79 /////////////////////////////////////////////////////////////////////////////// 85 unsigned int _hba_cmd_set( unsigned int channel, // channel index 86 unsigned int is_read, // to memory 87 unsigned int lba, // logic block address 88 paddr_t buffer, // buffer physical address 89 unsigned int count ) // number of blocks 90 { 91 unsigned int block_size; // defined by the block device (bytes) 92 unsigned int pxci; // command list status 93 unsigned int cmd_id; // command index in command list 94 80 unsigned int _hba_access( unsigned int use_irq, 81 unsigned int to_mem, 82 unsigned int lba, 83 unsigned long long buf_paddr, 84 unsigned int count ) 85 { 86 unsigned int procid = _get_procid(); 87 unsigned int x = procid >> (Y_WIDTH + P_WIDTH); 88 unsigned int y = (procid >> P_WIDTH) & ((1<<Y_WIDTH) - 1); 89 unsigned int p = procid & ((1<<P_WIDTH)-1); 90 91 #if GIET_DEBUG_IOC_DRIVER 92 _printf("\n[HBA DEBUG] P[%d,%d,%d] enters _hba_access at cycle %d\n" 93 " use_irq = %d / to_mem = %d / lba = %x / paddr = %l / count = %d\n", 94 x , y , p , _get_proctime() , use_irq , to_mem , lba , buf_paddr, count ); 95 #endif 96 97 unsigned int pxci; // HBA_PXCI register value 98 unsigned int ptw; // command list write pointer 99 unsigned int pxis; // HBA_PXIS register value 95 100 hba_cmd_desc_t* cmd_desc; // command descriptor pointer 96 101 hba_cmd_table_t* cmd_table; // command table pointer 97 102 98 block_size = _hba_get_block_size();99 100 103 // check buffer alignment 101 if( buf fer & (block_size-1))102 { 103 _p uts("\n[GIET ERROR] in _hba_set_cmd() : userbuffer not block aligned\n");104 if( buf_paddr & 0x1FF ) 105 { 106 _printf("\n[HBA ERROR] in _hba_access() : buffer not block aligned\n"); 104 107 return -1; 105 108 } 106 109 107 // get command list status from PXCI register 108 pxci = _hba_get_register( channel, HBA_PXCI ); 109 110 // get command index and return error if command list full 111 cmd_id = hba_cmd_slot[channel]; 112 if( pxci & (1<<cmd_id ) ) 113 { 114 _puts("\n[GIET ERROR] in _hba_set_cmd() : command list full for channel "); 115 _putd( channel ); 116 _puts("\n"); 117 return -1; 118 } 119 110 // get pointer on the next possible entry in command list 111 ptw = _atomic_increment( &_hba_cmd_ptw , 1 ); 112 113 // poll PXCI register until pointed entry empty 114 do 115 { 116 // get PXCI register 117 pxci = _hba_get_register( HBA_PXCI ); 118 } 119 while ( pxci & (1<<ptw) ); 120 120 121 // compute pointers on command descriptor and command table 121 cmd_desc = (hba_cmd_desc_t*)(&(hba_cmd_list[channel].desc[cmd_id]));122 cmd_table = (hba_cmd_table_t*)(&(hba_cmd_table[channel][cmd_id]));122 cmd_desc = &_hba_cmd_list[ptw]; 123 cmd_table = &_hba_cmd_table[ptw]; 123 124 124 125 // set buffer descriptor in command table 125 cmd_table->entry[0].dba = (unsigned int)(buf fer);126 cmd_table->entry[0].dbau = (unsigned int)(buf fer >> 32);127 cmd_table->entry[0].dbc = count * block_size;126 cmd_table->entry[0].dba = (unsigned int)(buf_paddr); 127 cmd_table->entry[0].dbau = (unsigned int)(buf_paddr >> 32); 128 cmd_table->entry[0].dbc = count * 512; 128 129 129 130 // initialize command table header … … 138 139 cmd_desc->prdtl[0] = 1; 139 140 cmd_desc->prdtl[1] = 0; 140 cmd_desc->ctba = (unsigned int)(hba_cmd_table_paddr[channel][cmd_id]); 141 cmd_desc->ctbau = (unsigned int)(hba_cmd_table_paddr[channel][cmd_id]>>32); 142 if( is_read ) cmd_desc->flag[0] = 0x00; 143 else cmd_desc->flag[0] = 0x40; 141 if( to_mem ) cmd_desc->flag[0] = 0x00; 142 else cmd_desc->flag[0] = 0x40; 144 143 145 // update PXCI register 146 _hba_set_register( channel, HBA_PXCI, (1<<cmd_id) ); 147 148 // update command pointer 149 hba_cmd_slot[channel] = (cmd_id + 1)%32; 150 151 return 0; 152 } 153 154 /* This can be used for a future use with buffer in virtual space 155 156 // get user space page table virtual address 157 user_pt_vbase = _get_context_slot(CTX_PTAB_ID); 158 vpn_min = buf_vaddr >> 12; 159 vpn_max = (buf_vaddr + (block_size*count) - 1) >> 12; 160 offset = buf_vaddr & 0xFFF; 161 offset_last = (buf_vaddr + (block_size*count) - 1) & 0xFFF; 162 163 // initialize all buffer descriptors in command table 164 // (loop on all virtual pages covering the user buffer) 165 for( vpn = vpn_min, buf_id = 0 ; vpn <= vpn_max ; vpn++ ) 166 { 167 paddr_t paddr; 168 unsigned int count; 169 unsigned int ppn; 170 unsigned int flags; 171 unsigned int ko; 172 unsigned int buf_id = 0; 173 174 // get ppn and flags 175 _v2p_translate( (page_table_t*)user_pt_vbase, 176 vpn, 177 &ppn, 178 &flags ); 179 180 // check access rights 181 if ((flags & PTE_U) == 0) 144 // set command in PXCI[ptw] 145 _hba_set_register( HBA_PXCI, pxci + (1<<ptw) ); 146 147 148 ///////////////////////////////////////////////////////////////////// 149 // In synchronous mode, we poll the PXCI register until completion 150 ///////////////////////////////////////////////////////////////////// 151 if ( use_irq == 0 ) 152 { 153 154 #if GIET_DEBUG_IOC_DRIVER 155 _printf("\n[HBA DEBUG] _hba_access() : P[%d,%d,%d] launch transfer" 156 " in polling mode at cycle %d\n", 157 x , y , p , _get_proctime() ); 158 #endif 159 // disable IRQs in PXIE register 160 _hba_set_register( HBA_PXIE , 0 ); 161 162 // poll PXCI[ptw] until command completed by HBA 163 do 182 164 { 183 _puts("[GIET ERROR] in _hba_set_cmd() : user buffer not in user space\n"); 184 return -1; 165 pxci = _hba_get_register( HBA_PXCI ) & (1<<ptw); 166 167 #if GIET_DEBUG_IOC_DRIVER 168 _printf("\n[HBA DEBUG] _hba_access() : P[%d,%d,%d] wait on HBA_STATUS ...\n", 169 x , y , p ); 170 #endif 185 171 } 186 if (((flags & PTE_W) == 0 ) && (is_read == 0) ) 172 while( pxci & (1<<ptw) ); 173 174 // get PXIS register 175 pxis = _hba_get_register( HBA_PXIS ); 176 177 // reset PXIS register 178 _hba_set_register( HBA_PXIS , 0 ); 179 } 180 181 ///////////////////////////////////////////////////////////////// 182 // in descheduling mode, we deschedule the task 183 // and use an interrupt to reschedule the task. 184 // We need a critical section, because we must reset the RUN bit 185 // before to launch the transfer, and we don't want to be 186 // descheduled between these two operations. 187 ///////////////////////////////////////////////////////////////// 188 else 189 { 190 191 #if GIET_DEBUG_IOC_DRIVER 192 _printf("\n[HBA DEBUG] _hba_access() : P[%d,%d,%d] launch transfer" 193 " in descheduling mode at cycle %d\n", 194 x , y , p , _get_proctime() ); 195 #endif 196 unsigned int save_sr; 197 unsigned int ltid = _get_current_task_id(); 198 199 // activates HBA interrupts 200 _hba_set_register( HBA_PXIE , 0x00000001 ); 201 202 // set _hba_gtid[ptw] 203 _hba_gtid[ptw] = (procid<<16) + ltid; 204 205 // enters critical section 206 _it_disable( &save_sr ); 207 208 // reset runnable 209 _set_task_slot( x, y, p, ltid, CTX_RUN_ID, 0 ); 210 211 // deschedule task 212 _ctx_switch(); 213 214 #if GIET_DEBUG_IOC_DRIVER 215 _printf("\n[HBA DEBUG] _hba_access() : P[%d,%d,%d] resume execution at cycle %d\n", 216 x , y , p , _get_proctime() ); 217 #endif 218 219 // restore SR 220 _it_restore( &save_sr ); 221 222 // get command status 223 pxis = _hba_status[ptw]; 224 } 225 226 #if GIET_DEBUG_IOC_DRIVER 227 _printf("\n[HBA DEBUG] _hba_access() : P[%d,%d,%d] exit at cycle %d\n", 228 x , y , p , _get_proctime() ); 229 #endif 230 231 if ( pxis & 0x40000000 ) return pxis; 232 else return 0; 233 234 } // end _hba_access() 235 236 237 //////////////////////// 238 unsigned int _hba_init() 239 { 240 unsigned int flags; 241 unsigned int vaddr; 242 unsigned long long paddr; 243 unsigned int c; 244 unsigned int pxclb; 245 unsigned int pxclbu; 246 247 // command list pointers 248 _hba_cmd_ptw = 0; 249 _hba_cmd_ptr = 0; 250 251 // Command list physical addresse 252 vaddr = (unsigned int)(_hba_cmd_list); 253 paddr = _v2p_translate( vaddr , &flags ); 254 pxclb = (unsigned int)paddr; 255 pxclbu = (unsigned int)(paddr>>32); 256 257 // Command tables physical addresses 258 for( c=0 ; c<32 ; c++ ) 259 { 260 // compute command table physical address 261 // for one entry in the command list 262 vaddr = (unsigned int)(&_hba_cmd_table[c]); 263 paddr = _v2p_translate( vaddr , &flags ); 264 265 // initialise the corresponding command descriptor 266 _hba_cmd_list[c].ctba = (unsigned int)paddr; 267 _hba_cmd_list[c].ctbau = (unsigned int)(paddr>>32); 268 } 269 270 // set HBA registers 271 _hba_set_register( HBA_PXCLB , pxclb ); 272 _hba_set_register( HBA_PXCLBU, pxclbu ); 273 _hba_set_register( HBA_PXIE , 0 ); 274 _hba_set_register( HBA_PXIS , 0 ); 275 _hba_set_register( HBA_PXCI , 0 ); 276 _hba_set_register( HBA_PXCMD , 1 ); 277 278 return 0; 279 } 280 281 282 ///////////////////////////////////// 283 void _hba_isr( unsigned int irq_type, // HWI / WTI 284 unsigned int irq_id, // index returned by ICU 285 unsigned int channel ) // unused 286 { 287 // get HBA_PXCI containing commands status 288 unsigned int pxci = _hba_get_register( HBA_PXCI ); 289 290 // scan active commands from (_hba_cmd_ptr) to (_hba_cmd_ptw-1) 291 unsigned int c; 292 for ( c = _hba_cmd_ptr ; 293 c != _hba_cmd_ptw ; 294 c = (c + 1) % 32 ) 295 { 296 if ( (pxci & (1<<c)) == 0 ) // command completed 187 297 { 188 _puts("[GIET ERROR] in _hba_set_cmd() : user buffer not writable\n"); 189 return -1; 298 // increment read pointer; 299 _hba_cmd_ptr++; 300 301 // save PXIS register 302 _hba_status[c] = _hba_get_register( HBA_PXIS ); 303 304 // reset PXIS register 305 _hba_set_register( HBA_PXIS , 0 ); 306 307 // identify waiting task 308 unsigned int remote_procid = _hba_gtid[c]>>16; 309 unsigned int ltid = _hba_gtid[c] & 0xFFFF; 310 unsigned int remote_cluster = remote_procid >> P_WIDTH; 311 unsigned int remote_x = remote_cluster >> Y_WIDTH; 312 unsigned int remote_y = remote_cluster & ((1<<Y_WIDTH)-1); 313 unsigned int remote_p = remote_procid & ((1<<P_WIDTH)-1); 314 315 // re-activates waiting task 316 _set_task_slot( remote_x, 317 remote_y, 318 remote_p, 319 ltid, 320 CTX_RUN_ID, 321 1 ); 322 323 // send a WAKUP WTI to processor running the waiting task 324 _xcu_send_wti( remote_cluster , 325 remote_p , 326 0 ); // don't force context switch 327 328 #if GIET_DEBUG_IOC_DRIVER 329 unsigned int procid = _get_procid(); 330 unsigned int x = procid >> (Y_WIDTH + P_WIDTH); 331 unsigned int y = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1); 332 unsigned int p = procid & ((1<<P_WIDTH)-1); 333 _printf("\n[HBA DEBUG] Processor[%d,%d,%d] executes _hba_isr() :\n" 334 " resume task %d running on P[%d,%d,%d] / status = %x at cyle %d\n", 335 x , y , p , 336 ltid , remote_x , remote_y , remote_p , _hba_status[c] , _get_proctime() ); 337 #endif 190 338 } 191 192 // check buffer index overflow 193 if( buf_id > 245 ) 339 else // command non completed 194 340 { 195 _puts("[GIET ERROR] in _hba_set_cmd() : max number of buffers is 248\n"); 196 return -1; 197 } 198 199 // buffer allocation 200 if( vpn == vpn_min ) // first page: one single buffer 201 { 202 paddr = (((paddr_t)ppn) << 12) + offset; 203 count = 0x1000 - offset; 204 cmd_table->entry[buf_id].dba = (unsigned int)(paddr); 205 cmd_table->entry[buf_id].dbau = (unsigned int)(paddr >> 32); 206 cmd_table->entry[buf_id].dbc = count; 207 208 buf_id++; 209 } 210 else if( vpn == vpn_max ) // last page: one single buffer 211 { 212 paddr = (((paddr_t)ppn) << 12); 213 count = offset_last; 214 cmd_table->entry[buf_id].dba = (unsigned int)(paddr); 215 cmd_table->entry[buf_id].dbau = (unsigned int)(paddr >> 32); 216 cmd_table->entry[buf_id].dbc = count; 217 218 buf_id++; 219 } 220 else if( offset ) // midle page and offset != 0: two buffers 221 { 222 paddr = (((paddr_t)ppn) << 12); 223 224 count = offset; 225 cmd_table->entry[buf_id].dba = (unsigned int)(paddr); 226 cmd_table->entry[buf_id].dbau = (unsigned int)(paddr >> 32); 227 cmd_table->entry[buf_id].dbc = count; 228 229 buf_id++; 230 231 paddr = (((paddr_t)ppn) << 12) + offset; 232 count = 0x1000 - offset; 233 cmd_table->entry[buf_id].dba = (unsigned int)(paddr); 234 cmd_table->entry[buf_id].dbau = (unsigned int)(paddr >> 32); 235 cmd_table->entry[buf_id].dbc = count; 236 237 buf_id++; 238 } 239 else // middle page and offset == 0: one buffer 240 { 241 paddr = (((paddr_t)ppn) << 12); 242 count = 0x1000; 243 cmd_table->entry[buf_id].dba = (unsigned int)(paddr); 244 cmd_table->entry[buf_id].dbau = (unsigned int)(paddr >> 32); 245 cmd_table->entry[buf_id].dbc = count; 246 247 buf_id++; 341 break; 248 342 } 249 343 } 250 */ 251 252 253 ////////////////////////////////////////////// 254 unsigned int _hba_init( unsigned int channel ) 255 { 256 unsigned int ppn; 257 unsigned int flags; 258 unsigned int vbase; 259 unsigned int c; // c == command index 260 261 // get page_table pointer 262 unsigned int pt = _get_context_slot(CTX_PTAB_ID); 263 264 // HBA registers TODO: ne faut_il pas un V2P pour PXCLB/PXCLBU ? (AG) 265 _hba_set_register( channel, HBA_PXCLB , (unsigned int)&hba_cmd_list[channel] ); 266 _hba_set_register( channel, HBA_PXCLBU, 0 ); 267 _hba_set_register( channel, HBA_PXIE , 0x40000001 ); 268 _hba_set_register( channel, HBA_PXIS , 0 ); 269 _hba_set_register( channel, HBA_PXCI , 0 ); 270 _hba_set_register( channel, HBA_PXCMD , 1 ); 271 272 // command list pointer 273 hba_cmd_slot[channel] = 0; 274 275 // Command list physical addresse 276 vbase = (unsigned int)(&hba_cmd_list[channel]); 277 _v2p_translate( (page_table_t*)pt, 278 vbase>>12, 279 &ppn, 280 &flags ); 281 hba_cmd_list_paddr[channel] = ((paddr_t)ppn) | (vbase & 0xFFF); 282 283 // Command tables physical addresses 284 for( c=0 ; c<32 ; c++ ) 285 { 286 vbase = (unsigned int)(&hba_cmd_table[channel][c]); 287 _v2p_translate( (page_table_t*)pt, 288 vbase>>12, 289 &ppn, 290 &flags ); 291 hba_cmd_table_paddr[channel][c] = ((paddr_t)ppn) | (vbase & 0xFFF); 292 } 293 294 return 0; 295 } 296 297 /////////////////////////////////////////////// 298 unsigned int _hba_write( unsigned int channel, 299 unsigned int mode, 300 unsigned int lba, 301 paddr_t buffer, 302 unsigned int count ) 303 { 304 return _hba_cmd_set( channel, 305 0, // write 306 lba, 307 buffer, 308 count ); 309 } 310 311 ////////////////////////////////////////////// 312 unsigned int _hba_read( unsigned int channel, 313 unsigned int mode, 314 unsigned int lba, 315 paddr_t buffer, 316 unsigned int count ) 317 { 318 return _hba_cmd_set( channel, 319 1, // read 320 lba, 321 buffer, 322 count ); 323 } 324 325 ////////////////////////////////// 326 unsigned int _hba_get_block_size() 327 { 328 // TODO The block size must be obtained from the hardware... 329 return 512; 330 } 331 332 //////////////////////////////////////////////////// 333 unsigned int _hba_get_status( unsigned int channel ) 334 { 335 336 if( channel >= NB_IOC_CHANNELS ) 337 { 338 _puts("\n[GIET ERROR] in _hba_get_status() : illegal channel\n"); 339 _exit(); 340 } 341 342 // get HBA_PXIS value 343 unsigned int status = _hba_get_register( channel, HBA_PXIS ); 344 345 // reset HBA_PXIS 346 _hba_set_register( channel, HBA_PXIS, 0 ); 347 348 return status; 349 } 344 } // end _hba_isr() 350 345 351 346 // Local Variables:
Note: See TracChangeset
for help on using the changeset viewer.