Changeset 602 for trunk/kernel/fs/fatfs.c
- Timestamp:
- Dec 3, 2018, 12:15:53 PM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/fs/fatfs.c
r568 r602 2 2 * fatfs.c - FATFS file system API implementation. 3 3 * 4 * Author Alain Greiner (2016,2017 )4 * Author Alain Greiner (2016,2017,2018) 5 5 * 6 6 * Copyright (c) UPMC Sorbonne Universites … … 42 42 ////////////////////////////////////////////////////////////////////////////////////////// 43 43 44 extern vfs_ctx_t fs_context[FS_TYPES_NR]; // allocated in vfs.c file45 46 ////////////////////////////////////////////////////////////////////////////////////////// 47 // FATFS specific andstatic functions44 extern vfs_ctx_t fs_context[FS_TYPES_NR]; // allocated in kernel_init.c file 45 46 ////////////////////////////////////////////////////////////////////////////////////////// 47 // FATFS specific static functions 48 48 ////////////////////////////////////////////////////////////////////////////////////////// 49 49 … … 89 89 uint32_t res = 0; 90 90 91 if ( little_endian )91 if ( little_endian ) 92 92 { 93 93 for( n = size ; n > 0 ; n-- ) res = (res<<8) | buffer[offset+n-1]; 94 94 } 95 else 95 else // big_endian 96 96 { 97 97 for( n = 0 ; n < size ; n++ ) res = (res<<8) | buffer[offset+n]; … … 100 100 101 101 } // end fatfs_get_record() 102 103 ////////////////////////////////////////////////////////////////////////////////////////// 104 // This function writes one, two, or four bytes from a 32 bits integer to a memory buffer, 105 // taking into account endianness. 106 ////////////////////////////////////////////////////////////////////////////////////////// 107 // @ offset : first byte of record in buffer. 108 // @ size : record length in bytes (1/2/4). 109 // @ buffer : pointer on buffer base. 110 // @ little endian : the most significant byte has the highest address when true. 111 // @ return the integer value in a 32 bits word. 112 ////////////////////////////////////////////////////////////////////////////////////////// 113 static void fatfs_set_record( uint32_t offset, 114 uint32_t size, 115 uint8_t * buffer, 116 uint32_t little_endian, 117 uint32_t value ) 118 { 119 uint32_t n; 120 121 if ( little_endian ) 122 { 123 for( n = size ; n > 0 ; n-- ) buffer[offset+n-1] = (uint8_t)(value>>((n-1)<<3)); 124 } 125 else // big_endian 126 { 127 for( n = 0 ; n < size ; n++ ) buffer[offset+n] = (uint8_t)(value>>((size-1-n)<<3)); 128 } 129 130 } // end fatfs_set_record() 102 131 103 132 ////////////////////////////////////////////////////////////////////////////////////////// … … 136 165 137 166 name[j] = '\0'; 138 } 167 168 } // fatfs_get_name_from_short() 139 169 140 170 ////////////////////////////////////////////////////////////////////////////////////////// … … 213 243 name[name_offset] = 0; 214 244 215 } // end get_name_from_long() 245 } // end fatfs_get_name_from_long() 246 247 ////////////////////////////////////////////////////////////////////////////////////////// 248 // This static function analyse the <name> input argument, and returns in other 249 // output arguments various informations required to store the name in FATFS directory. 250 // The <name> length cannot be larger than 31 characters : 251 // - Short name (less than 13 characters) require 1 LFN entry. 252 // - Medium names (from 14 to 26 characters require 2 LFN entries. 253 // - Large names (up to 31 characters) require 3 LFN entries. 254 ////////////////////////////////////////////////////////////////////////////////////////// 255 // @ name : [in] complete directory entry name. 256 // @ length : [out] total number of characters in name. 257 // @ nb_lfn : [out] number of LFN entries required to store the name. 258 // @ sfn : [out] a legal SFN name extracted from name / upper case and 8-3 format. 259 // @ checksum : [out] checksum to be stored in SFN. 260 // @ returns 0 on success / returns 1 if the name length is larger than 31 characters. 261 ////////////////////////////////////////////////////////////////////////////////////////// 262 static error_t fatfs_name_format( const char * name, 263 uint32_t * length, 264 uint32_t * nb_lfn, 265 char * sfn, 266 uint8_t * checksum ) 267 { 268 // compute name length 269 uint32_t name_length = strlen( name ); 270 *length = name_length; 271 272 uint32_t suffix_length = 0; 273 uint32_t prefix_length = 0; 274 uint32_t dot_found = 0; 275 uint32_t i; 276 277 // compute prefix and suffix length 278 // only the last '.' is taken into account 279 for ( i=0 ; i<name_length ; i++ ) 280 { 281 if (name[i] == '.' ) 282 { 283 if ( dot_found ) 284 { 285 prefix_length += suffix_length + 1; 286 suffix_length = 0; 287 } 288 else 289 { 290 dot_found = 1; 291 } 292 } 293 else 294 { 295 if ( dot_found) suffix_length++; 296 else prefix_length++; 297 } 298 } 299 300 // build SFN prefix (8bits) 301 if (prefix_length <= 8) 302 { 303 for( i=0 ; i<8 ; i++) 304 { 305 if ( i<prefix_length ) sfn[i] = to_upper( name[i] ); 306 else sfn[i] = 0x20; 307 } 308 } 309 else 310 { 311 for( i=0 ; i<6 ; i++) 312 { 313 sfn[i] = to_upper( name[i] ); 314 } 315 sfn[6] = 0x7E; 316 sfn[7] = 0x31; 317 } 318 319 // build SFN suffix (3 bits) 320 if ( suffix_length == 0 ) 321 { 322 sfn[8] = 0x20; 323 sfn[9] = 0x20; 324 sfn[10] = 0x20; 325 } 326 else if ( suffix_length == 1 ) 327 { 328 sfn[8] = to_upper( name[name_length-1] ); 329 sfn[9] = 0x20; 330 sfn[10] = 0x20; 331 } 332 else if ( suffix_length == 2 ) 333 { 334 sfn[8] = to_upper( name[name_length-2] ); 335 sfn[9] = to_upper( name[name_length-1] ); 336 sfn[10] = 0x20; 337 } 338 else 339 { 340 sfn[8] = to_upper( name[name_length-suffix_length] ); 341 sfn[9] = to_upper( name[name_length-suffix_length+1] ); 342 sfn[10] = to_upper( name[name_length-suffix_length+2] ); 343 } 344 345 // compute 8 bits checksum 346 uint8_t sum = 0; 347 for ( i=0 ; i<11 ; i++ ) 348 { 349 sum = (((sum & 0x01)<<7) | ((sum & 0xFE)>>1)) + sfn[i]; 350 } 351 *checksum = sum; 352 353 // set nb_lfn and length values 354 if ( name_length <= 13 ) 355 { 356 *nb_lfn = 1; 357 return 0; 358 } 359 else if ( name_length <= 26 ) 360 { 361 *nb_lfn = 2; 362 return 0; 363 } 364 else if ( name_length <= 31 ) 365 { 366 *nb_lfn = 3; 367 return 0; 368 } 369 else 370 { 371 return 1; 372 } 373 } // end fatfs_name_format() 374 375 ////////////////////////////////////////////////////////////////////////////////////////// 376 // This static function - atomically - decrements "free_clusters", and updates 377 // the "free_cluster_hint" shared variables in the FATFS context in the FAT cluster. 378 // It scan the FAT to find the first free slot larger than the <cluster> argument, 379 // and set "free_cluster_hint" <= (free - 1). 380 // 381 // WARNING : The free_lock protecting exclusive access to these variables 382 // must be taken by the calling function. 383 ////////////////////////////////////////////////////////////////////////////////////////// 384 // @ cluster : recently allocated cluster index in FAT. 385 ////////////////////////////////////////////////////////////////////////////////////////// 386 static error_t fatfs_free_clusters_decrement( uint32_t cluster ) 387 { 388 fatfs_ctx_t * loc_ctx; // local pointer on local FATFS context 389 fatfs_ctx_t * fat_ctx; // local pointer on FATFS in cluster containing FAT mapper 390 cxy_t mapper_cxy; // cluster identifier for cluster containing FAT mapper 391 xptr_t mapper_xp; // extended pointer on FAT mapper 392 xptr_t hint_xp; // extended pointer on "free_cluster_hint" shared variable 393 xptr_t numb_xp; // extended pointer on "free_clusters" shared variable 394 uint32_t numb; // "free_clusters" variable current value 395 uint32_t page_id; // page index in FAT mapper 396 uint32_t slot_id; // slot index in one page of FAT (1024 slots per page) 397 uint32_t page_max; // max number of pages in FAT mapper 398 xptr_t page_xp; // extended pointer on current page in FAT mapper 399 xptr_t slot_xp; // extended pointer on current slot in FAT mapper 400 401 #if DEBUG_FATFS_FREE_CLUSTERS 402 uint32_t cycle = (uint32_t)hal_get_cycles(); 403 thread_t * this = CURRENT_THREAD; 404 if( DEBUG_FATFS_FREE_CLUSTERS < (uint32_t)hal_get_cycles() ) 405 printk("\n[%s] thread[%x,%x] enter for allocated cluster %x / cycle %d\n", 406 __FUNCTION__, this->process->pid, this->trdid, cluster , cycle ); 407 #endif 408 409 // get local pointer on local FATFS context 410 loc_ctx = fs_context[FS_TYPE_FATFS].extend; 411 412 // get cluster containing FAT mapper 413 mapper_xp = loc_ctx->fat_mapper_xp; 414 mapper_cxy = GET_CXY( mapper_xp ); 415 416 // get local pointer on FATFS context in FAT cluster 417 fat_ctx = hal_remote_lpt( XPTR( mapper_cxy , &fs_context[FS_TYPE_FATFS].extend ) ); 418 419 // build extended pointers on free_clusters, and free_cluster_hint 420 hint_xp = XPTR( mapper_cxy , &fat_ctx->free_cluster_hint ); 421 numb_xp = XPTR( mapper_cxy , &fat_ctx->free_clusters ); 422 423 // update "free_clusters" 424 numb = hal_remote_l32( numb_xp ); 425 hal_remote_s32( numb_xp , numb - 1 ); 426 427 // scan FAT mapper to find the first free slot > cluster 428 // and update "free_cluster_hint" as (free - 1) 429 page_id = (cluster + 1) >> 10; 430 slot_id = (cluster + 1) & 0x3FF; 431 page_max = (loc_ctx->fat_sectors_count >> 3); 432 433 // scan FAT mapper / loop on pages 434 while ( page_id < page_max ) 435 { 436 // get current page from mapper 437 page_xp = mapper_remote_get_page( mapper_xp , page_id ); 438 439 if( page_xp == XPTR_NULL ) 440 { 441 printk("\n[ERROR] in %s : cannot access FAT mapper\n", __FUNCTION__ ); 442 return -1; 443 } 444 445 // scan FAT mapper / loop on slots 446 while ( slot_id < 1024 ) 447 { 448 // get extended pointer on current slot 449 slot_xp = ppm_page2base( page_xp ) + (slot_id << 2); 450 451 // test FAT slot value 452 if ( hal_remote_l32( slot_xp ) == FREE_CLUSTER ) 453 { 454 // update "free_cluster_hint" <= (free - 1) 455 hal_remote_s32( hint_xp , (page_id << 10) + slot_id - 1 ); 456 457 #if DEBUG_FATFS_FREE_CLUSTERS 458 cycle = (uint32_t)hal_get_cycles(); 459 if( DEBUG_FATFS_FREE_CLUSTERS < (uint32_t)hal_get_cycles() ) 460 printk("\n[%s] thread[%x,%x] exit / hint %x / free_clusters %x / cycle %d\n", 461 __FUNCTION__, this->process->pid, this->trdid, 462 hal_remote_l32(hint_xp), hal_remote_l32(numb_xp), cycle ); 463 #endif 464 return 0; 465 } 466 467 // increment slot_id 468 slot_id++; 469 470 } // end loop on slots 471 472 // update loop variables 473 page_id++; 474 slot_id = 0; 475 476 } // end loop on pages 477 478 // return error if no free cluster found 479 printk("\n[ERROR] in %s : No free cluster found\n", __FUNCTION__ ); 480 return -1; 481 482 } // end fatfs_free_clusters_decrement() 483 484 ////////////////////////////////////////////////////////////////////////////////////////// 485 // This static function atomically increments <free_clusters>, and updates 486 // the <free_cluster_hint> shared variables in the FATFS context in the FAT cluster. 487 // If the released cluster index is smaller than the current (hint + 1) value, 488 // it set "free_cluster_hint" <= cluster - 1. 489 // 490 // WARNING : The free_lock protecting exclusive access to these variables 491 // must be taken by the calling function. 492 ////////////////////////////////////////////////////////////////////////////////////////// 493 // @ cluster : recently released cluster index in FAT. 494 ////////////////////////////////////////////////////////////////////////////////////////// 495 static void fatfs_free_clusters_increment( uint32_t cluster ) 496 { 497 fatfs_ctx_t * loc_ctx; // local pointer on local FATFS context 498 fatfs_ctx_t * fat_ctx; // local pointer on FATFS in cluster containing FAT mapper 499 cxy_t fat_cxy; // cluster identifier for cluster containing FAT mapper 500 xptr_t hint_xp; // extended pointer on "free_cluster_hint" shared variable 501 xptr_t numb_xp; // extended pointer on "free_clusters" shared variable 502 uint32_t hint; // "free_cluster_hint" variable current value 503 uint32_t numb; // "free_clusters" variable current value 504 505 // get local pointer on local FATFS context 506 loc_ctx = fs_context[FS_TYPE_FATFS].extend; 507 508 // get cluster containing FAT mapper 509 fat_cxy = GET_CXY( loc_ctx->fat_mapper_xp ); 510 511 // get local pointer on FATFS context in FAT cluster 512 fat_ctx = hal_remote_lpt( XPTR( fat_cxy , &fs_context[FS_TYPE_FATFS].extend ) ); 513 514 // build extended pointers free_lock, free_clusters, and free_cluster_hint 515 hint_xp = XPTR( fat_cxy , &fat_ctx->free_cluster_hint ); 516 numb_xp = XPTR( fat_cxy , &fat_ctx->free_clusters ); 517 518 // get current value of free_cluster_hint and free_clusters 519 hint = hal_remote_l32( hint_xp ); 520 numb = hal_remote_l32( numb_xp ); 521 522 // update free_cluster_hint if required 523 if ( cluster < (hint + 1) ) hal_remote_s32( hint_xp , (cluster - 1) ); 524 525 // update free_clusters 526 hal_remote_s32( numb_xp , numb + 1 ); 527 528 #if DEBUG_FATFS_FREE_CLUSTERS 529 thread_t * this = CURRENT_THREAD; 530 if( DEBUG_FATFS_FREE_CLUSTERS < (uint32_t)hal_get_cycles() ) 531 printk("\n[%s] thread[%x,%x] updates free cluster info : hint %x / number %x\n", 532 __FUNCTION__, this->process->pid, this->trdid, 533 hal_remote_l32( hint_xp ), hal_remote_l32( numb_xp ) ); 534 #endif 535 536 } // end fatfs_free_clusters_increment() 537 538 ////////////////////////////////////////////////////////////////////////////////////////// 539 // This recursive function is called by the generic function fatfs_release_all_clusters() 540 // It release all clusters allocated to a given inode in the FAT mapper. 541 // The removal is done in reverse order of the linked list (from last to first). 542 // It does NOT update the FS on the IOC device. 543 ////////////////////////////////////////////////////////////////////////////////////////// 544 // @ fat_mapper_xp : extended pointer on FAT mapper. 545 // @ cluster : cluster index in FAT. 546 // @ return 0 if success / return -1 if error (cannot access FAT) 547 ////////////////////////////////////////////////////////////////////////////////////////// 548 static error_t fatfs_recursive_release( xptr_t fat_mapper_xp, 549 uint32_t cluster ) 550 { 551 uint32_t next; 552 553 // get next cluster from FAT mapper 554 if ( mapper_remote_get_32( fat_mapper_xp , cluster , &next ) ) return -1; 555 556 #if (DEBUG_FATFS_RELEASE_INODE & 1) 557 thread_t * this = CURRENT_THREAD; 558 if ( DEBUG_FATFS_RELEASE_INODE < (uint32_t)hal_get_cycles() ) 559 printk("\n[%s] thread[%x,%x] access FAT for cluster %x / next %x\n", 560 __FUNCTION__, this->process->pid, this->trdid, cluster, next ); 561 #endif 562 563 if ( next < END_OF_CHAIN_CLUSTER_MIN ) // non terminal case 564 { 565 // call fatfs_recursive_release() on next cluster 566 if ( fatfs_recursive_release( fat_mapper_xp , next ) ) return -1; 567 } 568 569 // update current cluster in FAT mapper 570 if ( mapper_remote_set_32( fat_mapper_xp, cluster , FREE_CLUSTER ) ) return -1; 571 572 // Update free_cluster_hint and free_clusters in FAT context 573 fatfs_free_clusters_increment( cluster ); 574 575 return 0; 576 577 } // end fatfs_recursive_release() 216 578 217 579 … … 220 582 ////////////////////////////////////////////////////////////////////////////////////////// 221 583 222 ////////////////////////////// ////////////////////////////////////////////////////////////584 ////////////////////////////// 223 585 void fatfs_ctx_display( void ) 224 586 { 587 // get pointer on local FATFS context 225 588 vfs_ctx_t * vfs_ctx = &fs_context[FS_TYPE_FATFS]; 226 589 fatfs_ctx_t * fatfs_ctx = (fatfs_ctx_t *)vfs_ctx->extend; 227 590 228 591 printk("\n*** FAT context ***\n" 229 "- fat_sectors = %d\n" 230 "- sector size = %d\n" 231 "- cluster size = %d\n" 232 "- fat_first_lba = %d\n" 233 "- data_first_lba = %d\n" 234 "- root_dir_cluster = %d\n" 235 "- mapper_xp = %l\n", 592 "- fat_sectors = %d\n" 593 "- sector size = %d\n" 594 "- cluster size = %d\n" 595 "- fat_first_lba = %d\n" 596 "- data_first_lba = %d\n" 597 "- root_dir_cluster = %d\n" 598 "- free_clusters = %d\n" 599 "- free_cluster_hint = %d\n" 600 "- fat_mapper_xp = %l\n", 236 601 fatfs_ctx->fat_sectors_count, 237 602 fatfs_ctx->bytes_per_sector, … … 240 605 fatfs_ctx->cluster_begin_lba, 241 606 fatfs_ctx->root_dir_cluster, 607 fatfs_ctx->free_clusters, 608 fatfs_ctx->free_cluster_hint, 242 609 fatfs_ctx->fat_mapper_xp ); 243 } 244 245 ///////////////////////////////////////////// 246 error_t fatfs_get_cluster( mapper_t * mapper, 247 uint32_t first_cluster_id, 610 611 } // end fatfs_ctx_display() 612 613 ////////////////////////////////////////// 614 void fatfs_display_fat( uint32_t page_id, 615 uint32_t nentries ) 616 { 617 uint32_t line; 618 uint32_t maxline; 619 620 // copute numner of lines to display 621 maxline = nentries >> 3; 622 if( nentries & 0x7 ) maxline++; 623 624 // get pointer on local FATFS context 625 vfs_ctx_t * vfs_ctx = &fs_context[FS_TYPE_FATFS]; 626 fatfs_ctx_t * fatfs_ctx = (fatfs_ctx_t *)vfs_ctx->extend; 627 628 // get extended pointer on FAT mapper 629 xptr_t fat_mapper_xp = fatfs_ctx->fat_mapper_xp; 630 631 // get extended pointer and cluster of FAT mapper requested page 632 xptr_t page_xp = mapper_remote_get_page( fat_mapper_xp , page_id ); 633 634 // get extended pointer on requested page base 635 xptr_t base_xp = ppm_page2base( page_xp ); 636 637 printk("\n***** FAT content / page %d *****\n", page_id ); 638 for( line = 0 ; line < maxline ; line++ ) 639 { 640 printk("%x : %X | %X | %X | %X | %X | %X | %X | %X\n", (line<<3), 641 hal_remote_l32( base_xp + ((line<<5) ) ), 642 hal_remote_l32( base_xp + ((line<<5) + 4 ) ), 643 hal_remote_l32( base_xp + ((line<<5) + 8 ) ), 644 hal_remote_l32( base_xp + ((line<<5) + 12 ) ), 645 hal_remote_l32( base_xp + ((line<<5) + 16 ) ), 646 hal_remote_l32( base_xp + ((line<<5) + 20 ) ), 647 hal_remote_l32( base_xp + ((line<<5) + 24 ) ), 648 hal_remote_l32( base_xp + ((line<<5) + 28 ) ) ); 649 } 650 651 } // end fatfs_display_fat() 652 653 /////////////////////////////////////////////////////// 654 error_t fatfs_get_cluster( uint32_t first_cluster_id, 248 655 uint32_t searched_page_index, 249 656 uint32_t * searched_cluster_id ) 250 657 { 251 page_t * current_page_desc;// pointer on current page descriptor252 uint32_t * current_page_buffer;// pointer on current page (array of uint32_t)658 xptr_t current_page_xp; // pointer on current page descriptor 659 uint32_t * buffer; // pointer on current page (array of uint32_t) 253 660 uint32_t current_page_index; // index of current page in FAT 254 661 uint32_t current_page_offset; // offset of slot in current page … … 256 663 uint32_t next_cluster_id; // content of current FAT slot 257 664 258 259 665 assert( (searched_page_index > 0) , 666 "no FAT access required for first page\n"); 260 667 261 668 #if DEBUG_FATFS_GET_CLUSTER 262 uint32_t cycle = (uint32_t)hal_get_cycles(); 669 uint32_t cycle = (uint32_t)hal_get_cycles(); 670 thread_t * this = CURRENT_THREAD; 263 671 if( DEBUG_FATFS_GET_CLUSTER < cycle ) 264 printk("\n[DBG] %s : thread %x enter / first_cluster_id %d / searched_index / cycle %d\n", 265 __FUNCTION__, CURRENT_THREAD, first_cluster_id, searched_page_index, cycle ); 266 #endif 267 268 // get number of FAT slots per page 269 uint32_t slots_per_page = CONFIG_PPM_PAGE_SIZE >> 2; 270 271 // initialize loop variable 272 current_page_index = first_cluster_id / slots_per_page; 273 current_page_offset = first_cluster_id % slots_per_page; 672 printk("\n[%s] thread[%x,%x] enter / first_cluster_id %d / searched_index / cycle %d\n", 673 __FUNCTION__, this->process->pid, this->trdid, first_cluster_id, searched_page_index, cycle ); 674 #endif 675 676 // get local pointer on local FATFS context 677 fatfs_ctx_t * ctx = fs_context[FS_TYPE_FATFS].extend; 678 679 // get extended pointer and cluster on FAT mapper 680 xptr_t mapper_xp = ctx->fat_mapper_xp; 681 cxy_t mapper_cxy = GET_CXY( mapper_xp ); 682 683 // initialize loop variable (1024 slots per page) 684 current_page_index = first_cluster_id >> 10; 685 current_page_offset = first_cluster_id & 0x3FF; 274 686 page_count_in_file = 0; 275 687 next_cluster_id = 0xFFFFFFFF; … … 279 691 { 280 692 // get pointer on current page descriptor 281 current_page_desc = mapper_get_page( mapper , current_page_index ); 282 283 if( current_page_desc == NULL ) return EIO; 693 current_page_xp = mapper_remote_get_page( mapper_xp , current_page_index ); 694 695 if( current_page_xp == XPTR_NULL ) 696 { 697 // TODO 698 return -1; 699 } 284 700 285 701 // get pointer on buffer for current page 286 xptr_t base_xp = ppm_page2base( XPTR( local_cxy , current_page_desc ));287 current_page_buffer = (uint32_t *)GET_PTR( base_xp );702 xptr_t base_xp = ppm_page2base( current_page_xp ); 703 buffer = (uint32_t *)GET_PTR( base_xp ); 288 704 289 705 // get FAT slot content 290 next_cluster_id = current_page_buffer[current_page_offset];706 next_cluster_id = hal_remote_l32( XPTR( mapper_cxy , &buffer[current_page_offset] ) ); 291 707 292 708 #if (DEBUG_FATFS_GET_CLUSTER & 1) 293 709 if( DEBUG_FATFS_GET_CLUSTER < cycle ) 294 printk("\n[ DBG] %s :traverse FAT / current_page_index = %d\n"710 printk("\n[%s] traverse FAT / current_page_index = %d\n" 295 711 "current_page_offset = %d / next_cluster_id = %d\n", 296 712 __FUNCTION__, current_page_index, current_page_offset , next_cluster_id ); … … 298 714 299 715 // update loop variables 300 current_page_index = next_cluster_id / slots_per_page;301 current_page_offset = next_cluster_id % slots_per_page;716 current_page_index = next_cluster_id >> 10; 717 current_page_offset = next_cluster_id & 0x3FF; 302 718 page_count_in_file++; 303 719 } 304 720 305 if( next_cluster_id == 0xFFFFFFFF ) return EIO;721 if( next_cluster_id == 0xFFFFFFFF ) return -1; 306 722 307 723 #if DEBUG_FATFS_GET_CLUSTER 308 724 cycle = (uint32_t)hal_get_cycles(); 309 725 if( DEBUG_FATFS_GET_CLUSTER < cycle ) 310 printk("\n[ DBG] %s : thread %xexit / searched_cluster_id = %d / cycle %d\n",311 __FUNCTION__, CURRENT_THREAD, next_cluster_id / cycle );726 printk("\n[%s] thread[%x,%x] exit / searched_cluster_id = %d / cycle %d\n", 727 __FUNCTION__, this->process->pid, this->trdid, next_cluster_id / cycle ); 312 728 #endif 313 729 … … 320 736 321 737 /////////////////////////////////////////////////////////////////////////////////////// 322 // Generic API : the following functions are called by the kernel (VFS)738 // Generic API : the following functions are called by the kernel VFS 323 739 // and must be defined by all supported file systems. 324 740 /////////////////////////////////////////////////////////////////////////////////////// … … 342 758 uint8_t * buffer; 343 759 344 #if DEBUG_FATFS_ INIT760 #if DEBUG_FATFS_CTX_INIT 345 761 uint32_t cycle = (uint32_t)hal_get_cycles(); 346 if( DEBUG_FATFS_INIT < cycle ) 347 printk("\n[DBG] %s : thread %x enter for fatfs_ctx = %x / cycle %d\n", 348 __FUNCTION__ , CURRENT_THREAD , fatfs_ctx , cycle ); 349 #endif 350 351 assert( (fatfs_ctx != NULL) , 352 "cannot allocate memory for FATFS context\n" ); 762 if( DEBUG_FATFS_CTX_INIT < cycle ) 763 printk("\n[%s] thread[%x,%x] enter for fatfs_ctx = %x / cycle %d\n", 764 __FUNCTION__ , this->process->pid, this->trdid, fatfs_ctx , cycle ); 765 #endif 766 767 // check argument 768 assert( (fatfs_ctx != NULL) , "pointer on FATFS context is NULL\n" ); 769 770 // check only cluster 0 does FATFS init 771 assert( (local_cxy == 0) , "only cluster 0 can initialize FATFS\n"); 353 772 354 773 // allocate a 512 bytes buffer to store the boot record … … 357 776 buffer = (uint8_t *)kmem_alloc( &req ); 358 777 359 assert( (buffer != NULL) , 360 "cannot allocate memory for 512 bytes buffer\n" ); 778 if( buffer == NULL ) 779 { 780 printk("\n[PANIC] in %s : cannot allocate buffer\n", __FUNCTION__ ); 781 hal_core_sleep(); 782 } 361 783 362 // load the boot record from device 363 // using a synchronous access to IOC device 784 // load the BOOT record from device 364 785 error = dev_ioc_sync_read( buffer , 0 , 1 ); 365 786 366 assert( (error == 0) , 367 "cannot access boot record\n" ); 368 369 #if (DEBUG_FATFS_INIT & 0x1) 370 if( DEBUG_FATFS_INIT < cycle ) 787 if ( error ) 788 { 789 printk("\n[PANIC] in %s : cannot access boot record\n", __FUNCTION__ ); 790 hal_core_sleep(); 791 } 792 793 #if (DEBUG_FATFS_CTX_INIT & 0x1) 794 if( DEBUG_FATFS_CTX_INIT < cycle ) 371 795 { 372 796 uint32_t line; … … 387 811 #endif 388 812 389 // checksector size from boot record813 // get sector size from boot record 390 814 uint32_t sector_size = fatfs_get_record( BPB_BYTSPERSEC , buffer , 1 ); 391 392 assert( (sector_size == 512) , 393 "sector size must be 512 bytes\n" ); 394 395 // check cluster size from boot record 815 if ( sector_size != 512 ) 816 { 817 printk("\n[PANIC] in %s : sector size must be 512 bytes\n", __FUNCTION__ ); 818 hal_core_sleep(); 819 } 820 821 // get cluster size from boot record 396 822 uint32_t nb_sectors = fatfs_get_record( BPB_SECPERCLUS , buffer , 1 ); 397 398 assert( (nb_sectors == 8) , 399 "cluster size must be 8 sectors\n" ); 400 401 // check number of FAT copies from boot record 823 if ( nb_sectors != 8 ) 824 { 825 printk("\n[PANIC] in %s : cluster size must be 8 sectors\n", __FUNCTION__ ); 826 hal_core_sleep(); 827 } 828 829 // get number of FAT copies from boot record 402 830 uint32_t nb_fats = fatfs_get_record( BPB_NUMFATS , buffer , 1 ); 403 404 assert( (nb_fats == 1) , 405 "number of FAT copies must be 1\n" ); 406 407 // get & check number of sectors in FAT from boot record 831 if ( nb_fats != 1 ) 832 { 833 printk("\n[PANIC] in %s : number of FAT copies must be 1\n", __FUNCTION__ ); 834 hal_core_sleep(); 835 } 836 837 // get number of sectors in FAT from boot record 408 838 uint32_t fat_sectors = fatfs_get_record( BPB_FAT32_FATSZ32 , buffer , 1 ); 409 410 assert( ((fat_sectors & 0xF) == 0) , 411 "FAT not multiple of 16 sectors\n"); 412 413 // get and check root cluster from boot record 839 if ( (fat_sectors & 0xF) != 0 ) 840 { 841 printk("\n[PANIC] in %s : FAT size not multiple of 16 sectors\n", __FUNCTION__ ); 842 hal_core_sleep(); 843 } 844 845 // get root cluster from boot record 414 846 uint32_t root_cluster = fatfs_get_record( BPB_FAT32_ROOTCLUS , buffer , 1 ); 415 416 assert( (root_cluster == 2) , 417 "root cluster index must be 2\n"); 847 if ( root_cluster != 2 ) 848 { 849 printk("\n[PANIC] in %s : root cluster index must be 2\n", __FUNCTION__ ); 850 hal_core_sleep(); 851 } 418 852 419 853 // get FAT lba from boot record 420 854 uint32_t fat_lba = fatfs_get_record( BPB_RSVDSECCNT , buffer , 1 ); 855 856 // get FS_INFO sector lba from boot record 857 uint32_t fs_info_lba = fatfs_get_record( BPB_FAT32_FSINFO , buffer , 1 ); 858 859 // load the FS_INFO record from device 860 error = dev_ioc_sync_read( buffer , fs_info_lba , 1 ); 861 862 if ( error ) 863 { 864 printk("\n[PANIC] in %s : cannot access FS_INFO record\n", __FUNCTION__ ); 865 hal_core_sleep(); 866 } 867 868 // get free clusters number from FS_INFO record 869 uint32_t free_clusters = fatfs_get_record( FS_FREE_CLUSTERS , buffer , 1 ); 870 if ( free_clusters >= fat_sectors << 7 ) 871 { 872 printk("\n[PANIC] in %s : unconsistent free_clusters\n", __FUNCTION__ ); 873 hal_core_sleep(); 874 } 875 876 // get cluster hint from FS_INFO record 877 uint32_t free_cluster_hint = fatfs_get_record( FS_FREE_CLUSTER_HINT , buffer , 1 ); 878 if ( free_cluster_hint >= fat_sectors << 7 ) 879 { 880 printk("\n[PANIC] in %s : unconsistent free_cluster_hint\n", __FUNCTION__ ); 881 hal_core_sleep(); 882 } 421 883 422 884 // release the 512 bytes buffer … … 427 889 // allocate a mapper for the FAT itself 428 890 mapper_t * fat_mapper = mapper_create( FS_TYPE_FATFS ); 429 430 assert( (fat_mapper != NULL) , 431 "no memory for FAT mapper" ); 891 if ( fat_mapper == NULL ) 892 { 893 printk("\n[PANIC] in %s : no memory for FAT mapper\n", __FUNCTION__ ); 894 hal_core_sleep(); 895 } 432 896 433 897 // WARNING : the inode field MUST be NULL for the FAT mapper … … 441 905 fatfs_ctx->cluster_begin_lba = fat_lba + fat_sectors; 442 906 fatfs_ctx->root_dir_cluster = 2; 443 fatfs_ctx->last_allocated_sector = 0; // TODO ???444 fatfs_ctx->last_allocated_index = 0; // TODO ???445 907 fatfs_ctx->fat_mapper_xp = XPTR( local_cxy , fat_mapper ); 446 447 #if DEBUG_FATFS_INIT 908 fatfs_ctx->free_clusters = free_clusters; 909 fatfs_ctx->free_cluster_hint = free_cluster_hint; 910 911 remote_queuelock_init( XPTR( local_cxy , &fatfs_ctx->free_lock ) , LOCK_FATFS_FREE ); 912 913 #if DEBUG_FATFS_CTX_INIT 448 914 cycle = (uint32_t)hal_get_cycles(); 449 if( DEBUG_FATFS_ INIT < cycle )450 printk("\n[ DBG] %s : thread %xexit for fatfs_ctx = %x / cycle %d\n",451 __FUNCTION__ , CURRENT_THREAD , fatfs_ctx, cycle );915 if( DEBUG_FATFS_CTX_INIT < cycle ) 916 printk("\n[%s] thread[%x,%x] exit for fatfs_ctx = %x / cycle %d\n", 917 __FUNCTION__, this->process->pid, this->trdid, fatfs_ctx, cycle ); 452 918 #endif 453 919 … … 463 929 } 464 930 465 ////////////////////////////////////////////// 466 error_t fatfs_ mapper_move_page( page_t * page,467 bool_t to_mapper)931 /////////////////////////////////////////////// 932 error_t fatfs_add_dentry( vfs_inode_t * inode, 933 vfs_dentry_t * dentry ) 468 934 { 469 935 error_t error; 470 vfs_inode_t * inode; 471 mapper_t * mapper; 472 uint32_t index; // page index in mapper 473 uint8_t * buffer; // page base address in mapper 474 uint32_t count; // number of sectors in a page 475 uint32_t lba; // block address on device 476 fatfs_ctx_t * fatfs_ctx; // pointer on local FATFS context 477 478 // get pointer on mapper and page index from page descriptor 479 mapper = page->mapper; 480 index = page->index; 481 482 // get inode pointer from mapper 483 inode = mapper->inode; 484 485 #if DEBUG_FATFS_MOVE 486 uint32_t cycle = (uint32_t)hal_get_cycles(); 487 if( DEBUG_FATFS_MOVE < cycle ) 488 printk("\n[DBG] %s : thread %x enter / page %d / inode %x / mapper %x / cycle %d\n", 489 __FUNCTION__ , CURRENT_THREAD , index , inode , mapper , cycle ); 490 #endif 491 492 // get page base address 493 xptr_t base_xp = ppm_page2base( XPTR( local_cxy , page ) ); 494 buffer = (uint8_t *)GET_PTR( base_xp ); 495 496 // get number of sectors for one page (from FATFS context) 497 fatfs_ctx = (fatfs_ctx_t *)fs_context[FS_TYPE_FATFS].extend; 498 count = fatfs_ctx->sectors_per_cluster; 499 500 // test FAT/normal inode 501 if( inode == NULL ) // it is the FAT mapper 502 { 503 // get lba from page index 504 lba = fatfs_ctx->fat_begin_lba + (count * index); 505 506 #if (DEBUG_FATFS_MOVE & 0x1) 507 if( DEBUG_FATFS_MOVE < cycle ) 508 printk("\n[DBG] %s : access FAT on device / lba = %d\n", __FUNCTION__ , lba ); 509 #endif 510 511 // access device 512 if( to_mapper ) error = dev_ioc_sync_read ( buffer , lba , count ); 513 else error = dev_ioc_write( buffer , lba , count ); 514 515 if( error ) return EIO; 516 } 517 else // it is a normal inode mapper 518 { 519 uint32_t searched_cluster_id; 520 521 // get first_cluster_id from inode extension 522 uint32_t first_cluster_id = (uint32_t)(intptr_t)inode->extend; 523 524 // compute cluster_id 525 if( index == 0 ) // no need to access FAT mapper 936 uint32_t length; // dentry name length 937 uint32_t nb_lfn; // number or required LFN 938 char sfn[11]; // buffer for SFN name 939 uint8_t checksum; // name checksum 940 mapper_t * mapper; // loal pointer on parent inode mapper 941 xptr_t mapper_xp; // extended pointer on parent inode mapper 942 xptr_t child_xp; // extended pointer on child inode 943 cxy_t child_cxy; // child inode cluster 944 vfs_inode_t * child_ptr; // child inode local pointer 945 uint32_t size; // child inode size 946 uint32_t type; // child inode type 947 uint32_t cluster; // child inode cluster index 948 949 #if DEBUG_FATFS_ADD_DENTRY 950 char dir_name[CONFIG_VFS_MAX_NAME_LENGTH]; 951 uint32_t cycle = (uint32_t)hal_get_cycles(); 952 thread_t * this = CURRENT_THREAD; 953 vfs_inode_get_name( XPTR( local_cxy , inode ) , dir_name ); 954 if( DEBUG_FATFS_ADD_DENTRY < cycle ) 955 printk("\n[%s] thread[%x,%x] enter / parent <%s> / child <%s> / cycle %d\n", 956 __FUNCTION__, this->process->pid, this->trdid, dir_name, dentry->name, cycle ); 957 #endif 958 959 // check arguments 960 assert( (inode != NULL) , "inode pointer is NULL\n" ); 961 assert( (dentry != NULL) , "dentry pointer is NULL\n" ); 962 assert( (inode->type == INODE_TYPE_DIR) , "inode is not a directory\n" ); 963 assert( (inode->mapper != NULL ) , "mapper pointer is NULL\n" ); 964 965 // get pointers on directory mapper 966 mapper = inode->mapper; 967 mapper_xp = XPTR( local_cxy , mapper ); 968 969 // get extended pointers on remote child inode 970 child_xp = dentry->child_xp; 971 child_cxy = GET_CXY( child_xp ); 972 child_ptr = GET_PTR( child_xp ); 973 974 // get relevant infos from child inode 975 type = hal_remote_l32( XPTR( child_cxy , &child_ptr->type ) ); 976 size = hal_remote_l32( XPTR( child_cxy , &child_ptr->size ) ); 977 cluster = (uint32_t)(intptr_t)hal_remote_lpt( XPTR( child_cxy , &child_ptr->extend ) ); 978 979 // analyse dentry name 980 error = fatfs_name_format( dentry->name, 981 &length, 982 &nb_lfn, 983 sfn, 984 &checksum ); 985 if ( error ) 986 { 987 printk("\n[ERROR] in %s : dentry name > 31 bytes\n", __FUNCTION__ ); 988 return -1; 989 } 990 991 // Search end of directory with two embedded loops: 992 // - scan the pages in the mapper 993 // - scan the entries in each page to find NO_MORE_ENTRY 994 995 xptr_t page_xp; // extended pointer on page descriptor 996 xptr_t base_xp; // extended pointer on page base 997 uint8_t * base; // local pointer on page base (array of bytes) 998 uint32_t page_id = 0; // page index in mapper 999 uint32_t offset = 0; // position in page 1000 uint32_t found = 0; // NO_MORE_ENTRY found 1001 1002 // loop on pages in mapper 1003 while ( found == 0 ) 1004 { 1005 // get extended pointer on page descriptor in mapper 1006 page_xp = mapper_remote_get_page( mapper_xp , page_id ); 1007 1008 if ( page_xp == XPTR_NULL ) 526 1009 { 527 searched_cluster_id = first_cluster_id; 1010 printk("\n[ERROR] in %s : cannot extend directory mapper\n", __FUNCTION__ ); 1011 return -1; 528 1012 } 529 else // FAT mapper access required 1013 1014 // get pointer on page base 1015 base_xp = ppm_page2base( page_xp ); 1016 base = GET_PTR( base_xp ); 1017 1018 // loop on directory entries in this page 1019 while ( (offset < 4096) && (found == 0) ) 530 1020 { 531 // get cluster and local pointer on FAT mapper 532 xptr_t fat_mapper_xp = fatfs_ctx->fat_mapper_xp; 533 cxy_t fat_mapper_cxy = GET_CXY( fat_mapper_xp ); 534 mapper_t * fat_mapper_ptr = (mapper_t *)GET_PTR( fat_mapper_xp ); 535 536 // access FAT mapper 537 if( fat_mapper_cxy == local_cxy ) // FAT mapper is local 1021 if ( fatfs_get_record( LDIR_ORD, (base + offset), 0 ) == NO_MORE_ENTRY ) 538 1022 { 539 540 #if (DEBUG_FATFS_MOVE & 0x1) 541 if( DEBUG_FATFS_MOVE < cycle ) 542 printk("\n[DBG] %s : access local FAT mapper\n" 543 "fat_mapper_cxy = %x / fat_mapper_ptr = %x / first_cluster_id = %d / index = %d\n", 544 __FUNCTION__ , fat_mapper_cxy , fat_mapper_ptr , first_cluster_id , index ); 545 #endif 546 error = fatfs_get_cluster( fat_mapper_ptr, 547 first_cluster_id, 548 index, 549 &searched_cluster_id ); 1023 found = 1; 1024 } 1025 else 1026 { 1027 offset = offset + 32; 550 1028 } 551 else // FAT mapper is remote 1029 } // end loop on entries 1030 1031 if ( found == 0 ) 1032 { 1033 page_id++; 1034 offset = 0; 1035 } 1036 } // end loop on pages 1037 1038 // Modify the directory mapper: depending on the name length, 1039 // the new child requires to write (3, 4, or 5) directory entries. 1040 // To actually register the new child, we use a 5 steps FSM 1041 // (one state per entry to be written), that is traversed as: 1042 // LFN3 -> LFN2 -> LFN1 -> NORMAL -> NOMORE 1043 // At most two pages are modified: 1044 // - the page containing the NO_MORE_ENTRY is always modified 1045 // - the following page can be modified if the name spread on to pages. 1046 1047 char * name = dentry->name; 1048 1049 uint32_t step; // FSM state 1050 1051 if ( nb_lfn == 1 ) step = 3; 1052 else if ( nb_lfn == 2 ) step = 4; 1053 else if ( nb_lfn == 3 ) step = 5; 1054 1055 uint8_t * entry; // pointer on directory entry to be written 1056 uint32_t i; // byte index in one 32 bytes directory 1057 uint32_t c; // character index in name 1058 1059 while ( step ) 1060 { 1061 // when the new child is split on two pages, 1062 // we need to access a new page in mapper 1063 if ( offset >= 4096 ) 1064 { 1065 // copy the modified page to IOC device 1066 fatfs_move_page( page_xp , false ); 1067 1068 // get the next page in FAT mapper 1069 page_xp = mapper_remote_get_page( mapper_xp , page_id + 1 ); 1070 1071 if ( page_xp == XPTR_NULL ) 552 1072 { 553 554 #if (DEBUG_FATFS_MOVE & 0x1) 555 if( DEBUG_FATFS_MOVE < cycle ) 556 printk("\n[DBG] %s : access remote FAT mapper\n" 557 "fat_mapper_cxy = %x / fat_mapper_ptr = %x / first_cluster_id = %d / index = %d\n", 558 __FUNCTION__ , fat_mapper_cxy , fat_mapper_ptr , first_cluster_id , index ); 559 #endif 560 rpc_fatfs_get_cluster_client( fat_mapper_cxy, 561 fat_mapper_ptr, 562 first_cluster_id, 563 index, 564 &searched_cluster_id, 565 &error ); 1073 printk("\n[ERROR] in %s : cannot extend directory mapper\n", __FUNCTION__ ); 1074 return -1; 566 1075 } 567 568 if( error ) return EIO; 1076 1077 // get pointer on page base 1078 base_xp = ppm_page2base( page_xp ); 1079 base = GET_PTR( base_xp ); 1080 1081 // update offset 1082 offset = 0; 569 1083 } 570 1084 571 #if (DEBUG_FATFS_MOVE & 0x1) 572 if( DEBUG_FATFS_MOVE < cycle ) 573 printk("\n[DBG] %s : access device for inode %x / cluster_id %d\n", 574 __FUNCTION__ , inode , searched_cluster_id ); 575 #endif 576 577 // get lba from cluster_id 578 lba = fatfs_lba_from_cluster( fatfs_ctx , searched_cluster_id ); 579 580 // access device 581 if( to_mapper ) error = dev_ioc_sync_read ( buffer , lba , count ); 582 else error = dev_ioc_write( buffer , lba , count ); 583 584 if( error ) return EIO; 585 } 586 587 #if DEBUG_FATFS_MOVE 1085 // compute directory entry address 1086 entry = base + offset; 1087 1088 #if (DEBUG_FATFS_ADD_DENTRY & 1) 1089 if( DEBUG_FATFS_ADD_DENTRY < cycle ) 1090 printk("\n[%s] FSM step = %d / offset = %x / nb_lfn = %d\n", 1091 __FUNCTION__, step, offset, nb_lfn ); 1092 #endif 1093 1094 // write 32 bytes (one directory entry) per iteration 1095 switch ( step ) 1096 { 1097 case 5: // write LFN3 entry 1098 { 1099 c = 26; 1100 // scan the 32 bytes in dir_entry 1101 for ( i = 0 ; i < 32 ; i++ ) 1102 { 1103 if (i == 0) 1104 { 1105 if ( nb_lfn == 3) entry[i] = 0x43; 1106 else entry[i] = 0x03; 1107 } 1108 else if ( ( ((i >= 1 ) && (i<=10) && ((i&1)==1)) || 1109 ((i >= 14) && (i<=25) && ((i&1)==0)) || 1110 ((i >= 28) && (i<=31) && ((i&1)==0)) ) && 1111 ( c < length ) ) 1112 { 1113 entry[i] = name[c]; 1114 c++; 1115 } 1116 else if (i == 11) entry[i] = 0x0F; 1117 else if (i == 13) entry[i] = checksum; 1118 else entry[i] = 0x00; 1119 } 1120 step--; 1121 break; 1122 } 1123 case 4: // write LFN2 entry 1124 { 1125 c = 13; 1126 // scan the 32 bytes in dir_entry 1127 for ( i = 0 ; i < 32 ; i++ ) 1128 { 1129 if (i == 0) 1130 { 1131 if ( nb_lfn == 2) entry[i] = 0x42; 1132 else entry[i] = 0x02; 1133 } 1134 else if ( ( ((i >= 1 ) && (i<=10) && ((i&1)==1)) || 1135 ((i >= 14) && (i<=25) && ((i&1)==0)) || 1136 ((i >= 28) && (i<=31) && ((i&1)==0)) ) && 1137 ( c < length ) ) 1138 { 1139 entry[i] = name[c]; 1140 c++; 1141 } 1142 else if (i == 11) entry[i] = 0x0F; 1143 else if (i == 13) entry[i] = checksum; 1144 else entry[i] = 0x00; 1145 } 1146 step--; 1147 break; 1148 } 1149 case 3: // Write LFN1 entry 1150 { 1151 c = 0; 1152 // scan the 32 bytes in dir_entry 1153 for ( i = 0 ; i < 32 ; i++ ) 1154 { 1155 if (i == 0) 1156 { 1157 if ( nb_lfn == 1) entry[i] = 0x41; 1158 else entry[i] = 0x01; 1159 } 1160 else if ( ( ((i >= 1 ) && (i<=10) && ((i&1)==1)) || 1161 ((i >= 14) && (i<=25) && ((i&1)==0)) || 1162 ((i >= 28) && (i<=31) && ((i&1)==0)) ) && 1163 ( c < length ) ) 1164 { 1165 entry[i] = name[c]; 1166 c++; 1167 } 1168 else if (i == 11) entry[i] = 0x0F; 1169 else if (i == 13) entry[i] = checksum; 1170 else entry[i] = 0x00; 1171 } 1172 step--; 1173 break; 1174 } 1175 case 2: // write NORMAL entry 1176 { 1177 // scan the 32 bytes in dir_entry 1178 for ( i = 0 ; i < 32 ; i++ ) 1179 { 1180 if ( i < 11 ) // 8.3 SFN 1181 { 1182 entry[i] = sfn[i]; 1183 } 1184 else if (i == 11) // ATTR 1185 { 1186 if (type == INODE_TYPE_DIR) entry[i] = 0x10; 1187 else entry[i] = 0x20; 1188 } 1189 else if (i == 20) entry[i] = cluster>>16; // cluster.B2 1190 else if (i == 21) entry[i] = cluster>>24; // cluster.B3 1191 else if (i == 26) entry[i] = cluster>>0; // cluster.B0 1192 else if (i == 27) entry[i] = cluster>>8; // cluster.B1 1193 else if (i == 28) entry[i] = size>>0; // size.B0 1194 else if (i == 29) entry[i] = size>>8; // size.B1 1195 else if (i == 30) entry[i] = size>>16; // size.B2 1196 else if (i == 31) entry[i] = size>>24; // size.B3 1197 else entry[i] = 0x00; 1198 } 1199 1200 // update the "extend" field in dentry descriptor 1201 dentry->extend = (void*)(intptr_t)(((page_id<<12) + offset)>>5); 1202 1203 step--; 1204 break; 1205 } 1206 case 1: // write NOMORE entry 1207 { 1208 entry [0] = 0x00; 1209 step--; 1210 break; 1211 } 1212 } // end switch step 1213 1214 offset += 32; 1215 1216 } // exit while 1217 1218 // copy the modified page to the IOC device 1219 fatfs_move_page( page_xp , false ); 1220 1221 #if DEBUG_FATFS_ADD_DENTRY 588 1222 cycle = (uint32_t)hal_get_cycles(); 589 if( DEBUG_FATFS_MOVE < cycle ) 590 printk("\n[DBG] %s : thread %x exit / page %d / inode %x / mapper %x / cycle %d\n", 591 __FUNCTION__ , CURRENT_THREAD , index , inode , mapper , cycle ); 592 #endif 593 594 #if (DEBUG_FATFS_MOVE & 0x1) 595 if( DEBUG_FATFS_MOVE < cycle ) 596 { 597 uint32_t * tab = (uint32_t *)buffer; 598 uint32_t line , word; 599 printk("\n***** %s : First 64 words of loaded page\n", __FUNCTION__ ); 600 for( line = 0 ; line < 8 ; line++ ) 601 { 602 printk("%X : ", line ); 603 for( word = 0 ; word < 8 ; word++ ) printk("%X ", tab[(line<<3) + word] ); 604 printk("\n"); 605 } 606 } 1223 if( DEBUG_FATFS_ADD_DENTRY < cycle ) 1224 printk("\n[%s] thread[%x,%x] exit / parent %s / child %s / cycle %d\n", 1225 __FUNCTION__, this->process->pid, this->trdid, dir_name, dentry->name, cycle ); 607 1226 #endif 608 1227 609 1228 return 0; 610 1229 611 } // end fatfs_mapper_move_page() 612 613 ///////////////////////////////////////////////////// 614 error_t fatfs_inode_load( vfs_inode_t * parent_inode, 1230 } // end fatfs_add_dentry() 1231 1232 ////////////////////////////////////////////////// 1233 error_t fatfs_remove_dentry( vfs_inode_t * inode, 1234 vfs_dentry_t * dentry ) 1235 { 1236 xptr_t mapper_xp; // extended pointer on mapper 1237 mapper_t * mapper; // local pointer on mapper 1238 xptr_t page_xp; // extended pointer on mapper page descriptor 1239 xptr_t base_xp; // extended pointer on mapper page base 1240 uint8_t * base; // local pointer on mapper page base 1241 1242 #if DEBUG_FATFS_REMOVE_DENTRY 1243 char dir_name[CONFIG_VFS_MAX_NAME_LENGTH]; 1244 uint32_t cycle = (uint32_t)hal_get_cycles(); 1245 thread_t * this = CURRENT_THREAD; 1246 vfs_inode_get_name( XPTR( local_cxy , inode ) , dir_name ); 1247 if( DEBUG_FATFS_REMOVE_DENTRY < cycle ) 1248 printk("\n[%s] thread[%x,%x] enter / parent <%s> / child <%s> / cycle %d\n", 1249 __FUNCTION__, this->process->pid, this->trdid, dir_name, dentry->name, cycle ); 1250 #endif 1251 1252 // check arguments 1253 assert( (inode != NULL) , "inode pointer is NULL\n" ); 1254 assert( (dentry != NULL) , "dentry pointer is NULL\n" ); 1255 assert( (inode->type == INODE_TYPE_DIR) , "inode is not a directory\n" ); 1256 assert( (inode->mapper != NULL ) , "mapper pointer is NULL\n" ); 1257 1258 // get pointers on directory mapper 1259 mapper = inode->mapper; 1260 mapper_xp = XPTR( local_cxy , mapper ); 1261 1262 // compute number of LFN entries 1263 uint32_t nb_lfn; 1264 uint32_t name_length = strlen( dentry->name ); 1265 1266 if ( name_length <= 13 ) nb_lfn = 1; 1267 else if ( name_length <= 26 ) nb_lfn = 2; 1268 else nb_lfn = 3; 1269 1270 // we must invalidate (2, 3 or 4) 32 bytes entries: 1271 // the NORMAL entry (registered in dentry->extend) and all preceding LFN entries 1272 // At most two pages are modified: 1273 // - the page containing the NORMAL entry is always modified. 1274 // - the preceding page is modified when the name spread on two pages. 1275 1276 // get 32 bytes directory entry index from dentry->extend 1277 uint32_t dentry_id = (uint32_t)(intptr_t)dentry->extend; 1278 1279 // get page index and offset in parent directory mapper 1280 uint32_t page_id = dentry_id >> 7; 1281 uint32_t offset = (dentry_id & 0x7F)<<5; 1282 1283 // get extended pointer on page descriptor from parent directory mapper 1284 page_xp = mapper_remote_get_page( mapper_xp , page_id ); 1285 1286 if ( page_xp == XPTR_NULL ) 1287 { 1288 printk("\n[ERROR] in %s : cannot extend directory mapper\n", __FUNCTION__ ); 1289 return -1; 1290 } 1291 1292 // get pointers on page base 1293 base_xp = ppm_page2base( page_xp ); 1294 base = GET_PTR( base_xp ); 1295 1296 // invalidate NORMAL entry in directory cache 1297 base[offset] = 0xE5; 1298 1299 // invalidate LFN entries 1300 while ( nb_lfn ) 1301 { 1302 if (offset == 0) // we must load page (page_id - 1) 1303 { 1304 1305 // check page_id 1306 assert( (page_id > 0), "page_id and offset cannot be both 0\n" ); 1307 1308 // copy the modified page to the IOC device 1309 fatfs_move_page( page_xp , false ); 1310 1311 // get extended pointer on page descriptor from parent directory mapper 1312 page_xp = mapper_remote_get_page( mapper_xp , page_id ); 1313 1314 if ( page_xp == XPTR_NULL ) 1315 { 1316 printk("\n[ERROR] in %s : cannot access directory mapper\n", __FUNCTION__ ); 1317 return -1; 1318 } 1319 1320 // get pointers on page base 1321 base_xp = ppm_page2base( page_xp ); 1322 base = GET_PTR( base_xp ); 1323 1324 // update offset 1325 offset = 4096; 1326 } 1327 1328 offset = offset - 32; 1329 1330 // check for LFN entry 1331 assert( (fatfs_get_record( DIR_ATTR, base + offset, 0 ) == ATTR_LONG_NAME_MASK ), 1332 "this directory entry must be a LFN\n"); 1333 1334 // invalidate LFN entry 1335 base[offset] = 0xE5; 1336 1337 nb_lfn--; 1338 } 1339 1340 // copy the modified page to the IOC device 1341 fatfs_move_page( page_xp , false ); 1342 1343 1344 #if DEBUG_FATFS_REMOVE_DENTRY 1345 cycle = (uint32_t)hal_get_cycles(); 1346 if( DEBUG_FATFS_REMOVE_DENTRY < cycle ) 1347 printk("\n[%s] thread[%x,%x] exit / parent %s / child %s / cycle %d\n", 1348 __FUNCTION__, this->process->pid, this->trdid, dir_name, dentry->name, cycle ); 1349 #endif 1350 1351 return 0; 1352 1353 } // end fatfs_remove_dentry 1354 1355 //////////////////////////////////////////////////////////////// 1356 error_t fatfs_child_init( vfs_inode_t * parent_inode, 615 1357 char * name, 616 1358 xptr_t child_inode_xp ) 617 1359 { 618 1360 // Two embedded loops: 619 // - scan the parent mapper pages1361 // - scan the parent directory mapper pages 620 1362 // - scan the directory entries in each 4 Kbytes page 621 1363 622 #if DEBUG_FATFS_LOAD 623 uint32_t cycle = (uint32_t)hal_get_cycles(); 624 if( DEBUG_FATFS_LOAD < cycle ) 625 printk("\n[DBG] %s : thread %x enter for child <%s> in parent inode %x / cycle %d\n", 626 __FUNCTION__ , CURRENT_THREAD , name , parent_inode , cycle ); 627 #endif 628 629 mapper_t * mapper = parent_inode->mapper; 630 631 assert( (mapper != NULL) , "parent mapper undefined\n"); 1364 #if DEBUG_FATFS_CHILD_INIT 1365 char parent_name[CONFIG_VFS_MAX_NAME_LENGTH]; 1366 uint32_t cycle = (uint32_t)hal_get_cycles(); 1367 thread_t * this = CURRENT_THREAD; 1368 vfs_inode_get_name( XPTR( local_cxy , parent_inode ) , parent_name ); 1369 if( DEBUG_FATFS_CHILD_INIT < cycle ) 1370 printk("\n[%s] thread[%x,%x] enter for child <%s> in parent <%s> / cycle %d\n", 1371 __FUNCTION__, this->process->pid, this->trdid, name , parent_name , cycle ); 1372 #endif 1373 1374 // check parent_inode and child_inode 1375 assert( (parent_inode != NULL) , "parent_inode is NULL\n" ); 1376 assert( (child_inode_xp != XPTR_NULL ) , "child_inode is XPTR_NULL\n" ); 1377 1378 mapper_t * mapper = parent_inode->mapper; 1379 xptr_t mapper_xp = XPTR( local_cxy , mapper ); 1380 1381 // check parent mapper 1382 assert( (mapper != NULL) , "parent mapper is NULL\n"); 632 1383 633 1384 char cname[CONFIG_VFS_MAX_NAME_LENGTH]; // name extracter from each directory entry … … 636 1387 char lfn2[16]; // buffer for one partial cname 637 1388 char lfn3[16]; // buffer for one partial cname 638 page_t * page; // pointer on current page descriptor 639 uint8_t * base; // pointer on current page base 640 uint32_t offset = 0; // byte offset in page 641 uint32_t index = 0; // page index in mapper 1389 xptr_t page_xp; // extended pointer on page descriptor 1390 xptr_t base_xp; // extended pointer on page base 1391 uint8_t * base; // local pointer on page base 642 1392 uint32_t attr; // directory entry ATTR field 643 1393 uint32_t ord; // directory entry ORD field 644 1394 uint32_t seq; // sequence index 645 uint32_t lfn = 0; // LFN entries number 646 uint32_t size = 0; // searched file/dir size (bytes) 647 uint32_t cluster = 0; // searched file/dir cluster index 648 uint32_t is_dir = 0; // searched file/dir type 649 uint32_t dentry; // directory entry index 650 int32_t found = 0; // not found (0) / name found (1) / end of dir (-1) 1395 uint32_t lfn = 0; // LFN entries number 1396 uint32_t size = 0; // searched file/dir size (bytes) 1397 uint32_t cluster = 0; // searched file/dir cluster index 1398 uint32_t is_dir = 0; // searched file/dir type 1399 int32_t found = 0; // not found (0) / name found (1) / end of dir (-1) 1400 uint32_t page_id = 0; // page index in mapper 1401 uint32_t dentry_id = 0; // directory entry index 1402 uint32_t offset = 0; // byte offset in page 651 1403 652 1404 // scan the parent directory mapper … … 654 1406 { 655 1407 // get one page 656 page = mapper_get_page( mapper , index);657 658 assert( (page != NULL) , "bad parent mapper\n");1408 page_xp = mapper_remote_get_page( mapper_xp , page_id ); 1409 1410 if( page_xp == XPTR_NULL) return EIO; 659 1411 660 1412 // get page base 661 xptr_t base_xp = ppm_page2base( XPTR( local_cxy , page ));662 base = (uint8_t *)GET_PTR( base_xp );663 664 #if (DEBUG_FATFS_ LOAD& 0x1)665 if( DEBUG_FATFS_ LOAD< cycle )1413 base_xp = ppm_page2base( page_xp ); 1414 base = (uint8_t *)GET_PTR( base_xp ); 1415 1416 #if (DEBUG_FATFS_CHILD_INIT & 0x1) 1417 if( DEBUG_FATFS_CHILD_INIT < cycle ) 666 1418 { 667 1419 uint32_t * buf = (uint32_t *)base; 668 1420 uint32_t line , word; 669 printk("\n ***** %s : First 16 dentries for parent inode %x\n",670 __FUNCTION__ , parent_ inode );1421 printk("\n[%s] First 16 dentries for <%s>\n", 1422 __FUNCTION__ , parent_name ); 671 1423 for( line = 0 ; line < 16 ; line++ ) 672 1424 { … … 728 1480 cluster = (fatfs_get_record( DIR_FST_CLUS_HI , base + offset , 1 ) << 16) | 729 1481 (fatfs_get_record( DIR_FST_CLUS_LO , base + offset , 1 ) ) ; 730 dentry = ((index<<12) + offset)>>5;731 is_dir = ((attr & ATTR_DIRECTORY) == ATTR_DIRECTORY);732 size = fatfs_get_record( DIR_FILE_SIZE , base + offset , 1 );733 found = 1;1482 dentry_id = ((page_id<<12) + offset)>>5; 1483 is_dir = ((attr & ATTR_DIRECTORY) == ATTR_DIRECTORY); 1484 size = fatfs_get_record( DIR_FILE_SIZE , base + offset , 1 ); 1485 found = 1; 734 1486 } 735 1487 offset = offset + 32; 736 1488 lfn = 0; 737 1489 } 738 } // end loop on directory entries 739 index++; 1490 } // end loop on directory entries in page 1491 1492 page_id++; 740 1493 offset = 0; 1494 741 1495 } // end loop on pages 742 1496 … … 746 1500 { 747 1501 748 #if DEBUG_FATFS_ LOAD1502 #if DEBUG_FATFS_CHILD_INIT 749 1503 cycle = (uint32_t)hal_get_cycles(); 750 if( DEBUG_FATFS_LOAD < cycle ) 751 printk("\n[DBG] %s : thread %x exit / child <%s> not found / cycle %d\n", 752 __FUNCTION__ , CURRENT_THREAD, name, cycle ); 753 #endif 754 755 return ENOENT; 756 } 757 else // found searched child name 758 { 759 // get child inode cluster and local pointer 760 cxy_t child_cxy = GET_CXY( child_inode_xp ); 761 vfs_inode_t * child_ptr = (vfs_inode_t *)GET_PTR( child_inode_xp ); 762 763 // update the child inode "type", "size", and "extend" fields 764 vfs_inode_type_t type = (is_dir) ? INODE_TYPE_DIR : INODE_TYPE_FILE; 765 766 hal_remote_s32( XPTR( child_cxy , &child_ptr->type ) , type ); 767 hal_remote_s32( XPTR( child_cxy , &child_ptr->size ) , size ); 768 hal_remote_s32( XPTR( child_cxy , &child_ptr->extend ) , cluster ); 769 770 #if DEBUG_FATFS_LOAD 1504 if( DEBUG_FATFS_CHILD_INIT < cycle ) 1505 printk("\n[%s] thread[%x,%x] exit / child <%s> not found / cycle %d\n", 1506 __FUNCTION__, this->process->pid, this->trdid, name, cycle ); 1507 #endif 1508 1509 return -1; 1510 } 1511 1512 // get child inode cluster and local pointer 1513 cxy_t inode_cxy = GET_CXY( child_inode_xp ); 1514 vfs_inode_t * inode_ptr = (vfs_inode_t *)GET_PTR( child_inode_xp ); 1515 1516 // get dentry pointers and cluster 1517 xptr_t dentry_xp = hal_remote_l64( XPTR( inode_cxy , &inode_ptr->parent_xp ) ); 1518 vfs_dentry_t * dentry_ptr = GET_PTR( dentry_xp ); 1519 cxy_t dentry_cxy = GET_CXY( dentry_xp ); 1520 1521 // dentry descriptor must be in same cluster as parent inode 1522 assert( (dentry_cxy == local_cxy) , "illegal dentry cluster\n" ); 1523 1524 // update the child inode "type", "size", and "extend" fields 1525 vfs_inode_type_t type = (is_dir) ? INODE_TYPE_DIR : INODE_TYPE_FILE; 1526 1527 hal_remote_s32( XPTR( inode_cxy , &inode_ptr->type ) , type ); 1528 hal_remote_s32( XPTR( inode_cxy , &inode_ptr->size ) , size ); 1529 hal_remote_s32( XPTR( inode_cxy , &inode_ptr->extend ) , cluster ); 1530 1531 // update the dentry "extend" field 1532 dentry_ptr->extend = (void *)(intptr_t)dentry_id; 1533 1534 #if DEBUG_FATFS_CHILD_INIT 771 1535 cycle = (uint32_t)hal_get_cycles(); 772 if( DEBUG_FATFS_LOAD < cycle ) 773 printk("\n[DBG] %s : thread %x exit / child <%s> loaded / cycle %d\n", 774 __FUNCTION__ , CURRENT_THREAD, name, cycle ); 775 #endif 776 777 return 0; 778 } 779 } // end fatfs_inode_load() 1536 if( DEBUG_FATFS_CHILD_INIT < cycle ) 1537 printk("\n[%s] thread[%x,%x] exit / child <%s> loaded in <%s> / cycle %d\n", 1538 __FUNCTION__, this->process->pid, this->trdid, name, parent_name, cycle ); 1539 #endif 1540 1541 return 0; 1542 1543 } // end fatfs_child_init() 1544 1545 /////////////////////////////////////////////// 1546 error_t fatfs_sync_inode( vfs_inode_t * inode ) 1547 { 1548 1549 // check inode pointer and cluster index 1550 assert( (inode != NULL) , "inode pointer undefined\n" ); 1551 assert( (inode->mapper != NULL ) , "mapper pointer undefined\n" ); 1552 assert( (inode->type == INODE_TYPE_FILE) , "inode must be a file\n" ); 1553 1554 #if DEBUG_FATFS_SYNC_INODE 1555 char name[CONFIG_VFS_MAX_NAME_LENGTH]; 1556 uint32_t cycle = (uint32_t)hal_get_cycles(); 1557 thread_t * this = CURRENT_THREAD; 1558 vfs_inode_get_name( XPTR( local_cxy , inode ) , name ); 1559 if( DEBUG_FATFS_SYNC_INODE < cycle ) 1560 printk("\n[%s] thread[%x,%x] enter for <%s> / cycle %d\n", 1561 __FUNCTION__ , this->process->pid, this->trdid, name, cycle ); 1562 #endif 1563 1564 error_t error; 1565 mapper_t * mapper; 1566 page_t * page; 1567 uint32_t page_id; 1568 1569 // get mapper from inode 1570 mapper = inode->mapper; 1571 1572 // compute max number of pages in mapper from file size 1573 uint32_t size = inode->size; 1574 uint32_t pages = size >> CONFIG_PPM_PAGE_SHIFT; 1575 if( size & CONFIG_PPM_PAGE_MASK ) pages++; 1576 1577 // get pointer on mapper radix tree 1578 grdxt_t * rt = &mapper->rt; 1579 1580 // scan all pages 1581 for( page_id = 0 ; page_id < pages ; page_id++ ) 1582 { 1583 // get page descriptor from mapper 1584 page = grdxt_lookup( rt , page_id ); 1585 1586 // check all existing pages 1587 if ( page != NULL ) 1588 { 1589 if ( page->flags & PG_DIRTY ) 1590 { 1591 1592 #if (DEBUG_FATFS_SYNC_INODE & 1) 1593 if( DEBUG_FATFS_SYNC_INODE < cycle ) 1594 printk("\n[%s] thread[%x,%x] synchronizes page %d from <%s> mapper to IOC device\n", 1595 __FUNCTION__, page_id, name ); 1596 #endif 1597 // build extended pointer on page descriptor 1598 xptr_t page_xp = XPTR( local_cxy , page ); 1599 1600 // move page from mapper to device 1601 error = fatfs_move_page( page_xp , false ); 1602 1603 if ( error ) return -1; 1604 1605 // reset page dirty flag 1606 ppm_page_undo_dirty( page_xp ); 1607 } 1608 } 1609 } // end loop on pages 1610 1611 #if DEBUG_FATFS_SYNC_INODE 1612 cycle = (uint32_t)hal_get_cycles(); 1613 if( DEBUG_FATFS_SYNC_INODE < cycle ) 1614 printk("\n[%s] thread[%x,%x] exit for <%s> / cycle %d\n", 1615 __FUNCTION__ , this->process->pid, this->trdid, name, cycle ); 1616 #endif 1617 1618 return 0; 1619 1620 } // end fatfs_sync_inode() 1621 1622 ////////////////////////////// 1623 error_t fatfs_sync_fat( void ) 1624 { 1625 1626 #if DEBUG_FATFS_SYNC_FAT 1627 uint32_t cycle = (uint32_t)hal_get_cycles(); 1628 thread_t * this = CURRENT_THREAD; 1629 if( DEBUG_FATFS_SYNC_FAT < cycle ) 1630 printk("\n[%s] thread[%x,%x] enter / cycle %d\n", 1631 __FUNCTION__ , this->process->pid, this->trdid, cycle ); 1632 #endif 1633 1634 uint32_t page_id; 1635 error_t error; 1636 1637 // get FAT mapper pointers an cluster 1638 fatfs_ctx_t * fatfs_ctx = fs_context[FS_TYPE_FATFS].extend; 1639 xptr_t mapper_xp = fatfs_ctx->fat_mapper_xp; 1640 cxy_t mapper_cxy = GET_CXY( mapper_xp ); 1641 mapper_t * mapper_ptr = GET_PTR( mapper_xp ); 1642 1643 // compute max number of 4 Kbytes pages in FAT mapper 1644 // TODO : this could be improved (see fatfs.h) [AG] 1645 uint32_t pages = fatfs_ctx->fat_sectors_count >> 3; 1646 1647 // get pointers on remote FAT mapper radix tree 1648 grdxt_t * rt_ptr = &mapper_ptr->rt; 1649 xptr_t rt_xp = XPTR( mapper_cxy , rt_ptr ); 1650 1651 // scan all pages 1652 for( page_id = 0 ; page_id < pages ; page_id++ ) 1653 { 1654 // get extended pointer on page descriptor from FAT mapper 1655 xptr_t page_xp = grdxt_remote_lookup( rt_xp , page_id ); 1656 1657 // check all existing pages 1658 if ( page_xp != XPTR_NULL ) 1659 { 1660 page_t * page_ptr = GET_PTR( page_xp ); 1661 uint32_t flags = hal_remote_l32( XPTR( mapper_cxy , &page_ptr->flags ) ); 1662 1663 if ( flags & PG_DIRTY ) 1664 { 1665 1666 #if (DEBUG_FATFS_SYNC_FAT & 1) 1667 if( DEBUG_FATFS_SYNC_FAT < cycle ) 1668 printk("\n[%s] thread[%x,%x] synchronizes page %d from FAT mapper to IOC device\n", 1669 __FUNCTION__, page_id ); 1670 #endif 1671 // move page from mapper to device 1672 error = fatfs_move_page( page_xp , false ); 1673 1674 if ( error ) return -1; 1675 1676 // reset page dirty flag 1677 ppm_page_undo_dirty( page_xp ); 1678 } 1679 } 1680 } // end loop on pages 1681 1682 #if DEBUG_FATFS_SYNC_FAT 1683 cycle = (uint32_t)hal_get_cycles(); 1684 if( DEBUG_FATFS_SYNC_FAT < cycle ) 1685 printk("\n[%s] thread[%x,%x] exit / cycle %d\n", 1686 __FUNCTION__ , this->process->pid, this->trdid, cycle ); 1687 #endif 1688 1689 return 0; 1690 1691 } // end fatfs_sync_fat() 1692 1693 //////////////////////////////////// 1694 error_t fatfs_sync_free_info( void ) 1695 { 1696 1697 #if DEBUG_FATFS_SYNC_FSINFO 1698 uint32_t cycle = (uint32_t)hal_get_cycles(); 1699 thread_t * this = CURRENT_THREAD; 1700 if( DEBUG_FATFS_SYNC_FSINFO < cycle ) 1701 printk("\n[%s] thread[%x,%x] enter / cycle %d\n", 1702 __FUNCTION__ , this->process->pid, this->trdid, cycle ); 1703 #endif 1704 1705 uint8_t * buffer; // dynamically allocated aligned 512 bytes buffer 1706 kmem_req_t req; 1707 error_t error; 1708 1709 // get FS_INFO lba, free_ from FATFS context 1710 fatfs_ctx_t * fatfs_ctx = fs_context[FS_TYPE_FATFS].extend; 1711 uint32_t lba = fatfs_ctx->fs_info_lba; 1712 uint32_t hint = fatfs_ctx->free_cluster_hint; 1713 uint32_t number = fatfs_ctx->free_clusters; 1714 1715 // allocate buffer to store the FS_INFO sector 1716 req.type = KMEM_512_BYTES; 1717 req.flags = AF_KERNEL | AF_ZERO; 1718 buffer = (uint8_t *)kmem_alloc( &req ); 1719 if( buffer == NULL ) 1720 { 1721 printk("\n[PANIC] in %s : cannot allocate buffer\n", __FUNCTION__ ); 1722 return ENOMEM; 1723 } 1724 1725 // load the FS_INFO sector from device to buffer 1726 error = dev_ioc_read( buffer , lba , 1 ); 1727 if ( error ) 1728 { 1729 printk("\n[PANIC] in %s : cannot read FS_INFO record\n", __FUNCTION__ ); 1730 return EIO; 1731 } 1732 1733 // update buffer 1734 fatfs_set_record( FS_FREE_CLUSTERS , buffer , 1 , number ); 1735 fatfs_set_record( FS_FREE_CLUSTER_HINT , buffer , 1 , hint ); 1736 1737 // write modified FS_INFO sector from buffer to device 1738 error = dev_ioc_write( buffer , lba , 1 ); 1739 if ( error ) 1740 { 1741 printk("\n[PANIC] in %s : cannot write FS_INFO record\n", __FUNCTION__ ); 1742 return EIO; 1743 } 1744 1745 // release the 512 bytes buffer 1746 req.type = KMEM_512_BYTES; 1747 req.ptr = buffer; 1748 kmem_free( &req ); 1749 1750 #if DEBUG_FATFS_SYNC_FSINFO 1751 cycle = (uint32_t)hal_get_cycles(); 1752 if( DEBUG_FATFS_SYNC_FSINFO < cycle ) 1753 printk("\n[%s] thread[%x,%x] exit / cycle %d\n", 1754 __FUNCTION__ , this->process->pid, this->trdid, cycle ); 1755 #endif 1756 1757 return 0; 1758 1759 } // end fatfs_sync_fs_info() 1760 1761 ////////////////////////////////////////////////////////// 1762 error_t fatfs_cluster_alloc( uint32_t * searched_cluster ) 1763 { 1764 uint32_t page_id; // page index in mapper 1765 uint32_t slot_id; // slot index in page (1024 slots per page) 1766 uint32_t hint; // first free cluster index in FAT 1767 uint32_t free_clusters; // total number of free clusters 1768 vfs_ctx_t * vfs_ctx; // local pointer on VFS context (same in all clusters) 1769 fatfs_ctx_t * loc_fatfs_ctx; // local pointer on local FATFS context 1770 fatfs_ctx_t * fat_fatfs_ctx; // local pointer on FATFS context in FAT cluster 1771 xptr_t mapper_xp; // extended pointer on FAT mapper 1772 cxy_t mapper_cxy; // Fat mapper cluster identifier 1773 xptr_t page_xp; // extended pointer on current page descriptor in mapper 1774 xptr_t slot_xp; // extended pointer on FAT slot defined by hint 1775 xptr_t lock_xp; // extended pointer on lock protecting free clusters info 1776 xptr_t hint_xp; // extended pointer on free_cluster_hint in FAT cluster 1777 xptr_t numb_xp; // extended pointer on free_clusters_number in FAT cluster 1778 1779 #if DEBUG_FATFS_CLUSTER_ALLOC 1780 uint32_t cycle = (uint32_t)hal_get_cycles(); 1781 thread_t * this = CURRENT_THREAD; 1782 if( DEBUG_FATFS_CLUSTER_ALLOC < cycle ) 1783 printk("\n[%s] thread[%x,%x] enter / cycle = %d\n", 1784 __FUNCTION__, this->process->pid, this->trdid, cycle ); 1785 #endif 1786 1787 // get local pointer on VFS context (same in all clusters) 1788 vfs_ctx = &fs_context[FS_TYPE_FATFS]; 1789 1790 // get local pointer on local FATFS context 1791 loc_fatfs_ctx = vfs_ctx->extend; 1792 1793 // get extended pointer and cluster on FAT mapper 1794 mapper_xp = loc_fatfs_ctx->fat_mapper_xp; 1795 mapper_cxy = GET_CXY( mapper_xp ); 1796 1797 // get local pointer on FATFS context in FAT cluster 1798 fat_fatfs_ctx = hal_remote_lpt( XPTR( mapper_cxy , &vfs_ctx->extend ) ); 1799 1800 // build relevant extended pointers in on free clusters info in FAT cluster 1801 lock_xp = XPTR( mapper_cxy , &fat_fatfs_ctx->free_lock ); 1802 hint_xp = XPTR( mapper_cxy , &fat_fatfs_ctx->free_cluster_hint ); 1803 numb_xp = XPTR( mapper_cxy , &fat_fatfs_ctx->free_clusters ); 1804 1805 // take the lock protecting free clusters 1806 remote_queuelock_acquire( lock_xp ); 1807 1808 // get hint and free_clusters values from FATFS context 1809 hint = hal_remote_l32( hint_xp ); 1810 free_clusters = hal_remote_l32( numb_xp ); 1811 1812 // get page index & slot index for the first free cluster 1813 page_id = (hint + 1) >> 10; 1814 slot_id = (hint + 1) & 0x3FF; 1815 1816 // get relevant page from mapper 1817 page_xp = mapper_remote_get_page( mapper_xp , page_id ); 1818 1819 if( page_xp == XPTR_NULL ) 1820 { 1821 printk("\n[ERROR] in %s : cannot acces FAT mapper\n", __FUNCTION__ ); 1822 return -1; 1823 } 1824 1825 // build extended pointer on free cluster slot 1826 slot_xp = ppm_page2base( page_xp ) + (slot_id<<2); 1827 1828 #if (DEBUG_FATFS_CLUSTER_ALLOC & 1) 1829 if( DEBUG_FATFS_CLUSTER_ALLOC < cycle ) 1830 printk("\n[%s] thread[%x,%x] get free info / hint %x / free_clusters %x\n", 1831 __FUNCTION__, this->process->pid, this->trdid, hint, free_clusters ); 1832 #endif 1833 1834 // check "free_clusters" 1835 if ( free_clusters == 0 ) 1836 { 1837 printk("\n[ERROR] in %s : no more free FATFS clusters\n", __FUNCTION__ ); 1838 remote_queuelock_acquire( lock_xp ); 1839 return -1; 1840 } 1841 else if ( free_clusters < CONFIG_VFS_FREE_CLUSTERS_MIN ) 1842 { 1843 printk("\n[WARNING] in %s : only %n free FATFS clusters\n", 1844 __FUNCTION__, CONFIG_VFS_FREE_CLUSTERS_MIN ); 1845 } 1846 1847 // check "hint" 1848 if( hal_remote_l32( slot_xp ) != FREE_CLUSTER ) 1849 { 1850 printk("\n[ERROR] in %s : illegal hint cluster\n", __FUNCTION__ ); 1851 remote_queuelock_acquire( lock_xp ); 1852 return -1; 1853 } 1854 1855 // update allocated cluster in FAT mapper 1856 hal_remote_s32( slot_xp , END_OF_CHAIN_CLUSTER_MAX ); 1857 1858 // update free cluster info 1859 fatfs_free_clusters_decrement( hint + 1 ); 1860 1861 // release free clusters busylock 1862 remote_queuelock_release( lock_xp ); 1863 1864 #if DEBUG_FATFS_CLUSTER_ALLOC 1865 cycle = (uint32_t)hal_get_cycles(); 1866 if( DEBUG_FATFS_CLUSTER_ALLOC < cycle ) 1867 printk("\n[%s] thread[%x,%x] exit / cluster %x / cycle %d\n", 1868 __FUNCTION__, this->process->pid, this->trdid, hint + 1, cycle ); 1869 #endif 1870 1871 *searched_cluster = hint + 1; 1872 return 0; 1873 1874 } // end fat_cluster_alloc() 1875 1876 ////////////////////////////////////////////// 1877 error_t fatfs_release_inode( xptr_t inode_xp ) 1878 { 1879 vfs_ctx_t * vfs_ctx; // local pointer on VFS context (same in all clusters). 1880 fatfs_ctx_t * loc_fatfs_ctx; // local pointer on local FATFS context 1881 fatfs_ctx_t * fat_fatfs_ctx; // local pointer on FATFS context in FAT cluster 1882 xptr_t mapper_xp; // extended pointer on FAT mapper 1883 cxy_t mapper_cxy; // Fat mapper cluster identifier 1884 xptr_t lock_xp; // extended pointer on lock protecting free clusters info. 1885 xptr_t first_xp; // extended pointer on inode extension 1886 uint32_t first_cluster; // first cluster index for released inode 1887 vfs_inode_t * inode_ptr; 1888 cxy_t inode_cxy; 1889 1890 // check inode pointer 1891 assert( (inode_xp != XPTR_NULL) , "inode pointer is NULL\n" ); 1892 1893 // get first_cluster from inode extension 1894 inode_ptr = GET_PTR( inode_xp ); 1895 inode_cxy = GET_CXY( inode_xp ); 1896 first_xp = XPTR( inode_cxy , &inode_ptr->extend ); 1897 first_cluster = (uint32_t)(intptr_t)hal_remote_lpt( first_xp ); 1898 1899 // check first cluster index 1900 assert( (first_cluster != 0) , "inode extend is NULL\n" ); 1901 1902 #if DEBUG_FATFS_RELEASE_INODE 1903 char name[CONFIG_VFS_MAX_NAME_LENGTH]; 1904 uint32_t cycle = (uint32_t)hal_get_cycles(); 1905 thread_t * this = CURRENT_THREAD; 1906 vfs_inode_get_name( inode_xp , name ); 1907 if( DEBUG_FATFS_RELEASE_INODE < cycle ) 1908 printk("\n[%s] thread[%x,%x] enter for <%s> / first_cluster %x / cycle %d\n", 1909 __FUNCTION__ , this->process->pid, this->trdid, name, first_cluster, cycle ); 1910 #endif 1911 1912 // get local pointer on VFS context (same in all clusters) 1913 vfs_ctx = &fs_context[FS_TYPE_FATFS]; 1914 1915 // get local pointer on local FATFS context 1916 loc_fatfs_ctx = vfs_ctx->extend; 1917 1918 // get extended pointer and cluster on FAT mapper 1919 mapper_xp = loc_fatfs_ctx->fat_mapper_xp; 1920 mapper_cxy = GET_CXY( mapper_xp ); 1921 1922 // get local pointer on FATFS context in FAT cluster 1923 fat_fatfs_ctx = hal_remote_lpt( XPTR( mapper_cxy , &vfs_ctx->extend ) ); 1924 1925 // get extended pointer on free clusters lock in FAT cluster 1926 lock_xp = XPTR( mapper_cxy , &fat_fatfs_ctx->free_lock ); 1927 1928 // take lock protecting free clusters 1929 remote_queuelock_acquire( lock_xp ); 1930 1931 // call the recursive function to release all clusters from FAT mapper 1932 if ( fatfs_recursive_release( mapper_xp , first_cluster ) ) 1933 { 1934 printk("\n[ERROR] in %s : cannot update FAT mapper\n", __FUNCTION__ ); 1935 remote_queuelock_release( lock_xp ); 1936 return -1; 1937 } 1938 1939 // release lock protecting free cluster 1940 remote_queuelock_release( lock_xp ); 1941 1942 #if (DEBUG_FATFS_RELEASE_INODE & 1) 1943 if( DEBUG_FATFS_RELEASE_INODE < cycle ) 1944 printk("\n[%s] inode <%s> removed from FAT mapper\n", __FUNCTION__, name ); 1945 #endif 1946 1947 // update FAT on IOC device (from FAT mapper) 1948 if ( fatfs_sync_fat() ) 1949 { 1950 printk("\n[ERROR] in %s : cannot update FAT on device\n", __FUNCTION__ ); 1951 return -1; 1952 } 1953 1954 #if (DEBUG_FATFS_RELEASE_INODE & 1) 1955 if( DEBUG_FATFS_RELEASE_INODE < cycle ) 1956 printk("\n[%s] inode <%s> removed from FAT on IOC device\n", __FUNCTION__, name ); 1957 #endif 1958 1959 // update FS-INFO sector on IOC device (from FATFS context) 1960 if ( fatfs_sync_free_info() ) 1961 { 1962 printk("\n[ERROR] in %s: cannot update FS_INFO on device\n", __FUNCTION__ ); 1963 return -1; 1964 } 1965 1966 #if DEBUG_FATFS_RELEASE_INODE 1967 cycle = (uint32_t)hal_get_cycles(); 1968 if( DEBUG_FATFS_RELEASE_INODE < cycle ) 1969 printk("\n[%s] thread[%x,%x] removed <%s> inode from FATFS / cycle %d\n", 1970 __FUNCTION__ , this->process->pid, this->trdid, name, cycle ); 1971 #endif 1972 1973 return 0; 1974 1975 } // end fatfs_release_inode() 1976 1977 ///////////////////////////////////////// 1978 error_t fatfs_move_page( xptr_t page_xp, 1979 bool_t to_mapper ) 1980 { 1981 error_t error; 1982 vfs_inode_t * inode_ptr; 1983 mapper_t * mapper_ptr; 1984 uint32_t page_id; // page index in mapper 1985 1986 #if DEBUG_FATFS_MOVE_PAGE 1987 uint32_t cycle = (uint32_t)hal_get_cycles(); 1988 thread_t * this = CURRENT_THREAD; 1989 char name[CONFIG_VFS_MAX_NAME_LENGTH]; 1990 #endif 1991 1992 // get page cluster an local pointer 1993 cxy_t page_cxy = GET_CXY( page_xp ); 1994 page_t * page_ptr = GET_PTR( page_xp ); 1995 1996 // get mapper pointer and page index from page descriptor 1997 mapper_ptr = hal_remote_lpt( XPTR( page_cxy , &page_ptr->mapper ) ); 1998 page_id = hal_remote_l32( XPTR( page_cxy , &page_ptr->index ) ); 1999 2000 // get pointer on local FATFS context 2001 fatfs_ctx_t * fatfs_ctx = fs_context[FS_TYPE_FATFS].extend; 2002 2003 // get page base address 2004 xptr_t base_xp = ppm_page2base( page_xp ); 2005 uint8_t * buffer = (uint8_t *)GET_PTR( base_xp ); 2006 2007 // get inode pointer from mapper 2008 inode_ptr = hal_remote_lpt( XPTR( page_cxy , &mapper_ptr->inode ) ); 2009 2010 ////////////////////////////// it is the FAT mapper 2011 if( inode_ptr == NULL ) 2012 { 2013 // get lba from FATFS context and page_id 2014 uint32_t lba = fatfs_ctx->fat_begin_lba + (page_id << 3); 2015 2016 // access device 2017 if( to_mapper ) error = dev_ioc_sync_read ( buffer , lba , 8 ); 2018 else error = dev_ioc_write( buffer , lba , 8 ); 2019 2020 if( error ) return EIO; 2021 2022 #if (DEBUG_FATFS_MOVE_PAGE & 0x1) 2023 if( DEBUG_FATFS_MOVE_PAGE < cycle ) 2024 { 2025 uint32_t * tab = (uint32_t *)buffer; 2026 uint32_t line , word; 2027 printk("\n***** %s : First 64 words of page %d in FAT mapper\n", 2028 __FUNCTION__ , page_id ); 2029 for( line = 0 ; line < 8 ; line++ ) 2030 { 2031 printk("%X : ", line ); 2032 for( word = 0 ; word < 8 ; word++ ) printk("%X ", tab[(line<<3) + word] ); 2033 printk("\n"); 2034 } 2035 } 2036 #endif 2037 2038 #if DEBUG_FATFS_MOVE_PAGE 2039 cycle = (uint32_t)hal_get_cycles(); 2040 if( DEBUG_FATFS_MOVE_PAGE < cycle ) 2041 { 2042 if (to_mapper) 2043 printk("\n[%s] thread[%x,%x] load page %d of FAT / cycle %d\n", 2044 __FUNCTION__, this->process->pid, this->trdid, page_id, cycle ); 2045 else 2046 printk("\n[%s] thread[%x,%x] sync page %d of FAT / cycle %d\n", 2047 __FUNCTION__, this->process->pid, this->trdid, page_id, cycle ); 2048 } 2049 #endif 2050 2051 } 2052 ///////////////////////// it is an inode mapper 2053 else 2054 { 2055 2056 #if DEBUG_FATFS_MOVE_PAGE 2057 vfs_inode_get_name( XPTR( page_cxy , inode_ptr ) , name ); 2058 #endif 2059 2060 uint32_t searched_cluster; 2061 uint32_t first_cluster; 2062 2063 // get first_cluster from inode extension 2064 void * extend = hal_remote_lpt( XPTR( page_cxy , &inode_ptr->extend ) ); 2065 first_cluster = (uint32_t)(intptr_t)extend; 2066 2067 // compute searched_cluster 2068 if( page_id == 0 ) // no need to access FAT mapper 2069 { 2070 // searched cluster is first cluster 2071 searched_cluster = first_cluster; 2072 } 2073 else // FAT mapper access required 2074 { 2075 // access FAT mapper to get searched cluster 2076 error = fatfs_get_cluster( first_cluster, 2077 page_id, 2078 &searched_cluster ); 2079 if( error ) return EIO; 2080 } 2081 2082 // get lba from searched_cluster 2083 uint32_t lba = fatfs_lba_from_cluster( fatfs_ctx , searched_cluster ); 2084 2085 // access device 2086 if( to_mapper ) error = dev_ioc_sync_read ( buffer , lba , 8 ); 2087 else error = dev_ioc_write( buffer , lba , 8 ); 2088 2089 if( error ) return EIO; 2090 2091 #if (DEBUG_FATFS_MOVE_PAGE & 0x1) 2092 if( DEBUG_FATFS_MOVE_PAGE < cycle ) 2093 { 2094 uint32_t * tab = (uint32_t *)buffer; 2095 uint32_t line , word; 2096 printk("\n***** %s : First 64 words of page %d in <%s> mapper\n", 2097 __FUNCTION__, page_id, name ); 2098 for( line = 0 ; line < 8 ; line++ ) 2099 { 2100 printk("%X : ", line ); 2101 for( word = 0 ; word < 8 ; word++ ) printk("%X ", tab[(line<<3) + word] ); 2102 printk("\n"); 2103 } 2104 } 2105 #endif 2106 2107 #if DEBUG_FATFS_MOVE_PAGE 2108 cycle = (uint32_t)hal_get_cycles(); 2109 if(DEBUG_FATFS_MOVE_PAGE < cycle) 2110 { 2111 if(to_mapper) 2112 printk("\n[%s] thread[%x,%x] load page %d of <%s> inode / cycle %d\n", 2113 __FUNCTION__, this->process->pid, this->trdid, page_id, name, cycle ); 2114 else 2115 printk("\n[%s] thread[%x,%x] sync page %d of <%s> inode / cycle %d\n", 2116 __FUNCTION__, this->process->pid, this->trdid, page_id, name, cycle ); 2117 } 2118 #endif 2119 2120 } 2121 2122 return 0; 2123 2124 } // end fatfs_move_page() 2125 2126
Note: See TracChangeset
for help on using the changeset viewer.