GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_utility_FAT_entry_write.c Lines: 40 40 100.0 %
Date: 2024-01-10 21:53:23 Branches: 20 20 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_FAT_entry_write                         PORTABLE C      */
41
/*                                                           6.1          */
42
/*  AUTHOR                                                                */
43
/*                                                                        */
44
/*    William E. Lamie, Microsoft Corporation                             */
45
/*                                                                        */
46
/*  DESCRIPTION                                                           */
47
/*                                                                        */
48
/*    This function writes to the supplied FAT entry to all FATs in       */
49
/*    the media.  12-bit, 16-bit, and 32-bit FAT writing is supported.    */
50
/*                                                                        */
51
/*  INPUT                                                                 */
52
/*                                                                        */
53
/*    media_ptr                             Media control block pointer   */
54
/*    cluster                               Cluster entry number          */
55
/*    next_cluster                          Next cluster integer pointer  */
56
/*                                                                        */
57
/*  OUTPUT                                                                */
58
/*                                                                        */
59
/*    return status                                                       */
60
/*                                                                        */
61
/*  CALLS                                                                 */
62
/*                                                                        */
63
/*    _fx_utility_FAT_flush                 FLUSH dirty entries in the    */
64
/*                                            FAT cache                   */
65
/*    _fx_fault_tolerant_add_fat_log        Add FAT redo log              */
66
/*                                                                        */
67
/*  CALLED BY                                                             */
68
/*                                                                        */
69
/*    FileX System Functions                                              */
70
/*                                                                        */
71
/*  RELEASE HISTORY                                                       */
72
/*                                                                        */
73
/*    DATE              NAME                      DESCRIPTION             */
74
/*                                                                        */
75
/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
76
/*  09-30-2020     William E. Lamie         Modified comment(s),          */
77
/*                                            resulting in version 6.1    */
78
/*                                                                        */
79
/**************************************************************************/
80
3575357
UINT  _fx_utility_FAT_entry_write(FX_MEDIA *media_ptr, ULONG cluster, ULONG next_cluster)
81
{
82
83
UINT                status, index, i;
84
FX_FAT_CACHE_ENTRY *cache_entry_ptr;
85
#ifdef FX_ENABLE_FAULT_TOLERANT
86
ULONG               FAT_sector;
87
88
    /* While fault_tolerant is enabled, only FAT entries in the same sector are allowed to be cached. */
89
    /* We must flush FAT sectors in the order of FAT chains. */
90
    if (media_ptr -> fx_media_fault_tolerant_enabled &&
91
        (media_ptr -> fx_media_fault_tolerant_state & FX_FAULT_TOLERANT_STATE_STARTED))
92
    {
93
94
        if (!(media_ptr -> fx_media_fault_tolerant_state & FX_FAULT_TOLERANT_STATE_SET_FAT_CHAIN))
95
        {
96
97
            /* Redirect this request to log file. */
98
            return(_fx_fault_tolerant_add_FAT_log(media_ptr, cluster, next_cluster));
99
        }
100
101
        /* Get sector number of the incoming FAT entry. */
102
        FAT_sector = _fx_utility_FAT_sector_get(media_ptr, cluster);
103
104
        /* Is FAT sector changed? */
105
        if (FAT_sector != media_ptr -> fx_media_fault_tolerant_cached_FAT_sector)
106
        {
107
108
            /* Are there any cached FAT entries? */
109
            if (media_ptr -> fx_media_fault_tolerant_cached_FAT_sector)
110
            {
111
112
                /* Current FAT entry is located in different sector. Force flush. */
113
                /* Flush the cached individual FAT entries */
114
                _fx_utility_FAT_flush(media_ptr);
115
116
#ifdef FX_ENABLE_EXFAT
117
                if (media_ptr -> fx_media_FAT_type == FX_exFAT)
118
                {
119
120
                    /* Flush exFAT bitmap.  */
121
                    _fx_utility_exFAT_bitmap_flush(media_ptr);
122
                }
123
#endif /* FX_ENABLE_EXFAT */
124
            }
125
126
            /* Record sector number of current FAT entry. */
127
            media_ptr -> fx_media_fault_tolerant_cached_FAT_sector = FAT_sector;
128
        }
129
    }
130
#endif /* FX_ENABLE_FAULT_TOLERANT */
131
132
#ifndef FX_MEDIA_STATISTICS_DISABLE
133
    /* Increment the number of FAT entry writes and cache hits.  */
134
3575357
    media_ptr -> fx_media_fat_entry_writes++;
135
3575357
    media_ptr -> fx_media_fat_entry_cache_write_hits++;
136
#endif
137
138
    /* Extended port-specific processing macro, which is by default defined to white space.  */
139

3575357
    FX_UTILITY_FAT_ENTRY_WRITE_EXTENSION
140
141
    /* Calculate the area of the cache for this FAT entry.  */
142
3575337
    index =  (cluster & FX_FAT_CACHE_HASH_MASK) * FX_FAT_CACHE_DEPTH;
143
144
    /* Build a pointer to the cache entry.  */
145
3575337
    cache_entry_ptr =  &media_ptr -> fx_media_fat_cache[index];
146
147
    /* First search for the entry in the FAT entry cache.  */
148
13127340
    for (i = 0; i < FX_FAT_CACHE_DEPTH; i++)
149
    {
150
151
        /* See if the entry matches the write request.  */
152
10811839
        if (((cache_entry_ptr + i) -> fx_fat_cache_entry_cluster) == cluster)
153
        {
154
155
            /* Yes, we have a matching entry.  Save the new information in the FAT
156
               cache and mark this entry as dirty.  */
157
1259836
            (cache_entry_ptr + i) -> fx_fat_cache_entry_value =     next_cluster;
158
1259836
            (cache_entry_ptr + i) -> fx_fat_cache_entry_dirty =     1;
159
160
            /* Determine if the driver has requested notification when data sectors in the media
161
               become free.  This can be useful to FLASH manager software.  */
162

1259836
            if ((media_ptr -> fx_media_driver_free_sector_update) && (next_cluster == FX_FREE_CLUSTER))
163
            {
164
165
                /* Yes, the driver does wish to know that these specific sector(s) are
166
                   not in use.  */
167
168
#ifndef FX_MEDIA_STATISTICS_DISABLE
169
170
                /* Increment the number of driver release sectors requests.  */
171
96495
                media_ptr -> fx_media_driver_release_sectors_requests++;
172
#endif
173
174
                /* This cluster is being released so inform the driver that the
175
                   corresponding sectors are now available.  */
176
96495
                media_ptr -> fx_media_driver_request =          FX_DRIVER_RELEASE_SECTORS;
177
96495
                media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
178
96495
                media_ptr -> fx_media_driver_logical_sector =   (media_ptr -> fx_media_data_sector_start +
179
96495
                                                                 ((cluster - FX_FAT_ENTRY_START) * media_ptr -> fx_media_sectors_per_cluster));
180
96495
                media_ptr -> fx_media_driver_sectors =          media_ptr -> fx_media_sectors_per_cluster;
181
182
                /* If trace is enabled, insert this event into the trace buffer.  */
183
                FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_RELEASE_SECTORS, media_ptr, media_ptr -> fx_media_driver_logical_sector, media_ptr -> fx_media_driver_sectors, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
184
185
                /* Call the driver.  */
186
96495
                (media_ptr -> fx_media_driver_entry)(media_ptr);
187
            }
188
189
            /* Done, return successful status.  */
190
1259836
            return(FX_SUCCESS);
191
        }
192
    }
193
194
    /* If we reach this point, we know that the FAT write request is not in
195
       the cache.  */
196
197
#ifndef FX_MEDIA_STATISTICS_DISABLE
198
    /* Decrement the number of cache hits.  */
199
2315501
    media_ptr -> fx_media_fat_entry_cache_write_hits--;
200
201
    /* Increment the number of cache misses.  */
202
2315501
    media_ptr -> fx_media_fat_entry_cache_write_misses++;
203
#endif
204
205
    /* Determine if the oldest entry is dirty and needs to be flushed.  */
206
2315501
    if (media_ptr -> fx_media_fat_cache[index + 3].fx_fat_cache_entry_dirty == 1)
207
    {
208
209
        /* Flush the dirty entry so it can be used to hold the current
210
           FAT entry write request.  */
211
87811
        status = _fx_utility_FAT_flush(media_ptr);
212
213
        /* Determine if the write was successful.  */
214
87811
        if (status != FX_SUCCESS)
215
        {
216
217
            /* No, return error status to caller.  */
218
47410
            return(status);
219
        }
220
221
    }
222
223
    /* Move all the cache entries down so the oldest is at the bottom.  */
224
2268091
    *(cache_entry_ptr + 3) =  *(cache_entry_ptr + 2);
225
2268091
    *(cache_entry_ptr + 2) =  *(cache_entry_ptr + 1);
226
2268091
    *(cache_entry_ptr + 1) =  *(cache_entry_ptr);
227
228
    /* Save the current FAT entry write request and mark as dirty.  */
229
2268091
    cache_entry_ptr -> fx_fat_cache_entry_dirty =    1;
230
2268091
    cache_entry_ptr -> fx_fat_cache_entry_cluster =  cluster;
231
2268091
    cache_entry_ptr -> fx_fat_cache_entry_value =    next_cluster;
232
233
    /* Determine if the driver has requested notification when data sectors in the media
234
       become free.  This can be useful to FLASH manager software.  */
235

2268091
    if ((media_ptr -> fx_media_driver_free_sector_update) && (next_cluster == FX_FREE_CLUSTER))
236
    {
237
238
        /* Yes, the driver does wish to know that these specific sector(s) are
239
           not in use.  */
240
241
#ifndef FX_MEDIA_STATISTICS_DISABLE
242
243
        /* Increment the number of driver release sectors requests.  */
244
66382
        media_ptr -> fx_media_driver_release_sectors_requests++;
245
#endif
246
247
        /* This cluster is being released so inform the driver that the
248
              corresponding sectors are now available.  */
249
66382
        media_ptr -> fx_media_driver_request =          FX_DRIVER_RELEASE_SECTORS;
250
66382
        media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
251
66382
        media_ptr -> fx_media_driver_logical_sector =   (media_ptr -> fx_media_data_sector_start +
252
66382
                                                         ((cluster - FX_FAT_ENTRY_START) * media_ptr -> fx_media_sectors_per_cluster));
253
66382
        media_ptr -> fx_media_driver_sectors =          media_ptr -> fx_media_sectors_per_cluster;
254
255
        /* If trace is enabled, insert this event into the trace buffer.  */
256
        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_RELEASE_SECTORS, media_ptr, media_ptr -> fx_media_driver_logical_sector, media_ptr -> fx_media_driver_sectors, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
257
258
        /* Call the driver.  */
259
66382
        (media_ptr -> fx_media_driver_entry)(media_ptr);
260
    }
261
262
    /* Return success to caller.  */
263
2268091
    return(FX_SUCCESS);
264
}
265