OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems-20020807/] [cpukit/] [libfs/] [src/] [dosfs/] [fat_fat_operations.c] - Blame information for rev 1026

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1026 ivang
/*
2
 *  fat_fat_operations.c
3
 *
4
 *  General operations on File Allocation Table
5
 *
6
 *  Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
7
 *  Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
8
 *
9
 *  @(#) fat_fat_operations.c,v 1.1 2002/02/28 20:43:50 joel Exp
10
 */
11
 
12
#include <sys/types.h>
13
#include <sys/stat.h>
14
#include <fcntl.h>
15
#include <unistd.h>
16
#include <errno.h>
17
#include <stdlib.h>
18
#include <assert.h>
19
 
20
#include <rtems/libio_.h>
21
 
22
#include "fat.h"
23
#include "fat_fat_operations.h"
24
 
25
/* fat_scan_fat_for_free_clusters --
26
 *     Allocate chain of free clusters from Files Allocation Table
27
 *
28
 * PARAMETERS:
29
 *     mt_entry - mount table entry
30
 *     chain    - the number of the first allocated cluster (first cluster
31
 *                in  the chain)
32
 *     count    - count of clusters to allocate (chain length)
33
 *
34
 * RETURNS:
35
 *     RC_OK on success, or error code if error occured (errno set
36
 *     appropriately)
37
 *
38
 *
39
 */
40
int
41
fat_scan_fat_for_free_clusters(
42
    rtems_filesystem_mount_table_entry_t *mt_entry,
43
    unsigned32                           *chain,
44
    unsigned32                            count,
45
    unsigned32                           *cls_added,
46
    unsigned32                           *last_cl
47
    )
48
{
49
    int            rc = RC_OK;
50
    fat_fs_info_t *fs_info = mt_entry->fs_info;
51
    unsigned32     cl4find = 2;
52
    unsigned32     next_cln = 0;
53
    unsigned32     save_cln = 0;
54
    unsigned32     data_cls_val = fs_info->vol.data_cls + 2;
55
    unsigned32     i = 2;
56
 
57
    *cls_added = 0;
58
 
59
    if (count == 0)
60
        return rc;
61
 
62
    if ((fs_info->vol.type & FAT_FAT32) &&
63
        (fs_info->vol.next_cl != FAT_UNDEFINED_VALUE))
64
        cl4find = fs_info->vol.next_cl;
65
 
66
    /*
67
     * fs_info->vol.data_cls is exactly the count of data clusters
68
     * starting at cluster 2, so the maximum valid cluster number is
69
     * (fs_info->vol.data_cls + 1)
70
     */
71
    while (i < data_cls_val)
72
    {
73
        rc = fat_get_fat_cluster(mt_entry, cl4find, &next_cln);
74
        if ( rc != RC_OK )
75
        {
76
            if (*cls_added != 0)
77
                fat_free_fat_clusters_chain(mt_entry, (*chain));
78
            return rc;
79
        }
80
 
81
        if ((next_cln & fs_info->vol.mask) == FAT_GENFAT_FREE)
82
        {
83
            /*
84
             * We are enforced to process allocation of the first free cluster
85
             * by separate 'if' statement because otherwise undo function
86
             * wouldn't work properly
87
             */
88
            if (*cls_added == 0)
89
            {
90
                *chain = cl4find;
91
                rc = fat_set_fat_cluster(mt_entry, cl4find, FAT_GENFAT_EOC);
92
                if ( rc != RC_OK )
93
                {
94
                    /*
95
                     * this is the first cluster we tried to allocate so no
96
                     * cleanup activity needed
97
                     */
98
                     return rc;
99
                }
100
            }
101
            else
102
            {
103
                /* set EOC value to new allocated cluster */
104
                rc = fat_set_fat_cluster(mt_entry, cl4find, FAT_GENFAT_EOC);
105
                if ( rc != RC_OK )
106
                {
107
                    /* cleanup activity */
108
                    fat_free_fat_clusters_chain(mt_entry, (*chain));
109
                    return rc;
110
                }
111
 
112
                rc = fat_set_fat_cluster(mt_entry, save_cln, cl4find);
113
                if ( rc != RC_OK )
114
                {
115
                    /* cleanup activity */
116
                    fat_free_fat_clusters_chain(mt_entry, (*chain));
117
                    /* trying to save last allocated cluster for future use */
118
                    fat_set_fat_cluster(mt_entry, cl4find, FAT_GENFAT_FREE);
119
                    fat_buf_release(fs_info);
120
                    return rc;
121
                }
122
            }
123
 
124
            save_cln = cl4find;
125
            (*cls_added)++;
126
 
127
            /* have we satisfied request ? */
128
            if (*cls_added == count)
129
            {
130
                if (fs_info->vol.type & FAT_FAT32)
131
                {
132
                    fs_info->vol.next_cl = save_cln;
133
                    if (fs_info->vol.free_cls != 0xFFFFFFFF)
134
                        fs_info->vol.free_cls -= (*cls_added);
135
                }
136
                *last_cl = save_cln;
137
                fat_buf_release(fs_info);
138
                return rc;
139
            }
140
        }
141
        i++;
142
        cl4find++;
143
        if (cl4find >= data_cls_val)
144
            cl4find = 2;
145
    }
146
 
147
    if (fs_info->vol.type & FAT_FAT32)
148
    {
149
        fs_info->vol.next_cl = save_cln;
150
        if (fs_info->vol.free_cls != 0xFFFFFFFF)
151
            fs_info->vol.free_cls -= (*cls_added);
152
    }
153
    *last_cl = save_cln;
154
    fat_buf_release(fs_info);
155
    return RC_OK;
156
}
157
 
158
/* fat_free_fat_clusters_chain --
159
 *     Free chain of clusters in Files Allocation Table.
160
 *
161
 * PARAMETERS:
162
 *     mt_entry - mount table entry
163
 *     chain    - number of the first cluster in  the chain
164
 *
165
 * RETURNS:
166
 *     RC_OK on success, or -1 if error occured (errno set appropriately)
167
 */
168
int
169
fat_free_fat_clusters_chain(
170
    rtems_filesystem_mount_table_entry_t *mt_entry,
171
    unsigned32                            chain
172
    )
173
{
174
    int            rc = RC_OK, rc1 = RC_OK;
175
    fat_fs_info_t *fs_info = mt_entry->fs_info;
176
    unsigned32     cur_cln = chain;
177
    unsigned32     next_cln = 0;
178
    unsigned32     freed_cls_cnt = 0;
179
 
180
    while ((cur_cln & fs_info->vol.mask) != fs_info->vol.eoc_val)
181
    {
182
        rc = fat_get_fat_cluster(mt_entry, cur_cln, &next_cln);
183
        if ( rc != RC_OK )
184
        {
185
            if ((fs_info->vol.type & FAT_FAT32) &&
186
                (fs_info->vol.free_cls != FAT_UNDEFINED_VALUE))
187
                fs_info->vol.free_cls += freed_cls_cnt;
188
            fat_buf_release(fs_info);
189
            return rc;
190
        }
191
 
192
        rc = fat_set_fat_cluster(mt_entry, cur_cln, FAT_GENFAT_FREE);
193
        if ( rc != RC_OK )
194
            rc1 = rc;
195
 
196
        freed_cls_cnt++;
197
        cur_cln = next_cln;
198
    }
199
 
200
    if (fs_info->vol.type & FAT_FAT32)
201
    {
202
        fs_info->vol.next_cl = chain;
203
        if (fs_info->vol.free_cls != FAT_UNDEFINED_VALUE)
204
            fs_info->vol.free_cls += freed_cls_cnt;
205
    }
206
 
207
    fat_buf_release(fs_info);
208
    if (rc1 != RC_OK)
209
        return rc1;
210
 
211
    return RC_OK;
212
}
213
 
214
/* fat_get_fat_cluster --
215
 *     Fetches the contents of the cluster (link to next cluster in the chain)
216
 *     from Files Allocation Table.
217
 *
218
 * PARAMETERS:
219
 *     mt_entry - mount table entry
220
 *     cln      - number of cluster to fetch the contents from
221
 *     ret_val  - contents of the cluster 'cln' (link to next cluster in
222
 *                the chain)
223
 *
224
 * RETURNS:
225
 *     RC_OK on success, or -1 if error occured
226
 *     and errno set appropriately
227
 */
228
int
229
fat_get_fat_cluster(
230
    rtems_filesystem_mount_table_entry_t *mt_entry,
231
    unsigned32                            cln,
232
    unsigned32                           *ret_val
233
    )
234
{
235
    int                     rc = RC_OK;
236
    register fat_fs_info_t *fs_info = mt_entry->fs_info;
237
    bdbuf_buffer           *block0 = NULL;
238
    unsigned32              sec = 0;
239
    unsigned32              ofs = 0;
240
 
241
    /* sanity check */
242
    if ( (cln < 2) || (cln > (fs_info->vol.data_cls + 1)) )
243
        set_errno_and_return_minus_one(EIO);
244
 
245
    sec = (FAT_FAT_OFFSET(fs_info->vol.type, cln) >> fs_info->vol.sec_log2) +
246
          fs_info->vol.afat_loc;
247
    ofs = FAT_FAT_OFFSET(fs_info->vol.type, cln) & (fs_info->vol.bps - 1);
248
 
249
    rc = fat_buf_access(fs_info, sec, FAT_OP_TYPE_READ, &block0);
250
    if (rc != RC_OK)
251
        return rc;
252
 
253
    switch ( fs_info->vol.type )
254
    {
255
        case FAT_FAT12:
256
            /*
257
             * we are enforced in complex computations for FAT12 to escape CPU
258
             * align problems for some architectures
259
             */
260
            *ret_val = (*((unsigned8 *)(block0->buffer + ofs)));
261
            if ( ofs == (fs_info->vol.bps - 1) )
262
            {
263
                rc = fat_buf_access(fs_info, sec + 1, FAT_OP_TYPE_READ,
264
                                    &block0);
265
                if (rc != RC_OK)
266
                    return rc;
267
 
268
                *ret_val |= (*((unsigned8 *)(block0->buffer)))<<8;
269
            }
270
            else
271
            {
272
                *ret_val |= (*((unsigned8 *)(block0->buffer + ofs + 1)))<<8;
273
            }
274
 
275
            if ( FAT_CLUSTER_IS_ODD(cln) )
276
                *ret_val = (*ret_val) >> FAT12_SHIFT;
277
            else
278
                *ret_val = (*ret_val) & FAT_FAT12_MASK;
279
 
280
            break;
281
 
282
        case FAT_FAT16:
283
            *ret_val = *((unsigned16 *)(block0->buffer + ofs));
284
            *ret_val = CF_LE_W(*ret_val);
285
            break;
286
 
287
        case FAT_FAT32:
288
            *ret_val = *((unsigned32 *)(block0->buffer + ofs));
289
            *ret_val = CF_LE_L(*ret_val);
290
            break;
291
 
292
        default:
293
            set_errno_and_return_minus_one(EIO);
294
            break;
295
    }
296
 
297
    return RC_OK;
298
}
299
 
300
/* fat_set_fat_cluster --
301
 *     Set the contents of the cluster (link to next cluster in the chain)
302
 *     from Files Allocation Table.
303
 *
304
 * PARAMETERS:
305
 *     mt_entry - mount table entry
306
 *     cln      - number of cluster to set contents to
307
 *     in_val   - value to set
308
 *
309
 * RETURNS:
310
 *     RC_OK on success, or -1 if error occured
311
 *     and errno set appropriately
312
 */
313
int
314
fat_set_fat_cluster(
315
    rtems_filesystem_mount_table_entry_t *mt_entry,
316
    unsigned32                            cln,
317
    unsigned32                            in_val
318
    )
319
{
320
    int                rc = RC_OK;
321
    fat_fs_info_t     *fs_info = mt_entry->fs_info;
322
    unsigned32         sec = 0;
323
    unsigned32         ofs = 0;
324
    unsigned16         fat16_clv = 0;
325
    unsigned32         fat32_clv = 0;
326
    bdbuf_buffer      *block0 = NULL;
327
 
328
    /* sanity check */
329
    if ( (cln < 2) || (cln > (fs_info->vol.data_cls + 1)) )
330
        set_errno_and_return_minus_one(EIO);
331
 
332
    sec = (FAT_FAT_OFFSET(fs_info->vol.type, cln) >> fs_info->vol.sec_log2) +
333
          fs_info->vol.afat_loc;
334
    ofs = FAT_FAT_OFFSET(fs_info->vol.type, cln) & (fs_info->vol.bps - 1);
335
 
336
    rc = fat_buf_access(fs_info, sec, FAT_OP_TYPE_READ, &block0);
337
    if (rc != RC_OK)
338
        return rc;
339
 
340
    switch ( fs_info->vol.type )
341
    {
342
        case FAT_FAT12:
343
            if ( FAT_CLUSTER_IS_ODD(cln) )
344
            {
345
                fat16_clv = CT_LE_W((((unsigned16)in_val) << FAT_FAT12_SHIFT));
346
 
347
                *((unsigned8 *)(block0->buffer + ofs)) =
348
                        (*((unsigned8 *)(block0->buffer + ofs))) & 0x0F;
349
 
350
                *((unsigned8 *)(block0->buffer + ofs)) =
351
                        (*((unsigned8 *)(block0->buffer + ofs))) |
352
                        (unsigned8)(fat16_clv & 0x00FF);
353
 
354
                fat_buf_mark_modified(fs_info);
355
 
356
                if ( ofs == (fs_info->vol.bps - 1) )
357
                {
358
                    rc = fat_buf_access(fs_info, sec + 1, FAT_OP_TYPE_READ,
359
                                        &block0);
360
                    if (rc != RC_OK)
361
                        return rc;
362
 
363
                     *((unsigned8 *)(block0->buffer)) &= 0x00;
364
 
365
                     *((unsigned8 *)(block0->buffer)) =
366
                            (*((unsigned8 *)(block0->buffer))) |
367
                            (unsigned8)((fat16_clv & 0xFF00)>>8);
368
 
369
                     fat_buf_mark_modified(fs_info);
370
                }
371
                else
372
                {
373
                    *((unsigned8 *)(block0->buffer + ofs + 1)) &= 0x00;
374
 
375
                    *((unsigned8 *)(block0->buffer + ofs + 1)) =
376
                            (*((unsigned8 *)(block0->buffer + ofs + 1))) |
377
                            (unsigned8)((fat16_clv & 0xFF00)>>8);
378
                }
379
            }
380
            else
381
            {
382
                fat16_clv = CT_LE_W((((unsigned16)in_val) & FAT_FAT12_MASK));
383
 
384
                *((unsigned8 *)(block0->buffer + ofs)) &= 0x00;
385
 
386
                *((unsigned8 *)(block0->buffer + ofs)) =
387
                        (*((unsigned8 *)(block0->buffer + ofs))) |
388
                        (unsigned8)(fat16_clv & 0x00FF);
389
 
390
                fat_buf_mark_modified(fs_info);
391
 
392
                if ( ofs == (fs_info->vol.bps - 1) )
393
                {
394
                    rc = fat_buf_access(fs_info, sec + 1, FAT_OP_TYPE_READ,
395
                                        &block0);
396
                    if (rc != RC_OK)
397
                        return rc;
398
 
399
                    *((unsigned8 *)(block0->buffer)) =
400
                            (*((unsigned8 *)(block0->buffer))) & 0xF0;
401
 
402
                    *((unsigned8 *)(block0->buffer)) =
403
                            (*((unsigned8 *)(block0->buffer))) |
404
                            (unsigned8)((fat16_clv & 0xFF00)>>8);
405
 
406
                    fat_buf_mark_modified(fs_info);
407
                }
408
                else
409
                {
410
                    *((unsigned8 *)(block0->buffer + ofs + 1)) =
411
                      (*((unsigned8 *)(block0->buffer + ofs + 1))) & 0xF0;
412
 
413
                    *((unsigned8 *)(block0->buffer + ofs+1)) =
414
                           (*((unsigned8 *)(block0->buffer + ofs+1))) |
415
                           (unsigned8)((fat16_clv & 0xFF00)>>8);
416
                }
417
            }
418
            break;
419
 
420
        case FAT_FAT16:
421
            *((unsigned16 *)(block0->buffer + ofs)) =
422
                    (unsigned16)(CT_LE_W(in_val));
423
            fat_buf_mark_modified(fs_info);
424
            break;
425
 
426
        case FAT_FAT32:
427
            fat32_clv = CT_LE_L((in_val & FAT_FAT32_MASK));
428
 
429
            *((unsigned32 *)(block0->buffer + ofs)) =
430
            (*((unsigned32 *)(block0->buffer + ofs))) & (CT_LE_L(0xF0000000));
431
 
432
            *((unsigned32 *)(block0->buffer + ofs)) =
433
                   fat32_clv | (*((unsigned32 *)(block0->buffer + ofs)));
434
 
435
            fat_buf_mark_modified(fs_info);
436
            break;
437
 
438
        default:
439
            set_errno_and_return_minus_one(EIO);
440
            break;
441
 
442
    }
443
 
444
    return RC_OK;
445
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.