/*FUNCTION*------------------------------------------------------------------- * * Function Name : MFS_Read_device_sector * Returned Value : error_code * Comments : * Reads one sector from the device *END*---------------------------------------------------------------------*/ _mfs_error MFS_Read_device_sector ( MFS_DRIVE_STRUCT_PTR drive_ptr, uint_32 sector_number, /*[IN] sector number to read/write from/to file system medium */ char_ptr sector_ptr /*[IN/OUT] address of where data is to be stored/written */ ) { return MFS_Read_device_sectors(drive_ptr, sector_number, 1, MFSCFG_MAX_READ_RETRIES, sector_ptr, NULL); }
uint32_t MFS_Read ( MFS_HANDLE_PTR handle, /*[IN] file handle upon which the action is to be taken */ MFS_DRIVE_STRUCT_PTR drive_ptr, uint32_t num_bytes, /*[IN] number of bytes to be read */ char *buffer_address, /*[IN/OUT] bytes are read into this buffer */ _mfs_error_ptr error_ptr /*[IN/OUT] error code is written to this address */ ) { uint32_t location; uint32_t bytes_read; uint32_t bytes_left_in_file; uint32_t copy_size; uint32_t cluster_offset; uint32_t sector_number, sector_index; uint32_t sector_offset; uint32_t whole_sectors; uint32_t cont_sectors; uint32_t proc_sectors; _mfs_error error, temp_error; bool eof_reached; uint32_t file_size; if ( num_bytes == 0 ) { MFS_set_error_and_return(error_ptr,MFS_NO_ERROR,0); } if ( buffer_address == NULL ) { MFS_set_error_and_return(error_ptr,MFS_INVALID_PARAMETER,0); } error = MFS_lock_dos_disk(drive_ptr); if ( error != MFS_NO_ERROR ) { MFS_set_error_and_return(error_ptr,error,0); } if ( handle->ACCESS != MFS_ACCESS_READ_ONLY && handle->ACCESS != MFS_ACCESS_READ_WRITE ) { MFS_unlock(drive_ptr,FALSE); MFS_set_error_and_return(error_ptr,MFS_ACCESS_DENIED,0); } if ( handle->CURRENT_CLUSTER == 0 ) { handle->PREVIOUS_CLUSTER = 0; handle->CURRENT_CLUSTER = clustoh(handle->DIR_ENTRY.HFIRST_CLUSTER, handle->DIR_ENTRY.LFIRST_CLUSTER); } else if ( handle->CURRENT_CLUSTER == CLUSTER_EOF ) { MFS_unlock(drive_ptr,FALSE); MFS_set_error_and_return(error_ptr,MFS_EOF,0); } bytes_read = 0; eof_reached = FALSE; location = handle->LOCATION; /* ** Can't read past file size */ file_size = mqx_dtohl(handle->DIR_ENTRY.FILE_SIZE); if ( location > file_size ) { location = file_size; } bytes_left_in_file = file_size - location; if ( num_bytes > bytes_left_in_file ) { eof_reached = TRUE; num_bytes = bytes_left_in_file; } if ( bytes_left_in_file ) { /* ** Read the number of bytes from the current file ** position to the end of the current cluster */ cluster_offset = OFFSET_WITHIN_CLUSTER(location); sector_index = CLUSTER_OFFSET_TO_SECTOR(cluster_offset); sector_number = CLUSTER_TO_SECTOR(handle->CURRENT_CLUSTER) + sector_index; sector_offset = OFFSET_WITHIN_SECTOR(location); /* Read partial sector if sector_offet is non-zero */ if (sector_offset != 0) { error = MFS_Read_data_sector(drive_ptr, handle, sector_number, TRUE); if ( error == MFS_NO_ERROR ) { /* The requested lenght of data may span the sector to it's end */ copy_size = min(num_bytes, drive_ptr->BPB.SECTOR_SIZE-sector_offset); _mem_copy(&drive_ptr->DATA_SECTOR_PTR[sector_offset], buffer_address, copy_size); bytes_read=copy_size; /* ** Check to see if we need to advance to the next sector, which has ** the side effect of increasing the cluster number if required. */ if ( (sector_offset+bytes_read) >= drive_ptr->BPB.SECTOR_SIZE ) { temp_error = MFS_next_data_sector(drive_ptr, handle, §or_index, §or_number); /* Only an error if we are not done reading */ if ( bytes_read<num_bytes ) { error = temp_error; } } } } /* Check whether the application buffer is properly aligned */ if ((((uint32_t)buffer_address+bytes_read) & drive_ptr->ALIGNMENT_MASK) == 0) { /* Yes, use zero copy approach */ whole_sectors = (num_bytes - bytes_read) >> drive_ptr->SECTOR_POWER; while ((whole_sectors > 0) && (error == MFS_NO_ERROR)) { cont_sectors = drive_ptr->BPB.SECTORS_PER_CLUSTER - sector_index; if (cont_sectors > whole_sectors) cont_sectors = whole_sectors; error = MFS_Read_device_sectors(drive_ptr, sector_number, cont_sectors, MFSCFG_MAX_READ_RETRIES, buffer_address+bytes_read, &proc_sectors); if (proc_sectors > 0) { bytes_read += proc_sectors * drive_ptr->BPB.SECTOR_SIZE; whole_sectors -= proc_sectors; /* Advance to next unprocessed sector */ sector_index += proc_sectors - 1; temp_error = MFS_next_data_sector(drive_ptr, handle, §or_index, §or_number); /* Only an error if we are not done reading */ if ((error==MFS_NO_ERROR) && (bytes_read<num_bytes)) { error = temp_error; } } } } else {