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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems-20020807/] [cpukit/] [libfs/] [src/] [dosfs/] [fat.h] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1026 ivang
/*
2
 *  fat.h
3
 *
4
 *  Constants/data structures/prototypes for low-level operations on a volume
5
 *  with FAT filesystem
6
 *
7
 *  Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
8
 *  Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
9
 *
10
 *  The license and distribution terms for this file may be
11
 *  found in the file LICENSE in this distribution or at
12
 *  http://www.OARcorp.com/rtems/license.html.
13
 *
14
 *  @(#) fat.h,v 1.2 2002/04/04 18:22:23 joel Exp
15
 */
16
 
17
#ifndef __DOSFS_FAT_H__
18
#define __DOSFS_FAT_H__
19
 
20
#ifdef __cplusplus
21
extern "C" {
22
#endif
23
 
24
#include <string.h>
25
 
26
#include <rtems/seterr.h>
27
 
28
/* XXX: temporary hack :(( */
29
#ifndef set_errno_and_return_minus_one
30
#define set_errno_and_return_minus_one rtems_set_errno_and_return_minus_one
31
#endif /* set_errno_and_return_minus_one */
32
 
33
#include <rtems/score/cpu.h>
34
#include <errno.h>
35
#include <rtems/bdbuf.h>
36
 
37
#ifndef RC_OK
38
#define RC_OK 0x00000000
39
#endif
40
 
41
/*
42
 * Remember that all FAT file system on disk data structure is
43
 * "little endian"!
44
 * (derived from linux)
45
 */
46
/*
47
 * Conversion from and to little-endian byte order. (no-op on i386/i486)
48
 *
49
 * Naming: Ca_b_c, where a: F = from, T = to, b: LE = little-endian,
50
 * BE = big-endian, c: W = word (16 bits), L = longword (32 bits)
51
 */
52
 
53
#if (CPU_BIG_ENDIAN == TRUE)
54
#    define CF_LE_W(v) CPU_swap_u16(v)
55
#    define CF_LE_L(v) CPU_swap_u32(v)
56
#    define CT_LE_W(v) CPU_swap_u16(v)
57
#    define CT_LE_L(v) CPU_swap_u32(v)
58
#else  
59
#    define CF_LE_W(v) (v)
60
#    define CF_LE_L(v) (v)
61
#    define CT_LE_W(v) (v)
62
#    define CT_LE_L(v) (v)
63
#endif  
64
 
65
#define MIN(a, b)  (((a) < (b)) ? (a) : (b))
66
 
67
#define FAT_HASH_SIZE   2
68
#define FAT_HASH_MODULE FAT_HASH_SIZE
69
 
70
 
71
#define FAT_SECTOR512_SIZE     512 /* sector size (bytes) */
72
#define FAT_SECTOR512_BITS       9 /* log2(SECTOR_SIZE) */
73
 
74
/* maximum + 1 number of clusters for FAT12 */
75
#define FAT_FAT12_MAX_CLN      4085 
76
 
77
/* maximum + 1 number of clusters for FAT16 */
78
#define FAT_FAT16_MAX_CLN      65525 
79
 
80
#define FAT_FAT12              0x01
81
#define FAT_FAT16              0x02
82
#define FAT_FAT32              0x04
83
 
84
#define FAT_UNDEFINED_VALUE     0xFFFFFFFF 
85
 
86
#define FAT_FAT12_EOC          0x0FFF
87
#define FAT_FAT16_EOC          0xFFFF
88
#define FAT_FAT32_EOC          0x0FFFFFFF
89
 
90
#define FAT_FAT12_FREE         0x0000
91
#define FAT_FAT16_FREE         0x0000
92
#define FAT_FAT32_FREE         0x00000000
93
 
94
#define FAT_GENFAT_EOC         0xFFFFFFFF
95
#define FAT_GENFAT_FREE        0x00000000
96
 
97
#define FAT_FAT12_SHIFT        0x04
98
 
99
#define FAT_FAT12_MASK         0x00000FFF
100
#define FAT_FAT16_MASK         0x0000FFFF
101
#define FAT_FAT32_MASK         0x0FFFFFFF
102
 
103
#define FAT_MAX_BPB_SIZE       90
104
 
105
/* size of useful information in FSInfo sector */
106
#define FAT_USEFUL_INFO_SIZE   12
107
 
108
#define FAT_VAL8(x, ofs)       (unsigned8)(*((unsigned8 *)(x) + (ofs)))
109
 
110
#define FAT_VAL16(x, ofs)                                   \
111
    (unsigned16)( (*((unsigned8 *)(x) + (ofs))) |           \
112
                  ((*((unsigned8 *)(x) + (ofs) + 1)) << 8) )
113
 
114
#define FAT_VAL32(x, ofs)                                          \
115
    (unsigned32)( (*((unsigned8 *)(x) + (ofs))) |                  \
116
                  ((*((unsigned8 *)(x) + (ofs) + 1)) << 8) |       \
117
                  ((*((unsigned8 *)(x) + (ofs) + 2)) << 16) |      \
118
                  ((*((unsigned8 *)(x) + (ofs) + 3)) << 24) )
119
 
120
/* macros to access boot sector fields */
121
#define FAT_BR_BYTES_PER_SECTOR(x)       FAT_VAL16(x, 11)
122
#define FAT_BR_SECTORS_PER_CLUSTER(x)    FAT_VAL8(x, 13) 
123
#define FAT_BR_RESERVED_SECTORS_NUM(x)   FAT_VAL16(x, 14)
124
#define FAT_BR_FAT_NUM(x)                FAT_VAL8(x, 16)
125
#define FAT_BR_FILES_PER_ROOT_DIR(x)     FAT_VAL16(x, 17)
126
#define FAT_BR_TOTAL_SECTORS_NUM16(x)    FAT_VAL16(x, 19)
127
#define FAT_BR_MEDIA(x)                  FAT_VAL8(x, 21) 
128
#define FAT_BR_SECTORS_PER_FAT(x)        FAT_VAL16(x, 22)
129
#define FAT_BR_TOTAL_SECTORS_NUM32(x)    FAT_VAL32(x, 32)
130
#define FAT_BR_SECTORS_PER_FAT32(x)      FAT_VAL32(x, 36)
131
#define FAT_BR_EXT_FLAGS(x)              FAT_VAL16(x, 40)
132
#define FAT_BR_FAT32_ROOT_CLUSTER(x)     FAT_VAL32(x, 44)
133
#define FAT_BR_FAT32_FS_INFO_SECTOR(x)   FAT_VAL16(x, 48)
134
#define FAT_FSINFO_LEAD_SIGNATURE(x)     FAT_VAL32(x, 0)
135
/*
136
 * I read FSInfo sector from offset 484 to access the information, so offsets
137
 * of these fields a relative
138
 */
139
#define FAT_FSINFO_FREE_CLUSTER_COUNT(x) FAT_VAL32(x, 4)
140
#define FAT_FSINFO_NEXT_FREE_CLUSTER(x)  FAT_VAL32(x, 8)
141
 
142
#define FAT_FSINFO_FREE_CLUSTER_COUNT_OFFSET 488
143
 
144
#define FAT_FSINFO_NEXT_FREE_CLUSTER_OFFSET  492
145
 
146
#define FAT_RSRVD_CLN                        0x02  
147
 
148
#define FAT_FSINFO_LEAD_SIGNATURE_VALUE      0x41615252
149
 
150
#define FAT_FSI_LEADSIG_SIZE                 0x04
151
 
152
#define FAT_FSI_INFO                         484
153
 
154
#define MS_BYTES_PER_CLUSTER_LIMIT           0x8000     /* 32K */
155
 
156
#define FAT_BR_EXT_FLAGS_MIRROR              0x0080
157
 
158
#define FAT_BR_EXT_FLAGS_FAT_NUM             0x000F
159
 
160
 
161
#define FAT_DIRENTRY_SIZE          32 
162
 
163
#define FAT_DIRENTRIES_PER_SEC512  16
164
 
165
/*
166
 * Volume descriptor
167
 * Description of the volume the FAT filesystem is located on - generally
168
 * the fields of the structure corresponde to Boot Sector and BPB Srtucture
169
 * (see M$ White Paper) fields
170
 */
171
typedef struct fat_vol_s
172
{
173
    unsigned16   bps;            /* bytes per sector */
174
    unsigned8    sec_log2;       /* log2 of bps */
175
    unsigned8    sec_mul;        /* log2 of 512bts sectors number per sector */
176
    unsigned8    spc;            /* sectors per cluster */
177
    unsigned8    spc_log2;       /* log2 of spc */
178
    unsigned16   bpc;            /* bytes per cluster */
179
    unsigned8    bpc_log2;       /* log2 of bytes per cluster */
180
    unsigned8    fats;           /* number of FATs */
181
    unsigned8    type;           /* FAT type */
182
    unsigned32   mask;
183
    unsigned32   eoc_val;
184
    unsigned16   fat_loc;        /* FAT start */
185
    unsigned32   fat_length;     /* sectors per FAT */
186
    unsigned32   rdir_loc;       /* root directory start */
187
    unsigned16   rdir_entrs;     /* files per root directory */
188
    unsigned32   rdir_secs;      /* sectors per root directory */
189
    unsigned32   rdir_size;      /* root directory size in bytes */
190
    unsigned32   tot_secs;       /* total count of sectors */
191
    unsigned32   data_fsec;      /* first data sector */
192
    unsigned32   data_cls;       /* count of data clusters */
193
    unsigned32   rdir_cl;        /* first cluster of the root directory */
194
    unsigned16   info_sec;       /* FSInfo Sector Structure location */
195
    unsigned32   free_cls;       /* last known free clusters count */
196
    unsigned32   next_cl;        /* next free cluster number */
197
    unsigned8    mirror;         /* mirroring enabla/disable */
198
    unsigned32   afat_loc;       /* active FAT location */
199
    unsigned8    afat;           /* the number of active FAT */
200
    dev_t        dev;            /* device ID */
201
    disk_device *dd;             /* disk device (see libblock) */
202
    void        *private_data;   /* reserved */
203
} fat_vol_t;
204
 
205
 
206
typedef struct fat_cache_s
207
{
208
    unsigned32     blk_num;
209
    rtems_boolean  modified;
210
    unsigned8      state;
211
    bdbuf_buffer   *buf;
212
} fat_cache_t;
213
 
214
/*
215
 * This structure identifies the instance of the filesystem on the FAT
216
 * ("fat-file") level.
217
 */
218
typedef struct fat_fs_info_s
219
{
220
    fat_vol_t      vol;           /* volume descriptor */
221
    Chain_Control *vhash;         /* "vhash" of fat-file descriptors */
222
    Chain_Control *rhash;         /* "rhash" of fat-file descriptors */
223
    char          *uino;          /* array of unique ino numbers */
224
    unsigned32     index;
225
    unsigned32     uino_pool_size; /* size */
226
    unsigned32     uino_base;
227
    fat_cache_t    c;             /* cache */
228
    unsigned8     *sec_buf; /* just placeholder for anything */
229
} fat_fs_info_t;
230
 
231
/*
232
 * if the name we looking for is file we store not only first data cluster
233
 * number, but and cluster number and offset for directory entry for this
234
 * name
235
 */
236
typedef struct fat_auxiliary_s
237
{
238
    unsigned32 cln;
239
    unsigned32 ofs;
240
} fat_auxiliary_t;
241
 
242
#define FAT_FAT_OFFSET(fat_type, cln)                  \
243
    ((fat_type) & FAT_FAT12 ? ((cln) + ((cln) >> 1)) : \
244
     (fat_type) & FAT_FAT16 ? ((cln) << 1)           : \
245
     ((cln) << 2))
246
 
247
#define FAT_CLUSTER_IS_ODD(n)  ((n) & 0x0001)
248
 
249
#define FAT12_SHIFT      0x4    /* half of a byte */
250
 
251
/* initial size of array of unique ino */
252
#define FAT_UINO_POOL_INIT_SIZE  0x100
253
 
254
/* cache support */
255
#define FAT_CACHE_EMPTY   0x0
256
#define FAT_CACHE_ACTUAL  0x1
257
 
258
#define FAT_OP_TYPE_READ  0x1
259
#define FAT_OP_TYPE_GET   0x2
260
 
261
static inline unsigned32
262
fat_cluster_num_to_sector_num(
263
    rtems_filesystem_mount_table_entry_t *mt_entry,
264
    unsigned32                            cln
265
    )
266
{
267
    register fat_fs_info_t *fs_info = mt_entry->fs_info;
268
 
269
    if ( (cln == 0) && (fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)) )
270
        return fs_info->vol.rdir_loc;
271
 
272
    return (((cln - FAT_RSRVD_CLN) << fs_info->vol.spc_log2) +
273
            fs_info->vol.data_fsec);
274
}
275
 
276
static inline unsigned32
277
fat_cluster_num_to_sector512_num(
278
    rtems_filesystem_mount_table_entry_t *mt_entry,
279
    unsigned32                            cln
280
    )
281
{
282
    fat_fs_info_t *fs_info = mt_entry->fs_info;
283
 
284
    if (cln == 1)
285
        return 1;
286
 
287
    return (fat_cluster_num_to_sector_num(mt_entry, cln) <<
288
            fs_info->vol.sec_mul);
289
}
290
 
291
static inline int
292
fat_buf_access(fat_fs_info_t *fs_info, unsigned32 blk, int op_type,
293
               bdbuf_buffer **buf)
294
{
295
    rtems_status_code sc = RTEMS_SUCCESSFUL;
296
    unsigned8         i;
297
    rtems_boolean     sec_of_fat;
298
 
299
 
300
    if (fs_info->c.state == FAT_CACHE_EMPTY)
301
    {
302
        if (op_type == FAT_OP_TYPE_READ)
303
            sc = rtems_bdbuf_read(fs_info->vol.dev, blk, &fs_info->c.buf);
304
        else
305
            sc = rtems_bdbuf_get(fs_info->vol.dev, blk, &fs_info->c.buf);
306
        if (sc != RTEMS_SUCCESSFUL)
307
            set_errno_and_return_minus_one(EIO);
308
        fs_info->c.blk_num = blk;
309
        fs_info->c.state = FAT_CACHE_ACTUAL;
310
    }
311
 
312
    sec_of_fat = ((fs_info->c.blk_num >= fs_info->vol.fat_loc) &&
313
                  (fs_info->c.blk_num < fs_info->vol.rdir_loc));
314
 
315
    if (fs_info->c.blk_num != blk)
316
    {
317
        if (fs_info->c.modified)
318
        {
319
            if (sec_of_fat && !fs_info->vol.mirror)
320
                memcpy(fs_info->sec_buf, fs_info->c.buf->buffer,
321
                       fs_info->vol.bps);
322
 
323
            sc = rtems_bdbuf_release_modified(fs_info->c.buf);
324
            if (sc != RTEMS_SUCCESSFUL)
325
                set_errno_and_return_minus_one(EIO);
326
            fs_info->c.modified = 0;
327
 
328
            if (sec_of_fat && !fs_info->vol.mirror)
329
            {
330
                bdbuf_buffer *b;
331
 
332
                for (i = 1; i < fs_info->vol.fats; i++)
333
                {
334
                    sc = rtems_bdbuf_get(fs_info->vol.dev,
335
                                         fs_info->c.blk_num +
336
                                         fs_info->vol.fat_length * i,
337
                                         &b);
338
                    if ( sc != RTEMS_SUCCESSFUL)
339
                        set_errno_and_return_minus_one(ENOMEM);
340
                    memcpy(b->buffer, fs_info->sec_buf, fs_info->vol.bps);
341
                    sc = rtems_bdbuf_release_modified(b);
342
                    if ( sc != RTEMS_SUCCESSFUL)
343
                        set_errno_and_return_minus_one(ENOMEM);
344
                }
345
            }
346
        }
347
        else
348
        {
349
            sc = rtems_bdbuf_release(fs_info->c.buf);
350
            if (sc != RTEMS_SUCCESSFUL)
351
                set_errno_and_return_minus_one(EIO);
352
 
353
        }
354
        if (op_type == FAT_OP_TYPE_READ)
355
            sc = rtems_bdbuf_read(fs_info->vol.dev, blk, &fs_info->c.buf);
356
        else
357
            sc = rtems_bdbuf_get(fs_info->vol.dev, blk, &fs_info->c.buf);
358
        if (sc != RTEMS_SUCCESSFUL)
359
            set_errno_and_return_minus_one(EIO);
360
        fs_info->c.blk_num = blk;
361
    }
362
    *buf = fs_info->c.buf;
363
    return RC_OK;
364
}
365
 
366
 
367
static inline int
368
fat_buf_release(fat_fs_info_t *fs_info)
369
{
370
    rtems_status_code sc = RTEMS_SUCCESSFUL;
371
    unsigned8         i;
372
    rtems_boolean     sec_of_fat;
373
 
374
    if (fs_info->c.state == FAT_CACHE_EMPTY)
375
        return RC_OK;
376
 
377
    sec_of_fat = ((fs_info->c.blk_num >= fs_info->vol.fat_loc) &&
378
                  (fs_info->c.blk_num < fs_info->vol.rdir_loc));
379
 
380
    if (fs_info->c.modified)
381
    {
382
        if (sec_of_fat && !fs_info->vol.mirror)
383
            memcpy(fs_info->sec_buf, fs_info->c.buf->buffer, fs_info->vol.bps);
384
 
385
        sc = rtems_bdbuf_release_modified(fs_info->c.buf);
386
        if (sc != RTEMS_SUCCESSFUL)
387
            set_errno_and_return_minus_one(EIO);
388
        fs_info->c.modified = 0;
389
 
390
        if (sec_of_fat && !fs_info->vol.mirror)
391
        {
392
            bdbuf_buffer *b;
393
 
394
            for (i = 1; i < fs_info->vol.fats; i++)
395
            {
396
                sc = rtems_bdbuf_get(fs_info->vol.dev,
397
                                     fs_info->c.blk_num +
398
                                     fs_info->vol.fat_length * i,
399
                                     &b);
400
                if ( sc != RTEMS_SUCCESSFUL)
401
                    set_errno_and_return_minus_one(ENOMEM);
402
                memcpy(b->buffer, fs_info->sec_buf, fs_info->vol.bps);
403
                sc = rtems_bdbuf_release_modified(b);
404
                if ( sc != RTEMS_SUCCESSFUL)
405
                    set_errno_and_return_minus_one(ENOMEM);
406
            }
407
        }
408
    }
409
    else
410
    {
411
        sc = rtems_bdbuf_release(fs_info->c.buf);
412
        if (sc != RTEMS_SUCCESSFUL)
413
            set_errno_and_return_minus_one(EIO);
414
    }
415
    fs_info->c.state = FAT_CACHE_EMPTY;
416
    return RC_OK;
417
}
418
 
419
static inline void
420
fat_buf_mark_modified(fat_fs_info_t *fs_info)
421
{
422
    fs_info->c.modified = TRUE;
423
}
424
 
425
 
426
 
427
ssize_t
428
_fat_block_read(rtems_filesystem_mount_table_entry_t *mt_entry,
429
                unsigned32                            start,
430
                unsigned32                            offset,
431
                unsigned32                            count,
432
                void                                 *buff);
433
 
434
ssize_t
435
_fat_block_write(rtems_filesystem_mount_table_entry_t *mt_entry,
436
                 unsigned32                            start,
437
                 unsigned32                            offset,
438
                 unsigned32                            count,
439
                 const void                           *buff);
440
 
441
ssize_t
442
fat_cluster_read(rtems_filesystem_mount_table_entry_t *mt_entry,
443
                  unsigned32                           cln,
444
                  void                                *buff);
445
 
446
ssize_t
447
fat_cluster_write(rtems_filesystem_mount_table_entry_t *mt_entry,
448
                   unsigned32                           cln,
449
                   const void                          *buff);
450
 
451
int
452
fat_init_volume_info(rtems_filesystem_mount_table_entry_t *mt_entry);
453
 
454
int
455
fat_init_clusters_chain(rtems_filesystem_mount_table_entry_t *mt_entry,
456
                        unsigned32                            start_cln);
457
 
458
unsigned32
459
fat_cluster_num_to_sector_num(rtems_filesystem_mount_table_entry_t *mt_entry,
460
                              unsigned32                            cln);
461
 
462
int
463
fat_shutdown_drive(rtems_filesystem_mount_table_entry_t *mt_entry);
464
 
465
 
466
unsigned32
467
fat_get_unique_ino(rtems_filesystem_mount_table_entry_t *mt_entry);
468
 
469
rtems_boolean
470
fat_ino_is_unique(rtems_filesystem_mount_table_entry_t *mt_entry,
471
                  unsigned32                            ino);
472
 
473
void
474
fat_free_unique_ino(rtems_filesystem_mount_table_entry_t *mt_entry,
475
                    unsigned32                            ino);
476
 
477
int
478
fat_fat32_update_fsinfo_sector(
479
  rtems_filesystem_mount_table_entry_t *mt_entry,
480
  unsigned32                            free_count,
481
  unsigned32                            next_free
482
  );
483
 
484
#ifdef __cplusplus
485
}
486
#endif
487
 
488
#endif /* __DOSFS_FAT_H__ */

powered by: WebSVN 2.1.0

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