GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_media_open.c Lines: 299 299 100.0 %
Date: 2024-03-11 05:15:45 Branches: 88 88 100.0 %

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

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