From 4412ca091e6379def8bc836163c6b580df76619c Mon Sep 17 00:00:00 2001 From: crunchy Date: Wed, 23 Apr 2003 08:34:01 +0000 Subject: start restructuring --- libmpio/src/fat.c | 1039 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1039 insertions(+) create mode 100644 libmpio/src/fat.c (limited to 'libmpio/src/fat.c') diff --git a/libmpio/src/fat.c b/libmpio/src/fat.c new file mode 100644 index 0000000..27974cd --- /dev/null +++ b/libmpio/src/fat.c @@ -0,0 +1,1039 @@ +/* + * + * $Id: fat.c,v 1.1 2003/04/23 08:34:15 crunchy Exp $ + * + * Library for USB MPIO-* + * + * Markus Germeier (mager@tzi.de) + * + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * */ + +#include "fat.h" +#include "io.h" +#include "debug.h" + +#include +#include + +/* I'm lazy so I hard code all the values */ + +BYTE mpio_part_016[0x10] = { + 0x80, 0x02, 0x0a, 0x00, 0x01, 0x03, 0x50, 0xf3, + 0x29, 0x00, 0x00, 0x00, 0xd7, 0x7c, 0x00, 0x00 +}; +BYTE mpio_part_032[0x10] = { + 0x80, 0x02, 0x04, 0x00, 0x01, 0x07, 0x50, 0xf3, + 0x23, 0x00, 0x00, 0x00, 0xdd, 0xf9, 0x00, 0x00 +}; +BYTE mpio_part_064[0x10] = { + 0x80, 0x01, 0x18, 0x00, 0x01, 0x07, 0x60, 0xf3, + 0x37, 0x00, 0x00, 0x00, 0xc9, 0xf3, 0x01, 0x00 +}; +BYTE mpio_part_128[0x10] = { + 0x80, 0x01, 0x10, 0x00, 0x06, 0x0f, 0x60, 0xf3, + 0x2f, 0x00, 0x00, 0x00, 0xd1, 0xe7, 0x03, 0x00 +}; + +/* ------------------------- */ + +BYTE mpio_pbr_head[0x10] = { + 0xe9, 0x00, 0x00, 0x4d, 0x53, 0x44, 0x4f, 0x53, + 0x35, 0x2e, 0x30, 0x00, 0x02, 0x20, 0x01, 0x00 +}; +BYTE mpio_pbr_016[0x13] = { + 0x02, 0x00, 0x01, 0xd7, 0x7c, 0xf8, 0x03, 0x00, + 0x10, 0x00, 0x04, 0x00, 0x29, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 +}; +BYTE mpio_pbr_032[0x13] = { + 0x02, 0x00, 0x01, 0xdd, 0xf9, 0xf8, 0x06, 0x00, + 0x10, 0x00, 0x08, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 +}; +BYTE mpio_pbr_064[0x13] = { + 0x02, 0x00, 0x01, 0x00, 0x00, 0xf8, 0x0c, 0x00, + 0x20, 0x00, 0x08, 0x00, 0x37, 0x00, 0x00, 0x00, + 0xc9, 0xf3, 0x01 +}; +BYTE mpio_pbr_128[0x13] = { + 0x02, 0x00, 0x01, 0x00, 0x00, 0xf8, 0x20, 0x00, + 0x20, 0x00, 0x10, 0x00, 0x2f, 0x00, 0x00, 0x00, + 0xd1, 0xe7, 0x03 +}; + +BYTE * +mpio_mbr_gen(BYTE size) +{ + BYTE *p; + + p = (BYTE *)malloc(SECTOR_SIZE); + memset(p, 0, SECTOR_SIZE); + + /* MBR signature */ + p[0x1fe] = 0x55; + p[0x1ff] = 0xaa; + + /* frist boot partition */ + switch(size) + { + case 16: + memcpy(p+0x1be, mpio_part_016, 0x10); + break; + case 32: + memcpy(p+0x1be, mpio_part_032, 0x10); + break; + case 64: + memcpy(p+0x1be, mpio_part_064, 0x10); + break; + case 128: + memcpy(p+0x1be, mpio_part_128, 0x10); + break; + default: + debug("This should never happen! (%d)\n", size); + exit(-1); + } + + /* all other partitions are set to zero */ + + return p; +} + +BYTE * +mpio_pbr_gen(BYTE size) +{ + BYTE *p; + + p = (BYTE *)malloc(SECTOR_SIZE); + memset(p, 0, SECTOR_SIZE); + + /* MBR signature */ + p[0x1fe] = 0x55; + p[0x1ff] = 0xaa; + + memcpy(p, mpio_pbr_head, 0x10); + /* BIOS parameter etc. */ + switch(size) + { + case 16: + memcpy(p+0x10, mpio_pbr_016, 0x13); + break; + case 32: + memcpy(p+0x10, mpio_pbr_032, 0x13); + break; + case 64: + memcpy(p+0x10, mpio_pbr_064, 0x13); + break; + case 128: + memcpy(p+0x10, mpio_pbr_128, 0x13); + break; + default: + debug("This should never happen! (%d)\n", size); + exit(-1); + } + + /* FAT id */ + if (size >=128) { + strcpy(p+0x36, "FAT16"); + } else { + strcpy(p+0x36, "FAT12"); + } + + return p; +} + +int +mpio_mbr_eval(mpio_smartmedia_t *sm) +{ + BYTE *pe; /* partition entry */ + int sector, head, cylinder; + + if ((sm->mbr[0x1fe] != 0x55) || (sm->mbr[0x1ff] != 0xaa)) + { + debug("This is not the MBR!\n"); + return 1; + } + + /* always use the first partition */ + /* we probably don't need to support others */ + pe = sm->mbr + 0x1be; + + head = (int)(*(pe+0x01) & 0xff); + sector = (int)(*(pe+0x02) & 0x3f); + cylinder = (int)((*(pe+0x02) >> 6) * 0x100 + *(pe + 0x03)); + + sm->pbr_offset=(cylinder * sm->geo.NumHead + head ) * + sm->geo.NumSector + sector - 1; + + return 0; + +} + + +int +mpio_pbr_eval(mpio_smartmedia_t *sm) +{ + BYTE *bpb; /* BIOS Parameter Block */ + int total_sector; + long temp; + + if ((sm->pbr[0x1fe] != 0x55) || (sm->pbr[0x1ff] != 0xaa)) + { + debug("This is not the PBR!\n"); + return 1; + } + + if (strncmp((sm->pbr+0x36),"FAT", 3) != 0) + { + debug("Did not find an FAT signature, *not* good!\n"); + return 2; + } + + bpb = sm->pbr + 0x0b; + + total_sector = (*(sm->pbr+0x14) * 0x100 + *(sm->pbr + 0x13)); + if (!total_sector) + total_sector = (*(sm->pbr+0x23) * 0x1000000 + + *(sm->pbr+0x22) * 0x10000 + + *(sm->pbr+0x21) * 0x100 + + *(sm->pbr+0x20)); + + /* 128 MB need 2 Bytes instead of 1.5 */ + if (sm->size != 128) + { + temp = ((total_sector / 0x20 * 0x03 / 0x02 / 0x200) + 0x01); + } else { + temp = ((total_sector / 0x20 * 0x02 / 0x200) + 0x01); + } + + sm->fat_offset = sm->pbr_offset + 0x01; + sm->fat_size = temp; + sm->fat_nums = *(sm->pbr + 0x10); + sm->dir_offset = sm->pbr_offset + 0x01 + temp * 2; + sm->max_cluster = (total_sector / BLOCK_SECTORS); + /* fix max clusters */ + temp*=2; + while (temp>=0x10) + { + sm->max_cluster--; + temp-=BLOCK_SECTORS; + } + + return 0; +} + + +void +mpio_fatentry_hw2entry(mpio_t *m, mpio_fatentry_t *f) +{ + mpio_smartmedia_t *sm; + BYTE chip, t; + DWORD value; + + if (f->mem == MPIO_INTERNAL_MEM) + { + sm = &m->internal; + + if (f->hw_address == 0xffffffff) + return ; + + value = f->hw_address; + t = value >> 24; + chip = 0; + + while(t/=2) + chip++; + + value &= 0xffffff; + value /= 0x20; + value += chip * (sm->max_cluster / sm->chips); + + f->entry = value; + + return; + } + + debug("This should never happen!\n"); + exit(-1); + + return; +} + + +void +mpio_fatentry_entry2hw(mpio_t *m, mpio_fatentry_t *f) +{ + mpio_smartmedia_t *sm; + DWORD cluster; + BYTE chip; + + if (f->mem == MPIO_INTERNAL_MEM) + { + sm = &m->internal; + + chip = f->entry / (sm->max_cluster / sm->chips); + cluster = f->entry - ((sm->max_cluster / sm->chips) * chip); + cluster *= 0x20; + cluster += 0x01000000 * (1 << chip); + + f->hw_address=cluster; + + return; + } + + debug("This should never happen!\n"); + exit(-1); + + return; +} + + + +int +mpio_bootblocks_read (mpio_t *m, mpio_mem_t mem) +{ + mpio_smartmedia_t *sm=0; + + int error; + + /* this should not be needed for internal memory, but ... */ + if (mem == MPIO_INTERNAL_MEM) sm = &m->internal; + if (mem == MPIO_EXTERNAL_MEM) sm = &m->external; + if (!sm) + return 1; + + /* in case the external mem is defective we need this here! */ + sm->fat=0; + sm->fat_size=0; + sm->fat_nums=0; + + /* TODO: check a few things more, just to be sure */ + + /* read CIS (just in case it might me usefull) */ + if (mpio_io_sector_read(m, mem, MPIO_BLOCK_CIS, sm->cis)) + { + debug("error reading CIS\n"); + return 1; + } + + /* read MBR */ + /* the MBR is always located @ logical block 0, sector 0! */ + if (mpio_io_sector_read(m, mem, 0, sm->mbr)) + { + debug("error reading MBR\n"); + return 1; + } + + if (error=mpio_mbr_eval(sm)) + { + debug("problem with the MBR (#%d), so I won't try to access the card any" + "further.\n", error); + return 1; + } + + /* read PBR */ + if (mpio_io_sector_read(m, mem, sm->pbr_offset, sm->pbr)) + { + debug("error reading PBR\n"); + return 1; + } + + if (error=mpio_pbr_eval(sm)) + { + debug("problem with the PBR (#%d), so I won't try to access the card any" + "further.\n", error); + return 1; + } + + return 0; +} + +mpio_fatentry_t * +mpio_fatentry_new(mpio_t *m, mpio_mem_t mem, DWORD sector, BYTE ftype) +{ + mpio_smartmedia_t *sm; + mpio_fatentry_t *new; + + new = malloc (sizeof(mpio_fatentry_t)); + + if (new) + { + new->m = m; + new->mem = mem; + new->entry = sector; + + /* init FAT entry */ + memset(new->i_fat, 0xff, 0x10); + new->i_fat[0x00] = 0xaa; /* start of file */ + new->i_fat[0x06] = ftype; + new->i_fat[0x0b] = 0x00; + new->i_fat[0x0c] = 0x00; + new->i_fat[0x0d] = 0x00; + if (m->model >= MPIO_MODEL_FD100) { + /* 0x0e is a copy of the file index number */ + new->i_fat[0x0f] = 0x00; + } else { + new->i_fat[0x0e] = 'P'; + new->i_fat[0x0f] = 'C'; + } + } + + if (mem == MPIO_INTERNAL_MEM) + mpio_fatentry_entry2hw(m, new); + + return new; +} + +int +mpio_fatentry_plus_plus(mpio_fatentry_t *f) +{ + f->entry++; + + if (f->mem == MPIO_INTERNAL_MEM) { + if (f->entry >= f->m->internal.max_cluster) + { + f->entry--; + mpio_fatentry_entry2hw(f->m, f); + return 0; + } + mpio_fatentry_entry2hw(f->m, f); + } + + if (f->mem == MPIO_EXTERNAL_MEM) { + if (f->entry > f->m->external.max_cluster) + { + f->entry--; + return 0; + } + } + + return 1; +} + + +/* read "fat_size" sectors of fat into the provided buffer */ +int +mpio_fat_read (mpio_t *m, mpio_mem_t mem, + mpio_callback_init_t progress_callback) +{ + mpio_smartmedia_t *sm; + BYTE recvbuff[SECTOR_SIZE]; + int i; + + if (mem == MPIO_INTERNAL_MEM) + { + sm = &m->internal; + if (mpio_io_spare_read(m, mem, 0, sm->size, 0, sm->fat, + (sm->fat_size * SECTOR_SIZE), progress_callback)) + return 1; + return 0; + } + + if (mem == MPIO_EXTERNAL_MEM) sm = &m->external; + + if (!sm) + return 1; + + for (i = 0; i < sm->fat_size; i++) { + if (mpio_io_sector_read(m, mem, (sm->fat_offset + i), recvbuff)) + return 1; + + memcpy(sm->fat + (i * SECTOR_SIZE), recvbuff, SECTOR_SIZE); + } + + return (0); +} + +int +mpio_fatentry_free(mpio_t *m, mpio_mem_t mem, mpio_fatentry_t *f ) +{ + int e,i ; + mpio_smartmedia_t *sm; + + if (mem == MPIO_INTERNAL_MEM) { + sm = &m->internal; + e = f->entry * 0x10; + + /* be more strict to avoid writing + * to defective blocks! + */ + i=0; + while (i<0x10) + { + if (sm->fat[e+i] != 0xff) + return 0; + i++; + } + return 1; + } + + if (mem == MPIO_EXTERNAL_MEM) { + sm = &m->internal; + if (mpio_fatentry_read(m, mem, f) == 0) + return 1; + } + + return 0; +} + +DWORD +mpio_fatentry_read(mpio_t *m, mpio_mem_t mem, mpio_fatentry_t *f ) +{ + mpio_smartmedia_t *sm; + int e; + int v; + + if (mem == MPIO_INTERNAL_MEM) { + sm = &m->internal; + e = f->entry * 0x10; + if (mpio_fatentry_is_defect(m, mem, f)) + return 0xffffffff; + + /* this is a special system file! */ + if((sm->fat[e+6] != FTYPE_MUSIC) && + (sm->fat[e+7] == 0xff) && + (sm->fat[e+8] == 0x00) && + (sm->fat[e+9] == 0xff) && + (sm->fat[e+10] == 0xff)) + return 0xffffffff; + /* this is a special system file! */ +/* this is not correct!! */ +/* if (sm->fat[e+6] == FTYPE_CONF) */ +/* return 0xffffffff; */ + /* this is a special system file! */ + if((sm->fat[e+6] != FTYPE_MUSIC) && + (sm->fat[e+0x0b] == 0xff) && + (sm->fat[e+0x0c] == 0xff) && + (sm->fat[e+0x0d] == 0xff)) + return 0xffffffff; + + if((sm->fat[e+7] == 0xff) && + (sm->fat[e+8] == 0xff) && + (sm->fat[e+9] == 0xff) && + (sm->fat[e+10] == 0xff)) + return 0xffffffff; + + v = sm->fat[e+7] * 0x1000000 + + sm->fat[e+8] * 0x10000 + + sm->fat[e+9] * 0x100 + + sm->fat[e+10]; + + return v; + } + + if (mem == MPIO_EXTERNAL_MEM) sm = &m->external; + + if (!sm->fat) + { + debug ("error, no space for FAT allocated!\n"); + return 0; + } + + + if (sm->size == 128) { + /* 2 Byte per entry */ + e = f->entry * 2; + v = sm->fat[e + 1] * 0x100 + sm->fat[e]; + } else { + /* 1.5 Byte per entry */ + /* Nibble order: x321 */ + e = (f->entry * 3 / 2); +/* printf("mager: byte (%d/%d)\n", e, e+1); */ + if ((f->entry & 0x01) == 0) { + /* LLxH */ + /* 21x3 */ + v = (sm->fat[e + 1] & 0x0f) * 0x100 + sm->fat[e]; + } else { + /* 1x32 */ + v = (sm->fat[e + 1] * 0x10) + (sm->fat[e] >> 4); + } + } + + return v; +} + +int +mpio_fatentry_write(mpio_t *m, mpio_mem_t mem, mpio_fatentry_t *f, WORD value) +{ + mpio_smartmedia_t *sm; + int e; + BYTE backup; + + if (mem == MPIO_INTERNAL_MEM) + { + debug("This should not be used for internal memory!\n"); + exit(-1); + } + + if (mem == MPIO_EXTERNAL_MEM) sm = &m->external; + + if (sm->size == 128) + { + /* 2 Byte per entry */ + e = f->entry * 2; + sm->fat[e] = value & 0xff; + sm->fat[e + 1] = (value >> 8 ) & 0xff; + } else { + /* 1.5 Byte per entry */ + e = (f->entry * 3 / 2); + if ((f->entry & 0x01) == 0) { + /* 21x3 */ + sm->fat[e] = value & 0xff; + backup = sm->fat[e + 1] & 0xf0; + sm->fat[e + 1] = backup | (( value / 0x100 ) & 0x0f); + } else { + /* 1x32 */ + sm->fat[e + 1] = (value / 0x10) & 0xff; + backup = sm->fat[e] & 0x0f; + sm->fat[e] = backup | ( (value * 0x10) & 0xf0 ); + } + } + + return 0; +} + +int +mpio_fat_internal_find_startsector(mpio_t *m, BYTE start) +{ + mpio_fatentry_t *f; + mpio_smartmedia_t *sm = &m->internal; + int found=-1; + + f = mpio_fatentry_new(m, MPIO_INTERNAL_MEM, 0, FTYPE_MUSIC); + + while(mpio_fatentry_plus_plus(f)) + { + if ((sm->fat[f->entry * 0x10] == 0xaa) && + (sm->fat[f->entry * 0x10 + 1] == start)) + found=f->entry; + } + + free(f); + + return found; +} + +BYTE +mpio_fat_internal_find_fileindex(mpio_t *m) +{ + mpio_fatentry_t *f; + mpio_smartmedia_t *sm = &m->internal; + BYTE index[256]; + BYTE found; /* hmm, ... */ + + memset(index, 1, 256); + + f = mpio_fatentry_new(m, MPIO_INTERNAL_MEM, 0, FTYPE_MUSIC); + while(mpio_fatentry_plus_plus(f)) + { + if (sm->fat[f->entry * 0x10 + 1] != 0xff) + index[sm->fat[f->entry * 0x10 + 1]] = 0; + } + free(f); + + found=6; + while((found<256) && (!index[found])) + found++; + + if (found==256) + { + debug("Oops, did not find a new fileindex!\n" + "This should never happen, aborting now!, Sorry!\n"); + exit(-1); + } + + return found; +} + + +int +mpio_fat_free_clusters(mpio_t *m, mpio_mem_t mem) +{ + mpio_smartmedia_t *sm; + mpio_fatentry_t *f; + int i; + int e = 0; + int fsize; + + if (mem == MPIO_INTERNAL_MEM) sm = &m->internal; + if (mem == MPIO_EXTERNAL_MEM) sm = &m->external; + + if (sm->fat) + { + f = mpio_fatentry_new(m, mem, 0, FTYPE_MUSIC); + do + { + if (mpio_fatentry_free(m, mem, f)) + e++; + } while (mpio_fatentry_plus_plus(f)); + free(f); + } else { + f = 0; + } + + + return (e * 16); +} + +mpio_fatentry_t * +mpio_fatentry_find_free(mpio_t *m, mpio_mem_t mem, BYTE ftype) +{ + mpio_fatentry_t *f; + + f = mpio_fatentry_new(m, mem, 1, ftype); + + while(mpio_fatentry_plus_plus(f)) + { + if (mpio_fatentry_free(m, mem, f)) + return f; + } + + free(f); + + return NULL; +} + +int +mpio_fatentry_next_free(mpio_t *m, mpio_mem_t mem, mpio_fatentry_t *f) +{ + mpio_fatentry_t backup; + + memcpy(&backup, f, sizeof(mpio_fatentry_t)); + + while(mpio_fatentry_plus_plus(f)) + { + if (mpio_fatentry_free(m, mem, f)) + { + if (mem == MPIO_INTERNAL_MEM) + f->i_fat[0x00] = 0xee; + return 1; + } + } + + /* no free entry found, restore entry */ + memcpy(f, &backup, sizeof(mpio_fatentry_t)); + + return 0; +} + +int +mpio_fatentry_next_entry(mpio_t *m, mpio_mem_t mem, mpio_fatentry_t *f) +{ + mpio_smartmedia_t *sm; + DWORD value; + DWORD endvalue; + + value = mpio_fatentry_read(m, mem, f); + + if (value == 0xaaaaaaaa) + return -1; + + if (mem == MPIO_INTERNAL_MEM) + { + sm = &m->internal; + f->hw_address = value; + + mpio_fatentry_hw2entry(m, f); + + endvalue = 0xffffffff; + } + + + if (mem == MPIO_EXTERNAL_MEM) + { + sm = &m->external; + f->entry = value; + + if (sm->size==128) + { + endvalue = 0xfff8; + } else { + endvalue = 0xff8; + } + } + + if (value >= endvalue) + return 0; + + return 1; +} + + +int +mpio_fat_clear(mpio_t *m, mpio_mem_t mem) +{ + mpio_smartmedia_t *sm; + mpio_fatentry_t *f; + + if (mem == MPIO_INTERNAL_MEM) { + sm = &m->internal; + + f = mpio_fatentry_new(m, mem, 1, FTYPE_MUSIC); + do { + mpio_fatentry_set_free(m, mem, f) ; + } while(mpio_fatentry_plus_plus(f)); + free(f); + } + + if (mem == MPIO_EXTERNAL_MEM) { + sm = &m->external; + memset(sm->fat, 0x00, (sm->fat_size * SECTOR_SIZE)); + sm->fat[0] = 0xf8; + sm->fat[1] = 0xff; + sm->fat[2] = 0xff; + /* for FAT 16 */ + if (sm->size == 128) + sm->fat[3] = 0xff; + } + + return 0; +} + +/* + * This function acutally writes both, + * the FAT _and_ the root directory + * + */ + +int +mpio_fat_write(mpio_t *m, mpio_mem_t mem) +{ + mpio_smartmedia_t *sm; + mpio_fatentry_t *f; + BYTE dummy[BLOCK_SIZE]; + WORD i; + DWORD block; + + if (mem == MPIO_INTERNAL_MEM) { + sm = &m->internal; + + if (sm->cdir == sm->root) + { + f=mpio_fatentry_new(m, mem, 0, FTYPE_MUSIC); + mpio_io_block_delete(m, mem, f); + free(f); + + memset(dummy, 0x00, BLOCK_SIZE); + + /* only write the root dir */ + for (i= 0; i< 0x20; i++) + { + + if (iroot->dir + SECTOR_SIZE * i)); + } else { + /* fill the rest of the block with zeros */ + mpio_io_sector_write(m, mem, i, dummy); + } + } + } else { + mpio_directory_write(m, mem, sm->cdir); + } + + } + + if (mem == MPIO_EXTERNAL_MEM) + { + sm=&m->external; + + memset(dummy, 0xff, BLOCK_SIZE); + + for (i = 0; i < (sm->dir_offset + DIR_NUM) ; i++) { + /* before writing to a new block delete it! */ + if (((i / 0x20) * 0x20) == i) { + block = mpio_zone_block_find_seq(m, mem, (i/0x20)); + if (block == MPIO_BLOCK_NOT_FOUND) + { + block = mpio_zone_block_find_free_seq(m, mem, (i/0x20)); + } + if (block == MPIO_BLOCK_NOT_FOUND) + { + debug("This should never happen!"); + exit(-1); + } + + mpio_io_block_delete_phys(m, mem, block); + } + + /* remeber: logical sector 0 is the MBR! */ + if (i == 0) + mpio_io_sector_write(m, mem, 0, sm->mbr); + if ((i > 0) && (i < sm->pbr_offset)) + mpio_io_sector_write(m, mem, i, dummy); + + if (i == sm->pbr_offset) + mpio_io_sector_write(m, mem, sm->pbr_offset, sm->pbr); + + if ((i >= sm->fat_offset) && (i < (sm->fat_offset + (2*sm->fat_size)))) + mpio_io_sector_write(m, mem, i, + (sm->fat + SECTOR_SIZE * + ((i - sm->fat_offset) % sm->fat_size))); + + if (i>=sm->dir_offset) + mpio_io_sector_write(m, mem, i, + (sm->root->dir + + (i - sm->dir_offset) * SECTOR_SIZE)); + } + + if (sm->cdir != sm->root) + mpio_directory_write(m, mem, sm->cdir); + + } + + + return 0; +} + +int +mpio_fatentry_set_free (mpio_t *m, mpio_mem_t mem, mpio_fatentry_t *f) +{ + int e; + mpio_smartmedia_t *sm; + + if (mem == MPIO_INTERNAL_MEM) + { + sm = &m->internal; + e = f->entry * 0x10; + memset((sm->fat+e), 0xff, 0x10); + } + + if (mem == MPIO_EXTERNAL_MEM) + { + sm = &m->internal; + mpio_fatentry_write(m, mem, f, 0); + } + + return 0; +} + +int +mpio_fatentry_set_defect(mpio_t *m, mpio_mem_t mem, mpio_fatentry_t *f) +{ + int e; + mpio_smartmedia_t *sm; + + if (mem == MPIO_INTERNAL_MEM) + { + sm = &m->internal; + e = f->entry * 0x10; + memset((sm->fat+e), 0xaa, 0x10); + } + + if (mem == MPIO_EXTERNAL_MEM) + { + sm = &m->internal; + mpio_fatentry_write(m, mem, f, 0xfff7); + } + + return 0; +} + +int +mpio_fatentry_is_defect(mpio_t *m, mpio_mem_t mem, mpio_fatentry_t *f) +{ + int e; + mpio_smartmedia_t *sm; + + if (mem == MPIO_INTERNAL_MEM) + { + sm = &m->internal; + e = f->entry * 0x10; + if (mpio_fatentry_free(m, mem, f)) + return 0; + /* check if this block became defective */ + if (m->model >= MPIO_MODEL_FD100) { + /* newer models */ + if ((sm->fat[e+0x0f] != 0) || + (sm->fat[e+0x01] != sm->fat[e+0x0e])) + { + debug("defective block encountered, abort reading! (newer models check)\n"); + return 1; + } + } else + if ((sm->fat[e+0x0e] != 'P') || + (sm->fat[e+0x0f] != 'C') || + ((sm->fat[e+0x00] != 0xaa) && + (sm->fat[e+0x00] != 0xee))) + { + debug("defective block encountered, abort reading! (older models check)\n"); + return 1; + } + } + + if (mem == MPIO_EXTERNAL_MEM) + { + if (mpio_fatentry_read(m, mem, f)==0xfff7) + return 1; + } + + return 0; +} + +int +mpio_fatentry_set_eof(mpio_t *m, mpio_mem_t mem, mpio_fatentry_t *f) +{ + int e; + mpio_smartmedia_t *sm; + + if (mem == MPIO_INTERNAL_MEM) + { + sm = &m->internal; + e = f->entry * 0x10; + memset((f->i_fat+0x07), 0xff, 4); + memcpy((sm->fat+e), f->i_fat, 0x10); + } + + if (mem == MPIO_EXTERNAL_MEM) + { + sm = &m->internal; + mpio_fatentry_write(m, mem, f, 0xffff); + } + + return 0; +} + +int +mpio_fatentry_set_next(mpio_t *m, mpio_mem_t mem, + mpio_fatentry_t *f, mpio_fatentry_t *value) +{ + int e; + mpio_smartmedia_t *sm; + + if (mem == MPIO_INTERNAL_MEM) + { + sm = &m->internal; + e = f->entry * 0x10; + + f->i_fat[0x07]= value->hw_address / 0x1000000; + f->i_fat[0x08]=(value->hw_address / 0x10000 ) & 0xff; + f->i_fat[0x09]=(value->hw_address / 0x100 ) & 0xff; + f->i_fat[0x0a]= value->hw_address & 0xff; + + memcpy((sm->fat+e), f->i_fat, 0x10); + } + + if (mem == MPIO_EXTERNAL_MEM) + { + sm = &m->internal; + mpio_fatentry_write(m, mem, f, value->entry); + } + + return 0; +} + -- cgit v1.2.3