⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fat.c

📁 编译后直接运行的MP3播放器全部C语言源代码 一个包含FAT文件系统、系统引导 Boot、FLASH Driver等内容的
💻 C
📖 第 1 页 / 共 5 页
字号:
    {        DEBUGF( "fat_mount() - Couldn't read FSInfo (error code %d)\n", rc);        return rc * 10 - 4;    }    fat_bpb.fsinfo.freecount = BYTES2INT32(buf, FSINFO_FREECOUNT);    fat_bpb.fsinfo.nextfree = BYTES2INT32(buf, FSINFO_NEXTFREE);    /* calculate freecount if unset */    if ( fat_bpb.fsinfo.freecount == 0xffffffff )    {        fat_recalc_free();    }    LDEBUGF("Freecount: %d\n",fat_bpb.fsinfo.freecount);    LDEBUGF("Nextfree: 0x%x\n",fat_bpb.fsinfo.nextfree);    LDEBUGF("Cluster count: 0x%x\n",fat_bpb.dataclusters);    LDEBUGF("Sectors per cluster: %d\n",fat_bpb.bpb_secperclus);    LDEBUGF("FAT sectors: 0x%x\n",fat_bpb.fatsize);    return 0;}void fat_recalc_free(void){    int free = 0;    unsigned i;    for (i = 0; i<fat_bpb.fatsize; i++) {        unsigned int j;        unsigned int* fat = cache_fat_sector(i);        for (j = 0; j < CLUSTERS_PER_FAT_SECTOR; j++) {            unsigned int c = i * CLUSTERS_PER_FAT_SECTOR + j;            if ( c > fat_bpb.dataclusters+1 ) /* nr 0 is unused */                break;                  if (!(SWAB32(fat[j]) & 0x0fffffff)) {                free++;                if ( fat_bpb.fsinfo.nextfree == 0xffffffff )                    fat_bpb.fsinfo.nextfree = c;            }        }    }    fat_bpb.fsinfo.freecount = free;    update_fsinfo();}static int bpb_is_sane(void){    if(fat_bpb.bpb_bytspersec != 512)    {        DEBUGF( "bpb_is_sane() - Error: sector size is not 512 (%d)\n",                fat_bpb.bpb_bytspersec);        return -1;    }    if(fat_bpb.bpb_secperclus * fat_bpb.bpb_bytspersec > 128*1024)    {        DEBUGF( "bpb_is_sane() - Error: cluster size is larger than 128K "                "(%d * %d = %d)\n",                fat_bpb.bpb_bytspersec, fat_bpb.bpb_secperclus,                fat_bpb.bpb_bytspersec * fat_bpb.bpb_secperclus);        return -2;    }    if(fat_bpb.bpb_numfats != 2)    {        DEBUGF( "bpb_is_sane() - Warning: NumFATS is not 2 (%d)\n",                fat_bpb.bpb_numfats);    }    if(fat_bpb.bpb_media != 0xf0 && fat_bpb.bpb_media < 0xf8)    {        DEBUGF( "bpb_is_sane() - Warning: Non-standard "                "media type (0x%02x)\n",                fat_bpb.bpb_media);    }    if(fat_bpb.last_word != 0xaa55)    {        DEBUGF( "bpb_is_sane() - Error: Last word is not "                "0xaa55 (0x%04x)\n", fat_bpb.last_word);        return -3;    }    if (fat_bpb.fsinfo.freecount >        (fat_bpb.totalsectors - fat_bpb.firstdatasector)/        fat_bpb.bpb_secperclus)    {        DEBUGF( "bpb_is_sane() - Error: FSInfo.Freecount > disk size "                 "(0x%04x)\n", fat_bpb.fsinfo.freecount);        return -4;    }    return 0;}static void *cache_fat_sector(int fatsector){    int secnum = fatsector + fat_bpb.bpb_rsvdseccnt;    int cache_index = secnum & FAT_CACHE_MASK;    struct fat_cache_entry *fce = &fat_cache[cache_index];    unsigned char *sectorbuf = &fat_cache_sectors[cache_index][0];    int rc;    /* Delete the cache entry if it isn't the sector we want */    if(fce->inuse && fce->secnum != secnum)    {        /* Write back if it is dirty */        if(fce->dirty)        {            rc = ata_write_sectors(fce->secnum+fat_bpb.startsector, 1,                                   sectorbuf);            if(rc < 0)            {                panicf("cache_fat_sector() - Could not write sector %d"                       " (error %d)\n",                       secnum, rc);            }            if(fat_bpb.bpb_numfats > 1)            {                /* Write to the second FAT */                rc = ata_write_sectors(fce->secnum+fat_bpb.startsector+                                       fat_bpb.fatsize, 1, sectorbuf);                if(rc < 0)                {                    panicf("cache_fat_sector() - Could not write sector %d"                           " (error %d)\n",                           secnum + fat_bpb.fatsize, rc);                }            }        }        fce->secnum = 8; /* Normally an unused sector */        fce->dirty = false;        fce->inuse = false;    }    /* Load the sector if it is not cached */    if(!fce->inuse)    {        rc = ata_read_sectors(secnum + fat_bpb.startsector,1,                              sectorbuf);        if(rc < 0)        {            DEBUGF( "cache_fat_sector() - Could not read sector %d"                    " (error %d)\n", secnum, rc);            return NULL;        }        fce->inuse = true;        fce->secnum = secnum;    }    return sectorbuf;}static unsigned int find_free_cluster(unsigned int startcluster){    unsigned int sector;    unsigned int offset;    unsigned int i;    sector = startcluster / CLUSTERS_PER_FAT_SECTOR;    offset = startcluster % CLUSTERS_PER_FAT_SECTOR;        for (i = 0; i<fat_bpb.fatsize; i++) {        unsigned int j;        unsigned int nr = (i + sector) % fat_bpb.fatsize;        unsigned int* fat = cache_fat_sector(nr);        if ( !fat )            break;        for (j = 0; j < CLUSTERS_PER_FAT_SECTOR; j++) {            int k = (j + offset) % CLUSTERS_PER_FAT_SECTOR;            if (!(SWAB32(fat[k]) & 0x0fffffff)) {                unsigned int c = nr * CLUSTERS_PER_FAT_SECTOR + k;                 /* Ignore the reserved clusters 0 & 1, and also                    cluster numbers out of bounds */                if ( c < 2 || c > fat_bpb.dataclusters+1 )                    continue;                LDEBUGF("find_free_cluster(%x) == %x\n",startcluster,c);                fat_bpb.fsinfo.nextfree = c;                return c;            }        }        offset = 0;    }    LDEBUGF("find_free_cluster(%x) == 0\n",startcluster);    return 0; /* 0 is an illegal cluster number */}static int update_fat_entry(unsigned int entry, unsigned int val){    int sector = entry / CLUSTERS_PER_FAT_SECTOR;    int offset = entry % CLUSTERS_PER_FAT_SECTOR;    unsigned int* sec;    LDEBUGF("update_fat_entry(%x,%x)\n",entry,val);    if (entry==val)        panicf("Creating FAT loop: %x,%x\n",entry,val);    if ( entry < 2 )        panicf("Updating reserved FAT entry %d.\n",entry);    sec = cache_fat_sector(sector);    if (!sec)    {        DEBUGF( "update_entry() - Could not cache sector %d\n", sector);        return -1;    }    fat_cache[(sector + fat_bpb.bpb_rsvdseccnt) & FAT_CACHE_MASK].dirty = true;    if ( val ) {        if (!(SWAB32(sec[offset]) & 0x0fffffff) &&            fat_bpb.fsinfo.freecount > 0)            fat_bpb.fsinfo.freecount--;    }    else {        if (SWAB32(sec[offset]) & 0x0fffffff)            fat_bpb.fsinfo.freecount++;    }    LDEBUGF("update_fat_entry: %d free clusters\n", fat_bpb.fsinfo.freecount);    /* don't change top 4 bits */    sec[offset] &= SWAB32(0xf0000000);    sec[offset] |= SWAB32(val & 0x0fffffff);    return 0;}static int read_fat_entry(unsigned int entry){    int sector = entry / CLUSTERS_PER_FAT_SECTOR;    int offset = entry % CLUSTERS_PER_FAT_SECTOR;    unsigned int* sec;    sec = cache_fat_sector(sector);    if (!sec)    {        DEBUGF( "read_fat_entry() - Could not cache sector %d\n", sector);        return -1;    }    return SWAB32(sec[offset]) & 0x0fffffff;}static int get_next_cluster(unsigned int cluster){    int next_cluster;    next_cluster = read_fat_entry(cluster);    /* is this last cluster in chain? */    if ( next_cluster >= FAT_EOF_MARK )        return 0;    else        return next_cluster;}static int update_fsinfo(void){    unsigned char fsinfo[SECTOR_SIZE];    unsigned int* intptr;    int rc;        /* update fsinfo */    rc = ata_read_sectors(fat_bpb.startsector + fat_bpb.bpb_fsinfo, 1,fsinfo);    if (rc < 0)    {        DEBUGF( "flush_fat() - Couldn't read FSInfo (error code %d)\n", rc);        return rc * 10 - 1;    }    intptr = (int*)&(fsinfo[FSINFO_FREECOUNT]);    *intptr = SWAB32(fat_bpb.fsinfo.freecount);    intptr = (int*)&(fsinfo[FSINFO_NEXTFREE]);    *intptr = SWAB32(fat_bpb.fsinfo.nextfree);    rc = ata_write_sectors(fat_bpb.startsector + fat_bpb.bpb_fsinfo,1,fsinfo);    if (rc < 0)    {        DEBUGF( "flush_fat() - Couldn't write FSInfo (error code %d)\n", rc);        return rc * 10 - 2;    }    return 0;}static int flush_fat(void){    int i;    int rc;    unsigned char *sec;    int secnum;    LDEBUGF("flush_fat()\n");    for(i = 0;i < FAT_CACHE_SIZE;i++)    {        if(fat_cache[i].inuse && fat_cache[i].dirty)        {            secnum = fat_cache[i].secnum + fat_bpb.startsector;            LDEBUGF("Flushing FAT sector %x\n", secnum);            sec = fat_cache_sectors[i];            /* Write to the first FAT */            rc = ata_write_sectors(secnum, 1, sec);            if(rc)            {                DEBUGF( "flush_fat() - Couldn't write"                        " sector %d (error %d)\n", secnum, rc);                return rc * 10 - 1;            }            if(fat_bpb.bpb_numfats > 1 )            {                /* Write to the second FAT */                rc = ata_write_sectors(secnum + fat_bpb.fatsize, 1, sec);                if (rc)                {                    DEBUGF( "flush_fat() - Couldn't write"                             " sector %d (error %d)\n",                            secnum + fat_bpb.fatsize, rc);                    return rc * 10 - 2;                }            }            fat_cache[i].dirty = false;        }    }    rc = update_fsinfo();    if (rc < 0)        return rc * 10 - 3;    return 0;}static void fat_time(unsigned short* date,                     unsigned short* time,                     unsigned short* tenth ){#ifdef HAVE_RTC    struct tm* tm = get_time();    if (date)        *date = ((tm->tm_year - 80) << 9) |            ((tm->tm_mon + 1) << 5) |            tm->tm_mday;    if (time)        *time = (tm->tm_hour << 11) |            (tm->tm_min << 5) |            (tm->tm_sec >> 1);    if (tenth)        *tenth = (tm->tm_sec & 1) * 100;#else    /* non-RTC version returns an increment from the supplied time, or a     * fixed standard time/date if no time given as input */    bool next_day = false;        if (time)    {        if (0 == *time)        {            /* set to 00:15:00 */            *time = (15 << 5);        }        else        {            unsigned short mins = (*time >> 5) & 0x003F;            unsigned short hours = (*time >> 11) & 0x001F;            if ((mins += 10) >= 60)            {                mins = 0;                hours++;            }            if ((++hours) >= 24)            {                hours = hours - 24;                next_day = true;            }            *time = (hours << 11) | (mins << 5);        }    }        if (date)    {        if (0 == *date)        {            /* set to 1 August 2003 */            *date = ((2003 - 1980) << 9) | (8 << 5) | 1;        }        else        {            unsigned short day = *date & 0x001F;            unsigned short month = (*date >> 5) & 0x000F;            unsigned short year = (*date >> 9) & 0x007F;            if (next_day)            {                /* do a very simple day increment - never go above 28 days */                if (++day > 28)                {                    day = 1;                    if (++month > 12)                    {                        month = 1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -