GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_utility_logical_sector_read.c Lines: 125 125 100.0 %
Date: 2024-03-11 05:15:45 Branches: 64 64 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
/**   Utility                                                             */
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_utility.h"
30
#ifdef FX_ENABLE_FAULT_TOLERANT
31
#include "fx_fault_tolerant.h"
32
#endif /* FX_ENABLE_FAULT_TOLERANT */
33
34
35
/**************************************************************************/
36
/*                                                                        */
37
/*  FUNCTION                                               RELEASE        */
38
/*                                                                        */
39
/*    _fx_utility_logical_sector_read                     PORTABLE C      */
40
/*                                                           6.2.0        */
41
/*  AUTHOR                                                                */
42
/*                                                                        */
43
/*    William E. Lamie, Microsoft Corporation                             */
44
/*                                                                        */
45
/*  DESCRIPTION                                                           */
46
/*                                                                        */
47
/*    This function handles logical sector read requests for all FileX    */
48
/*    components.  If the logical sector is currently in the logical      */
49
/*    sector cache, the function simply sets the appropriate pointer and  */
50
/*    returns a successful status to the caller.  Otherwise, physical I/O */
51
/*    is requested through the corresponding I/O driver.                  */
52
/*                                                                        */
53
/*    Note: Conversion of the logical sector is done inside the driver.   */
54
/*          This results in a performance boost for FLASH or RAM media    */
55
/*          devices.                                                      */
56
/*                                                                        */
57
/*  INPUT                                                                 */
58
/*                                                                        */
59
/*    media_ptr                             Media control block pointer   */
60
/*    logical_sector                        Logical sector number         */
61
/*    buffer_ptr                            Pointer of receiving buffer   */
62
/*    sectors                               Number of sectors to read     */
63
/*    sector_type                           Type of sector(s) to read     */
64
/*                                                                        */
65
/*  OUTPUT                                                                */
66
/*                                                                        */
67
/*    return status                                                       */
68
/*                                                                        */
69
/*  CALLS                                                                 */
70
/*                                                                        */
71
/*    _fx_utility_logical_sector_cache_entry_read                         */
72
/*                                          Read logical sector cache     */
73
/*    _fx_utility_logical_sector_flush      Flush and invalidate sectors  */
74
/*                                          that overlap with non-cache   */
75
/*                                          sector I/O.                   */
76
/*    _fx_utility_memory_copy               Copy cache sector             */
77
/*    _fx_fault_tolerant_read_directory_sector                            */
78
/*                                          Read directory sector         */
79
/*                                                                        */
80
/*  CALLED BY                                                             */
81
/*                                                                        */
82
/*    FileX System Functions                                              */
83
/*                                                                        */
84
/*  RELEASE HISTORY                                                       */
85
/*                                                                        */
86
/*    DATE              NAME                      DESCRIPTION             */
87
/*                                                                        */
88
/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
89
/*  09-30-2020     William E. Lamie         Modified comment(s),          */
90
/*                                            verified memcpy usage, and  */
91
/*                                            added conditional to        */
92
/*                                            disable cache,              */
93
/*                                            resulting in version 6.1    */
94
/*  04-02-2021     Bhupendra Naphade        Modified comment(s),          */
95
/*                                            updated check for logical   */
96
/*                                            sector value,               */
97
/*                                            resulting in version 6.1.6  */
98
/*  10-31-2022     Tiejun Zhou              Modified comment(s),          */
99
/*                                            fixed memory buffer when    */
100
/*                                            cache is disabled,          */
101
/*                                            resulting in version 6.2.0  */
102
/*                                                                        */
103
/**************************************************************************/
104
9725510
UINT  _fx_utility_logical_sector_read(FX_MEDIA *media_ptr, ULONG64 logical_sector,
105
                                      VOID *buffer_ptr, ULONG sectors, UCHAR sector_type)
106
{
107
#ifndef FX_DISABLE_CACHE
108
FX_CACHED_SECTOR *cache_entry;
109
FX_CACHED_SECTOR *previous_cache_entry;
110
ULONG64           end_sector;
111
#endif /* FX_DISABLE_CACHE */
112
113
#ifdef FX_ENABLE_FAULT_TOLERANT
114
UINT              status;
115
#endif /* FX_ENABLE_FAULT_TOLERANT */
116
117
118
#ifndef FX_MEDIA_STATISTICS_DISABLE
119
120
    /* Determine if the request is for FAT sector.  */
121
9725510
    if (sector_type == FX_FAT_SECTOR)
122
    {
123
124
        /* Increment the number of FAT sector reads.  */
125
6008785
        media_ptr -> fx_media_fat_sector_reads++;
126
    }
127
128
    /* Increment the number of logical sectors read.  */
129
9725510
    media_ptr -> fx_media_logical_sector_reads++;
130
#endif
131
132
    /* Extended port-specific processing macro, which is by default defined to white space.  */
133

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

5310
        if ((media_ptr -> fx_media_driver_status == FX_SUCCESS) && (sectors < (media_ptr -> fx_media_sector_cache_size / 4)))
507
        {
508
509
            /* Yes, read of direct sectors was successful.  */
510
511
            /* Copy the sectors directly read into the cache so they are available on
512
               subsequent read requests.  */
513
4828
            while (sectors)
514
            {
515
516
                /* Attempt to read the cache entry.  */
517
3551
                cache_entry =  _fx_utility_logical_sector_cache_entry_read(media_ptr, logical_sector, &previous_cache_entry);
518
519
                /* Extended port-specific processing macro, which is by default defined to white space.  */
520

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