Changeset 295 for soft/giet_vm/giet_drivers/hba_driver.c
- Timestamp:
- Mar 26, 2014, 6:44:44 PM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
soft/giet_vm/giet_drivers/hba_driver.c
r289 r295 2 2 // File : hba_driver.c 3 3 // Date : 23/11/2013 4 // Author : alain greiner and zhang4 // Author : alain greiner 5 5 // Copyright (c) UPMC-LIP6 6 6 /////////////////////////////////////////////////////////////////////////////////// … … 9 9 // block oriented, external storage contrÃŽler, respecting the AHCI standard. 10 10 // 11 // It can exist only one ahci-device controler in the architecture. 11 // The seg_ioc_base (standard HBA virtual base address) and seg_ioc_base_bis 12 // (backup HBA virtual base address) must be defined in giet_vsegs.ld file. 13 ////////////////////////////////////////////////////////////////////////////////// 14 // Implementation notes: 12 15 // 13 // The _ioc_read() and _ioc_write() functions use the _ioc_access() function,14 // that is always blocking, but can be called in 4 modes:16 // 1. In order to share code, the two _hba_read() and _hba_write() functions 17 // call the same _hba_set_cmd() function. 15 18 // 16 // - In BOOT_PA mode, the _ioc_access() function use the buffer virtual address 17 // as a physical address (as the page tables are not build) and use a polling 18 // policy on the IOC_STATUS register to detect transfer completion, as 19 // hardware interrupts are not activated. This mode is used by the 20 // boot code to load the map.bin file into memory. 21 // 22 // - In BOOT_VA mode, the _ioc_access() function makes a V2P translation to 23 // compute the buffer physical address, and use a polling policy on IOC_STATUS 24 // register to detect transfer completion. This mode is used by the boot code 25 // to load the various .elf files into memory. 26 // 27 // - In KERNEL mode, the _ioc_access() function makes a V2P translation to 28 // compute the buffer physical address, and use a descheduling strategy: 29 // The ISR executed when transfer completes should restart the calling task. 30 // There is no checking of user access right to the memory buffer. 31 // This mode must be used to access IOC, for an "open" system call. 32 // 33 // - In USER mode, the _ioc_access() function makes a V2P translation to 34 // compute the buffer physical address, and use a descheduling strategy: 35 // The ISR executed when transfer completes should restart the calling task, 36 // The user access right to the memory buffer must be checked. 37 // This mode must be used to access IOC, for a "read/write" system call. 38 // 39 // As the IOC component can be used by several programs running in parallel, 40 // the _ioc_lock variable guaranties exclusive access to the device. The 41 // _ioc_read() and _ioc_write() functions use atomic LL/SC to get the lock. 42 // 43 // The IOMMU can be activated or not: 44 // 45 // 1) When the IOMMU is used, a fixed size 2Mbytes vseg is allocated to 46 // the IOC peripheral, in the I/O virtual space, and the user buffer is 47 // dynamically remapped in the IOMMU page table. The corresponding entry 48 // in the IOMMU PT1 is defined by the kernel _ioc_iommu_ix1 variable. 49 // The number of pages to be unmapped is stored in the _ioc_npages variable. 50 // The number of PT2 entries is dynamically computed and stored in the 51 // kernel _ioc_iommu_npages variable. It cannot be larger than 512. 52 // The user buffer is unmapped by the _ioc_completed() function when 53 // the transfer is completed. 54 // 55 // 2/ If the IOMMU is not used, we check that the user buffer is mapped to a 56 // contiguous physical buffer (this is generally true because the user space 57 // page tables are statically constructed to use contiguous physical memory). 58 // 59 // Finally, the memory buffer must fulfill the following conditions: 60 // - The buffer must be word aligned, 61 // - The buffer must be mapped in user space for an user access, 62 // - The buffer must be writable in case of (to_mem) access, 63 // - The total number of physical pages occupied by the user buffer cannot 64 // be larger than 512 pages if the IOMMU is activated, 65 // - All physical pages occupied by the user buffer must be contiguous 66 // if the IOMMU is not activated. 67 // An error code is returned if these conditions are not verified. 68 /////////////////////////////////////////////////////////////////////////////////// 69 // The seg_ioc_base virtual base addresses must be defined in giet_vsegs.ld file. 19 // 2. All accesses to HBA registers are done by the two 20 // _hba_set_register() and _hba_get_register() low-level functions, 21 // that are handling virtual / physical extended addressing. 70 22 /////////////////////////////////////////////////////////////////////////////////// 71 23 … … 80 32 #include <vmem.h> 81 33 82 #if !defined( NB_HBA_CHANNELS ) 83 # error: You must define NB_HBA_CHANNELS in the hard_config.h file 84 #endif 85 86 #if ( NB_HBA_CHANNELS > 8 ) 87 # error: NB_HBA_CHANNELS cannot be larger than 8 88 #endif 89 90 #if !defined( USE_IOB ) 91 # error: You must define USE_IOB in the hard_config.h file 92 #endif 93 94 #if !defined(GIET_USE_IOMMU) 95 # error: You must define GIET_USE_IOMMU in the giet_config.h file 34 #if !defined( NB_IOC_CHANNELS ) 35 # error: You must define NB_IOC_CHANNELS in the hard_config.h file 36 #endif 37 38 #if ( NB_IOC_CHANNELS > 8 ) 39 # error: NB_IOC_CHANNELS cannot be larger than 8 96 40 #endif 97 41 … … 103 47 104 48 // command list array (one per channel) 105 hba_cmd_list_t hba_cmd_list[NB_ HBA_CHANNELS] __attribute__((aligned(0x1000)));49 hba_cmd_list_t hba_cmd_list[NB_IOC_CHANNELS] __attribute__((aligned(0x1000))); 106 50 107 51 // command tables array (32 command tables per channel) 108 hba_cmd_table_t hba_cmd_table[NB_ HBA_CHANNELS][32] __attribute__((aligned(0x1000)));52 hba_cmd_table_t hba_cmd_table[NB_IOC_CHANNELS][32] __attribute__((aligned(0x1000))); 109 53 110 54 // command list physical addresses array (one per channel) 111 paddr_t hba_cmd_list_paddr[NB_ HBA_CHANNELS];55 paddr_t hba_cmd_list_paddr[NB_IOC_CHANNELS]; 112 56 113 57 // command tables physical addresses array (32 command tables per channel) 114 paddr_t hba_cmd_table_paddr[NB_ HBA_CHANNELS][32];58 paddr_t hba_cmd_table_paddr[NB_IOC_CHANNELS][32]; 115 59 116 60 // command list pointer array (one per channel) 117 unsigned int hba_cmd_slot[NB_HBA_CHANNELS]; 118 119 ////////////////////////////////////////////////////////////////// 120 // This function returns the status of a given channel. 121 // return 0 if success, >0 if error 122 ////////////////////////////////////////////////////////////////// 123 unsigned int _hba_get_status( unsigned int channel, 124 unsigned int* status ) 125 { 126 volatile unsigned int* hba_address; 127 hba_address = (unsigned int*)(&seg_ioc_base) + (HBA_SPAN*channel); 128 129 if( channel >= NB_HBA_CHANNELS ) 130 { 131 _tty_get_lock( 0 ); 132 _puts("\n[GIET ERROR] in _hba_get_status() : illegal channel\n"); 133 _tty_release_lock( 0 ); 134 return 1; 135 } 136 else 137 { 138 *status = hba_address[HBA_PXIS]; 139 return 0; 140 } 141 } 142 ////////////////////////////////////////////////////////////////// 143 // This function reset the status resgister for a given channel. 144 // return 0 if success, >0 if error 145 ////////////////////////////////////////////////////////////////// 146 unsigned int _hba_reset_status( unsigned int channel ) 147 { 148 volatile unsigned int* hba_address; 149 hba_address = (unsigned int*)(&seg_ioc_base) + (HBA_SPAN*channel); 150 151 if( channel >= NB_HBA_CHANNELS ) 152 { 153 _tty_get_lock( 0 ); 154 _puts("\n[GIET ERROR] in _hba_reset_status() : illegal channel\n"); 155 _tty_release_lock( 0 ); 156 return 1; 157 } 158 else 159 { 160 hba_address[HBA_PXIS] = 0; 161 return 0; 162 } 163 } 61 unsigned int hba_cmd_slot[NB_IOC_CHANNELS]; 62 63 ////////////////////////////////////////////////////////////////////////////// 64 // This low level function returns the value of register (channel / index) 65 ////////////////////////////////////////////////////////////////////////////// 66 unsigned int _hba_get_register( unsigned int channel, 67 unsigned int index ) 68 { 69 unsigned int* vaddr = (unsigned int*)&seg_ioc_base + channel*HBA_SPAN + index; 70 return _io_extended_read( vaddr ); 71 } 72 73 ////////////////////////////////////////////////////////////////////////////// 74 // This low level function set a new value in register (channel / index) 75 ////////////////////////////////////////////////////////////////////////////// 76 void _hba_set_register( unsigned int channel, 77 unsigned int index, 78 unsigned int value ) 79 { 80 unsigned int* vaddr = (unsigned int*)&seg_ioc_base + channel*HBA_SPAN + index; 81 _io_extended_write( vaddr, value ); 82 } 83 84 164 85 /////////////////////////////////////////////////////////////////////////////// 165 86 // This function register a command in both the command list … … 171 92 // return 0 if success, > 0 if error 172 93 /////////////////////////////////////////////////////////////////////////////// 173 unsigned int _hba_cmd_set( unsigned int is_read, // to memory 94 unsigned int _hba_cmd_set( unsigned int channel, // channel index 95 unsigned int is_read, // to memory 174 96 unsigned int lba, // logic block address 175 unsigned int buf_vaddr, // buffer virtual address97 paddr_t buffer, // buffer physical address 176 98 unsigned int count ) // number of blocks 177 99 { 178 volatile unsigned int *hba_address;179 180 100 unsigned int block_size; // defined by the block device (bytes) 181 unsigned int channel_id; // channel index182 101 unsigned int pxci; // command list status 183 102 unsigned int cmd_id; // command index in command list 184 unsigned int buf_id; // for physical buffers covering user buffer 185 unsigned int user_pt_vbase; // user page table virtual base address 186 unsigned int vpn; // for all pages covering the userbuffer 187 unsigned int vpn_min; // first virtual page index for user buffer 188 unsigned int vpn_max; // last virtual page index for user buffer 189 unsigned int offset; // unaligned bytes in page frame: buf_vaddr & 0xFFF 190 unsigned int offset_last; // unaligned bytes in last frame 103 191 104 hba_cmd_desc_t* cmd_desc; // command descriptor pointer 192 105 hba_cmd_table_t* cmd_table; // command table pointer … … 195 108 196 109 // check buffer alignment 197 if( buf_vaddr & (block_size-1) ) 198 { 199 _tty_get_lock( 0 ); 200 _puts("\n[GIET ERROR] in _hba_set_cmd() : user buffer not block aligned\n"); 201 _tty_release_lock( 0 ); 110 if( buffer & (block_size-1) ) 111 { 112 _printf("\n[GIET ERROR] in _hba_set_cmd() : user buffer not block aligned\n"); 202 113 return 1; 203 114 } 204 115 205 // get channel index 206 channel_id = _get_context_slot(CTX_HBA_ID); 207 if ( channel_id == 0xFFFFFFFF ) 208 { 209 _tty_get_lock( 0 ); 210 _puts("\n[GIET ERROR] in _hba_set_cmd() : no HBA channel allocated\n"); 211 _tty_release_lock( 0 ); 116 // get command list status from PXCI register 117 pxci = _hba_get_register( channel, HBA_PXCI ); 118 119 // get command index and return error if command list full 120 cmd_id = hba_cmd_slot[channel]; 121 if( pxci & (1<<cmd_id ) ) 122 { 123 _printf("\n[GIET ERROR] in _hba_set_cmd() : command list full for channel %d\n", 124 channel ); 212 125 return 1; 213 126 } 214 127 215 // get hba device address216 hba_address = (unsigned int*)(&seg_ioc_base) + (HBA_SPAN * channel_id);217 218 // get command list status219 pxci = hba_address[HBA_PXCI];220 221 // get command index and return error if command list full222 cmd_id = hba_cmd_slot[channel_id];223 if( pxci & (1<<cmd_id ) )224 {225 _tty_get_lock( 0 );226 _puts("\n[GIET ERROR] in _hba_set_cmd() : command list full in channel \n");227 _putd( channel_id );228 _puts("\n");229 _tty_release_lock( 0 );230 return 1;231 }232 233 128 // compute pointers on command descriptor and command table 234 cmd_desc = (hba_cmd_desc_t*)(&(hba_cmd_list[channel_id].desc[cmd_id])); 235 cmd_table = (hba_cmd_table_t*)(&(hba_cmd_table[channel_id][cmd_id])); 129 cmd_desc = (hba_cmd_desc_t*)(&(hba_cmd_list[channel].desc[cmd_id])); 130 cmd_table = (hba_cmd_table_t*)(&(hba_cmd_table[channel][cmd_id])); 131 132 // set buffer descriptor in command table 133 cmd_table->entry[0].dba = (unsigned int)(buffer); 134 cmd_table->entry[0].dbau = (unsigned int)(buffer >> 32); 135 cmd_table->entry[0].dbc = count * block_size; 136 137 // initialize command table header 138 cmd_table->header.lba0 = (char)lba; 139 cmd_table->header.lba1 = (char)(lba>>8); 140 cmd_table->header.lba2 = (char)(lba>>16); 141 cmd_table->header.lba3 = (char)(lba>>24); 142 cmd_table->header.lba4 = 0; 143 cmd_table->header.lba5 = 0; 144 145 // initialise command descriptor 146 cmd_desc->prdtl[0] = 1; 147 cmd_desc->prdtl[1] = 0; 148 cmd_desc->ctba = (unsigned int)(hba_cmd_table_paddr[channel][cmd_id]); 149 cmd_desc->ctbau = (unsigned int)(hba_cmd_table_paddr[channel][cmd_id]>>32); 150 if( is_read ) cmd_desc->flag[0] = 0x00; 151 else cmd_desc->flag[0] = 0x40; 152 153 // update PXCI register 154 _hba_set_register( channel, HBA_PXCI, (1<<cmd_id) ); 155 156 // update command pointer 157 hba_cmd_slot[channel] = (cmd_id + 1)%32; 158 159 return 0; 160 } 161 162 /* This can be used for a future use with buffer in virtual space 236 163 237 164 // get user space page table virtual address … … 262 189 if ( ko ) 263 190 { 264 _tty_get_lock( 0 ); 265 _puts("[GIET ERROR] in _hba_set_cmd() : user buffer unmapped\n"); 266 _tty_release_lock( 0 ); 191 _printf("[GIET ERROR] in _hba_set_cmd() : user buffer unmapped\n"); 267 192 return 1; 268 193 } 269 194 if ((flags & PTE_U) == 0) 270 195 { 271 _tty_get_lock( 0 ); 272 _puts("[GIET ERROR] in _hba_set_cmd() : user buffer not in user space\n"); 273 _tty_release_lock( 0 ); 196 _printf("[GIET ERROR] in _hba_set_cmd() : user buffer not in user space\n"); 274 197 return 1; 275 198 } 276 199 if (((flags & PTE_W) == 0 ) && (is_read == 0) ) 277 200 { 278 _tty_get_lock( 0 ); 279 _puts("[GIET ERROR] in _hba_set_cmd() : user buffer not writable\n"); 280 _tty_release_lock( 0 ); 201 _printf("[GIET ERROR] in _hba_set_cmd() : user buffer not writable\n"); 281 202 return 1; 282 203 } … … 285 206 if( buf_id > 245 ) 286 207 { 287 _tty_get_lock( 0 ); 288 _puts("[GIET ERROR] in _hba_set_cmd() : max number of buffers is 248\n"); 289 _tty_release_lock( 0 ); 208 _printf("[GIET ERROR] in _hba_set_cmd() : max number of buffers is 248\n"); 290 209 return 1; 291 210 } … … 301 220 302 221 #if GIET_DEBUG_HBA_DRIVER 303 _p uts("\n- buf_index = ");222 _printf("\n- buf_index = "); 304 223 _putd( buf_id ); 305 _p uts(" / paddr = ");224 _printf(" / paddr = "); 306 225 _putl( paddr ); 307 _p uts(" / count = ");226 _printf(" / count = "); 308 227 _putd( count ); 309 _p uts("\n");228 _printf("\n"); 310 229 #endif 311 230 buf_id++; … … 320 239 321 240 #if GIET_DEBUG_HBA_DRIVER 322 _p uts("\n- buf_index = ");241 _printf("\n- buf_index = "); 323 242 _putd( buf_id ); 324 _p uts(" / paddr = ");243 _printf(" / paddr = "); 325 244 _putl( paddr ); 326 _p uts(" / count = ");245 _printf(" / count = "); 327 246 _putd( count ); 328 _p uts("\n");247 _printf("\n"); 329 248 #endif 330 249 buf_id++; … … 340 259 341 260 #if GIET_DEBUG_HBA_DRIVER 342 _p uts("\n- buf_index = ");261 _printf("\n- buf_index = "); 343 262 _putd( buf_id ); 344 _p uts(" / paddr = ");263 _printf(" / paddr = "); 345 264 _putl( paddr ); 346 _p uts(" / count = ");265 _printf(" / count = "); 347 266 _putd( count ); 348 _p uts("\n");267 _printf("\n"); 349 268 #endif 350 269 buf_id++; … … 357 276 358 277 #if GIET_DEBUG_HBA_DRIVER 359 _p uts("\n- buf_index = ");278 _printf("\n- buf_index = "); 360 279 _putd( buf_id ); 361 _p uts(" / paddr = ");280 _printf(" / paddr = "); 362 281 _putl( paddr ); 363 _p uts(" / count = ");282 _printf(" / count = "); 364 283 _putd( count ); 365 _p uts("\n");284 _printf("\n"); 366 285 #endif 367 286 buf_id++; … … 376 295 377 296 #if GIET_DEBUG_HBA_DRIVER 378 _p uts("\n- buf_index = ");297 _printf("\n- buf_index = "); 379 298 _putd( buf_id ); 380 _p uts(" / paddr = ");299 _printf(" / paddr = "); 381 300 _putl( paddr ); 382 _p uts(" / count = ");301 _printf(" / count = "); 383 302 _putd( count ); 384 _p uts("\n");303 _printf("\n"); 385 304 #endif 386 305 buf_id++; 387 306 } 388 307 } 389 390 // initialize command table header 391 cmd_table->header.lba0 = (char)lba; 392 cmd_table->header.lba1 = (char)(lba>>8); 393 cmd_table->header.lba2 = (char)(lba>>16); 394 cmd_table->header.lba3 = (char)(lba>>24); 395 396 // initialise command descriptor 397 cmd_desc->prdtl[0] = (unsigned char)(buf_id); 398 cmd_desc->prdtl[1] = (unsigned char)(buf_id>>8); 399 cmd_desc->ctba = (unsigned int)(hba_cmd_table_paddr[channel_id][cmd_id]); 400 cmd_desc->ctbau = (unsigned int)(hba_cmd_table_paddr[channel_id][cmd_id]>>32); 401 if( is_read ) cmd_desc->flag[0] = 0x00; 402 else cmd_desc->flag[0] = 0x40; 403 404 // update PXCI register 405 hba_address[HBA_PXCI] = (1<<cmd_id); 406 407 // update command pointer 408 hba_cmd_slot[channel_id] = (cmd_id + 1)%32; 409 410 return 0; 411 } 308 */ 309 310 412 311 /////////////////////////////////////////////////////////////////// 413 312 // Register a write command in Command List and Command Table 414 // for a single buffer.313 // for a single physical buffer. 415 314 // Returns 0 if success, > 0 if error. 416 315 /////////////////////////////////////////////////////////////////// 417 unsigned int _hba_write( unsigned int mode, 316 unsigned int _hba_write( unsigned int channel, 317 unsigned int mode, 418 318 unsigned int lba, 419 void*buffer,319 paddr_t buffer, 420 320 unsigned int count ) 421 321 { 422 return _hba_cmd_set( 0, lba, (unsigned int)buffer, count ); 322 return _hba_cmd_set( channel, 323 0, // write 324 lba, 325 buffer, 326 count ); 423 327 } 424 328 425 329 /////////////////////////////////////////////////////////////////// 426 330 // Register a read command in Command List and Command Table 427 // for a single buffer.331 // for a single physical buffer. 428 332 // Returns 0 if success, > 0 if error. 429 333 /////////////////////////////////////////////////////////////////// 430 unsigned int _hba_read( unsigned int mode, 334 unsigned int _hba_read( unsigned int channel, 335 unsigned int mode, 431 336 unsigned int lba, 432 void*buffer,337 paddr_t buffer, 433 338 unsigned int count ) 434 339 { 435 return _hba_cmd_set( 1, lba, (unsigned int)buffer, count ); 436 } 340 return _hba_cmd_set( channel, 341 1, // read 342 lba, 343 buffer, 344 count ); 345 } 346 437 347 ////////////////////////////////////////////////////////////////// 438 348 // This function initializes for a given channel … … 453 363 unsigned int pt = _get_context_slot(CTX_PTAB_ID); 454 364 455 // HBA registers 456 unsigned int* hba_address; 457 hba_address = (unsigned int*)&seg_ioc_base + HBA_SPAN * channel; 458 459 hba_address[HBA_PXCLB] = (unsigned int)(&hba_cmd_list[channel]); 460 hba_address[HBA_PXCLBU] = 0; 461 hba_address[HBA_PXIE] = 0x40000001; 462 hba_address[HBA_PXIS] = 0; 463 hba_address[HBA_PXCI] = 0; 464 hba_address[HBA_PXCMD] = 1; 365 // HBA registers TODO: ne faut_il pas un V2P pour PXCLB/PXCLBU ? (AG) 366 _hba_set_register( channel, HBA_PXCLB , (unsigned int)&hba_cmd_list[channel] ); 367 _hba_set_register( channel, HBA_PXCLBU, 0 ); 368 _hba_set_register( channel, HBA_PXIE , 0x40000001 ); 369 _hba_set_register( channel, HBA_PXIS , 0 ); 370 _hba_set_register( channel, HBA_PXCI , 0 ); 371 _hba_set_register( channel, HBA_PXCMD , 1 ); 465 372 466 373 // command list pointer … … 475 382 if ( fail ) 476 383 { 477 _tty_get_lock( 0 ); 478 _puts("[GIET ERROR] in _hba_init() : command list unmapped\n"); 479 _tty_release_lock( 0 ); 384 _printf("[GIET ERROR] in _hba_init() : command list unmapped\n"); 480 385 return 1; 481 386 } … … 492 397 if ( fail ) 493 398 { 494 _tty_get_lock( 0 ); 495 _puts("[GIET ERROR] in _hba_init() : command table unmapped\n"); 496 _tty_release_lock( 0 ); 399 _printf("[GIET ERROR] in _hba_init() : command table unmapped\n"); 497 400 return 1; 498 401 } … … 513 416 } 514 417 418 ///////////////////////////////////////////////////////////////////////////////////// 419 // This function returns the content of the HBA_PXIS register for a given channel, 420 // and reset this register to acknoledge IRQ. 421 // return 0 if success, > 0 if error 422 ///////////////////////////////////////////////////////////////////////////////////// 423 unsigned int _hba_get_status( unsigned int channel ) 424 { 425 426 if( channel >= NB_IOC_CHANNELS ) 427 { 428 _printf("\n[GIET ERROR] in _hba_get_status() : illegal channel\n"); 429 _exit(); 430 } 431 432 // get HBA_PXIS value 433 unsigned int status = _hba_get_register( channel, HBA_PXIS ); 434 435 // reset HBA_PXIS 436 _hba_set_register( channel, HBA_PXIS, 0 ); 437 438 return status; 439 } 515 440 516 441 // Local Variables:
Note: See TracChangeset
for help on using the changeset viewer.