fat_ioct.c
上传用户:yj_qqy
上传日期:2017-01-28
资源大小:2911k
文件大小:32k
- /*
- **********************************************************************
- * Micrium, Inc.
- * 949 Crestview Circle
- * Weston, FL 33327-1848
- *
- * uC/FS
- *
- * (c) Copyright 2001 - 2003, Micrium, Inc.
- * All rights reserved.
- *
- ***********************************************************************
- ----------------------------------------------------------------------
- File : fat_ioctc.c
- Purpose : FAT File System Layer IOCTL
- ----------------------------------------------------------------------
- Known problems or limitations with current version
- ----------------------------------------------------------------------
- None.
- ---------------------------END-OF-HEADER------------------------------
- */
- /*********************************************************************
- *
- * #include Section
- *
- **********************************************************************
- */
- #include "fs_conf.h"
- #include "fs_port.h"
- #include "fs_dev.h"
- #include "fs_api.h"
- #include "fs_fsl.h"
- #include "fs_int.h"
- #include "fs_os.h"
- #include "fs_lbl.h"
- #include "fs_fat.h"
- #include "fs_clib.h"
- /*********************************************************************
- *
- * #define constants
- *
- **********************************************************************
- */
- #define FS_KNOWNMEDIA_NUM sizeof(_FS_wd_format_media_table) / sizeof(_FS_wd_format_media_type)
- #ifndef FS_FAT_NOFORMAT
- #define FS_FAT_NOFORMAT 0
- #endif
- #ifndef FS_FAT_DISKINFO
- #define FS_FAT_DISKINFO 1
- #endif
- #ifndef FS_SUPPORT_SEC_ACCESS
- #define FS_SUPPORT_SEC_ACCESS 1
- #endif
- /*********************************************************************
- *
- * Local data types
- *
- **********************************************************************
- */
- #if (FS_FAT_NOFORMAT==0)
- typedef struct {
- FS_i32 media_id;
- FS_u32 totsec32;
- FS_u32 hiddsec;
- FS_u16 totsec16;
- FS_u16 rootentcnt;
- FS_u16 fatsz16;
- FS_u16 secpertrk;
- FS_u16 numheads;
- char secperclus;
- char media;
- char fsystype;
- } _FS_wd_format_media_type;
- typedef struct {
- FS_u32 SecNum;
- FS_u32 Num;
- } _FS_FAT_ROOTENTCNT ;
- typedef struct {
- FS_u32 SecNum;
- FS_u16 Num;
- } _FS_FAT_SECPERCLUST;
- /*********************************************************************
- *
- * Local Variables
- *
- **********************************************************************
- */
- /* media_id totsec32 hidsec totsec16 rootent fatsz16 secpertrk numheads secperclus media fstype */
- static const _FS_wd_format_media_type _FS_wd_format_media_table[] = {
- { FS_MEDIA_RAM_16KB, 0x00000000UL, 0x00000000UL, 0x0020, 0x0040, 0x0001, 0x0004, 0x0004, 0x01, (char) 0xf8, 0 },
- { FS_MEDIA_RAM_64KB, 0x00000000UL, 0x00000000UL, 0x0080, 0x0040, 0x0001, 0x0004, 0x0004, 0x01, (char) 0xf8, 0 },
- { FS_MEDIA_RAM_128KB, 0x00000000UL, 0x00000000UL, 0x0100, 0x0080, 0x0001, 0x0004, 0x0004, 0x01, (char) 0xf8, 0 },
- { FS_MEDIA_RAM_256KB, 0x00000000UL, 0x00000000UL, 0x0200, 0x0080, 0x0002, 0x0004, 0x0004, 0x01, (char) 0xf8, 0 },
- { FS_MEDIA_RAM_512KB, 0x00000000UL, 0x00000000UL, 0x0400, 0x00e0, 0x0003, 0x0004, 0x0004, 0x01, (char) 0xf8, 0 },
- { FS_MEDIA_FD_144MB, 0x00000000UL, 0x00000000UL, 0x0b40, 0x00e0, 0x0009, 0x0012, 0x0002, 0x01, (char) 0xf0, 0 },
- { FS_MEDIA_SMC_1MB, 0x00000000UL, 0x0000000DUL, 0x07c3, 0x0100, 0x0001, 0x0004, 0x0004, 0x08, (char) 0xf8, 0 },
- { FS_MEDIA_SMC_2MB, 0x00000000UL, 0x0000000bUL, 0x0f95, 0x0100, 0x0002, 0x0008, 0x0004, 0x08, (char) 0xf8, 0 },
- { FS_MEDIA_SMC_4MB, 0x00000000UL, 0x0000001bUL, 0x1f25, 0x0100, 0x0002, 0x0008, 0x0004, 0x10, (char) 0xf8, 0 },
- { FS_MEDIA_SMC_8MB, 0x00000000UL, 0x00000019UL, 0x3e67, 0x0100, 0x0003, 0x0010, 0x0004, 0x10, (char) 0xf8, 0 },
- { FS_MEDIA_SMC_16MB, 0x00000000UL, 0x00000029UL, 0x7cd7, 0x0100, 0x0003, 0x0010, 0x0004, 0x20, (char) 0xf8, 0 },
- { FS_MEDIA_SMC_32MB, 0x00000000UL, 0x00000023UL, 0xf9dd, 0x0100, 0x0006, 0x0010, 0x0008, 0x20, (char) 0xf8, 0 },
- { FS_MEDIA_SMC_64MB, 0x0001f3c9UL, 0x00000037UL, 0x0000, 0x0100, 0x000c, 0x0020, 0x0008, 0x20, (char) 0xf8, 0 },
- { FS_MEDIA_SMC_128MB, 0x0003e7d1UL, 0x0000002fUL, 0x0000, 0x0100, 0x0020, 0x0020, 0x0010, 0x20, (char) 0xf8, 1 },
- { FS_MEDIA_MMC_32MB, 0x00000000UL, 0x00000020UL, 0xf460, 0x0200, 0x003d, 0x0020, 0x0004, 0x04, (char) 0xf8, 1 },
- { FS_MEDIA_MMC_64MB, 0x0001e8e0UL, 0x00000020UL, 0x0000, 0x0200, 0x007a, 0x0020, 0x0008, 0x04, (char) 0xf8, 1 },
- { FS_MEDIA_MMC_128MB, 0x0003d2e0UL, 0x00000020UL, 0x0000, 0x0200, 0x00f5, 0x0020, 0x0008, 0x04, (char) 0xf8, 1 },
- { FS_MEDIA_SD_16MB, 0x00000000UL, 0x00000039UL, 0x7187, 0x0200, 0x0003, 0x0020, 0x0002, 0x20, (char) 0xf8, 0 },
- { FS_MEDIA_SD_64MB, 0x0001dbd9UL, 0x00000027UL, 0x0000, 0x0200, 0x000c, 0x0020, 0x0008, 0x20, (char) 0xf8, 0 },
- { FS_MEDIA_SD_128MB, 0x0003c09fUL, 0x00000061UL, 0x0000, 0x0200, 0x001f, 0x0020, 0x0008, 0x20, (char) 0xf8, 1 },
- { FS_MEDIA_CF_32MB, 0x00000000UL, 0x00000020UL, 0xf760, 0x0200, 0x007c, 0x0020, 0x0004, 0x02, (char) 0xf8, 1 },
- { FS_MEDIA_CF_64MB, 0x0001e860UL, 0x00000020UL, 0x0000, 0x0200, 0x007b, 0x0020, 0x0004, 0x04, (char) 0xf8, 1 }
- };
- /* table for getting number of root entries for a given media size */
- static const _FS_FAT_ROOTENTCNT _FS_auto_rootcnt[] = {
- { 0x100, 0x40 },
- { 0x200, 0x80 },
- { 0x0b40UL, 0xe0 },
- { 0x0001f3c9UL, 0x100 },
- { 0xffffffffUL, 0x200 }
- };
- /* table for calculating cluster size */
- static const _FS_FAT_SECPERCLUST _FS_auto_secperclust[] = {
- /* medias up to 512MB are formatted with FAT16 */
- { 0x0b40UL, 0x0001 },
- { 32680UL, 0x0002 },
- { 262144UL, 0x0004 },
- { 524288UL, 0x0008 },
- { 1048576UL, 0x0010 },
- /* medias bigger than 512MB are formatted with FAT32 */
- { 16777216UL, 0x0008 },
- { 33554432UL, 0x0010 },
- { 67108864UL, 0x0020 },
- { 0xffffffffUL, 0x0040 }
- };
- #endif /* FS_FAT_NOFORMAT==0 */
- /*********************************************************************
- *
- * Local functions
- *
- **********************************************************************
- */
- #if (FS_FAT_NOFORMAT==0)
- /*********************************************************************
- *
- * _FS_fat_format
- *
- Description:
- FS internal function. Format a media using specified parameters.
- Currently this function needs many parameters. The function will be
- improved.
- Parameters:
- pDriver - Pointer to a device driver function table.
- Unit - Unit number.
- SecPerClus - Number of sector per allocation unit.
- RootEntCnt - For FAT12/FAT16, this is the number of 32 byte root
- directory entries. 0 for FAT32.
- TotSec16 - 16-bit total count of sectors. If zero, TotSec32 must
- be none-zero.
- TotSec32 - 32-bit total count of sectors. If zero, TotSec16 must
- be none-zero.
- Media - Media byte.
- FATSz16 - 16-bit count of sectors occupied by one FAT. 0 for
- FAT32 volumes, which use FATSz32.
- FATSz32 - 32-bit count of sectors occupied by one FAT. This is
- valid for FAT32 medias only.
- SecPerTrk - Sectors per track.
- NumHeads - Number of heads.
- HiddSec - Count of hidden sectors preceding the partition.
- FSysType - ==0 => FAT12
- ==1 => FAT16
- ==2 => FAT32
-
- Return value:
- >=0 - Media has been formatted.
- <0 - An error has occured.
- */
- static int _FS_fat_format(const FS__device_type *pDriver,FS_u32 Unit, char SecPerClus,
- FS_u16 RootEntCnt, FS_u16 TotSec16, FS_u32 TotSec32, char Media,
- FS_u16 FATSz16, FS_u32 FATSz32, FS_u16 SecPerTrk,FS_u16 NumHeads,
- FS_u32 HiddSec, char FSysType) {
- FS__FAT_BPB bpb;
- FS_u32 sector;
- FS_u32 value;
- char *buffer;
- int i;
- int j;
- int n;
-
- buffer = FS__fat_malloc(FS_FAT_SEC_SIZE);
- if (!buffer) {
- return -1;
- }
- FS__CLIB_memset(buffer, 0x00, (FS_size_t)FS_FAT_SEC_SIZE);
- /* Setup BPB */
- FS__CLIB_memset(&bpb, 0x00, (FS_size_t)sizeof(bpb));
- bpb.BytesPerSec = 0x0200; /* _512_,1024,2048,4096 */
- bpb.SecPerClus = SecPerClus; /* sec in allocation unit */
- if (FSysType != 2) {
- bpb.RsvdSecCnt = 0x0001; /* 1 for FAT12 & FAT16 */
- }
- #if (FS_FAT_NOFAT32==0)
- else {
- bpb.RsvdSecCnt = 0x0020; /* 32 for FAT32 */
- }
- #else
- /* FAT32 disabled */
- else {
- FS__fat_free(buffer);
- return -1;
- }
- #endif /* FS_FAT_NOFAT32==0 */
- bpb.NumFATs = 0x02; /* 2 */
- bpb.RootEntCnt = RootEntCnt; /* number of root dir entries */
- bpb.TotSec16 = TotSec16; /* RSVD+FAT+ROOT+DATA (<64k) */
- bpb.FATSz16 = FATSz16; /* number of FAT sectors */
- bpb.TotSec32 = TotSec32; /* RSVD+FAT+ROOT+FATA (>=64k) */
- bpb.Signature = 0xaa55; /* 0xAA55 Signature */
- /* setup BPB specifics for FAT32 */
- bpb.FATSz32 = FATSz32; /* number of FAT sectors */
- bpb.ExtFlags = 0x0000; /* mirroring info */
- bpb.RootClus = 0x00000002UL; /* root dir clus for FAT32 */
- bpb.FSInfo = 0x0001; /* position of FSInfo structure */
- /*
- Prepare buffer with information of the BPB
- offset 0 - 35 is same for FAT12/FAT16 and FAT32
- */
- /* jmpBoot = 0xe9 0x0000 */
- buffer[0] = (char)0xe9;
- buffer[1] = (char)0x00;
- buffer[2] = (char)0x00;
- /* OEMName = ' ' */
- for (i = 3; i < 11; i++) {
- buffer[i] = (char)0x20;
- }
- /* BytesPerSec */
- buffer[11] = (char)(bpb.BytesPerSec & 0xff);
- buffer[12] = (char)((unsigned int)(bpb.BytesPerSec & 0xff00) >> 8);
- /* SecPerClus */
- buffer[13] = (char)bpb.SecPerClus;
- /* RsvdSecCnt */
- buffer[14] = (char)(bpb.RsvdSecCnt & 0xff);
- buffer[15] = (char)((unsigned int)(bpb.RsvdSecCnt & 0xff00) >> 8);
- /* NumFATs */
- buffer[16] = (char)bpb.NumFATs;
- /* RootEntCnt */
- buffer[17] = (char)(bpb.RootEntCnt & 0xff);
- buffer[18] = (char)((unsigned int)(bpb.RootEntCnt & 0xff00) >> 8);
- /* TotSec16 */
- buffer[19] = (char)(bpb.TotSec16 & 0xff);
- buffer[20] = (char)((unsigned int)(bpb.TotSec16 & 0xff00) >> 8);
- /* Media */
- buffer[21] = Media;
- /* FATSz16 */
- buffer[22] = (char)(bpb.FATSz16 & 0xff);
- buffer[23] = (char)((unsigned int)(bpb.FATSz16 & 0xff00) >> 8);
- /* SecPerTrk */
- buffer[24] = (char)(SecPerTrk & 0xff);
- buffer[25] = (char)((unsigned int)(SecPerTrk & 0xff00) >> 8);
- /* NumHeads */
- buffer[26] = (char)(NumHeads & 0xff);
- buffer[27] = (char)((unsigned int)(NumHeads & 0xff00) >> 8);
- /* HiddSec */
- buffer[28] = (char)(HiddSec & 0xff);
- buffer[29] = (char)((FS_u32)(HiddSec & 0x0000ff00UL) >> 8);
- buffer[30] = (char)((FS_u32)(HiddSec & 0x00ff0000UL) >> 16);
- buffer[31] = (char)((FS_u32)(HiddSec & 0xff000000UL) >> 24);
- /* TotSec32 */
- buffer[32] = (char)(bpb.TotSec32 & 0xff);
- buffer[33] = (char)((FS_u32)(bpb.TotSec32 & 0x0000ff00UL) >> 8);
- buffer[34] = (char)((FS_u32)(bpb.TotSec32 & 0x00ff0000UL) >> 16);
- buffer[35] = (char)((FS_u32)(bpb.TotSec32 & 0xff000000UL) >> 24);
- /* Offset 36 and above have different meanings for FAT12/FAT16 and FAT32 */
- if (FSysType != 2) {
- /* FAT12/FAT16 */
- /* DrvNum = 0x00 (floppy) */
- buffer[36] = (char)0x00;
- /* Reserved1 = 0x00 (floppy) */
- buffer[37] = (char)0x00;
- /* BootSig = 0x00 (next three fields are not 'present') */
- buffer[38] = (char)0x00;
- /* VolID = 0x00000000 (serial number, e.g. date/time) */
- for (i = 39; i < 43; i++) {
- buffer[i] = (char)0x00;
- }
- /* VolLab = ' ' */
- for (i = 43; i < 54; i++) {
- buffer[i] = (char)0x20;
- }
- /* FilSysType = 'FAT12' */
- if (FSysType == 0) {
- FS__CLIB_strncpy(&buffer[54], "FAT12 ", 8);
- }
- else {
- FS__CLIB_strncpy(&buffer[54], "FAT16 ", 8);
- }
- }
- #if (FS_FAT_NOFAT32==0)
- else {
- /* FAT32 */
- /* FATSz32 */
- buffer[36] = (char)(bpb.FATSz32 & 0xff);
- buffer[37] = (char)((FS_u32)(bpb.FATSz32 & 0x0000ff00UL) >> 8);
- buffer[38] = (char)((FS_u32)(bpb.FATSz32 & 0x00ff0000UL) >> 16);
- buffer[39] = (char)((FS_u32)(bpb.FATSz32 & 0xff000000UL) >> 24);
- /* EXTFlags */
- buffer[40] = (char)(bpb.ExtFlags & 0xff);
- buffer[41] = (char)((unsigned int)(bpb.ExtFlags & 0xff00) >> 8);
- /* FSVer = 0:0 */
- buffer[42] = 0x00;
- buffer[43] = 0x00;
- /* RootClus */
- buffer[44] = (char)(bpb.RootClus & 0xff);
- buffer[45] = (char)((FS_u32)(bpb.RootClus & 0x0000ff00UL) >> 8);
- buffer[46] = (char)((FS_u32)(bpb.RootClus & 0x00ff0000UL) >> 16);
- buffer[47] = (char)((FS_u32)(bpb.RootClus & 0xff000000UL) >> 24);
- /* FSInfo */
- buffer[48] = (char)(bpb.FSInfo & 0xff);
- buffer[49] = (char)((unsigned int)(bpb.FSInfo & 0xff00) >> 8);
- /* BkBootSec = 0x0006; */
- buffer[50] = 0x06;
- buffer[51] = 0x00;
- /* Reserved */
- for (i = 52; i < 64; i++) {
- buffer[i] = (char)0x00;
- }
- /* DrvNum = 0x00 (floppy) */
- buffer[64] = (char)0x00;
- /* Reserved1 = 0x00 (floppy) */
- buffer[65] = (char)0x00;
- /* BootSig = 0x00 (next three fields are not 'present') */
- buffer[66] = (char)0x00;
- /* VolID = 0x00000000 (serial number, e.g. date/time) */
- for (i = 67; i < 71; i++) {
- buffer[i] = (char)0x00;
- }
- /* VolLab = ' ' */
- for (i = 71; i < 82; i++) {
- buffer[i] = (char)0x20;
- }
- /* FilSysType = 'FAT12' */
- FS__CLIB_strncpy(&buffer[82], "FAT32 ", 8);
- }
- #endif /* FS_FAT_NOFAT32==0 */
- /* Signature = 0xAA55 */
- buffer[510] = (char)0x55;
- buffer[511] = (char)0xaa;
- /* Write BPB to media */
- i = FS__lb_write(pDriver, Unit, 0, (void*)buffer);
- if (i < 0) {
- FS__fat_free(buffer);
- return -1;
- }
- if (FSysType == 2) {
- /* Write backup BPB */
- i = FS__lb_write(pDriver, Unit, 6, (void*)buffer);
- if (i<0) {
- FS__fat_free(buffer);
- return -1;
- }
- }
- /* Init FAT 1 & 2 */
- FS__CLIB_memset(buffer, 0x00, (FS_size_t)FS_FAT_SEC_SIZE);
- for (sector = 0; sector < 2 * (bpb.FATSz16 + bpb.FATSz32); sector++) {
- value = sector % (bpb.FATSz16 + bpb.FATSz32);
- if (value != 0) {
- i = FS__lb_write(pDriver, Unit, bpb.RsvdSecCnt + sector, (void*)buffer);
- if (i<0) {
- FS__fat_free(buffer);
- return -1;
- }
- }
- }
- buffer[0] = (char)Media;
- buffer[1] = (char)0xff;
- buffer[2] = (char)0xff;
- if (FSysType != 0) {
- buffer[3] = (char)0xff;
- }
- #if (FS_FAT_NOFAT32==0)
- if (FSysType == 2) {
- buffer[4] = (char)0xff;
- buffer[5] = (char)0xff;
- buffer[6] = (char)0xff;
- buffer[7] = (char)0x0f;
- buffer[8] = (char)0xff;
- buffer[9] = (char)0xff;
- buffer[10] = (char)0xff;
- buffer[11] = (char)0x0f;
- }
- #endif /* FS_FAT_NOFAT32==0 */
- for (i = 0; i < 2; i++) {
- j = FS__lb_write(pDriver, Unit, (FS_u32)bpb.RsvdSecCnt + i * ((FS_u32)bpb.FATSz16+bpb.FATSz32), (void*)buffer);
- if (j < 0) {
- FS__fat_free(buffer);
- return -1;
- } // two fat table
- }
- /* Init root directory area */
- FS__CLIB_memset(buffer, 0x00, (FS_size_t)FS_FAT_SEC_SIZE);
- if (bpb.RootEntCnt != 0) {
- /* FAT12/FAT16 */
- n = (((FS_u32)bpb.RootEntCnt * 32) / (FS_u32)512); //n show the sectors accupied by root directory entries
- for (i = 0; i < n; i++) {
- j = FS__lb_write(pDriver, Unit, bpb.RsvdSecCnt + 2 * bpb.FATSz16 + i, (void*)buffer); //reserved sectors under fat12/16 is 1
- if (j < 0) {
- FS__fat_free(buffer);
- return -1;
- }
- }
- }
- #if (FS_FAT_NOFAT32==0)
- else {
- /* FAT32 */
- n = bpb.SecPerClus;
- for (i = 0; i < n; i++) {
- j = FS__lb_write(pDriver, Unit, bpb.RsvdSecCnt + 2 * bpb.FATSz32 + (bpb.RootClus - 2) * n + i, (void*)buffer);
- if (j < 0) {
- FS__fat_free(buffer);
- return -1;
- }
- }
- }
- #endif /* FS_FAT_NOFAT32==0 */
- #if (FS_FAT_NOFAT32==0)
- if (FSysType == 2) {
- /* Init FSInfo */
- FS__CLIB_memset(buffer, 0x00, (FS_size_t)FS_FAT_SEC_SIZE);
- /* LeadSig = 0x41615252 */
- buffer[0] = (char)0x52;
- buffer[1] = (char)0x52;
- buffer[2] = (char)0x61;
- buffer[3] = (char)0x41;
- /* StructSig = 0x61417272 */
- buffer[484] = (char)0x72;
- buffer[485] = (char)0x72;
- buffer[486] = (char)0x41;
- buffer[487] = (char)0x61;
- /* Invalidate last known free cluster count */
- buffer[488] = (char)0xff;
- buffer[489] = (char)0xff;
- buffer[490] = (char)0xff;
- buffer[491] = (char)0xff;
- /* Give hint for free cluster search */
- buffer[492] = (char)0xff;
- buffer[493] = (char)0xff;
- buffer[494] = (char)0xff;
- buffer[495] = (char)0xff;
- /* TrailSig = 0xaa550000 */
- buffer[508] = (char)0x00;
- buffer[509] = (char)0x00;
- buffer[510] = (char)0x55;
- buffer[511] = (char)0xaa;
- i = FS__lb_write(pDriver, Unit, bpb.FSInfo, (void*)buffer);
- if (i < 0) {
- FS__fat_free(buffer);
- return -1;
- }
- }
- #endif /* FS_FAT_NOFAT32==0 */
- FS__fat_free(buffer);
- return 0;
- }
- /*********************************************************************
- *
- * _FS_FAT_AutoFormat
- *
- Description:
- FS internal function. Get information about the media from the
- device driver. Based on that informaton, calculate parameters for
- formatting that media and call the format routine.
- Parameters:
- Idx - Index of device in the device information table
- referred by FS__pDevInfo.
- Unit - Unit number.
-
- Return value:
- >=0 - Media has been formatted.
- <0 - An error has occured.
- */
- static int _FS_FAT_AutoFormat(int Idx, FS_u32 Unit) {
- struct {
- FS_u32 hiddennum;
- FS_u32 headnum;
- FS_u32 secnum;
- FS_u32 partsize;
- } devinfo;
- FS_u32 rootentcnt;
- FS_u32 fatsz;
- FS_u32 rootdirsectors;
- FS_u32 tmpval1;
- FS_u32 tmpval2;
- FS_u32 fatsz32;
- FS_u32 totsec32;
- FS_u32 resvdseccnt;
- FS_u16 totsec16;
- FS_u16 fatsz16;
- int i;
- unsigned char secperclust;
- char fsystype;
- /* Get info from device */
- devinfo.hiddennum = 0x00001111UL;
- devinfo.headnum = 0x00002222UL;
- devinfo.secnum = 0x00003333UL;
- devinfo.partsize = 0x00004444UL;
- i = FS__lb_ioctl(FS__pDevInfo[Idx].devdriver, Unit, FS_CMD_GET_DEVINFO, 0, (void*)&devinfo);
- if (i) {
- return -1;
- }
- /* Check if the driver really supports FS_CMD_GET_DEVINFO */
- if (devinfo.hiddennum == 0x00001111UL) {
- if (devinfo.headnum == 0x00002222UL) {
- if (devinfo.secnum == 0x00003333UL) {
- if (devinfo.partsize == 0x00004444UL) {
- return -1;
- }
- }
- }
- }
- if (devinfo.partsize <= 1048576UL) {
- fsystype = 1; /* FAT16 */
- }
- #if (FS_FAT_NOFAT32==0)
- else {
- fsystype = 2; /* FAT32 */
- }
- #else
- else {
- /* FAT32 disabled */
- return -1;
- }
- #endif /* FS_FAT_NOFAT32==0 */
- /* Set correct RootEntCnt & ResvdSecCnt */
- if (fsystype != 2) {
- /* FAT16 */
- i = 0;
- while (_FS_auto_rootcnt[i].SecNum < devinfo.partsize) {
- i++;
- }
- rootentcnt = (FS_u16)_FS_auto_rootcnt[i].Num;
- resvdseccnt = 1;
- }
- #if (FS_FAT_NOFAT32==0)
- else {
- /* FAT32 */
- rootentcnt = 0;
- resvdseccnt = 0x20;
- }
- #endif /* FS_FAT_NOFAT32==0 */
- /* Determinate SecPerClust */
- i = 0;
- while (_FS_auto_secperclust[i].SecNum < devinfo.partsize) {
- i++;
- }
- secperclust = (unsigned char) _FS_auto_secperclust[i].Num;
- /*
- FAT16/FAT32 FAT size calculation
- The formula used is following the Microsoft specification
- version 1.03 very closely. Therefore the calculated FAT
- size can be up to 8 sectors bigger than required for the
- media. This is a waste of up to 8 sectors, but not a problem
- regarding correctness of the media's data.
- */
- rootdirsectors = ((rootentcnt * 32 ) + 511) / 512;
- tmpval1 = devinfo.partsize - (resvdseccnt + rootdirsectors);
- tmpval2 = (256 * secperclust) + 2;
- #if (FS_FAT_NOFAT32==0)
- if (fsystype == 2) {
- tmpval2 = tmpval2 / 2;
- }
- #endif /* FS_FAT_NOFAT32==0 */
- fatsz = (tmpval1 + (tmpval2 - 1)) / tmpval2;
- if (fsystype != 2) {
- fatsz16 = (FS_u16)fatsz;
- fatsz32 = 0;
- }
- #if (FS_FAT_NOFAT32==0)
- else {
- fatsz16 = 0;
- fatsz32 = fatsz;
- }
- #endif /* FS_FAT_NOFAT32==0 */
- /* Number of total sectors (512 byte units) of the media
- This is independent of FAT type (FAT12/FAT16/FAT32) */
- if (devinfo.partsize < 0x10000UL) {
- totsec16 = (FS_u16)devinfo.partsize;
- totsec32 = 0;
- }
- else {
- totsec16 = 0;
- totsec32 = devinfo.partsize;
- }
- /* Format media using calculated values */
- i = _FS_fat_format(FS__pDevInfo[Idx].devdriver,
- Unit,
- secperclust,
- (FS_u16)rootentcnt,
- totsec16,
- totsec32,
- (char)0xf8,
- fatsz16,
- fatsz32,
- (FS_u16)devinfo.secnum,
- (FS_u16)devinfo.headnum,
- devinfo.hiddennum,
- fsystype);
- return i;
- }
- #endif /* FS_FAT_NOFORMAT==0 */
- #if FS_FAT_DISKINFO
- /*********************************************************************
- *
- * _FS_fat_GetTotalFree
- *
- Description:
- FS internal function. Store information about used/unused clusters
- in a FS_DISKFREE_T data structure.
- Parameters:
- Idx - Index of device in the device information table
- referred by FS__pDevInfo.
- Unit - Unit number.
- pDiskData - Pointer to a FS_DISKFREE_T data structure.
-
- Return value:
- ==0 - Information is stored in pDiskData.
- <0 - An error has occured.
- */
- static int _FS_fat_GetTotalFree(int Idx, FS_u32 Unit, FS_DISKFREE_T *pDiskData) {
- FS_u32 freeclust;
- FS_u32 usedclust;
- FS_u32 totclust;
- FS_u32 fatentry;
- FS_u32 fatsize;
- FS_i32 fatoffs;
- FS_i32 bytespersec;
- FS_i32 cursec;
- FS_i32 fatsec;
- FS_i32 lastsec;
- FS_i32 fatindex;
- int fattype;
- int err;
- char *buffer;
- unsigned char a;
- unsigned char b;
- #if (FS_FAT_NOFAT32==0)
- unsigned char c;
- unsigned char d;
- #endif
-
- if (!pDiskData) {
- return -1; /* No pointer to a FS_DISKFREE_T structure */
- }
- buffer = FS__fat_malloc(FS_FAT_SEC_SIZE);
- if (!buffer) {
- return -1;
- }
- fattype = FS__fat_which_type(Idx, Unit);
- #if (FS_FAT_NOFAT32!=0)
- if (fattype == 2) {
- FS__fat_free(buffer);
- return -1;
- }
- #endif /* FS_FAT_NOFAT32!=0 */
- fatsize = FS__FAT_aBPBUnit[Idx][Unit].FATSz16;
- if (fatsize == 0) {
- fatsize = FS__FAT_aBPBUnit[Idx][Unit].FATSz32;
- }
- bytespersec = (FS_i32)FS__FAT_aBPBUnit[Idx][Unit].BytesPerSec;
- /* Calculate total allocation units on disk */
- totclust = FS__FAT_aBPBUnit[Idx][Unit].TotSec16;
- if (!totclust) {
- totclust = FS__FAT_aBPBUnit[Idx][Unit].TotSec32;
- }
- totclust -= FS__FAT_aBPBUnit[Idx][Unit].RsvdSecCnt;
- totclust -= 2*fatsize;
- usedclust = FS__FAT_aBPBUnit[Idx][Unit].RootEntCnt;
- usedclust *= 0x20;
- usedclust /= bytespersec;
- totclust -= usedclust;
- totclust /= FS__FAT_aBPBUnit[Idx][Unit].SecPerClus;
- /* Scan FAT for free and used entries */
- cursec = 0;
- fatsec = 0;
- lastsec = -1;
- fatentry = 0xffffUL;
- freeclust = 0;
- usedclust = 0;
- while (1) {
- if (cursec >= (FS_i32)totclust) {
- break; /* Last cluster reached */
- }
- if (fatsec >= (FS_i32)fatsize + FS__FAT_aBPBUnit[Idx][Unit].RsvdSecCnt) {
- break; /* End of FAT reached */
- }
- if (fattype == 1) {
- fatindex = (cursec + 2) + ((cursec + 2) / 2); /* FAT12 */
- }
- else if (fattype == 2) {
- fatindex = (cursec + 2) * 4; /* FAT32 */
- }
- else {
- fatindex = (cursec + 2) * 2; /* FAT16 */
- }
- fatsec = FS__FAT_aBPBUnit[Idx][Unit].RsvdSecCnt + (fatindex / bytespersec);
- fatoffs = fatindex % bytespersec;
- if (fatsec != lastsec) {
- err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, fatsec, (void*)buffer);
- if (err < 0) {
- err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, fatsize + fatsec, (void*)buffer);
- if (err < 0) {
- FS__fat_free(buffer);
- return -1;
- }
- /* Try to repair original FAT sector with contents of copy */
- FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsec, (void*)buffer);
- }
- lastsec = fatsec;
- }
- if (fattype == 1) {
- if (fatoffs == (bytespersec - 1)) {
- a = buffer[fatoffs];
- err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, fatsec+1, (void*)buffer);
- if (err < 0) {
- err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, fatsize + fatsec + 1, (void*)buffer);
- if (err < 0) {
- FS__fat_free(buffer);
- return -1;
- }
- /* Try to repair original FAT sector with contents of copy */
- FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsec + 1, (void*)buffer);
- }
- lastsec = fatsec + 1;
- b = buffer[0];
- }
- else {
- a = buffer[fatoffs];
- b = buffer[fatoffs + 1];
- }
- if (cursec & 1) {
- fatentry = ((a & 0xf0) >> 4 ) + 16 * b;
- }
- else {
- fatentry = a + 256 * (b & 0x0f);
- }
- fatentry &= 0x0fff;
- }
- #if (FS_FAT_NOFAT32==0)
- else if (fattype == 2) {
- a = buffer[fatoffs];
- b = buffer[fatoffs + 1];
- c = buffer[fatoffs + 2];
- d = buffer[fatoffs + 3];
- fatentry = a + 0x100UL * b + 0x10000UL * c + 0x1000000UL * d;
- fatentry &= 0x0fffffffUL;
- }
- #endif /* FS_FAT_NOFAT32==0 */
- else {
- a = buffer[fatoffs];
- b = buffer[fatoffs + 1];
- fatentry = a + 256 * b;
- fatentry &= 0xffffUL;
- }
- cursec++;
- if (fatentry == 0) {
- freeclust++;
- }
- else {
- usedclust++;
- }
- }
- FS__fat_free(buffer);
- pDiskData->total_clusters = totclust;
- pDiskData->avail_clusters = freeclust;
- pDiskData->sectors_per_cluster = FS__FAT_aBPBUnit[Idx][Unit].SecPerClus;
- pDiskData->bytes_per_sector = (FS_u16)bytespersec;
- return 0;
- }
- #endif /* FS_FAT_DISKINFO */
- /*********************************************************************
- *
- * Global functions
- *
- **********************************************************************
- */
- /*********************************************************************
- *
- * FS__fat_ioctl
- *
- Description:
- FS internal function. Execute device command. The FAT layer checks
- first, if it has to process the command (e.g. format). Any other
- command is passed to the device driver.
- Parameters:
- Idx - Index of device in the device information table
- referred by FS__pDevInfo.
- Unit - Unit number.
- Cmd - Command to be executed.
- Aux - Parameter depending on command.
- pBuffer - Pointer to a buffer used for the command.
-
- Return value:
- Command specific. In general a negative value means an error.
- */
- int FS__fat_ioctl(int Idx, FS_u32 Unit, FS_i32 Cmd, FS_i32 Aux, void *pBuffer) {
- int x;
- #if ((FS_SUPPORT_SEC_ACCESS) || (FS_FAT_NOFORMAT==0))
- int i;
- #endif
- #if (FS_FAT_NOFORMAT==0)
- int j;
- #endif
- FS__lb_ioctl(FS__pDevInfo[Idx].devdriver, Unit, FS_CMD_INC_BUSYCNT, 0, (void*)0); /* Turn on busy signal */
- #if (FS_FAT_NOFORMAT==0)
- if (Cmd == FS_CMD_FORMAT_MEDIA) {
- j = 0;
- while (1) {
- if (j >= FS_KNOWNMEDIA_NUM) {
- break; /* Not a known media */
- }
- if (_FS_wd_format_media_table[j].media_id == Aux) {
- break; /* Media found in the list */
- }
- j++;
- } //find the right media
- if (j >= FS_KNOWNMEDIA_NUM) { //can't find the right media
- FS__lb_ioctl(FS__pDevInfo[Idx].devdriver, Unit, FS_CMD_DEC_BUSYCNT, 0, (void*)0); /* Turn off busy signal */
- return -1;
- }
- i = FS__lb_status(FS__pDevInfo[Idx].devdriver, Unit); //get status of device, if ok return 1
- if (i >= 0) {
- x = _FS_fat_format(FS__pDevInfo[Idx].devdriver,
- Unit,
- _FS_wd_format_media_table[j].secperclus,
- _FS_wd_format_media_table[j].rootentcnt,
- _FS_wd_format_media_table[j].totsec16,
- _FS_wd_format_media_table[j].totsec32,
- _FS_wd_format_media_table[j].media,
- _FS_wd_format_media_table[j].fatsz16,
- 0,
- _FS_wd_format_media_table[j].secpertrk,
- _FS_wd_format_media_table[j].numheads,
- _FS_wd_format_media_table[j].hiddsec,
- _FS_wd_format_media_table[j].fsystype);
- i = FS__lb_ioctl(FS__pDevInfo[Idx].devdriver, Unit, FS_CMD_FLUSH_CACHE, 0, (void*)0);
- if (i < 0) {
- x = i;
- }
- else {
- /* Invalidate BPB */
- for (i = 0; i < (int)FS__maxdev; i++) {
- for (j = 0; j < (int)FS__fat_maxunit; j++) {
- FS__FAT_aBPBUnit[i][j].Signature = 0x0000;
- }
- }
- }
- }
- else {
- FS__lb_ioctl(FS__pDevInfo[Idx].devdriver, Unit, FS_CMD_DEC_BUSYCNT, 0, (void*)0); /* Turn off busy signal */
- return -1;
- }
- }
- else if (Cmd == FS_CMD_FORMAT_AUTO) {
- i = FS__lb_status(FS__pDevInfo[Idx].devdriver, Unit);
- if (i >= 0) {
- x = _FS_FAT_AutoFormat(Idx, Unit);
- i = FS__lb_ioctl(FS__pDevInfo[Idx].devdriver, Unit, FS_CMD_FLUSH_CACHE, 0, (void*)0);
- if (i < 0) {
- x = i;
- }
- }
- else {
- x = -1;
- }
- }
- #else /* FS_FAT_NOFORMAT==0 */
- if (Cmd == FS_CMD_FORMAT_MEDIA) {
- x = -1; /* Format command is not supported */
- }
- #endif /* FS_FAT_NOFORMAT==0 */
- #if FS_FAT_DISKINFO
- else if (Cmd == FS_CMD_GET_DISKFREE) {
- i = FS__fat_checkunit(Idx, Unit);
- if (i > 0) {
- x = _FS_fat_GetTotalFree(Idx, Unit, (FS_DISKFREE_T*)pBuffer);
- i = FS__lb_ioctl(FS__pDevInfo[Idx].devdriver, Unit, FS_CMD_FLUSH_CACHE, 0, (void*)0);
- if (i < 0) {
- x = i;
- }
- }
- else {
- x = -1;
- }
- }
- #else /* FS_FAT_DISKINFO==0 */
- else if (Cmd == FS_CMD_GET_DISKFREE) {
- x = -1; /* Diskinfo command not supported */
- }
- #endif /* FS_FAT_DISKINFO */
- #if FS_SUPPORT_SEC_ACCESS
- else if ((Cmd == FS_CMD_READ_SECTOR) || (Cmd == FS_CMD_WRITE_SECTOR)) {
- if (!pBuffer) {
- FS__lb_ioctl(FS__pDevInfo[Idx].devdriver, Unit, FS_CMD_DEC_BUSYCNT, 0, (void*)0);
- return -1;
- }
- i = FS__lb_status(FS__pDevInfo[Idx].devdriver, Unit);
- if (i >= 0) {
- if (Cmd == FS_CMD_READ_SECTOR) {
- x = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, Aux, pBuffer);
- }
- else {
- x = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, Aux, pBuffer);
- }
- }
- else {
- x = -1;
- }
- }
- #else /* FS_SUPPORT_SEC_ACCESS */
- else if ((Cmd == FS_CMD_READ_SECTOR) || (Cmd == FS_CMD_WRITE_SECTOR)) {
- FS__lb_ioctl(FS__pDevInfo[Idx].devdriver, Unit, FS_CMD_DEC_BUSYCNT, 0, (void*)0);
- return -1;
- }
- #endif /* FS_SUPPORT_SEC_ACCESS */
- else {
- /* Maybe command for driver */
- x = FS__lb_ioctl(FS__pDevInfo[Idx].devdriver, Unit, Cmd, Aux, (void*)pBuffer);
- }
- FS__lb_ioctl(FS__pDevInfo[Idx].devdriver, Unit, FS_CMD_DEC_BUSYCNT, 0, (void*)0); /* Turn off busy signal */
- return x;
- }