GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_media_open.c Lines: 299 299 100.0 %
Date: 2024-01-10 21:53:23 Branches: 88 88 100.0 %

Line Branch Exec Source
1
/**************************************************************************/
2
/*                                                                        */
3
/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4
/*                                                                        */
5
/*       This software is licensed under the Microsoft Software License   */
6
/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7
/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8
/*       and in the root directory of this software.                      */
9
/*                                                                        */
10
/**************************************************************************/
11
12
13
/**************************************************************************/
14
/**************************************************************************/
15
/**                                                                       */
16
/** FileX Component                                                       */
17
/**                                                                       */
18
/**   Media                                                               */
19
/**                                                                       */
20
/**************************************************************************/
21
/**************************************************************************/
22
23
#define FX_SOURCE_CODE
24
25
26
/* Include necessary system files.  */
27
28
#include "fx_api.h"
29
#include "fx_system.h"
30
#include "fx_media.h"
31
#include "fx_utility.h"
32
33
34
/**************************************************************************/
35
/*                                                                        */
36
/*  FUNCTION                                               RELEASE        */
37
/*                                                                        */
38
/*    _fx_media_open                                      PORTABLE C      */
39
/*                                                           6.2.0        */
40
/*  AUTHOR                                                                */
41
/*                                                                        */
42
/*    William E. Lamie, Microsoft Corporation                             */
43
/*                                                                        */
44
/*  DESCRIPTION                                                           */
45
/*                                                                        */
46
/*    This function opens the specified media with the supplied device    */
47
/*    driver.  The specified media must conform to the FAT compatible     */
48
/*    file format, which is verified during the media open process.  In   */
49
/*    addition, the supplied FileX device driver must also conform to     */
50
/*    the FileX device driver specification.                              */
51
/*                                                                        */
52
/*    The FAT boot sector (512 bytes) that is verified by this            */
53
/*    function must look like the following:                              */
54
/*                                                                        */
55
/*          Byte Offset         Meaning             Size                  */
56
/*                                                                        */
57
/*            0x000         Jump Instructions        3                    */
58
/*            0x003         OEM Name                 8                    */
59
/*            0x00B        *Bytes per Sector         2                    */
60
/*            0x00D        *Sectors per Cluster      1                    */
61
/*            0x00E        *Reserved Sectors         2                    */
62
/*            0x010        *Number of FATs           1                    */
63
/*            0x011        *Max Root Dir Entries     2                    */
64
/*            0x013        *Number of Sectors        2                    */
65
/*            0x015         Media Type               1                    */
66
/*            0x016        *Sectors per FAT          2                    */
67
/*            0x018        *Sectors per Track        2                    */
68
/*            0x01A        *Number of Heads          2                    */
69
/*            0x01C        *Hidden Sectors           4                    */
70
/*            0x020        *Huge Sectors             4                    */
71
/*            0x024         Drive Number             1                    */
72
/*            0x025         Reserved                 1                    */
73
/*            0x026         Boot Signature           1                    */
74
/*            0x027         Volume ID                4                    */
75
/*            0x02B         Volume Label             11                   */
76
/*            0x036         File System Type         8                    */
77
/*             ...              ...                 ...                   */
78
/*            0x1FE       **Signature (0x55aa)       2                    */
79
/*                                                                        */
80
/*            * Denotes which elements of the boot record                 */
81
/*              FileX uses.                                               */
82
/*                                                                        */
83
/*            **Denotes the element is checked by the I/O                 */
84
/*              driver.  This eliminates the need for a minimum           */
85
/*              512-byte buffer for FileX.                                */
86
/*                                                                        */
87
/*  Note: All values above are in little endian format, i.e. the LSB is   */
88
/*        in the lowest address.                                          */
89
/*                                                                        */
90
/*  INPUT                                                                 */
91
/*                                                                        */
92
/*    media_ptr                             Media control block pointer   */
93
/*    media_name                            Pointer to media name string  */
94
/*    media_driver                          Media driver entry function   */
95
/*    driver_info_ptr                       Optional information pointer  */
96
/*                                            supplied to media driver    */
97
/*    memory_ptr                            Pointer to memory used by the */
98
/*                                            FileX for this media.       */
99
/*    memory_size                           Size of media memory - must   */
100
/*                                            at least 512 bytes and      */
101
/*                                            one sector size.            */
102
/*                                                                        */
103
/*  OUTPUT                                                                */
104
/*                                                                        */
105
/*    return status                                                       */
106
/*                                                                        */
107
/*  CALLS                                                                 */
108
/*                                                                        */
109
/*    I/O Driver                                                          */
110
/*    _fx_utility_exFAT_bitmap_initialize   Initialize exFAT bitmap       */
111
/*    _fx_utility_16_unsigned_read          Read 16-bit unsigned value    */
112
/*    _fx_utility_32_unsigned_read          Read 32-bit unsigned value    */
113
/*    _fx_utility_logical_sector_flush      Invalidate log sector cache   */
114
/*    _fx_media_boot_info_extract           Extract media information     */
115
/*    _fx_utility_FAT_entry_read            Pickup FAT entry contents     */
116
/*    tx_mutex_create                       Create protection mutex       */
117
/*                                                                        */
118
/*  CALLED BY                                                             */
119
/*                                                                        */
120
/*    Application Code                                                    */
121
/*                                                                        */
122
/*  RELEASE HISTORY                                                       */
123
/*                                                                        */
124
/*    DATE              NAME                      DESCRIPTION             */
125
/*                                                                        */
126
/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
127
/*  09-30-2020     William E. Lamie         Modified comment(s), and      */
128
/*                                            added conditional to        */
129
/*                                            disable force memset,       */
130
/*                                            build options and cache,    */
131
/*                                            resulting in version 6.1    */
132
/*  01-31-2022     William E. Lamie         Modified comment(s), fixed    */
133
/*                                            errors without cache,       */
134
/*                                            resulting in version 6.1.10 */
135
/*  10-31-2022     Tiejun Zhou              Modified comment(s),          */
136
/*                                            fixed memory buffer when    */
137
/*                                            cache is disabled,          */
138
/*                                            resulting in version 6.2.0  */
139
/*                                                                        */
140
/**************************************************************************/
141
7254
UINT  _fx_media_open(FX_MEDIA *media_ptr, CHAR *media_name,
142
                     VOID (*media_driver)(FX_MEDIA *), VOID *driver_info_ptr,
143
                     VOID *memory_ptr, ULONG memory_size)
144
{
145
146
FX_MEDIA_PTR      tail_ptr;
147
ULONG             cluster_number;
148
ULONG             FAT_entry, FAT_sector, FAT_read_sectors;
149
ULONG             i, j;
150
#ifndef FX_DISABLE_CACHE
151
FX_CACHED_SECTOR *cache_entry_ptr;
152
#endif /* FX_DISABLE_CACHE */
153
UINT              status;
154
UINT              additional_info_sector;
155
UCHAR            *original_memory_ptr;
156
ULONG             bytes_in_buffer;
157
FX_INT_SAVE_AREA
158
159
160
#ifndef FX_DISABLE_BUILD_OPTIONS
161
    /* Reference the version ID and option words to ensure they are linked in.  */
162
7254
    if ((_fx_system_build_options_1 | _fx_system_build_options_2 | _fx_system_build_options_3) == 0 ||
163
7253
        _fx_version_id[0] == 0)
164
    {
165
166
        /* We should never get here!  */
167
2
        return(FX_NOT_IMPLEMENTED);
168
    }
169
#endif /* FX_DISABLE_BUILD_OPTIONS */
170
171
#ifdef FX_DISABLE_FORCE_MEMORY_OPERATION
172
    _fx_utility_memory_set((UCHAR *)media_ptr, 0, sizeof(FX_MEDIA));
173
#endif /* FX_DISABLE_FORCE_MEMORY_OPERATION */
174
#ifdef FX_DISABLE_CACHE
175
    media_ptr -> fx_media_memory_buffer_sector = (ULONG64)-1;
176
#endif /* FX_DISABLE_CACHE */
177
178
    /* Save the basic information in the media control block.  */
179
7252
    media_ptr -> fx_media_name =                        media_name;
180
7252
    media_ptr -> fx_media_driver_entry =                media_driver;
181
7252
    media_ptr -> fx_media_memory_buffer =               (UCHAR *)memory_ptr;
182
7252
    media_ptr -> fx_media_memory_size =                 memory_size;
183
#ifndef FX_DISABLE_FORCE_MEMORY_OPERATION
184
7252
    media_ptr -> fx_media_disable_burst_cache =         FX_FALSE;
185
7252
    media_ptr -> fx_media_FAT_type =                    0;
186
#endif /* FX_DISABLE_FORCE_MEMORY_OPERATION */
187
188
    /* Save the original memory pointer.  */
189
7252
    original_memory_ptr =  (UCHAR *)memory_ptr;
190
191
#ifndef FX_MEDIA_STATISTICS_DISABLE
192
193
    /* Clear the optional media statistics.  */
194
7252
    media_ptr -> fx_media_directory_attributes_reads =  0;
195
7252
    media_ptr -> fx_media_directory_attributes_sets =  0;
196
7252
    media_ptr -> fx_media_directory_creates =  0;
197
7252
    media_ptr -> fx_media_directory_default_gets =  0;
198
7252
    media_ptr -> fx_media_directory_default_sets =  0;
199
7252
    media_ptr -> fx_media_directory_deletes =  0;
200
7252
    media_ptr -> fx_media_directory_first_entry_finds =  0;
201
7252
    media_ptr -> fx_media_directory_first_full_entry_finds =  0;
202
7252
    media_ptr -> fx_media_directory_information_gets =  0;
203
7252
    media_ptr -> fx_media_directory_local_path_clears =  0;
204
7252
    media_ptr -> fx_media_directory_local_path_gets =  0;
205
7252
    media_ptr -> fx_media_directory_local_path_restores =  0;
206
7252
    media_ptr -> fx_media_directory_local_path_sets =  0;
207
7252
    media_ptr -> fx_media_directory_name_tests =  0;
208
7252
    media_ptr -> fx_media_directory_next_entry_finds =  0;
209
7252
    media_ptr -> fx_media_directory_next_full_entry_finds =  0;
210
7252
    media_ptr -> fx_media_directory_renames =  0;
211
7252
    media_ptr -> fx_media_file_allocates =  0;
212
7252
    media_ptr -> fx_media_file_attributes_reads =  0;
213
7252
    media_ptr -> fx_media_file_attributes_sets =  0;
214
7252
    media_ptr -> fx_media_file_best_effort_allocates =  0;
215
7252
    media_ptr -> fx_media_file_closes =  0;
216
7252
    media_ptr -> fx_media_file_creates =  0;
217
7252
    media_ptr -> fx_media_file_deletes =  0;
218
7252
    media_ptr -> fx_media_file_opens =  0;
219
7252
    media_ptr -> fx_media_file_reads =  0;
220
7252
    media_ptr -> fx_media_file_relative_seeks =  0;
221
7252
    media_ptr -> fx_media_file_renames =  0;
222
7252
    media_ptr -> fx_media_file_seeks =  0;
223
7252
    media_ptr -> fx_media_file_truncates =  0;
224
7252
    media_ptr -> fx_media_file_truncate_releases =  0;
225
7252
    media_ptr -> fx_media_file_writes =  0;
226
7252
    media_ptr -> fx_media_aborts =  0;
227
7252
    media_ptr -> fx_media_flushes =  0;
228
7252
    media_ptr -> fx_media_reads =  0;
229
7252
    media_ptr -> fx_media_writes =  0;
230
7252
    media_ptr -> fx_media_directory_entry_reads =  0;
231
7252
    media_ptr -> fx_media_directory_entry_writes =  0;
232
7252
    media_ptr -> fx_media_directory_searches =  0;
233
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
234
7252
    media_ptr -> fx_media_directory_search_cache_hits =  0;
235
#endif
236
7252
    media_ptr -> fx_media_directory_free_searches =  0;
237
7252
    media_ptr -> fx_media_fat_entry_reads =  0;
238
7252
    media_ptr -> fx_media_fat_entry_writes =  0;
239
7252
    media_ptr -> fx_media_fat_entry_cache_read_hits =  0;
240
7252
    media_ptr -> fx_media_fat_entry_cache_read_misses =  0;
241
7252
    media_ptr -> fx_media_fat_entry_cache_write_hits =  0;
242
7252
    media_ptr -> fx_media_fat_entry_cache_write_misses =  0;
243
7252
    media_ptr -> fx_media_fat_cache_flushes =  0;
244
7252
    media_ptr -> fx_media_fat_sector_reads =  0;
245
7252
    media_ptr -> fx_media_fat_sector_writes =  0;
246
7252
    media_ptr -> fx_media_logical_sector_reads =  0;
247
7252
    media_ptr -> fx_media_logical_sector_writes =  0;
248
7252
    media_ptr -> fx_media_logical_sector_cache_read_hits =  0;
249
7252
    media_ptr -> fx_media_logical_sector_cache_read_misses =  0;
250
7252
    media_ptr -> fx_media_driver_read_requests =  0;
251
7252
    media_ptr -> fx_media_driver_write_requests =  0;
252
7252
    media_ptr -> fx_media_driver_boot_read_requests =  0;
253
7252
    media_ptr -> fx_media_driver_boot_write_requests =  0;
254
7252
    media_ptr -> fx_media_driver_release_sectors_requests =  0;
255
7252
    media_ptr -> fx_media_driver_flush_requests =  0;
256
#endif
257
#ifdef FX_ENABLE_FAULT_TOLERANT
258
    media_ptr -> fx_media_fault_tolerant_enabled = FX_FALSE;
259
    media_ptr -> fx_media_fault_tolerant_state = 0;
260
#endif /* FX_ENABLE_FAULT_TOLERANT */
261
262
    /* If trace is enabled, insert this event into the trace buffer.  */
263
    FX_TRACE_IN_LINE_INSERT(FX_TRACE_MEDIA_OPEN, media_ptr, media_driver, memory_ptr, memory_size, FX_TRACE_MEDIA_EVENTS, 0, 0)
264
265
    /* Initialize the supplied media I/O driver.  First, build the
266
       initialize driver request.  */
267
7252
    media_ptr -> fx_media_driver_request =              FX_DRIVER_INIT;
268
7252
    media_ptr -> fx_media_driver_status =               FX_IO_ERROR;
269
7252
    media_ptr -> fx_media_driver_info =                 driver_info_ptr;
270
7252
    media_ptr -> fx_media_driver_write_protect =        FX_FALSE;
271
7252
    media_ptr -> fx_media_driver_free_sector_update =   FX_FALSE;
272
7252
    media_ptr -> fx_media_driver_data_sector_read =     FX_FALSE;
273
274
    /* If trace is enabled, insert this event into the trace buffer.  */
275
    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_INIT, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
276
277
    /* Call the specified I/O driver with the initialize request.  */
278
7252
    (media_ptr -> fx_media_driver_entry) (media_ptr);
279
280
    /* Determine if the I/O driver initialized successfully.  */
281
7252
    if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
282
    {
283
284
        /* Return the driver error status.  */
285
836
        return(FX_IO_ERROR);
286
    }
287
288
#ifndef FX_MEDIA_STATISTICS_DISABLE
289
290
    /* Increment the number of driver boot read requests.  */
291
6416
    media_ptr -> fx_media_driver_boot_read_requests++;
292
#endif
293
294
    /* Read the boot sector from the device.  Build the read boot sector
295
       command.  */
296
6416
    media_ptr -> fx_media_driver_request =          FX_DRIVER_BOOT_READ;
297
6416
    media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
298
6416
    media_ptr -> fx_media_driver_buffer =           memory_ptr;
299
6416
    media_ptr -> fx_media_driver_sectors =          1;
300
6416
    media_ptr -> fx_media_driver_sector_type =      FX_BOOT_SECTOR;
301
302
    /* If trace is enabled, insert this event into the trace buffer.  */
303
    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_BOOT_READ, media_ptr, memory_ptr, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
304
305
    /* Invoke the driver to read the boot sector.  */
306
6416
    (media_ptr -> fx_media_driver_entry) (media_ptr);
307
308
    /* Determine if the boot sector was read correctly. */
309
6416
    if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
310
    {
311
312
        /* Build the "uninitialize" I/O driver request.  */
313
388
        media_ptr -> fx_media_driver_request =      FX_DRIVER_UNINIT;
314
388
        media_ptr -> fx_media_driver_status =       FX_IO_ERROR;
315
316
        /* If trace is enabled, insert this event into the trace buffer.  */
317
        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_UNINIT, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
318
319
        /* Call the specified I/O driver with the uninitialize request.  */
320
388
        (media_ptr -> fx_media_driver_entry) (media_ptr);
321
322
        /* Return the boot sector error status.  */
323
388
        return(FX_BOOT_ERROR);
324
    }
325
326
    /* Extract and validate the media parameters from the boot sector.  */
327
6028
    if (_fx_media_boot_info_extract(media_ptr) != FX_SUCCESS)
328
    {
329
330
        /* Build the "uninitialize" I/O driver request.  */
331
6
        media_ptr -> fx_media_driver_request =      FX_DRIVER_UNINIT;
332
6
        media_ptr -> fx_media_driver_status =       FX_IO_ERROR;
333
334
        /* If trace is enabled, insert this event into the trace buffer.  */
335
        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_UNINIT, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
336
337
        /* Call the specified I/O driver with the uninitialize request.  */
338
6
        (media_ptr -> fx_media_driver_entry) (media_ptr);
339
340
        /* Return the invalid media error status.  */
341
6
        return(FX_MEDIA_INVALID);
342
    }
343
344
    /* Pickup the additional info sector number. This will only be used in FAT32 situations.  */
345
6022
    additional_info_sector =  _fx_utility_16_unsigned_read(&media_ptr -> fx_media_driver_buffer[48]);
346
347
    /* Is there at least one?  */
348
6022
    if (memory_size < media_ptr -> fx_media_bytes_per_sector)
349
    {
350
351
        /* Build the "uninitialize" I/O driver request.  */
352
1
        media_ptr -> fx_media_driver_request =      FX_DRIVER_UNINIT;
353
1
        media_ptr -> fx_media_driver_status =       FX_IO_ERROR;
354
355
        /* If trace is enabled, insert this event into the trace buffer.  */
356
        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_UNINIT, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
357
358
        /* Call the specified I/O driver with the uninitialize request.  */
359
1
        (media_ptr -> fx_media_driver_entry) (media_ptr);
360
361
        /* Error in the buffer size supplied by user.  */
362
1
        return(FX_BUFFER_ERROR);
363
    }
364
365
#ifndef FX_DISABLE_CACHE
366
    /* Determine how many logical sectors can be cached with user's supplied
367
       buffer area - there must be at least enough for one sector!  */
368
6021
    media_ptr -> fx_media_sector_cache_size =  memory_size / media_ptr -> fx_media_bytes_per_sector;
369
370
    /* If trace is enabled, register this object.  */
371
    FX_TRACE_OBJECT_REGISTER(FX_TRACE_OBJECT_TYPE_MEDIA, media_ptr, media_name, FX_MAX_FAT_CACHE, media_ptr -> fx_media_sector_cache_size)
372
373
    /* Adjust the internal cache to fit the fixed number of sector cache control blocks
374
       built into the media control block.  */
375
6021
    if (media_ptr -> fx_media_sector_cache_size > FX_MAX_SECTOR_CACHE)
376
    {
377
378
        /* Adjust the number of cache sectors downward.  If this is insufficient,
379
           the FX_MAX_SECTOR_CACHE constant in FX_API.H must be changed and the FileX
380
           library must be rebuilt.  */
381
1
        media_ptr -> fx_media_sector_cache_size =  FX_MAX_SECTOR_CACHE;
382
    }
383
384
    /* Otherwise, everything is okay.  Initialize the data structures for managing the
385
       logical sector cache.  */
386
6021
    i =  (UINT)media_ptr -> fx_media_sector_cache_size;
387
6021
    cache_entry_ptr =  media_ptr -> fx_media_sector_cache;
388
21611
    while (i--)
389
    {
390
391
        /* Initialize each of the cache entries.  */
392
15590
        cache_entry_ptr -> fx_cached_sector_memory_buffer =  (UCHAR *)memory_ptr;
393
15590
        cache_entry_ptr -> fx_cached_sector =                (~(ULONG64)0);
394
15590
        cache_entry_ptr -> fx_cached_sector_buffer_dirty =   FX_FALSE;
395
15590
        cache_entry_ptr -> fx_cached_sector_valid =          FX_FALSE;
396
15590
        cache_entry_ptr -> fx_cached_sector_next_used =      cache_entry_ptr + 1;
397
398
        /* Move to the next cache sector entry.  */
399
15590
        cache_entry_ptr++;
400
401
        /* Update the memory pointer to the next buffer slot.  */
402
15590
        memory_ptr =  (VOID *)(((UCHAR *)memory_ptr) + media_ptr -> fx_media_bytes_per_sector);
403
    }
404
405
    /* Backup to the last cache entry to set its next pointer to NULL.  */
406
6021
    cache_entry_ptr--;
407
6021
    cache_entry_ptr -> fx_cached_sector_next_used =  FX_NULL;
408
409
    /* Remember the last memory address used by the caching logic.  */
410
6021
    media_ptr -> fx_media_sector_cache_end =  ((UCHAR *)memory_ptr) - 1;
411
412
    /* Setup the head pointer of the list.  */
413
6021
    media_ptr -> fx_media_sector_cache_list_ptr =  media_ptr -> fx_media_sector_cache;
414
415
    /* Setup the bit map that keeps track of the valid hashed cache logical sectors.  */
416
6021
    media_ptr -> fx_media_sector_cache_hashed_sector_valid =  0;
417
418
    /* Clear the counter of the number of outstanding dirty sectors.  */
419
6021
    media_ptr -> fx_media_sector_cache_dirty_count =  0;
420
421
    /* Determine if the logical sector cache should be managed by the hash function
422
       instead of the linear search. The cache must be a power of 2 that is between the
423
       minimum and maximum cache size.  */
424
6021
    if ((media_ptr -> fx_media_sector_cache_size >= FX_SECTOR_CACHE_HASH_ENABLE) &&
425
138
        ((media_ptr -> fx_media_sector_cache_size ^ (media_ptr -> fx_media_sector_cache_size - 1)) ==
426
138
         (media_ptr -> fx_media_sector_cache_size | (media_ptr -> fx_media_sector_cache_size - 1))))
427
    {
428
429
430
        /* Set the logical sector cache hash flag. When this flag is set, the logical
431
           sector cache is accessed with a hash function instead of a linear search.  */
432
136
        media_ptr -> fx_media_sector_cache_hashed =  FX_TRUE;
433
136
        media_ptr -> fx_media_sector_cache_hash_mask =
434
136
            ((media_ptr -> fx_media_sector_cache_size / FX_SECTOR_CACHE_DEPTH) - 1);
435
    }
436
    else
437
    {
438
439
        /* Clear the logical sector cache flag.  */
440
5885
        media_ptr -> fx_media_sector_cache_hashed =  FX_FALSE;
441
    }
442
#else
443
    media_ptr -> fx_media_memory_buffer = memory_ptr;
444
#endif /* FX_DISABLE_CACHE */
445
446
#ifndef FX_DISABLE_FORCE_MEMORY_OPERATION
447
    /* Initialize the FAT cache entry array.  */
448
391365
    for (i = 0; i < FX_MAX_FAT_CACHE; i++)
449
    {
450
451
        /* Clear entry in the FAT cache.  */
452
385344
        media_ptr -> fx_media_fat_cache[i].fx_fat_cache_entry_cluster =   0;
453
385344
        media_ptr -> fx_media_fat_cache[i].fx_fat_cache_entry_value   =   0;
454
385344
        media_ptr -> fx_media_fat_cache[i].fx_fat_cache_entry_dirty   =   0;
455
    }
456
457
    /* Initialize the secondary FAT update map.  */
458
12042
    for (i = 0; i < FX_FAT_MAP_SIZE; i++)
459
    {
460
461
        /* Clear bit map entry for secondary FAT update.  */
462
6021
        media_ptr -> fx_media_fat_secondary_update_map[i] =  0;
463
    }
464
#endif /* FX_DISABLE_FORCE_MEMORY_OPERATION */
465
466
#ifdef FX_ENABLE_EXFAT
467
    if (media_ptr -> fx_media_FAT_type != FX_exFAT)
468
    {
469
#endif /* FX_ENABLE_EXFAT */
470
471
        /* Root_sector_start has been computed */
472
6021
        media_ptr -> fx_media_root_sector_start =  media_ptr -> fx_media_reserved_sectors +
473
6021
            (media_ptr -> fx_media_number_of_FATs *
474
6021
             media_ptr -> fx_media_sectors_per_FAT);
475
476
        /* Calculate the number of directory sectors.  */
477
6021
        media_ptr -> fx_media_root_sectors =
478
6021
            ((media_ptr -> fx_media_root_directory_entries * FX_DIR_ENTRY_SIZE) +
479
6021
             media_ptr -> fx_media_bytes_per_sector - 1) /
480
6021
            media_ptr -> fx_media_bytes_per_sector;
481
482
        /* Calculate the starting data sector.  */
483
6021
        media_ptr -> fx_media_data_sector_start =  media_ptr -> fx_media_root_sector_start +
484
6021
            media_ptr -> fx_media_root_sectors;
485
486
        /* Calculate the total number of clusters.  */
487
6021
        media_ptr -> fx_media_total_clusters =  (ULONG)((media_ptr -> fx_media_total_sectors - media_ptr -> fx_media_data_sector_start) /
488
6021
                                                            media_ptr -> fx_media_sectors_per_cluster);
489
490
        /* Determine if a 12-bit FAT is in use.  */
491
6021
        if (media_ptr -> fx_media_total_clusters < FX_12_BIT_FAT_SIZE)
492
        {
493
494
            /* Yes, 12-bit FAT is present.  Set flag accordingly.  */
495
106
            media_ptr -> fx_media_12_bit_FAT = FX_TRUE;
496
106
            media_ptr -> fx_media_32_bit_FAT = FX_FALSE;
497
#ifdef FX_ENABLE_EXFAT
498
            media_ptr -> fx_media_FAT_type = FX_FAT12;
499
#endif /* FX_ENABLE_EXFAT */
500
501
            /* No additional information sector in FAT12.  */
502
106
            media_ptr -> fx_media_FAT32_additional_info_sector =  0;
503
504
            /* Set FAT last and FAT reserved. */
505
106
            media_ptr -> fx_media_fat_reserved = FX_RESERVED_1;
506
106
            media_ptr -> fx_media_fat_last = FX_LAST_CLUSTER_2;
507
        }
508
5915
        else if (media_ptr -> fx_media_total_clusters < FX_16_BIT_FAT_SIZE)
509
        {
510
511
            /* A 16-bit FAT is present.  Set flag accordingly.  */
512
2083
            media_ptr -> fx_media_12_bit_FAT =  FX_FALSE;
513
2083
            media_ptr -> fx_media_32_bit_FAT =  FX_FALSE;
514
#ifdef FX_ENABLE_EXFAT
515
            media_ptr -> fx_media_FAT_type = FX_FAT16;
516
#endif /* FX_ENABLE_EXFAT */
517
518
            /* No additional information sector in FAT16.  */
519
2083
            media_ptr -> fx_media_FAT32_additional_info_sector =  0;
520
521
            /* Set FAT last and FAT reserved. */
522
2083
            media_ptr -> fx_media_fat_reserved = FX_RESERVED_1;
523
2083
            media_ptr -> fx_media_fat_last = FX_LAST_CLUSTER_2;
524
        }
525
        else
526
        {
527
528
            /* Yes, a 32-bit FAT is present.  */
529
3832
            media_ptr -> fx_media_12_bit_FAT =  FX_FALSE;
530
3832
            media_ptr -> fx_media_32_bit_FAT =  FX_TRUE;
531
#ifdef FX_ENABLE_EXFAT
532
            media_ptr -> fx_media_FAT_type = FX_FAT32;
533
#endif /* FX_ENABLE_EXFAT */
534
535
            /* Save the additional information sector FAT32. This was read from the boot
536
               sector earlier in this routine. */
537
3832
            media_ptr -> fx_media_FAT32_additional_info_sector =  additional_info_sector;
538
539
            /* Set FAT last and FAT reserved. */
540
3832
            media_ptr -> fx_media_fat_reserved = FX_RESERVED_1_32;
541
3832
            media_ptr -> fx_media_fat_last = FX_LAST_CLUSTER_2_32;
542
        }
543
#ifdef FX_ENABLE_EXFAT
544
    }
545
    else
546
    {
547
548
        /* Set FAT last and FAT reserved. */
549
        media_ptr -> fx_media_fat_reserved = FX_RESERVED_1_exFAT;
550
        media_ptr -> fx_media_fat_last = FX_LAST_CLUSTER_exFAT;
551
    }
552
#endif /* FX_ENABLE_EXFAT */
553
554
    /* Determine if a 32-bit FAT is present. If so, calculate the size of the root directory (since
555
       it is variable in FAT32.  */
556
#ifdef FX_ENABLE_EXFAT
557
    if (media_ptr -> fx_media_32_bit_FAT == FX_TRUE ||
558
        (media_ptr -> fx_media_FAT_type == FX_exFAT))
559
#else
560
6021
    if (media_ptr -> fx_media_32_bit_FAT == FX_TRUE)
561
#endif /* FX_ENABLE_EXFAT */
562
    {
563
#ifdef FX_ENABLE_EXFAT
564
        if (media_ptr -> fx_media_32_bit_FAT == FX_TRUE)
565
        {
566
#endif /* FX_ENABLE_EXFAT */
567
568
            /* Root First cluster starts from at least cluster 2, or higher. */
569
3832
            if (media_ptr -> fx_media_root_cluster_32 < FX_FAT_ENTRY_START)
570
            {
571
1
                return(FX_MEDIA_INVALID);
572
            }
573
574
            /* Calculate logical number of root dir sector.  */
575
3831
            media_ptr -> fx_media_root_sector_start = media_ptr -> fx_media_data_sector_start +
576
3831
                (media_ptr -> fx_media_root_cluster_32 - FX_FAT_ENTRY_START) *
577
3831
                media_ptr -> fx_media_sectors_per_cluster;
578
#ifdef FX_ENABLE_EXFAT
579
        }
580
#endif /* FX_ENABLE_EXFAT */
581
582
        /* Calculate maximum possible value for fx_media_root_directory_entries */
583
3831
        i = 0;
584
3831
        for (cluster_number = media_ptr -> fx_media_root_cluster_32;;)
585
        {
586
587
73290
            status =  _fx_utility_FAT_entry_read(media_ptr, cluster_number, &FAT_entry);
588
73290
            i++;
589
            /* Determine if the read was successful.  */
590
73290
            if (status != FX_SUCCESS)
591
            {
592
593
                /* Build the "uninitialize" I/O driver request.  */
594
376
                media_ptr -> fx_media_driver_request =      FX_DRIVER_UNINIT;
595
376
                media_ptr -> fx_media_driver_status =       FX_IO_ERROR;
596
597
                /* If trace is enabled, insert this event into the trace buffer.  */
598
                FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_UNINIT, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
599
600
                /* Call the specified I/O driver with the uninitialize request.  */
601
376
                (media_ptr -> fx_media_driver_entry) (media_ptr);
602
603
376
                return(FX_FAT_READ_ERROR);
604
            }
605
606

72914
            if ((cluster_number == FAT_entry) || (i > media_ptr -> fx_media_total_clusters))
607
            {
608
609
                /* Build the "uninitialize" I/O driver request.  */
610
2
                media_ptr -> fx_media_driver_request =      FX_DRIVER_UNINIT;
611
2
                media_ptr -> fx_media_driver_status =       FX_IO_ERROR;
612
613
                /* If trace is enabled, insert this event into the trace buffer.  */
614
                FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_UNINIT, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
615
616
                /* Call the specified I/O driver with the uninitialize request.  */
617
2
                (media_ptr -> fx_media_driver_entry) (media_ptr);
618
619
2
                return(FX_FAT_READ_ERROR);
620
            }
621
72912
            if (FAT_entry >= FX_RESERVED_1_32)
622
            {
623
3453
                break;
624
            }
625
69459
            cluster_number = FAT_entry;
626
        }
627
628
        /* Calculate the number of directory entries.  */
629
3453
        media_ptr -> fx_media_root_directory_entries =  (i * media_ptr -> fx_media_sectors_per_cluster *
630
3453
                                                         media_ptr -> fx_media_bytes_per_sector) / FX_DIR_ENTRY_SIZE;
631
    }
632
633
#ifndef FX_DISABLE_FORCE_MEMORY_OPERATION
634
    /* Calculate the number of available clusters.  */
635
5642
    media_ptr -> fx_media_available_clusters =  0;
636
637
    /* Set the cluster search start to an invalid value.  */
638
5642
    media_ptr -> fx_media_cluster_search_start =  0;
639
#endif /* FX_DISABLE_FORCE_MEMORY_OPERATION */
640
641
    /* Determine if there is 32-bit FAT additional information sector. */
642
5642
    if (media_ptr -> fx_media_FAT32_additional_info_sector)
643
    {
644
645
    UCHAR *buffer_ptr;
646
    ULONG  signature;
647
648
649
        /* Yes, read the FAT32 additional information sector to get the available cluster count and
650
           the hint for the first available cluster.  */
651
652
#ifndef FX_DISABLE_CACHE
653
        /* Setup a pointer to the first cached entry's buffer.  */
654
3453
        buffer_ptr =  (media_ptr -> fx_media_sector_cache_list_ptr) -> fx_cached_sector_memory_buffer;
655
656
        /* Invalidate this cache entry.  */
657
3453
        (media_ptr -> fx_media_sector_cache_list_ptr) -> fx_cached_sector =  (~((ULONG64) 0));
658
3453
        (media_ptr -> fx_media_sector_cache_list_ptr) -> fx_cached_sector_valid =  FX_FALSE;
659
#else
660
        buffer_ptr =  media_ptr -> fx_media_memory_buffer;
661
        media_ptr -> fx_media_memory_buffer_sector = (ULONG64)-1;
662
#endif /* FX_DISABLE_CACHE */
663
664
        /* Read the FAT32 additional information sector from the device.  */
665
3453
        media_ptr -> fx_media_driver_request =          FX_DRIVER_READ;
666
3453
        media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
667
3453
        media_ptr -> fx_media_driver_buffer =           buffer_ptr;
668
3453
        media_ptr -> fx_media_driver_logical_sector =   media_ptr -> fx_media_FAT32_additional_info_sector;
669
3453
        media_ptr -> fx_media_driver_sectors =          1;
670
3453
        media_ptr -> fx_media_driver_sector_type =      FX_DIRECTORY_SECTOR;
671
672
#ifndef FX_MEDIA_STATISTICS_DISABLE
673
674
        /* Increment the number of driver read sector(s) requests.  */
675
3453
        media_ptr -> fx_media_driver_read_requests++;
676
#endif
677
678
        /* If trace is enabled, insert this event into the trace buffer.  */
679
        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_READ, media_ptr, media_ptr -> fx_media_FAT32_additional_info_sector, 1, buffer_ptr, FX_TRACE_INTERNAL_EVENTS, 0, 0)
680
681
        /* Invoke the driver to read the FAT32 additional information sector.  */
682
3453
        (media_ptr -> fx_media_driver_entry) (media_ptr);
683
684
        /* Determine if the FAT32 sector was read correctly. */
685
3453
        if (media_ptr -> fx_media_driver_status == FX_SUCCESS)
686
        {
687
688
            /* Yes, setup a pointer into the FAT32 additional information sector.  */
689
3063
            buffer_ptr =  media_ptr -> fx_media_driver_buffer;
690
691
            /* Pickup the first signature long word.  */
692
3063
            signature =  _fx_utility_32_unsigned_read(&buffer_ptr[0]);
693
694
            /* Determine if the signature is correct.  */
695
3063
            if (signature == 0x41615252)
696
            {
697
698
                /* Yes, the first signature is correct, now pickup the next signature.  */
699
2025
                signature =  _fx_utility_32_unsigned_read(&buffer_ptr[484]);
700
701
                /* Determine if this signature is correct.  */
702
2025
                if (signature == 0x61417272)
703
                {
704
705
                    /* Yes, we have a good FAT32 additional information sector.  */
706
707
                    /* Pickup the current available cluster count on the media.  */
708
2024
                    media_ptr -> fx_media_available_clusters =  _fx_utility_32_unsigned_read(&buffer_ptr[488]);
709
710
                    /* Initialize the last reported available cluster count to the same value.  */
711
2024
                    media_ptr -> fx_media_FAT32_additional_info_last_available =  media_ptr -> fx_media_available_clusters;
712
713
                    /* Pickup the hint for the starting free cluster search.  */
714
2024
                    media_ptr -> fx_media_cluster_search_start =  _fx_utility_32_unsigned_read(&buffer_ptr[492]);
715
716
                    /* Perform a quick sanity check on the available cluster count and the starting free
717
                       cluster search.  */
718
2024
                    if ((media_ptr -> fx_media_available_clusters > media_ptr -> fx_media_total_clusters) ||
719
2023
                        (media_ptr -> fx_media_cluster_search_start > media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START) ||
720
2022
                        (media_ptr -> fx_media_cluster_search_start < FX_FAT_ENTRY_START))
721
                    {
722
723
                        /* Something is wrong, clear the available cluster count and search so the regular processing
724
                           is used.  */
725
3
                        media_ptr -> fx_media_available_clusters =    0;
726
3
                        media_ptr -> fx_media_cluster_search_start =  0;
727
728
                        /* We don't invalidate the additional info sector here because only the data is bad.  */
729
                    }
730
                }
731
                else
732
                {
733
734
                    /* Signature is bad, invalidate the additional info sector.  */
735
1
                    media_ptr -> fx_media_FAT32_additional_info_sector =  0;
736
                }
737
            }
738
            else
739
            {
740
741
                /* Signature is bad, invalidate the additional info sector.  */
742
1038
                media_ptr -> fx_media_FAT32_additional_info_sector =  0;
743
            }
744
        }
745
        else
746
        {
747
748
            /* IO error trying to read additional information sector, invalidate the additional info sector.  */
749
390
            media_ptr -> fx_media_FAT32_additional_info_sector =  0;
750
        }
751
    }
752
753
    /* Search the media to find the first available cluster as well as the total
754
       available clusters.  */
755
756
    /* Determine what type of FAT is present.  */
757
5642
    if (media_ptr -> fx_media_12_bit_FAT)
758
    {
759
760
        /* A 12-bit FAT is present.  Utilize the FAT entry read utility to pickup
761
           each FAT entry's contents.  */
762
763
        /* Loop to read each cluster entry in the first FAT.  */
764
106
        for (cluster_number =  FX_FAT_ENTRY_START;
765
80329
             cluster_number < (media_ptr -> fx_media_total_clusters) + FX_FAT_ENTRY_START;
766
80223
             cluster_number++)
767
        {
768
769
            /* Read a FAT entry.  */
770
80224
            status =  _fx_utility_FAT_entry_read(media_ptr, cluster_number, &FAT_entry);
771
772
            /* Determine if the read was successful.  */
773
80224
            if (status != FX_SUCCESS)
774
            {
775
776
                /* Build the "uninitialize" I/O driver request.  */
777
1
                media_ptr -> fx_media_driver_request =      FX_DRIVER_UNINIT;
778
1
                media_ptr -> fx_media_driver_status =       FX_IO_ERROR;
779
780
                /* If trace is enabled, insert this event into the trace buffer.  */
781
                FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_UNINIT, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
782
783
                /* Call the specified I/O driver with the uninitialize request.  */
784
1
                (media_ptr -> fx_media_driver_entry) (media_ptr);
785
786
1
                return(FX_FAT_READ_ERROR);
787
            }
788
789
            /* Now determine if the FAT entry is available.  */
790
80223
            if (FAT_entry == FX_FREE_CLUSTER)
791
            {
792
793
                /* Increment the number of available clusters.  */
794
79652
                media_ptr -> fx_media_available_clusters++;
795
796
                /* Determine if the starting free cluster has been found yet.  */
797
79652
                if (media_ptr -> fx_media_cluster_search_start == 0)
798
                {
799
800
                    /* Remember the first free cluster to start further searches from.  */
801
105
                    media_ptr -> fx_media_cluster_search_start =  cluster_number;
802
                }
803
            }
804
        }
805
    }
806
#ifdef FX_ENABLE_EXFAT
807
    else if ((media_ptr -> fx_media_available_clusters == 0)
808
             && (media_ptr -> fx_media_FAT_type != FX_exFAT))
809
#else
810
5536
    else if (media_ptr -> fx_media_available_clusters == 0)
811
#endif /* FX_ENABLE_EXFAT */
812
    {
813
814
        /* A 16 or 32-bit FAT is present. Read directly into the logical sector
815
           cache memory to optimize I/O on larger devices. Since we are looking for
816
           values of zero, endian issues are not important.  */
817
818
        /* Invalidate the current logical sector cache.  */
819
3515
        _fx_utility_logical_sector_flush(media_ptr, ((ULONG64) 1), (ULONG64) (media_ptr -> fx_media_total_sectors), FX_TRUE);
820
821
        /* Reset the memory pointer.  */
822
3515
        media_ptr -> fx_media_memory_buffer =  original_memory_ptr;
823
824
        /* Loop through all FAT sectors in the primary FAT.  The first two entries are
825
           examined in this loop, but they are always unavailable.  */
826
3515
        cluster_number =  0;
827
#ifndef FX_DISABLE_CACHE
828
2512506
        for (i = 0; i < media_ptr -> fx_media_sectors_per_FAT; i = i + media_ptr -> fx_media_sector_cache_size)
829
        {
830
831
            /* Calculate the starting next FAT sector.  */
832
2508992
            FAT_sector =  media_ptr -> fx_media_reserved_sectors + i;
833
834
            /* Calculate how many sectors to read.  */
835
2508992
            FAT_read_sectors =  media_ptr -> fx_media_sectors_per_FAT - i;
836
837
            /* Determine if there is not enough memory to read the remaining FAT sectors.  */
838
2508992
            if (FAT_read_sectors > media_ptr -> fx_media_sector_cache_size)
839
            {
840
2507932
                FAT_read_sectors =  media_ptr -> fx_media_sector_cache_size;
841
            }
842
#else
843
        for (i = 0; i < media_ptr -> fx_media_sectors_per_FAT; i++)
844
        {
845
846
            /* Calculate the starting next FAT sector.  */
847
            FAT_sector =  media_ptr -> fx_media_reserved_sectors + i;
848
849
            /* Calculate how many sectors to read.  */
850
            FAT_read_sectors =  1;
851
#endif /* FX_DISABLE_CACHE */
852
853
            /* Read the FAT sectors directly from the driver.  */
854
2508992
            media_ptr -> fx_media_driver_request =          FX_DRIVER_READ;
855
2508992
            media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
856
2508992
            media_ptr -> fx_media_driver_buffer =           media_ptr -> fx_media_memory_buffer;
857
2508992
            media_ptr -> fx_media_driver_logical_sector =   FAT_sector;
858
2508992
            media_ptr -> fx_media_driver_sectors =          FAT_read_sectors;
859
2508992
            media_ptr -> fx_media_driver_sector_type =      FX_FAT_SECTOR;
860
861
            /* If trace is enabled, insert this event into the trace buffer.  */
862
            FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_READ, media_ptr, FAT_sector, FAT_read_sectors, media_ptr -> fx_media_memory_buffer, FX_TRACE_INTERNAL_EVENTS, 0, 0)
863
864
            /* Invoke the driver to read the FAT sectors.  */
865
2508992
            (media_ptr -> fx_media_driver_entry) (media_ptr);
866
867
            /* Determine if the read was successful.  */
868
2508992
            if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
869
            {
870
871
                /* Build the "uninitialize" I/O driver request.  */
872
1
                media_ptr -> fx_media_driver_request =      FX_DRIVER_UNINIT;
873
1
                media_ptr -> fx_media_driver_status =       FX_IO_ERROR;
874
875
                /* If trace is enabled, insert this event into the trace buffer.  */
876
                FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_UNINIT, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
877
878
                /* Call the specified I/O driver with the uninitialize request.  */
879
1
                (media_ptr -> fx_media_driver_entry) (media_ptr);
880
881
1
                return(FX_FAT_READ_ERROR);
882
            }
883
884
            /* Calculate the number of bytes in the buffer.  */
885
2508991
            bytes_in_buffer =  (media_ptr -> fx_media_bytes_per_sector * FAT_read_sectors);
886
887
            /* Walk through the sector cache memory to search for available clusters and the first
888
               available if not already found.  */
889
113190054
            for (j = 0; j < bytes_in_buffer;)
890
            {
891
892
                /* Check for a 32-bit FAT.  */
893
110684577
                if (media_ptr -> fx_media_32_bit_FAT)
894
                {
895
896
                    /* Pickup 32-bit FAT entry.  */
897
98092567
                    FAT_entry =  *((ULONG *)&(media_ptr -> fx_media_memory_buffer[j]));
898
899
                    /* Advance to next FAT entry.  */
900
98092567
                    j = j + 4;
901
                }
902
                else
903
                {
904
905
                    /* Process a 16-bit FAT entry.  */
906
12592010
                    FAT_entry =  (((ULONG)(media_ptr -> fx_media_memory_buffer[j])) & 0xFF) |
907
12592010
                        ((((ULONG)(media_ptr -> fx_media_memory_buffer[j + 1])) & 0xFF) << 8);
908
909
                    /* Advance to next FAT entry.  */
910
12592010
                    j =  j + 2;
911
                }
912
913
                /* Determine if the FAT entry is free.  */
914
110684577
                if (FAT_entry == FX_FREE_CLUSTER)
915
                {
916
917
                    /* Entry is free, increment available clusters.  */
918
110657298
                    media_ptr -> fx_media_available_clusters++;
919
920
                    /* Determine if the starting free cluster has been found yet.  */
921
110657298
                    if (media_ptr -> fx_media_cluster_search_start == 0)
922
                    {
923
924
                        /* Remember the first free cluster to start further searches from.  */
925
3516
                        media_ptr -> fx_media_cluster_search_start =  cluster_number;
926
                    }
927
                }
928
929
                /* Increment the cluster number.  */
930
110684577
                cluster_number++;
931
932
                /* Determine if we have reviewed all FAT entries.  */
933
110684577
                if (cluster_number >= (media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START))
934
                {
935
936
                    /* Yes, we have looked at all the FAT entries.  */
937
938
                    /* Ensure that the outer loop terminates as well.  */
939
3514
                    i = media_ptr -> fx_media_sectors_per_FAT;
940
3514
                    break;
941
                }
942
            }
943
        }
944
    }
945
#ifdef FX_ENABLE_EXFAT
946
    else if (media_ptr -> fx_media_FAT_type == FX_exFAT)
947
    {
948
        status = _fx_utility_exFAT_bitmap_initialize(media_ptr);
949
950
        if ((FX_SUCCESS         != status)  &&
951
            (FX_NO_MORE_SPACE   != status))
952
        {
953
            return(status);
954
        }
955
    }
956
#endif /* FX_ENABLE_EXFAT */
957
958
    /* If there were no free clusters, just set the search pointer to the
959
       first cluster number.  */
960
5640
    if (media_ptr -> fx_media_cluster_search_start == 0)
961
    {
962
1
        media_ptr -> fx_media_cluster_search_start =  FX_FAT_ENTRY_START;
963
    }
964
965
    /* Setup the current working directory fields to default to the root
966
       directory.  */
967
5640
    media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name =
968
5640
        media_ptr -> fx_media_default_path.fx_path_name_buffer;
969
5640
    media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_short_name[0] =  0;
970
5640
    media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name[0] =        0;
971
5640
    media_ptr -> fx_media_default_path.fx_path_string[0] =                      (CHAR)0;
972
5640
    media_ptr -> fx_media_default_path.fx_path_string[FX_MAXIMUM_PATH - 1] =      (CHAR)0;
973
5640
    media_ptr -> fx_media_default_path.fx_path_current_entry =                         0;
974
975
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
976
977
    /* Invalidate the previously found directory entry.  */
978
5640
    media_ptr -> fx_media_last_found_name[0] =  0;
979
#endif
980
981
#ifndef FX_DISABLE_FORCE_MEMORY_OPERATION
982
    /* Initialize the opened file linked list and associated counter.  */
983
5640
    media_ptr -> fx_media_opened_file_list =      FX_NULL;
984
5640
    media_ptr -> fx_media_opened_file_count =     0;
985
#endif /* FX_DISABLE_FORCE_MEMORY_OPERATION */
986
987
    /* Create the media protection structure if FX_SINGLE_THREAD is not
988
       defined.  */
989
#ifndef FX_SINGLE_THREAD
990
991
#ifndef FX_DONT_CREATE_MUTEX
992
993
    /* Create ThreadX mutex for protection.  */
994
5640
    tx_mutex_create(&(media_ptr -> fx_media_protect), "FileX Media Mutex", TX_NO_INHERIT);
995
#endif
996
997
#endif
998
999
#ifdef FX_DONT_CREATE_MUTEX
1000
1001
    /* Load the media ID field in the media control block.  This allows the FX_PROTECT
1002
       call to succeed.  */
1003
    media_ptr -> fx_media_id =  (ULONG)FX_MEDIA_ID;
1004
1005
    /* Protect against other threads accessing the media.  */
1006
    FX_PROTECT
1007
#endif
1008
1009
    /* Lockout interrupts.  */
1010
5640
    FX_DISABLE_INTS
1011
1012
    /* At this point, the media has been opened successfully.  Place the
1013
       media on the linked list of currently opened media.  */
1014
1015
    /* Load the media ID field in the media control block.  */
1016
5640
    media_ptr -> fx_media_id =  (ULONG)FX_MEDIA_ID;
1017
1018
    /* Place the thread on the list of opened media.  First,
1019
       check for an empty list.  */
1020
5640
    if (_fx_system_media_opened_ptr)
1021
    {
1022
1023
        /* Pickup tail pointer.  */
1024
5
        tail_ptr =  _fx_system_media_opened_ptr -> fx_media_opened_previous;
1025
1026
        /* Place the new media in the list.  */
1027
5
        _fx_system_media_opened_ptr -> fx_media_opened_previous =  media_ptr;
1028
5
        tail_ptr -> fx_media_opened_next =  media_ptr;
1029
1030
        /* Setup this media's opened links.  */
1031
5
        media_ptr -> fx_media_opened_previous =  tail_ptr;
1032
5
        media_ptr -> fx_media_opened_next =      _fx_system_media_opened_ptr;
1033
    }
1034
    else
1035
    {
1036
1037
        /* The opened media list is empty.  Add the media to empty list.  */
1038
5635
        _fx_system_media_opened_ptr =           media_ptr;
1039
5635
        media_ptr -> fx_media_opened_next =     media_ptr;
1040
5635
        media_ptr -> fx_media_opened_previous = media_ptr;
1041
    }
1042
1043
    /* Increment the opened media counter.  */
1044
5640
    _fx_system_media_opened_count++;
1045
1046
    /* Invoke media open callback. */
1047
5640
    if (media_ptr -> fx_media_open_notify)
1048
    {
1049
1
        media_ptr -> fx_media_open_notify(media_ptr);
1050
    }
1051
1052
    /* Restore interrupts.  */
1053
5640
    FX_RESTORE_INTS
1054
1055
#ifdef FX_DONT_CREATE_MUTEX
1056
1057
    /* Release media protection.  */
1058
    FX_UNPROTECT
1059
#endif
1060
1061
    /* Return a successful status.  */
1062
5640
    return(FX_SUCCESS);
1063
}
1064