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

📄 fat32.c

📁 这是一个基于8255扩展端口的keil c51固件
💻 C
字号:
/*
  Copyright (C) 2003 Bart Bilos <boombox666@yahoo.com>.

  code adapted and modified from the yampp project

  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License
  as published by the Free Software Foundation; either version 2
  of the License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software Foundation, 
  Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/

#include <stdio.h>                /* prototype declarations for I/O functions */
#include <string.h>               /* memory operations */
#include "IDE_LIB.h"              /* IDE working variables */
#include "fat32.h"
#include "util.h"

// current BPB
Bpb CurrBPB;
// sector buffer
char sector_data[512];
// housekeeping vars
// first sector of FAT
unsigned long FirstFATSector;
// first data sector
unsigned long FirstDataSectorD;
// first directory cluster
unsigned long FirstDirCluster;
// how many sectors per cluster
unsigned int  SecPerClust;

// fixes the BPB from big endian to little endian format
void fixBPB(Bpb *a_Bpb) {
  a_Bpb->BPB_BytsPerSec = int_big_endian(a_Bpb->BPB_BytsPerSec); 
  a_Bpb->BPB_ResvdSecCnt = int_big_endian(a_Bpb->BPB_ResvdSecCnt);
  a_Bpb->BPB_RootEntCnt = int_big_endian(a_Bpb->BPB_RootEntCnt);
  a_Bpb->BPB_TotSec16 = int_big_endian(a_Bpb->BPB_TotSec16);
  a_Bpb->BPB_FATSz16 = int_big_endian(a_Bpb->BPB_FATSz16);
  a_Bpb->BPB_SecPerTrk = int_big_endian(a_Bpb->BPB_SecPerTrk);
  a_Bpb->BPB_NumHeads = int_big_endian(a_Bpb->BPB_NumHeads);
  a_Bpb->BPB_HiddSec = long_big_endian(a_Bpb->BPB_HiddSec);
  a_Bpb->BPB_TotSec32 = long_big_endian(a_Bpb->BPB_TotSec32);
  a_Bpb->BPB_FATSz32 = long_big_endian(a_Bpb->BPB_FATSz32);
  a_Bpb->BPB_ExtFlags = int_big_endian(a_Bpb->BPB_ExtFlags);
  a_Bpb->BPB_FSVer = int_big_endian(a_Bpb->BPB_FSVer);
  a_Bpb->BPB_RootClus = long_big_endian(a_Bpb->BPB_RootClus);
  a_Bpb->BPB_FSInfo = int_big_endian(a_Bpb->BPB_FSInfo);
  a_Bpb->BPB_BkBootSec = int_big_endian(a_Bpb->BPB_BkBootSec); 
  a_Bpb->BS_VolID = long_big_endian(a_Bpb->BS_VolID);
}

// calculates the sector number from the cluster number 
unsigned long clust2sect(unsigned long clust) {
return clust * SecPerClust + FirstDataSectorD;
}

// gives the cluster of the root dir
unsigned long rootdir() {
return FirstDirCluster;
}

// reads the harddrive MBR.
// locates the first partition.
// checks if its fat32
char init_fat32(void) {
  Bootsector *startsect; 
  unsigned long int first_sector=0;
  startsect = (Bootsector * ) sector_data;
  // read sector 0 
  if(read_sector(first_sector,sector_data) != 0) {
    return 1;  
  }
  // locate partition and load BPB
  first_sector = long_big_endian(startsect->BS_partition_start);
  if(read_sector(first_sector,sector_data) != 0) {
	  return 1;
  }
  // copy relevant part of BPB from sector to the struct
  memcpy(&CurrBPB,sector_data,90);
  fixBPB(&CurrBPB);
  FirstFATSector	= CurrBPB.BPB_ResvdSecCnt + first_sector;
  FirstDataSectorD = CurrBPB.BPB_ResvdSecCnt + (CurrBPB.BPB_NumFATs * CurrBPB.BPB_FATSz32) + first_sector; // This is FirstDataSector
  FirstDirCluster	= CurrBPB.BPB_RootClus;
  SecPerClust = CurrBPB.BPB_SecPerClus;
  FirstDataSectorD -= (2 * SecPerClust); 
  return 0;
}

// check if sector has suitable directory entries
char checksect(unsigned long a_sect_tocheck) {
read_sector(a_sect_tocheck,sector_data);
// just check if the first byte is non null
if(sector_data[0]!=0) return 1;
else return 0;
}

/*
// print out statistics about the specific entry
void FAT32entrydata(direntry *a_entry){
  int i;
  char fileentry[12];
  for(i=0;i<12;i++)
    fileentry[i] = a_entry->DE_Name[i];
  fileentry[11]=0;
  printf("%s ",fileentry);
  if(ATTR_NORMAL & a_entry->DE_Attributes) {
    printf("N");  
  } else {
    printf("-");
  }
  if(ATTR_READONLY & a_entry->DE_Attributes) {
    printf("R");
  } else {
    printf("-");
  }
  if(ATTR_HIDDEN & a_entry->DE_Attributes) {
    printf("H");
  } else {
    printf("-");
  }
  if(ATTR_SYSTEM & a_entry->DE_Attributes) {
    printf("S");
  } else {
    printf("-");
  }
  if(ATTR_VOLUME & a_entry->DE_Attributes) {
    printf("V");
  } else {
    printf("-");
  }
  if(ATTR_LONG_FILENAME & a_entry->DE_Attributes) {
    printf("L");
  } else {
    printf("-");
  }
  if(ATTR_ARCHIVE & a_entry->DE_Attributes) {
    printf("A");
  } else {
    printf("-");
  } 
  if(ATTR_DIRECTORY & a_entry->DE_Attributes) {
    printf("D");
  } else {
    printf("-");
  } 
  printf(" starting at %6x",int_big_endian(a_entry->DE_StartCluster));
  printf(" %10lu bytes big \n",long_big_endian(a_entry->DE_FileSize));
}

// goes through an table at a_clust and returns the first directory it finds
// or 0 if the table has no directories
unsigned int traverse_dir(unsigned long int a_clust) {
  direntry *de;
  unsigned long nextdir=0;
  int i;
	unsigned long dwStartSector  = clust2sect(a_clust);
  while(checksect(dwStartSector)){
    // sector read in and seems fine
    de = (direntry * ) sector_data;
    // reset sector pointer
    for(i=0;i<16;i++){
      if(de->DE_Name[0] != SLOT_EMPTY) {
        FAT32entrydata(de);
        if(ATTR_DIRECTORY&de->DE_Attributes) {
          // check here for the . and .. directories
          nextdir = int_big_endian(de->DE_StartCluster);
        }
      } else {
        return nextdir;
      }
      de++;
    }
  dwStartSector++;
  }
  return nextdir;
}

*/

// seek a file in the cluster, if found return the direntry
direntry *getfileentry(unsigned long a_cluster, char * filename) {
  direntry *de;
  unsigned long startsect = clust2sect(a_cluster);
  int i;

  while(checksect(startsect)){
    de = (direntry * ) sector_data;
    for(i=0;i<16;i++){
      if(de->DE_Name[0] != SLOT_EMPTY) {
        if(memcmp (de->DE_Name,filename,11) == 0) {
          return de;
        }
      } 
      de++;
    }
  }
return NULL;
}

// amount of open files
filehandle filehandles[FILES+1] = 0;

// initialise the file system
void initfiles(void) {
  unsigned char i;
  // clear all start sectors so they will all be free
  for (i = 0; i < FILES+1;i++)
    filehandles[i].fh_startsect = 0;
}

// open file in current dir with FAT 11 char filenotation
unsigned char fopen (char *a_filename) {
  direntry *file;
  int i;
  file = getfileentry(rootdir(),a_filename);
  // has a file been found?
  if(file == NULL)
    // no exit and report
    return 0;
  else {
    // yes, seek first empty entry
    for(i = 1;i < FILES; i++) {
      if(filehandles[i].fh_startsect == 0) {
        // fill empty handle
        filehandles[i].fh_startsect = clust2sect(int_big_endian(file->DE_StartCluster) | int_big_endian(file->DE_HighClust<<16));
        filehandles[i].fh_fileptr = 0;
        filehandles[i].fh_size = long_big_endian(file->DE_FileSize);
        // return with handle number
        return i;
      }
    }
    return 0;
  }
}

// position the file pointer
unsigned long fseek(unsigned char a_handle, unsigned long pos, char mode) {
  if(a_handle < FILES+1) {
    // set file pointer to pos
    if(mode == 0) {
      if(pos < filehandles[a_handle].fh_size) {
        filehandles[a_handle].fh_fileptr = pos;
      } else 
      return pos;
    }
    // set file pointer to end of file
    if(mode == 1){
      filehandles[a_handle].fh_fileptr = filehandles[a_handle].fh_size;
      return filehandles[a_handle].fh_size;
    }
  }
  else 
    return 0;
}

// close the handle
unsigned char fclose (unsigned char a_handle) {
  if(a_handle < FILES+1) {
    filehandles[a_handle].fh_startsect = 0;
  }
  else 
    return 0;
}
  
  // read from file
unsigned char fread (unsigned char a_handle, char *a_buffer,unsigned int a_bytes) {
  filehandle * currfile = & filehandles[a_handle];
  int sects = a_bytes >> 9;
  int rest = (a_bytes & 0x01FF);
  long int startsect = currfile->fh_startsect;
  long int size = currfile->fh_size;
  long int bytesread=0;
  // is the amount of bytes read greater than the total size
  if((a_bytes + currfile->fh_fileptr) > currfile->fh_size)
    // yes return
    return 0;
  // no proceed
  for(sects;sects != 0;sects--){
    // read whole multiples of 512
    read_sector(startsect,sector_data);
    memcpy(a_buffer,sector_data,512);
    a_buffer = a_buffer + 512;
    bytesread = bytesread + 512;
    startsect++;
  }
  if(rest != 0){
    // read the remainder
    read_sector(startsect,sector_data);
    memcpy(a_buffer,sector_data,rest);
    bytesread = bytesread + rest;
    startsect++;
  }
  // update filepointer
  currfile->fh_fileptr = currfile->fh_fileptr + bytesread;
  // return amount of data read
  return bytesread;
}

⌨️ 快捷键说明

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