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

Line Branch Exec Source
1
/**************************************************************************/
2
/*                                                                        */
3
/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4
/*                                                                        */
5
/*       This software is licensed under the Microsoft Software License   */
6
/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7
/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8
/*       and in the root directory of this software.                      */
9
/*                                                                        */
10
/**************************************************************************/
11
12
13
/**************************************************************************/
14
/**************************************************************************/
15
/**                                                                       */
16
/** FileX Component                                                       */
17
/**                                                                       */
18
/**   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
/*  RELEASE HISTORY                                                       */
86
/*                                                                        */
87
/*    DATE              NAME                      DESCRIPTION             */
88
/*                                                                        */
89
/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
90
/*  09-30-2020     William E. Lamie         Modified comment(s),          */
91
/*                                            verified memcpy usage, and  */
92
/*                                            added conditional to        */
93
/*                                            disable cache,              */
94
/*                                            resulting in version 6.1    */
95
/*  04-02-2021     Bhupendra Naphade        Modified comment(s),          */
96
/*                                            updated check for logical   */
97
/*                                            sector value,               */
98
/*                                            resulting in version 6.1.6  */
99
/*  10-31-2022     Tiejun Zhou              Modified comment(s),          */
100
/*                                            fixed memory buffer when    */
101
/*                                            cache is disabled,          */
102
/*                                            resulting in version 6.2.0  */
103
/*                                                                        */
104
/**************************************************************************/
105
9725510
UINT  _fx_utility_logical_sector_read(FX_MEDIA *media_ptr, ULONG64 logical_sector,
106
                                      VOID *buffer_ptr, ULONG sectors, UCHAR sector_type)
107
{
108
#ifndef FX_DISABLE_CACHE
109
FX_CACHED_SECTOR *cache_entry;
110
FX_CACHED_SECTOR *previous_cache_entry;
111
ULONG64           end_sector;
112
#endif /* FX_DISABLE_CACHE */
113
114
#ifdef FX_ENABLE_FAULT_TOLERANT
115
UINT              status;
116
#endif /* FX_ENABLE_FAULT_TOLERANT */
117
118
119
#ifndef FX_MEDIA_STATISTICS_DISABLE
120
121
    /* Determine if the request is for FAT sector.  */
122
9725510
    if (sector_type == FX_FAT_SECTOR)
123
    {
124
125
        /* Increment the number of FAT sector reads.  */
126
6008785
        media_ptr -> fx_media_fat_sector_reads++;
127
    }
128
129
    /* Increment the number of logical sectors read.  */
130
9725510
    media_ptr -> fx_media_logical_sector_reads++;
131
#endif
132
133
    /* Extended port-specific processing macro, which is by default defined to white space.  */
134

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

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

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