aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgermeier <germeier>2002-09-28 00:32:41 +0000
committergermeier <germeier>2002-09-28 00:32:41 +0000
commitd1017e771e1bfad59061844c0f32a7306289e335 (patch)
treea47a26c78babbba71c69ad4edf812c70991b4fae
parentd9ec7993f9705a100043fc890eaa050bcba05349 (diff)
downloadmpiosh-d1017e771e1bfad59061844c0f32a7306289e335.tar.gz
mpiosh-d1017e771e1bfad59061844c0f32a7306289e335.tar.bz2
mpiosh-d1017e771e1bfad59061844c0f32a7306289e335.zip
reading support on external memory should now be correct.
-rw-r--r--ChangeLog5
-rw-r--r--libmpio/defs.h19
-rw-r--r--libmpio/fat.c11
-rw-r--r--libmpio/io.c343
-rw-r--r--libmpio/io.h15
-rw-r--r--libmpio/mpio.c26
-rw-r--r--mpiosh/callback.c11
7 files changed, 267 insertions, 163 deletions
diff --git a/ChangeLog b/ChangeLog
index f059c90..1ab54ec 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2002-09-28 Markus Germeier <mager@tzi.de>
+ * a lot of changes!
+ * reading from external memory should work now correctly
+ * BEWARE: all write operations are still broken on external mem!
+
2002-09-24 Markus Germeier <mager@tzi.de>
* libmpio/directory.c (mpio_dentry_put): fixed 8.3 handling
to allow correct writing of CONFIG.DAT
diff --git a/libmpio/defs.h b/libmpio/defs.h
index 68a87ca..2cdb225 100644
--- a/libmpio/defs.h
+++ b/libmpio/defs.h
@@ -1,7 +1,7 @@
/* -*- linux-c -*- */
/*
- * $Id: defs.h,v 1.10 2002/09/24 15:38:03 germeier Exp $
+ * $Id: defs.h,v 1.11 2002/09/28 00:32:41 germeier Exp $
*
* Library for USB MPIO-*
*
@@ -71,6 +71,17 @@ typedef enum { FTYPE_MUSIC = 0x01,
typedef BYTE (*mpio_callback_t)(int, int) ;
typedef BYTE (*mpio_callback_init_t)(mpio_mem_t, int, int) ;
+/* zone lookup table */
+#define MPIO_ZONE_MAX 8 /* 8* 16MB = 128MB */
+#define MPIO_ZONE_PBLOCKS 1024 /* physical blocks per zone */
+#define MPIO_ZONE_LBLOCKS 1000 /* logical blocks per zone */
+typedef WORD mpio_zonetable_t[MPIO_ZONE_MAX][MPIO_ZONE_PBLOCKS];
+
+#define MPIO_BLOCK_FREE 0xffff
+#define MPIO_BLOCK_DEFECT 0xffee
+#define MPIO_BLOCK_CIS 0xaaaa
+#define MPIO_BLOCK_NOT_FOUND 0xcccccccc
+
/* filenames */
#define MPIO_FILENAME_LEN 129
typedef BYTE mpio_filename_t[MPIO_FILENAME_LEN];
@@ -97,9 +108,6 @@ typedef BYTE mpio_filename_t[MPIO_FILENAME_LEN];
#define CMD_SIZE 0x40
-#define OFFSET_CIS 0x20 /* always fixed? :salmoon */
-#define OFFSET_MBR 0x40 /* always fixed? :salmoon */
-
#define INFO_LINE 81
/* error codes */
@@ -183,6 +191,9 @@ typedef struct {
int max_blocks;
BYTE * spare;
+ /* lookup table for phys.<->log. block mapping */
+ mpio_zonetable_t zonetable;
+
/* seems to be a fixed size according to the
Samsung documentation */
BYTE dir[DIR_SIZE]; /* file index */
diff --git a/libmpio/fat.c b/libmpio/fat.c
index 1a09f7b..5690206 100644
--- a/libmpio/fat.c
+++ b/libmpio/fat.c
@@ -1,6 +1,6 @@
/*
*
- * $Id: fat.c,v 1.14 2002/09/24 15:38:03 germeier Exp $
+ * $Id: fat.c,v 1.15 2002/09/28 00:32:41 germeier Exp $
*
* Library for USB MPIO-*
*
@@ -112,16 +112,15 @@ mpio_bootblocks_read (mpio_t *m, mpio_mem_t mem)
/* TODO: check a few things more, just to be sure */
/* read CIS (just in case it might me usefull) */
- /* fixed @ offset 0x20 */
- if (mpio_io_sector_read(m, mem, 0x20, sm->cis))
+ if (mpio_io_sector_read(m, mem, MPIO_BLOCK_CIS, sm->cis))
{
debug("error reading CIS\n");
return 1;
}
/* read MBR */
- /* fixed @ offset 0x40 */
- if (mpio_io_sector_read(m, mem, 0x40, sm->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;
@@ -142,7 +141,7 @@ mpio_bootblocks_read (mpio_t *m, mpio_mem_t mem)
cylinder = (int)((*(pe+0x02) >> 6) * 0x100 + *(pe + 0x03));
sm->pbr_offset=(cylinder * sm->geo.NumHead + head ) *
- sm->geo.NumSector + sector - 1 + OFFSET_MBR;
+ sm->geo.NumSector + sector - 1 /*+ OFFSET_MBR */;
/* read PBR */
if (mpio_io_sector_read(m, mem, sm->pbr_offset, sm->pbr))
diff --git a/libmpio/io.c b/libmpio/io.c
index 7a5b58e..6a11866 100644
--- a/libmpio/io.c
+++ b/libmpio/io.c
@@ -2,7 +2,7 @@
/*
*
- * $Id: io.c,v 1.16 2002/09/23 22:38:03 germeier Exp $
+ * $Id: io.c,v 1.17 2002/09/28 00:32:41 germeier Exp $
*
* Library for USB MPIO-*
*
@@ -45,11 +45,11 @@
#include "ecc.h"
BYTE model2externalmem(mpio_model_t);
-WORD index2blockaddress(WORD);
-WORD cluster2blockaddress(DWORD, BYTE);
-int cluster2block(int mem, int sector);
+WORD blockaddress_encode(WORD);
+WORD blockaddress_decode(BYTE *);
void fatentry2hw(mpio_fatentry_t *, BYTE *, DWORD *);
+/* small hack to handle external addressing on different MPIO models */
BYTE
model2externalmem(mpio_model_t model)
{
@@ -68,91 +68,10 @@ model2externalmem(mpio_model_t model)
return m;
}
-void
-fatentry2hw(mpio_fatentry_t *f, BYTE *chip, DWORD *address)
-{
- mpio_smartmedia_t *sm;
-
- if (f->mem == MPIO_INTERNAL_MEM)
- {
- sm = &f->m->internal;
- /* hexdump((char *)&f->entry, 4); */
- /* hexdump((char *)&f->hw_address, 4); */
- *chip = f->hw_address / 0x1000000;
- *address = f->hw_address & 0x0ffffff;
- }
- if (f->mem == MPIO_EXTERNAL_MEM)
- {
- sm = &f->m->external;
- *chip = MPIO_EXTERNAL_MEM;
- *address = cluster2block(sm->size, f->entry);
- *address *= BLOCK_SECTORS;
-
- /* add offset to start of "data" area! */
- *address += (sm->dir_offset + DIR_NUM - (2 * BLOCK_SECTORS));
- }
- return;
-}
-
-
-
-/*
- * HELP!
- *
- * somebody explain me these values!!!
- *
- */
-
-int
-cluster2block(int mem, int sector)
-{
- int a = sector;
-
- /* No Zone-based block management for SmartMedia below 32MB !!*/
-
- /* The jumps are defect sectors on a specific SM medium and have to
- be handled with a proper logic block -> physical block which
- include a bad block management */
-
-/* if (mem == 32) */
-/* { */
-/* if (sector >= 830) */
-/* a++; */
-/* if (a >= 1001) */
-/* a += 21; */
-/* } */
-
-/* if (mem == 64) */
-/* { */
-/* /\* I'm so large in *not* knowing! *\/ */
-/* if (sector >= 89) */
-/* a++; */
-/* if (a >= 1000) */
-/* a += 21; */
-/* if (a >= 2021) */
-/* a += 24; */
-/* if (a >= 3045) */
-/* a += 24; */
-/* /\* WHAT? *\/ */
-/* if (a >= 3755) */
-/* a++; */
-/* } */
-
- if (mem > 16)
- {
- /* two blocks are already spent elsewhere */
- /* question is: where (CIS and ??) */
- if (sector >= 998)
- a += 22;
- /* ... and then add 24 empty blocks every 1000 sectors */
- a += ((sector - 998) / 1000 * 24);
- }
-
- return a;
-}
+/* encoding and decoding of blockaddresses */
WORD
-index2blockaddress(WORD ba)
+blockaddress_encode(WORD ba)
{
WORD addr;
BYTE p = 0, c = 0;
@@ -182,48 +101,195 @@ index2blockaddress(WORD ba)
return addr;
}
+
WORD
-cluster2blockaddress(DWORD index, BYTE size)
+blockaddress_decode(BYTE *entry)
{
- DWORD ba;
- WORD block_address;
+ WORD ba;
+ WORD value;
+ BYTE p=0, high, low;
+ int i, t;
+
+ /* check for "easy" defect block */
+ t=1;
+ for(i=0; i<0x10; i++)
+ if (entry[i] != 0)
+ t=0;
+ if (t)
+ return MPIO_BLOCK_DEFECT;
+
+ /* check for "easy" defect block */
+ t=1;
+ for(i=0; i<0x10; i++)
+ if (entry[i] != 0xff)
+ t=0;
+ if (t)
+ return MPIO_BLOCK_FREE;
+
+ /* check for "strange" errors */
+ if ((entry[6] != entry[11]) ||
+ (entry[7] != entry[12]))
+ {
+ debug("error: different block addresses found:\n");
+ hexdumpn(1, entry, 0x10);
+ return MPIO_BLOCK_DEFECT;
+ }
+
+ ba = entry[6] * 0x100 + entry[7];
+
+ /* special values */
+ if (ba == 0xffff)
+ return MPIO_BLOCK_DEFECT;
+ if (ba == 0x0000)
+ return MPIO_BLOCK_CIS;
+
+ /* check parity */
+ value = ba;
+ while (value)
+ {
+ if (value & 0x01)
+ p ^= 0x01;
+
+ value /= 2;
+ }
+ if (p)
+ {
+ debug("parity error found in block address: %2x\n", ba);
+ return MPIO_BLOCK_DEFECT;
+ }
+
+ high = ((ba / 0x100) & 0x07);
+ low = ((ba & 0x0ff) / 2);
+
+ return (high * 0x80 + low);
+}
- /* The jumps are defect sectors on a specific SM medium and have to
- be handled with a proper logic block -> physical block which
- include a bad block management */
+/* foobar */
+
+void
+fatentry2hw(mpio_fatentry_t *f, BYTE *chip, DWORD *address)
+{
+ mpio_smartmedia_t *sm;
- if (index<0x40)
+ if (f->mem == MPIO_INTERNAL_MEM)
+ {
+ sm = &f->m->internal;
+ /* hexdump((char *)&f->entry, 4); */
+ /* hexdump((char *)&f->hw_address, 4); */
+ *chip = f->hw_address / 0x1000000;
+ *address = f->hw_address & 0x0ffffff;
+ }
+ if (f->mem == MPIO_EXTERNAL_MEM)
{
- block_address=0;
+ sm = &f->m->external;
+ *chip = MPIO_EXTERNAL_MEM;
+ *address = mpio_zone_block_find(f->m, f->mem, f->entry);
+ debugn(3, "mager: %06x (logical: %04x)\n", *address, f->entry);
+ }
+ return;
+}
+
+/*
+ * zone management
+ */
+
+int
+mpio_zone_init(mpio_t *m, mpio_cmd_t mem)
+{
+ mpio_smartmedia_t *sm;
+ int i;
+ int zone, block, e;
+
+ if (mem != MPIO_EXTERNAL_MEM)
+ {
+ debug("called function with wrong memory selection!\n");
+ return -1;
+ }
+ sm = &m->external;
+
+ for(i=0; i<sm->max_blocks; i++)
+ {
+ zone = i / MPIO_ZONE_PBLOCKS;
+ block= i % MPIO_ZONE_PBLOCKS;
+
+ e = i * 0x10;
+
+ sm->zonetable[zone][block]=blockaddress_decode(sm->spare+e);
+
+ hexdumpn(4, sm->spare+e, 0x10);
+ debugn(2, "decoded: %03x\n", sm->zonetable[zone][block]);
+ }
+
+}
+
+DWORD
+mpio_zone_block_find(mpio_t *m, mpio_cmd_t mem, DWORD lblock)
+{
+ mpio_smartmedia_t *sm;
+ int i, f, v;
+ int zone, block;
+
+ if (mem != MPIO_EXTERNAL_MEM)
+ {
+ debug("called function with wrong memory selection!\n");
+ return -1;
+ }
+ sm = &m->external;
+
+ /* OK, I can't explain this right now, but it does work,
+ * see Software Driver v3.0, page 31
+ */
+ v = lblock + (sm->size/64);
+
+ if (lblock == MPIO_BLOCK_CIS)
+ {
+ zone = 0;
+ block = MPIO_BLOCK_CIS;
} else {
- if (index >= 0x8000)
- {
- ba = ((index % 0x8000) / 0x20);
-/* if (size == 64) */
-/* { */
-/* if (index >= 0x1d5e0) */
-/* ba--; */
-/* } */
- } else {
- ba = (index / 0x20) - 2;
-/* if (size == 32) */
-/* { */
-/* if (ba >= 0x33f) */
-/* ba--; */
-/* } */
-/* if (size == 64) */
-/* { */
-/* if (ba >= 0x05b) */
-/* ba--; */
-/* } */
+ zone = v / MPIO_ZONE_LBLOCKS;
+ block = v % MPIO_ZONE_LBLOCKS;
+ }
+
+ f=0;
+ for (i=(MPIO_ZONE_PBLOCKS-1); i >=0; i--)
+ {
+
+ if (sm->zonetable[zone][i]==block)
+ {
+ f++;
+ v=i;
}
- block_address= index2blockaddress(ba);
- debugn(2, "block-foo: %06x %04x %04x\n", index, ba, block_address);
+ }
+
+ if (f>1)
+ debug("found more than one block, using first one\n");
+
+ if (!f)
+ {
+ debug("block not found\n");
+ return MPIO_BLOCK_NOT_FOUND;
}
- return block_address;
+ return ((zone * BLOCK_SECTORS * MPIO_ZONE_PBLOCKS ) + v * BLOCK_SECTORS);
}
+void
+mpio_zone_block_set(mpio_t *m, mpio_cmd_t mem, DWORD pblock)
+{
+ int zone, block, pb;
+
+ pb = pblock / BLOCK_SECTORS;
+ zone = pb / MPIO_ZONE_PBLOCKS;
+ block = pb % MPIO_ZONE_PBLOCKS;
+
+ m->external.zonetable[zone][block] = MPIO_BLOCK_FREE ;
+
+}
+
+DWORD
+mpio_zone_block_free(mpio_t *m, mpio_cmd_t mem, DWORD lblock)
+{
+}
/*
* low-low level functions
@@ -419,7 +485,7 @@ int
mpio_io_sector_read(mpio_t *m, BYTE mem, DWORD index, BYTE *output)
{
mpio_smartmedia_t *sm=0;
-
+ DWORD sector;
int nwrite, nread;
BYTE cmdpacket[CMD_SIZE], recvbuff[SECTOR_TRANS];
@@ -431,7 +497,24 @@ mpio_io_sector_read(mpio_t *m, BYTE mem, DWORD index, BYTE *output)
exit (-1);
}
- mpio_io_set_cmdpacket (m, GET_SECTOR, mem, index, sm->size, 0, cmdpacket);
+ if (mem == MPIO_INTERNAL_MEM)
+ {
+ sector = index;
+ } else {
+ /* find the correct physical block first! */
+ if (index == MPIO_BLOCK_CIS)
+ {
+ sector = mpio_zone_block_find(m, mem, index);
+ } else {
+ sector = mpio_zone_block_find(m, mem, /* yuck */
+ ((index / 0x20) - (sm->size/64)));
+ sector+= (index % 0x20);
+ }
+ }
+
+ debugn (2, "sector: %8x (%06x)\n", index, sector);
+
+ mpio_io_set_cmdpacket (m, GET_SECTOR, mem, sector, sm->size, 0, cmdpacket);
debugn (5, "\n>>> MPIO\n");
hexdump (cmdpacket, sizeof(cmdpacket));
@@ -533,8 +616,8 @@ mpio_io_sector_write(mpio_t *m, BYTE mem, DWORD index, BYTE *input)
memset(sendbuff + SECTOR_SIZE, 0xff, 0x10);
memcpy(sendbuff, input, SECTOR_SIZE);
- if (mem==MPIO_EXTERNAL_MEM)
- block_address = cluster2blockaddress(index, sm->size);
+/* if (mem==MPIO_EXTERNAL_MEM) */
+/* block_address = cluster2blockaddress(index, sm->size); */
{
/* generate ECC information for spare area ! */
@@ -584,7 +667,6 @@ mpio_io_block_read(mpio_t *m, BYTE mem, mpio_fatentry_t *f, BYTE *output)
BYTE chip;
DWORD address;
BYTE cmdpacket[CMD_SIZE], recvbuff[BLOCK_TRANS];
- DWORD block_address, ba;
if (mem == MPIO_INTERNAL_MEM) sm = &m->internal;
if (mem == MPIO_EXTERNAL_MEM) sm = &m->external;
@@ -630,18 +712,6 @@ mpio_io_block_read(mpio_t *m, BYTE mem, mpio_fatentry_t *f, BYTE *output)
((recvbuff +(i * SECTOR_TRANS)
+ SECTOR_SIZE + 8))))
debug ("ECC error @ (%02x : %06x)\n", chip, address);
-
- if (i==0)
- {
- block_address = cluster2blockaddress(address, sm->size);
-
- ba = recvbuff[(i * SECTOR_TRANS) + SECTOR_SIZE + 0x06] * 0x100 +
- recvbuff[(i * SECTOR_TRANS) + SECTOR_SIZE + 0x07] ;
- if (block_address != ba)
- debugn(2,"different block_addresses during read: %04x vs. %04x\n",
- block_address, ba);
- }
-
}
memcpy(output + (i * SECTOR_SIZE),
@@ -739,6 +809,7 @@ mpio_io_block_delete(mpio_t *m, BYTE mem, mpio_fatentry_t *f)
if (mem == MPIO_EXTERNAL_MEM) sm = &m->external;
fatentry2hw(f, &chip, &address);
+ mpio_zone_block_free(m, mem, address);
/* Send command packet to MPIO */
@@ -818,7 +889,7 @@ mpio_io_block_write(mpio_t *m, BYTE mem, mpio_fatentry_t *f, BYTE *data)
/* fill in block information */
if (mem == MPIO_EXTERNAL_MEM)
{
- block_address = cluster2blockaddress(address, sm->size);
+/* block_address = cluster2blockaddress(address, sm->size); */
ba = (block_address / 0x100) & 0xff;
sendbuff[(i * SECTOR_TRANS) + SECTOR_SIZE + 0x06] = ba;
diff --git a/libmpio/io.h b/libmpio/io.h
index cd8b70c..44b3cbe 100644
--- a/libmpio/io.h
+++ b/libmpio/io.h
@@ -2,7 +2,7 @@
/*
*
- * $Id: io.h,v 1.8 2002/09/23 22:38:03 germeier Exp $
+ * $Id: io.h,v 1.9 2002/09/28 00:32:41 germeier Exp $
*
* Library for USB MPIO-*
*
@@ -33,6 +33,19 @@
#include "defs.h"
+/* phys.<->log. block mapping */
+int mpio_zone_init(mpio_t *, mpio_cmd_t);
+/* context, memory bank, logical block */
+/* returns address of physical block! */
+DWORD mpio_zone_block_find(mpio_t *, mpio_cmd_t, DWORD);
+/* context, memory bank, logical block, physical address */
+/* mark physical block free (internal maintenance) */
+void mpio_zone_block_set(mpio_t *, mpio_cmd_t, DWORD);
+/* context, memory bank, logical block */
+/* find used physical block and mark it as unused! */
+/* returns address of physical block! (to delete the physical block!) */
+DWORD mpio_zone_block_free(mpio_t *, mpio_cmd_t, DWORD);
+
/* real I/O */
int mpio_io_set_cmdpacket(mpio_t *, mpio_cmd_t, mpio_mem_t,
DWORD, BYTE, BYTE, BYTE *);
diff --git a/libmpio/mpio.c b/libmpio/mpio.c
index 6e2fd45..330a744 100644
--- a/libmpio/mpio.c
+++ b/libmpio/mpio.c
@@ -1,6 +1,6 @@
/*
*
- * $Id: mpio.c,v 1.27 2002/09/24 15:38:03 germeier Exp $
+ * $Id: mpio.c,v 1.28 2002/09/28 00:32:41 germeier Exp $
*
* Library for USB MPIO-*
*
@@ -193,11 +193,6 @@ mpio_init_external(mpio_t *m)
"mpio-devel@lists.sourceforge.net\n");
}
- mpio_bootblocks_read(m, MPIO_EXTERNAL_MEM);
- sm->fat = malloc(SECTOR_SIZE*sm->fat_size);
- mpio_fat_read(m, MPIO_EXTERNAL_MEM, NULL);
- mpio_rootdir_read(m, MPIO_EXTERNAL_MEM);
-
/* for reading the spare area later! */
sm->max_blocks = sm->size/16*1024; /* 1 cluster == 16 KB */
sm->spare = malloc(sm->max_blocks * 0x10);
@@ -272,11 +267,20 @@ mpio_init(mpio_callback_init_t progress_callback)
mpio_fat_read(new_mpio, MPIO_INTERNAL_MEM, progress_callback);
/* read the spare area (for block mapping) */
- sm = &new_mpio->external;
- mpio_io_spare_read(new_mpio, MPIO_EXTERNAL_MEM, 0,
- sm->size, 0, sm->spare,
- (sm->max_blocks * 0x10), progress_callback);
+ if (new_mpio->external.id)
+ {
+ sm = &new_mpio->external;
+ mpio_io_spare_read(new_mpio, MPIO_EXTERNAL_MEM, 0,
+ sm->size, 0, sm->spare,
+ (sm->max_blocks * 0x10), progress_callback);
+ mpio_zone_init(new_mpio, MPIO_EXTERNAL_MEM);
+ mpio_bootblocks_read(new_mpio, MPIO_EXTERNAL_MEM);
+ sm->fat = malloc(SECTOR_SIZE*sm->fat_size);
+ mpio_fat_read(new_mpio, MPIO_EXTERNAL_MEM, NULL);
+ mpio_rootdir_read(new_mpio, MPIO_EXTERNAL_MEM);
+ }
+
return new_mpio;
}
@@ -400,8 +404,6 @@ mpio_file_get(mpio_t *m, mpio_mem_t mem, mpio_filename_t filename,
do
{
- debugn(2, "entry: %4x\n", f->entry);
-
mpio_io_block_read(m, mem, f, block);
if (filesize > BLOCK_SIZE) {
diff --git a/mpiosh/callback.c b/mpiosh/callback.c
index cc99d29..e4c64ab 100644
--- a/mpiosh/callback.c
+++ b/mpiosh/callback.c
@@ -2,7 +2,7 @@
*
* Author: Andreas Büsching <crunchy@tzi.de>
*
- * $Id: callback.c,v 1.19 2002/09/24 15:38:03 germeier Exp $
+ * $Id: callback.c,v 1.20 2002/09/28 00:32:41 germeier Exp $
*
* Copyright (C) 2001 Andreas Büsching <crunchy@tzi.de>
*
@@ -169,9 +169,12 @@ mpiosh_cmd_mem(char *args[])
mpiosh.card = MPIO_EXTERNAL_MEM;
mpiosh.prompt = PROMPT_EXT;
printf("WARNING\n");
- printf("Support for external memory is not complete and will"
- " probably *not* work !!\n");
- printf("WARNING\n");
+ printf("Support for external memory is work in progress!!\n");
+ printf("Assumed status:\n");
+ printf("reading : works (untested)\n");
+ printf("deleting : broken\n");
+ printf("writing : broken\n");
+ printf("formatting: broken\n");
printf("external memory card is selected\n");
} else {
printf("no external memory card is available\n");