GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_utility_logical_sector_read.c Lines: 125 125 100.0 %
Date: 2026-03-06 18:49:02 Branches: 64 64 100.0 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 * Copyright (c) 2026-present Eclipse ThreadX contributors
4
 *
5
 * This program and the accompanying materials are made available under the
6
 * terms of the MIT License which is available at
7
 * https://opensource.org/licenses/MIT.
8
 *
9
 * SPDX-License-Identifier: MIT
10
 **************************************************************************/
11
12
13
/**************************************************************************/
14
/**************************************************************************/
15
/**                                                                       */
16
/** FileX Component                                                       */
17
/**                                                                       */
18
/**   Utility                                                             */
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_utility.h"
31
#ifdef FX_ENABLE_FAULT_TOLERANT
32
#include "fx_fault_tolerant.h"
33
#endif /* FX_ENABLE_FAULT_TOLERANT */
34
35
36
/**************************************************************************/
37
/*                                                                        */
38
/*  FUNCTION                                               RELEASE        */
39
/*                                                                        */
40
/*    _fx_utility_logical_sector_read                     PORTABLE C      */
41
/*                                                           6.2.0        */
42
/*  AUTHOR                                                                */
43
/*                                                                        */
44
/*    William E. Lamie, Microsoft Corporation                             */
45
/*                                                                        */
46
/*  DESCRIPTION                                                           */
47
/*                                                                        */
48
/*    This function handles logical sector read requests for all FileX    */
49
/*    components.  If the logical sector is currently in the logical      */
50
/*    sector cache, the function simply sets the appropriate pointer and  */
51
/*    returns a successful status to the caller.  Otherwise, physical I/O */
52
/*    is requested through the corresponding I/O driver.                  */
53
/*                                                                        */
54
/*    Note: Conversion of the logical sector is done inside the driver.   */
55
/*          This results in a performance boost for FLASH or RAM media    */
56
/*          devices.                                                      */
57
/*                                                                        */
58
/*  INPUT                                                                 */
59
/*                                                                        */
60
/*    media_ptr                             Media control block pointer   */
61
/*    logical_sector                        Logical sector number         */
62
/*    buffer_ptr                            Pointer of receiving buffer   */
63
/*    sectors                               Number of sectors to read     */
64
/*    sector_type                           Type of sector(s) to read     */
65
/*                                                                        */
66
/*  OUTPUT                                                                */
67
/*                                                                        */
68
/*    return status                                                       */
69
/*                                                                        */
70
/*  CALLS                                                                 */
71
/*                                                                        */
72
/*    _fx_utility_logical_sector_cache_entry_read                         */
73
/*                                          Read logical sector cache     */
74
/*    _fx_utility_logical_sector_flush      Flush and invalidate sectors  */
75
/*                                          that overlap with non-cache   */
76
/*                                          sector I/O.                   */
77
/*    _fx_utility_memory_copy               Copy cache sector             */
78
/*    _fx_fault_tolerant_read_directory_sector                            */
79
/*                                          Read directory sector         */
80
/*                                                                        */
81
/*  CALLED BY                                                             */
82
/*                                                                        */
83
/*    FileX System Functions                                              */
84
/*                                                                        */
85
/**************************************************************************/
86
9725510
UINT  _fx_utility_logical_sector_read(FX_MEDIA *media_ptr, ULONG64 logical_sector,
87
                                      VOID *buffer_ptr, ULONG sectors, UCHAR sector_type)
88
{
89
#ifndef FX_DISABLE_CACHE
90
FX_CACHED_SECTOR *cache_entry;
91
FX_CACHED_SECTOR *previous_cache_entry;
92
ULONG64           end_sector;
93
#endif /* FX_DISABLE_CACHE */
94
95
#ifdef FX_ENABLE_FAULT_TOLERANT
96
UINT              status;
97
#endif /* FX_ENABLE_FAULT_TOLERANT */
98
99
100
#ifndef FX_MEDIA_STATISTICS_DISABLE
101
102
    /* Determine if the request is for FAT sector.  */
103
9725510
    if (sector_type == FX_FAT_SECTOR)
104
    {
105
106
        /* Increment the number of FAT sector reads.  */
107
6008785
        media_ptr -> fx_media_fat_sector_reads++;
108
    }
109
110
    /* Increment the number of logical sectors read.  */
111
9725510
    media_ptr -> fx_media_logical_sector_reads++;
112
#endif
113
114
    /* Extended port-specific processing macro, which is by default defined to white space.  */
115

9725510
    FX_UTILITY_LOGICAL_SECTOR_READ_EXTENSION
116
117
#ifndef FX_DISABLE_CACHE
118
    /* Determine if the request is for the internal media buffer area.  */
119
9695034
    if ((((UCHAR *)buffer_ptr) >= media_ptr -> fx_media_memory_buffer) &&
120
9689723
        (((UCHAR *)buffer_ptr) <= media_ptr -> fx_media_sector_cache_end))
121
    {
122
123
        /* Internal cache buffer is requested.  */
124
125
        /* Examine the logical sector cache.  */
126
9689713
        cache_entry = _fx_utility_logical_sector_cache_entry_read(media_ptr, logical_sector, &previous_cache_entry);
127
128
        /* Was the sector found?  */
129
9689713
        if (cache_entry == FX_NULL)
130
        {
131
132
            /* Yes, the sector was found. Return success!  */
133
7025560
            return(FX_SUCCESS);
134
        }
135
136
        /* At this point, we need to read in a sector from the media.  */
137
138
#ifndef FX_MEDIA_STATISTICS_DISABLE
139
140
        /* Increment the number of logical sectors cache read misses.  */
141
2664153
        media_ptr -> fx_media_logical_sector_cache_read_misses++;
142
#endif
143
144
#ifndef FX_MEDIA_STATISTICS_DISABLE
145
146
        /* If trace is enabled, insert this event into the trace buffer.  */
147
        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_LOG_SECTOR_CACHE_MISS, media_ptr, logical_sector, media_ptr -> fx_media_logical_sector_cache_read_misses, media_ptr -> fx_media_sector_cache_size, FX_TRACE_INTERNAL_EVENTS, 0, 0)
148
#else
149
150
        /* If trace is enabled, insert this event into the trace buffer.  */
151
        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_LOG_SECTOR_CACHE_MISS, media_ptr, logical_sector, 0, media_ptr -> fx_media_sector_cache_size, FX_TRACE_INTERNAL_EVENTS, 0, 0)
152
#endif
153
154
        /* First, check and see if the last used entry has been
155
           modified.  */
156
2664153
        if ((cache_entry -> fx_cached_sector_valid) &&
157
984800
            (cache_entry -> fx_cached_sector_buffer_dirty))
158
        {
159
160
            /* Yes, we need to flush this buffer out to the physical media
161
               before we read in the new buffer.  */
162
163
#ifndef FX_MEDIA_STATISTICS_DISABLE
164
165
            /* Increment the number of driver write sector(s) requests.  */
166
233241
            media_ptr -> fx_media_driver_write_requests++;
167
#endif
168
169
            /* Build write request to the driver.  */
170
233241
            media_ptr -> fx_media_driver_request =          FX_DRIVER_WRITE;
171
233241
            media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
172
233241
            media_ptr -> fx_media_driver_buffer =           cache_entry -> fx_cached_sector_memory_buffer;
173
#ifdef FX_DRIVER_USE_64BIT_LBA
174
            media_ptr -> fx_media_driver_logical_sector =   cache_entry -> fx_cached_sector;
175
#else
176
233241
            media_ptr -> fx_media_driver_logical_sector =   (ULONG)cache_entry -> fx_cached_sector;
177
#endif
178
233241
            media_ptr -> fx_media_driver_sectors =          1;
179
233241
            media_ptr -> fx_media_driver_sector_type =      cache_entry -> fx_cached_sector_type;
180
181
            /* Determine if the sector is a data sector or a system sector.  */
182
233241
            if (cache_entry -> fx_cached_sector_type != FX_DATA_SECTOR)
183
            {
184
185
                /* System sector is present.  */
186
180409
                media_ptr -> fx_media_driver_system_write =  FX_TRUE;
187
            }
188
189
            /* If trace is enabled, insert this event into the trace buffer.  */
190
            FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_WRITE, media_ptr, cache_entry -> fx_cached_sector, 1, cache_entry -> fx_cached_sector_memory_buffer, FX_TRACE_INTERNAL_EVENTS, 0, 0)
191
192
            /* Invoke the driver to write the sector.  */
193
233241
            (media_ptr -> fx_media_driver_entry) (media_ptr);
194
195
            /* Clear the system write flag.  */
196
233241
            media_ptr -> fx_media_driver_system_write =  FX_FALSE;
197
198
            /* Check for successful completion.  */
199
233241
            if (media_ptr -> fx_media_driver_status)
200
            {
201
202
                /* Error writing a cached sector out.  Return the
203
                   error status.  */
204
21862
                return(media_ptr -> fx_media_driver_status);
205
            }
206
207
            /* Clear the buffer dirty flag since it has been flushed
208
               out.  */
209
211379
            cache_entry -> fx_cached_sector_buffer_dirty =  FX_FALSE;
210
211
            /* Decrement the number of outstanding dirty cache entries.  */
212
211379
            media_ptr -> fx_media_sector_cache_dirty_count--;
213
        }
214
215
        /* At this point, we can go out and setup this cached sector
216
           entry.  */
217
218
        /* Compare against logical sector to make sure it is valid.  */
219
2642291
        if (logical_sector >= media_ptr -> fx_media_total_sectors)
220
        {
221
4
            return(FX_SECTOR_INVALID);
222
        }
223
224
#ifndef FX_MEDIA_STATISTICS_DISABLE
225
226
        /* Increment the number of driver read sector(s) requests.  */
227
2642287
        media_ptr -> fx_media_driver_read_requests++;
228
#endif
229
230
        /* Build Read request to the driver.  */
231
2642287
        media_ptr -> fx_media_driver_request =          FX_DRIVER_READ;
232
2642287
        media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
233
2642287
        media_ptr -> fx_media_driver_buffer =           cache_entry -> fx_cached_sector_memory_buffer;
234
#ifdef FX_DRIVER_USE_64BIT_LBA
235
        media_ptr -> fx_media_driver_logical_sector =   logical_sector;
236
#else
237
2642287
        media_ptr -> fx_media_driver_logical_sector =   (ULONG)logical_sector;
238
#endif
239
2642287
        media_ptr -> fx_media_driver_sectors =          1;
240
2642287
        media_ptr -> fx_media_driver_sector_type =      sector_type;
241
242
        /* Determine if the sector is a data sector or a system sector.  */
243
2642287
        if (sector_type == FX_DATA_SECTOR)
244
        {
245
246
            /* Data sector is present.  */
247
106977
            media_ptr -> fx_media_driver_data_sector_read =  FX_TRUE;
248
        }
249
250
        /* If trace is enabled, insert this event into the trace buffer.  */
251
        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_READ, media_ptr, logical_sector, 1, cache_entry -> fx_cached_sector_memory_buffer, FX_TRACE_INTERNAL_EVENTS, 0, 0)
252
253
        /* Invoke the driver to read the sector.  */
254
2642287
        (media_ptr -> fx_media_driver_entry) (media_ptr);
255
256
        /* Clear data sector is present flag.  */
257
2642287
        media_ptr -> fx_media_driver_data_sector_read =  FX_FALSE;
258
259
        /* Determine if the read was successful.  */
260
2642287
        if (media_ptr -> fx_media_driver_status == FX_SUCCESS)
261
        {
262
263
            /* Remember the sector number.  */
264
1995414
            cache_entry -> fx_cached_sector =  logical_sector;
265
266
            /* Make the cache entry valid.  */
267
1995414
            cache_entry -> fx_cached_sector_valid =  FX_TRUE;
268
269
            /* Remember the sector type.  */
270
1995414
            cache_entry -> fx_cached_sector_type =  sector_type;
271
272
            /* Place this entry that the head of the cached sector
273
               list.  */
274
275
            /* Determine if we need to update the last used list.  */
276
1995414
            if (previous_cache_entry)
277
            {
278
279
                /* Yes, the current entry is not at the front of the list
280
                   so we need to change the order.  */
281
282
                /* Link the previous entry to this entry's next pointer.  */
283
7650
                previous_cache_entry -> fx_cached_sector_next_used =
284
7650
                    cache_entry -> fx_cached_sector_next_used;
285
286
                /* Place this entry at the head of the list.  */
287
7650
                cache_entry -> fx_cached_sector_next_used =
288
7650
                    media_ptr -> fx_media_sector_cache_list_ptr;
289
7650
                media_ptr -> fx_media_sector_cache_list_ptr =  cache_entry;
290
            }
291
292
#ifdef FX_ENABLE_FAULT_TOLERANT
293
            if (media_ptr -> fx_media_fault_tolerant_enabled &&
294
                (media_ptr -> fx_media_fault_tolerant_state & FX_FAULT_TOLERANT_STATE_STARTED) &&
295
                (sector_type == FX_DIRECTORY_SECTOR))
296
            {
297
298
                /* Read sector from log file. */
299
                status = _fx_fault_tolerant_read_directory_sector(media_ptr, logical_sector, cache_entry -> fx_cached_sector_memory_buffer, 1);
300
301
                /* Check for successful completion.  */
302
                if (status)
303
                {
304
305
                    /* Return the error status. */
306
                    return(status);
307
                }
308
            }
309
#endif /* FX_ENABLE_FAULT_TOLERANT */
310
        }
311
        else
312
        {
313
314
            /* Invalidate the cache entry on read errors.  */
315
646873
            cache_entry -> fx_cached_sector_valid =  FX_FALSE;
316
317
            /* Put all ones in the sector value.  */
318
646873
            cache_entry -> fx_cached_sector =  (~(ULONG64)0);
319
        }
320
321
        /* Simply setup the pointer to this buffer and return.  */
322
2642287
        media_ptr -> fx_media_memory_buffer =  cache_entry -> fx_cached_sector_memory_buffer;
323
324
        /* Return the driver status.  */
325
2642287
        return(media_ptr -> fx_media_driver_status);
326
    }
327
#else
328
    if ((logical_sector == media_ptr -> fx_media_memory_buffer_sector) && (sectors == 1) && (buffer_ptr == media_ptr -> fx_media_memory_buffer))
329
    {
330
#ifdef FX_ENABLE_FAULT_TOLERANT
331
        if (media_ptr -> fx_media_fault_tolerant_enabled &&
332
            (media_ptr -> fx_media_fault_tolerant_state & FX_FAULT_TOLERANT_STATE_STARTED) &&
333
            (sector_type == FX_DIRECTORY_SECTOR))
334
        {
335
336
            /* Read sector from log file. */
337
            status = _fx_fault_tolerant_read_directory_sector(media_ptr, logical_sector, buffer_ptr, 1);
338
339
            /* Check for successful completion.  */
340
            if (status)
341
            {
342
343
                /* Return the error status. */
344
                return(status);
345
            }
346
        }
347
#endif /* FX_ENABLE_FAULT_TOLERANT */
348
        return(FX_SUCCESS);
349
    }
350
#endif
351
    else
352
    {
353
354
        /* Direct I/O to application buffer area.  */
355
356
        /* Compare against logical sector to make sure it is valid.  */
357
5321
        if ((logical_sector + sectors - 1) > (ULONG)media_ptr -> fx_media_total_sectors)
358
        {
359
1
            return(FX_SECTOR_INVALID);
360
        }
361
362
#ifndef FX_DISABLE_CACHE
363
        /* Attempt to fill the beginning of the buffer from cached sectors.  */
364
5332
        while (sectors)
365
        {
366
367
            /* Determine if the sector is in the cache.  */
368
5322
            if (_fx_utility_logical_sector_cache_entry_read(media_ptr, logical_sector, &previous_cache_entry))
369
            {
370
371
                /* Not in the cache - get out of the loop!  */
372
5310
                break;
373
            }
374
375
            /* Yes, sector is in the cache. Copy the data from the cache to the destination buffer.  */
376
12
            _fx_utility_memory_copy(media_ptr -> fx_media_memory_buffer, buffer_ptr, media_ptr -> fx_media_bytes_per_sector); /* Use case of memcpy is verified. */
377
378
            /* Advance the destination buffer.  */
379
12
            buffer_ptr =  ((UCHAR *)buffer_ptr) + media_ptr -> fx_media_bytes_per_sector;
380
381
            /* Advance the sector and decrement the number of sectors left.  */
382
12
            logical_sector++;
383
12
            sectors--;
384
        }
385
386
        /* Calculate the end sector.  */
387
5320
        end_sector = logical_sector + sectors - 1;
388
389
        /* Attempt to fill the end of the buffer from the opposite direction.  */
390
5331
        while (sectors)
391
        {
392
393
            /* Determine if the sector is in the cache.  */
394
5321
            if (_fx_utility_logical_sector_cache_entry_read(media_ptr, end_sector, &previous_cache_entry))
395
            {
396
397
                /* Not in the cache - get out of the loop!  */
398
5310
                break;
399
            }
400
401
            /* Yes, sector is in the cache. Copy the data from the cache to the destination buffer.  */
402
11
            _fx_utility_memory_copy(media_ptr -> fx_media_memory_buffer, /* Use case of memcpy is verified. */
403
11
                                    ((UCHAR *)buffer_ptr) + ((sectors - 1) * media_ptr -> fx_media_bytes_per_sector),
404
11
                                    media_ptr -> fx_media_bytes_per_sector);
405
406
            /* Move sector to previous sector and decrement the number of sectors left.  */
407
11
            end_sector--;
408
11
            sectors--;
409
        }
410
411
        /* Determine if there are still sectors left to read.  */
412
5320
        if (sectors == 0)
413
        {
414
415
            /* No more sectors to read - return success!  */
416
10
            return(FX_SUCCESS);
417
        }
418
419
        /* Flush and invalidate any entries in the cache that are in this direct I/O read request range.  */
420
5310
        _fx_utility_logical_sector_flush(media_ptr, logical_sector, (ULONG64) sectors, FX_TRUE);
421
#endif /* FX_DISABLE_CACHE */
422
423
#ifndef FX_MEDIA_STATISTICS_DISABLE
424
425
        /* Increment the number of driver read sector(s) requests.  */
426
5310
        media_ptr -> fx_media_driver_read_requests++;
427
#endif
428
429
        /* Build read request to the driver.  */
430
5310
        media_ptr -> fx_media_driver_request =          FX_DRIVER_READ;
431
5310
        media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
432
5310
        media_ptr -> fx_media_driver_buffer =           buffer_ptr;
433
#ifdef FX_DRIVER_USE_64BIT_LBA
434
        media_ptr -> fx_media_driver_logical_sector =   logical_sector;
435
#else
436
5310
        media_ptr -> fx_media_driver_logical_sector =   (ULONG)logical_sector;
437
#endif
438
5310
        media_ptr -> fx_media_driver_sectors =          sectors;
439
5310
        media_ptr -> fx_media_driver_sector_type =      sector_type;
440
441
        /* Determine if the sector is a data sector or a system sector.  */
442
5310
        if (sector_type == FX_DATA_SECTOR)
443
        {
444
445
            /* Data sector is present.  */
446
5301
            media_ptr -> fx_media_driver_data_sector_read =  FX_TRUE;
447
        }
448
449
        /* If trace is enabled, insert this event into the trace buffer.  */
450
        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_READ, media_ptr, logical_sector, sectors, buffer_ptr, FX_TRACE_INTERNAL_EVENTS, 0, 0)
451
452
        /* Invoke the driver to read the sector.  */
453
5310
        (media_ptr -> fx_media_driver_entry) (media_ptr);
454
455
        /* Clear data sector is present flag.  */
456
5310
        media_ptr -> fx_media_driver_data_sector_read =  FX_FALSE;
457
458
#ifdef FX_DISABLE_CACHE
459
        if ((media_ptr -> fx_media_driver_status == FX_SUCCESS) && (sectors == 1) && (buffer_ptr == media_ptr -> fx_media_memory_buffer))
460
        {
461
            media_ptr -> fx_media_memory_buffer_sector = logical_sector;
462
#ifdef FX_ENABLE_FAULT_TOLERANT
463
            if (media_ptr -> fx_media_fault_tolerant_enabled &&
464
                (media_ptr -> fx_media_fault_tolerant_state & FX_FAULT_TOLERANT_STATE_STARTED) &&
465
                (sector_type == FX_DIRECTORY_SECTOR))
466
            {
467
468
                /* Read sector from log file. */
469
                status = _fx_fault_tolerant_read_directory_sector(media_ptr, logical_sector, buffer_ptr, 1);
470
471
                /* Check for successful completion.  */
472
                if (status)
473
                {
474
475
                    /* Return the error status. */
476
                    return(status);
477
                }
478
            }
479
#endif /* FX_ENABLE_FAULT_TOLERANT */
480
            return(FX_SUCCESS);
481
        }
482
#endif /* FX_DISABLE_CACHE */
483
484
#ifndef FX_DISABLE_DIRECT_DATA_READ_CACHE_FILL
485
486
        /* Determine if the read was successful and if number of sectors just read will
487
           reasonably fit into the cache.  */
488

5310
        if ((media_ptr -> fx_media_driver_status == FX_SUCCESS) && (sectors < (media_ptr -> fx_media_sector_cache_size / 4)))
489
        {
490
491
            /* Yes, read of direct sectors was successful.  */
492
493
            /* Copy the sectors directly read into the cache so they are available on
494
               subsequent read requests.  */
495
4828
            while (sectors)
496
            {
497
498
                /* Attempt to read the cache entry.  */
499
3551
                cache_entry =  _fx_utility_logical_sector_cache_entry_read(media_ptr, logical_sector, &previous_cache_entry);
500
501
                /* Extended port-specific processing macro, which is by default defined to white space.  */
502

3551
                FX_UTILITY_LOGICAL_SECTOR_READ_EXTENSION_1
503
504
                /* At this point, a cache entry should always be present since we invalidated
505
                   the cache over this sector range previously. In any case, check for the error
506
                   condition.  */
507
3551
                if (cache_entry == FX_NULL)
508
                {
509
510
                    /* This case should never happen, however, if it does simply give up on updating the
511
                       cache with the sectors from the direct read.  */
512
1
                    return(FX_SUCCESS);
513
                }
514
515
                /* Determine if the cache entry is dirty and needs to be written out before it is used.  */
516
3550
                if ((cache_entry -> fx_cached_sector_valid) &&
517
3433
                    (cache_entry -> fx_cached_sector_buffer_dirty))
518
                {
519
520
                    /* Yes, we need to flush this buffer out to the physical media
521
                       before we read in the new buffer.  */
522
523
#ifndef FX_MEDIA_STATISTICS_DISABLE
524
525
                    /* Increment the number of driver write sector(s) requests.  */
526
132
                    media_ptr -> fx_media_driver_write_requests++;
527
#endif
528
529
                    /* Build write request to the driver.  */
530
132
                    media_ptr -> fx_media_driver_request =          FX_DRIVER_WRITE;
531
132
                    media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
532
132
                    media_ptr -> fx_media_driver_buffer =           cache_entry -> fx_cached_sector_memory_buffer;
533
#ifdef FX_DRIVER_USE_64BIT_LBA
534
                    media_ptr -> fx_media_driver_logical_sector =   cache_entry -> fx_cached_sector;
535
#else
536
132
                    media_ptr -> fx_media_driver_logical_sector =   (ULONG)cache_entry -> fx_cached_sector;
537
#endif
538
132
                    media_ptr -> fx_media_driver_sectors =          1;
539
132
                    media_ptr -> fx_media_driver_sector_type =      cache_entry -> fx_cached_sector_type;
540
541
                    /* Only data sectors may be dirty when FX_FAULT_TOLERANT is defined */
542
#ifndef FX_FAULT_TOLERANT
543
                    /* Determine if the sector is a data sector or a system sector.  */
544
132
                    if (cache_entry -> fx_cached_sector_type != FX_DATA_SECTOR)
545
                    {
546
547
                        /* System sector is present.  */
548
44
                        media_ptr -> fx_media_driver_system_write =  FX_TRUE;
549
                    }
550
#endif /* FX_FAULT_TOLERANT */
551
552
                    /* If trace is enabled, insert this event into the trace buffer.  */
553
                    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_WRITE, media_ptr, cache_entry -> fx_cached_sector, 1, cache_entry -> fx_cached_sector_memory_buffer, FX_TRACE_INTERNAL_EVENTS, 0, 0)
554
555
                    /* Invoke the driver to write the sector.  */
556
132
                    (media_ptr -> fx_media_driver_entry) (media_ptr);
557
558
                    /* Clear the system write flag.  */
559
132
                    media_ptr -> fx_media_driver_system_write =  FX_FALSE;
560
561
                    /* Check for successful completion.  */
562
132
                    if (media_ptr -> fx_media_driver_status)
563
                    {
564
565
                        /* Error writing a cached sector out.  Return the
566
                           error status.  */
567
1
                        return(media_ptr -> fx_media_driver_status);
568
                    }
569
570
                    /* Clear the buffer dirty flag since it has been flushed
571
                       out.  */
572
131
                    cache_entry -> fx_cached_sector_buffer_dirty =  FX_FALSE;
573
574
                    /* Decrement the number of outstanding dirty cache entries.  */
575
131
                    media_ptr -> fx_media_sector_cache_dirty_count--;
576
                }
577
578
                /* Now setup the cache entry with information from the new sector.  */
579
580
                /* Remember the sector number.  */
581
3549
                cache_entry -> fx_cached_sector =  logical_sector;
582
583
                /* Make the cache entry valid.  */
584
3549
                cache_entry -> fx_cached_sector_valid =  FX_TRUE;
585
586
                /* Remember the sector type.  */
587
3549
                cache_entry -> fx_cached_sector_type =  sector_type;
588
589
                /* Place this entry that the head of the cached sector
590
                   list.  */
591
592
                /* Determine if we need to update the last used list.  */
593
3549
                if (previous_cache_entry)
594
                {
595
596
                    /* Yes, the current entry is not at the front of the list
597
                       so we need to change the order.  */
598
599
                    /* Link the previous entry to this entry's next pointer.  */
600
34
                    previous_cache_entry -> fx_cached_sector_next_used =
601
34
                        cache_entry -> fx_cached_sector_next_used;
602
603
                    /* Place this entry at the head of the list.  */
604
34
                    cache_entry -> fx_cached_sector_next_used =
605
34
                        media_ptr -> fx_media_sector_cache_list_ptr;
606
34
                    media_ptr -> fx_media_sector_cache_list_ptr =  cache_entry;
607
                }
608
609
                /* Copy the data from the destination buffer to the cache entry.  */
610
3549
                _fx_utility_memory_copy(buffer_ptr, /* Use case of memcpy is verified. */
611
                                        cache_entry -> fx_cached_sector_memory_buffer,
612
3549
                                        media_ptr -> fx_media_bytes_per_sector);
613
614
                /* Advance the destination buffer.  */
615
3549
                buffer_ptr =  ((UCHAR *)buffer_ptr) + media_ptr -> fx_media_bytes_per_sector;
616
617
                /* Advance the source sector and decrement the sector count.  */
618
3549
                logical_sector++;
619
3549
                sectors--;
620
            }
621
        }
622
#endif
623
624
        /* Return the driver status.  */
625
5308
        return(media_ptr -> fx_media_driver_status);
626
    }
627
}
628