* functions
*/
-u32 pffs_get_ptr(t_pffs *pffs,u8 sector) {
-
- u16 data[3];
- u32 iaddr;
- u32 daddr;
- u8 fnlen;
- u8 found;
+#define pffs_check_magic(data) (((data)&PFFS_INDEX_MAGIC_MASK)==PFFS_INDEX_MAGIC)
+#define pffs_fnlen(data) (((data)&PFFS_FNLEN_MASK)>>4)
+#define pffs_daddr_msb(data) (((data)&PFFS_LEN_MSB_MASK))
+#define pffs_sec_erase(pffs,sec) pffs->fe(pffs->base_addr|pffs->sec_addr[sec])
- iaddr=0;
- daddr=0;
- found=0;
+u32 pffs_find_index(t_pffs *pffs,u8 sector) {
- while(1) {
- pffs->fr(pffs->base_addr+pffs->sec_addr[sector]+iaddr,data,6);
- if(!((data[0]&0xff00)==PFFS_INDEX_MAGIC))
- break;
- found=1;
- fnlen=(data[0]&0x00f0)>>4;
- iaddr+=(6+fnlen+fnlen);
- daddr=((data[0]&0x000f)<<16)|data[1];
- }
+ u16 data;
- pffs->data_ptr=daddr;
+ pffs->fr(pffs->base_addr+pffs->sec_addr[sector],&data,2);
- if(found) {
- pffs->index_ptr=pffs->sec_addr[sector]+iaddr;
- return 0;
+ if((data&0xf000)==PFFS_INDEX_MAGIC) {
+ pffs->index_sec=sector;
+ return PFFS_INDEX_FOUND;
}
- else
- return -1;
+
+ return PFFS_NO_INDEX_FOUND;
}
int pffs_sec_empty(t_pffs *pffs,u8 sec) {
addr=pffs->base_addr|pffs->sec_addr[sec];
while(addr<(pffs->base_addr|pffs->sec_addr[sec+1])) {
- data=*((u16 *)(addr));
+ pffs->fr(addr,&data,2);
if(data!=0xffff)
- return 0;
+ return PFFS_SEC_NOT_EMPTY;
addr+=2;
}
- return 1;
+ return PFFS_SEC_EMPTY;
}
-#define pffs_sec_erase(pffs,sec) pffs->fe(pffs->base_addr|pffs->sec_addr[sec])
+int pffs_find_data_tmp(t_pffs *pffs,u8 sector) {
+
+ u32 iaddr,daddr,dend,dstart;
+ u16 data[3];
+ u8 fnlen;
-int pffs_reorientate(t_pffs *pffs) {
+ iaddr=pffs->base_addr|pffs->sec_addr[pffs->index_sec];
+ dstart=pffs->sec_addr[sector];
+ dend=pffs->sec_addr[sector+1];
- u8 sec,sec0,sec1;
+ while(iaddr<(pffs->base_addr|pffs->sec_addr[sector+1])) {
+ pffs->fr(iaddr,data,6);
+ if(pffs_check_magic(data[0]))
+ break;
+ daddr=pffs_daddr_msb(data[0])|data[1];
+ if((daddr+data[2]<dstart)|(daddr>=dend)) {
+ fnlen=pffs_fnlen(data[0]);
+ iaddr+=(6+fnlen+fnlen);
+ continue;
+ }
+ else
+ return PFFS_NO_DATA_TMP;
+ }
+
+ pffs->data_tmp_sec=sector;
+ if(pffs_sec_empty(pffs,sector)!=PFFS_SEC_EMPTY)
+ pffs->fe(pffs->base_addr|dstart);
+
+ return PFFS_DATA_TMP_FOUND;;
+}
+
+int pffs_orientate(t_pffs *pffs) {
+
+ u8 sec,sec0,sec1,found;
- /* check index sectors */
sec0=pffs->sec_num_index[0];
sec1=pffs->sec_num_index[1];
- if(!(pffs_get_ptr(pffs,sec0)&pffs_get_ptr(pffs,sec1)))
- return 0;
+
+ found=0;
+
+ /* check index sectors */
+ if(pffs_find_index(pffs,sec0)==PFFS_INDEX_FOUND)
+ found=1;
+ else if(pffs_find_index(pffs,sec1)==PFFS_INDEX_FOUND)
+ found=1;
+
+ /* chose temp data sector */
+ if(found) {
+ sec0=pffs->sec_num_data[0];
+ sec1=pffs->sec_num_data[1];
+ for(sec=sec1;sec>=sec0;sec--)
+ if(pffs_find_data_tmp(pffs,sec)==PFFS_DATA_TMP_FOUND)
+ break;
+
+ return PFFS_INDEX_FOUND;
+ }
/* initial run => no data + no index assumed => check whether erased! */
// erase index sectors
pffs_sec_erase(pffs,sec0);
if(!pffs_sec_empty(pffs,sec1))
pffs_sec_erase(pffs,sec1);
+ pffs->index_sec=sec0;
// erase data sectors
sec0=pffs->sec_num_data[0];
sec1=pffs->sec_num_data[1];
+ pffs->data_tmp_sec=sec1;
for(sec=sec0;sec<=sec1;sec++)
if(!pffs_sec_empty(pffs,sec))
pffs_sec_erase(pffs,sec);
return 0;
}
-int pffs_flash_register(t_pffs *pffs,u32 base_addr,u8 sec_num,u32 *sec_addr,
+int pffs_get_data_sec(t_pffs_fd *fd) {
+
+ t_pffs *pffs;
+ u8 sec,sec0,sec1;
+
+ pffs->fd->pffs;
+ sec0=pffs->sec_num_data[0];
+ sec1=pffs->sec_num_data[1];
+
+ for(sec=sec0;sec<sec1;sec++) {
+ if((addr<pffs->sec_addr[sec+1])&(addr>=pffs->sec_addr[sec])) {
+ fd->data_sec=sec;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+int pffs_rearrange(t_pffs *pffs) {
+
+
+
+ return 0;
+}
+
+int pffs_flash_register(t_pffs *pffs,u32 base_addr,u32 *sec_addr,
u8 sec_num_data_min,u8 sec_num_data_max,
u8 sec_num_index0,u8 sec_num_index1,
int (*fw)(u32 addr,u16 *buf,int len),
/* assign physical flash specs */
pffs->base_addr=base_addr;
- pffs->sec_num=sec_num;
pffs->sec_addr=sec_addr;
/* specified index and data sectors */
pffs->fr=fr;
pffs->fe=fe;
- /* orientate */
- pffs_reorientate(pffs);
-
pffs->state|=PFFS_REGISTERED;
return 0;
int pffs_init(t_pffs *pffs) {
+ /* check whether a flash is registered */
if(!(pffs->state&PFFS_REGISTERED))
return -1;
+ /* orientate */
+ pffs_orientate(pffs);
+
+ return 0;
+}
+
+int pffs_find_file(t_pffs *pffs,char *file,u32 *iaddr,u32 *daddr,u16 *len) {
+
+ u8 fnl;
+ u16 data[PFFS_MAX_FILENAME_SIZE+PFFS_HEADER_SIZE];
+
+ *iaddr=pffs->base_addr|pffs->sec_addr[pffs->index_sec];
+
+ while(*iaddr<pffs->sec_addr[pffs->index_sec+1]) {
+ pffs->fr(*iaddr,data,3);
+
+ if(!pffs_check_magic(data[0]))
+ break;
+
+ fnl=pffs_fnlen(data[0]);
+ pffs->fr(*iaddr+6,data+3,fnl+fnl);
+
+ if(!strncmp(file,(char *)(data+3),fnl+fnl)) {
+ *daddr=pffs->base_addr|((data[0]&0x000f)<<16)|data[1];
+ *len=data[2];
+ return PFFS_FILE_FOUND;
+ }
+
+ *iaddr+=(6+fnl+fnl);
+ }
+
+ return PFFS_FILE_NOT_FOUND;
+}
+
+int pffs_open_read(t_pffs_fd *fd) {
+
+ int ret;
+
+ ret=pffs_find_file(fd->pffs,fd->file,
+ &(fd->iaddr),&(fd->daddr),&(fd->len));
+
+ if(ret==PFFS_FILE_FOUND) {
+ fd->dptr=fd->daddr;
+ fd->mode=PFFS_READ;
+ }
+
+ return ret;
+}
+
+int pffs_write_index_init(t_pffs_fd *fd) {
+
+ t_pffs *pffs;
+ u16 data[PFFS_HEADER_SIZE+PFFS_MAX_FILENAME_SIZE];
+
+ pffs=fd->pffs;
+ fns=fd->fn-size;
+
+ if(fd->iaddr+6+fns+fns>=pffs->sec_addr[pffs->index_sec+1])
+ return PFFS_NO_INDEX_SPACE_LEFT;
+
+ data[0]=0x7f00|(fns<<4)|((fd->daddr>>16)&0xf);
+ data[1]=fd->daddr&0xffff;
+ pffs->fw(fd->iaddr,data,4);
+ pffs->fw(fd->iaddr+6,fd->file,fns+fns);
+
+ return PFFS_INDEX_WROTE_INIT;
+}
+
+int pffs_write_finish(t_pffs_fd *fd) {
+
+ fd->pffs->fw(fd->iaddr+4,&(fd->len),2);
+
return 0;
}
+int pffs_open_write(t_pffs_fd *fd) {
+
+ int ret;
+
+ ret=pffs_find_file(fd->pffs,fd->file,
+ &(fd->iaddr),&(fd->daddr),&(fd->len));
+
+ switch(ret) {
+ case PFFS_FILE_NOT_FOUND:
+ ret=pffs_write_index_init();
+ if(ret!=PFFS_INDEX_WROTE_INIT)
+ break;
+ fd->dptr=fd->daddr;
+ fd->len=0;
+ fd->mode=PFFS_WRITE;
+ break;
+ case PFFS_FILE_FOUND:
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+int pffs_open(t_pffs *pffs,t_pffs_fd *fd,char *file,u8 mode) {
+
+ int ret;
+
+ /* the pffs struct */
+ fd->pffs=pffs;
+
+ /* filename */
+ fd->fn_size=strlen(file);
+ if(fd->fn_size&1)
+ fd->file[fd->fn_size++]='\0';
+ fd->fn_size>>1;
+ if(fd->fn_size>PFFS_MAX_FILENAME_SIZE)
+ return PFFS_FILENAME_TOO_LONG;
+ strncpy(fd->file,file,fd->fn_size+fd->fn_size);
+
+ /* clear fd mode */
+ fd->mode=0;
+
+ /* action */
+ switch(mode) {
+ case PFFS_READ:
+ ret=pffs_open_read(fd);
+ break;
+ case PFFS_WRITE:
+ ret=pffs_open_write(fd);
+ break;
+ case PFFS_RDWR:
+ default:
+ return PFFS_MODE_UNSUPPORTED;
+ }
+
+ return ret;
+}
+
+int pffs_read(t_pffs_fd *fd,u8 *buf,int len) {
+
+ int missing;
+ int sec_end;
+
+ /* check whether valid */
+ if(!(fd->mode&PFFS_READ))
+ return PFFS_EINVAL;
+
+ /* check len */
+ if(len&1)
+ return PFFS_INVALID_LEN;
+
+ /* check how much we read */
+ missing=fd->len-(fd->dptr-fd->daddr);
+ if(len>missing)
+ len=missing;
+
+ if((fd->dptr+len)>=pffs->sec_addr[pffs->sec_num_data[1]+1])
+ sec_end=pffs->sec_addr[pffs->sec_num_data[1]+1]-fd->dptr;
+
+
+ /* read */
+ fd->pffs->fr(fd->dptr,(u16 *)buf,len);
+ fd->dptr+=len;;
+
+ return len;
+}
+
+int pffs_write(t_pffs_fd *fd,u8 buf,int len) {
+
+ /* check whether valid */
+ if(!(fd->mode&PFFS_WRITE))
+ return PFFS_EINVAL;
+
+ /* check len */
+ if(len&1)
+ return PFFS_INVALID_LEN;
+
+ missing=PFFS_MAX_FILE_SIZE-fd->len;
+ if(len>missing)
+ len=missing;
+
+ /* check for */
+ if(fd->dptr+len>=pffs->)
+}
+