Add support for more FAT partitions; support for SD cards greater than 4Gb; TSC2007 touchscreen driver improvements

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4092 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo
2011-11-15 16:44:45 +00:00
parent d5a6c4870e
commit 0fe0a10e9f
6 changed files with 251 additions and 70 deletions
+8
View File
@@ -2202,3 +2202,11 @@
PIC32 port is almost complete but still not ready for prime time. PIC32 port is almost complete but still not ready for prime time.
6.12 2011-xx-xx Gregory Nutt <gnutt@nuttx.org> 6.12 2011-xx-xx Gregory Nutt <gnutt@nuttx.org>
* fs/fat/fs_fat32util.c and fs_fat32.h: Logic extended to look in up to
four partitions for a valid FAT file system.
* drivers/input/tsc2007.c: Add support for 8-bit conversions; make sure
that A/D converters are active before requesting conversions.
* drivers/mmcsd0/mmcsd_sdio.c: Increase capacity variable from size_t
to uin64_t (if available) so that SD cards with capacities greater
than 4Gb can be supported.
+1 -1
View File
@@ -202,7 +202,7 @@ static inline void dispatch_syscall(uint32_t *regs)
#endif #endif
} }
/* Set up the return vaue. First, check if a context switch occurred. /* Set up the return value. First, check if a context switch occurred.
* In this case, regs will no longer be the same as current_regs. In * In this case, regs will no longer be the same as current_regs. In
* the case of a context switch, we will have to save the return value * the case of a context switch, we will have to save the return value
* in the TCB where it can be returned later when the task is restarted. * in the TCB where it can be returned later when the task is restarted.
+110 -32
View File
@@ -91,6 +91,29 @@
#define DEV_FORMAT "/dev/input%d" #define DEV_FORMAT "/dev/input%d"
#define DEV_NAMELEN 16 #define DEV_NAMELEN 16
/* Commands *****************************************************************/
#define TSC2007_SETUP (TSC2007_CMD_FUNC_SETUP)
#ifdef CONFIG_TSC2007_8BIT
# define TSC2007_ACTIVATE_Y (TSC2007_CMD_8BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_YON)
# define TSC2007_MEASURE_Y (TSC2007_CMD_8BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_YPOS)
# define TSC2007_ACTIVATE_X (TSC2007_CMD_8BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_XON)
# define TSC2007_MEASURE_X (TSC2007_CMD_8BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_XPOS)
# define TSC2007_ACTIVATE_Z (TSC2007_CMD_8BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_YXON)
# define TSC2007_MEASURE_Z1 (TSC2007_CMD_8BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_Z1POS)
# define TSC2007_MEASURE_Z2 (TSC2007_CMD_8BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_Z2POS)
# define TSC2007_ENABLE_PENIRQ (TSC2007_CMD_8BIT | TSC2007_CMD_PWRDN_IRQEN)
#else
# define TSC2007_ACTIVATE_Y (TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_YON)
# define TSC2007_MEASURE_Y (TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_YPOS)
# define TSC2007_ACTIVATE_X (TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_XON)
# define TSC2007_MEASURE_X (TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_XPOS)
# define TSC2007_ACTIVATE_Z (TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_YXON)
# define TSC2007_MEASURE_Z1 (TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_Z1POS)
# define TSC2007_MEASURE_Z2 (TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_Z2POS)
# define TSC2007_ENABLE_PENIRQ (TSC2007_CMD_12BIT | TSC2007_CMD_PWRDN_IRQEN)
#endif
/**************************************************************************** /****************************************************************************
* Private Types * Private Types
****************************************************************************/ ****************************************************************************/
@@ -156,6 +179,7 @@ static int tsc2007_sample(FAR struct tsc2007_dev_s *priv,
FAR struct tsc2007_sample_s *sample); FAR struct tsc2007_sample_s *sample);
static int tsc2007_waitsample(FAR struct tsc2007_dev_s *priv, static int tsc2007_waitsample(FAR struct tsc2007_dev_s *priv,
FAR struct tsc2007_sample_s *sample); FAR struct tsc2007_sample_s *sample);
static int tsc2007_activate(FAR struct tsc2007_dev_s *priv, uint8_t cmd);
static int tsc2007_transfer(FAR struct tsc2007_dev_s *priv, uint8_t cmd); static int tsc2007_transfer(FAR struct tsc2007_dev_s *priv, uint8_t cmd);
static void tsc2007_worker(FAR void *arg); static void tsc2007_worker(FAR void *arg);
static int tsc2007_interrupt(int irq, FAR void *context); static int tsc2007_interrupt(int irq, FAR void *context);
@@ -377,6 +401,48 @@ errout:
return ret; return ret;
} }
/****************************************************************************
* Name: tsc2007_activate
****************************************************************************/
static int tsc2007_activate(FAR struct tsc2007_dev_s *priv, uint8_t cmd)
{
struct i2c_msg_s msg;
uint8_t data;
int ret;
/* Send the setup command (with no ACK) followed by the A/D converter
* activation command (ACKed).
*/
data = TSC2007_SETUP;
msg.addr = priv->config->address; /* 7-bit address */
msg.flags = 0; /* Write transaction, beginning with START */
msg.buffer = &data; /* Transfer from this address */
msg.length = 1; /* Send one byte following the address */
/* Ignore errors from the setup command (because it is not ACKed) */
(void)I2C_TRANSFER(priv->i2c, &msg, 1);
/* Now activate the A/D converter */
data = cmd;
msg.addr = priv->config->address; /* 7-bit address */
msg.flags = 0; /* Write transaction, beginning with START */
msg.buffer = &data; /* Transfer from this address */
msg.length = 1; /* Send one byte following the address */
ret = I2C_TRANSFER(priv->i2c, &msg, 1);
if (ret < 0)
{
idbg("I2C_TRANSFER failed: %d\n", ret);
}
return ret;
}
/**************************************************************************** /****************************************************************************
* Name: tsc2007_transfer * Name: tsc2007_transfer
****************************************************************************/ ****************************************************************************/
@@ -529,16 +595,17 @@ static void tsc2007_worker(FAR void *arg)
* in the cases previously listed." * in the cases previously listed."
*/ */
y = tsc2007_transfer(priv, (void)tsc2007_activate(priv, TSC2007_ACTIVATE_X);
(TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_YPOS)); y = tsc2007_transfer(priv, TSC2007_MEASURE_Y);
/* "Voltage is then applied to the other axis, and the A/D converter /* "Voltage is then applied to the other axis, and the A/D converter
* converts the voltage representing the X position on the screen. This * converts the voltage representing the X position on the screen. This
* process provides the X and Y coordinates to the associated processor." * process provides the X and Y coordinates to the associated processor."
*/ */
x = tsc2007_transfer(priv, (void)tsc2007_activate(priv, TSC2007_ACTIVATE_Y);
(TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_XPOS)); x = tsc2007_transfer(priv, TSC2007_MEASURE_X);
/* "... To determine pen or finger touch, the pressure of the touch must be /* "... To determine pen or finger touch, the pressure of the touch must be
* determined. ... There are several different ways of performing this * determined. ... There are several different ways of performing this
@@ -556,15 +623,14 @@ static void tsc2007_worker(FAR void *arg)
* Read Z1 and Z2 values. * Read Z1 and Z2 values.
*/ */
z1 = tsc2007_transfer(priv, (void)tsc2007_activate(priv, TSC2007_ACTIVATE_Z);
(TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_Z1POS)); z1 = tsc2007_transfer(priv, TSC2007_MEASURE_Z1);
z2 = tsc2007_transfer(priv, (void)tsc2007_activate(priv, TSC2007_ACTIVATE_Z);
(TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_Z2POS)); z2 = tsc2007_transfer(priv, TSC2007_MEASURE_Z2);
/* Power down ADC and enable PENIRQ */ /* Power down ADC and enable PENIRQ */
(void)tsc2007_transfer(priv, (void)tsc2007_transfer(priv, TSC2007_ENABLE_PENIRQ);
(TSC2007_CMD_12BIT | TSC2007_CMD_PWRDN_IRQEN));
/* Now calculate the pressure using the first method, reduced to: /* Now calculate the pressure using the first method, reduced to:
* *
@@ -574,21 +640,23 @@ static void tsc2007_worker(FAR void *arg)
if (z1 == 0) if (z1 == 0)
{ {
idbg("Z1 zero\n"); idbg("Z1 zero\n");
goto errout; pressure = 0;
} }
else
pressure = (x * config->rxplate * (z2 - z1)) / z1;
pressure = (pressure + 2048) >> 12;
ivdbg("Position: (%d,%4d) pressure: %u z1/2: (%d,%d)\n",
x, y, pressure, z1, z2);
/* Ignore out of range caculcations */
if (pressure > 0x0fff)
{ {
idbg("Dropped out-of-range pressure: %d\n", pressure); pressure = (x * config->rxplate * (z2 - z1)) / z1;
goto errout; pressure = (pressure + 2048) >> 12;
ivdbg("Position: (%d,%4d) pressure: %u z1/2: (%d,%d)\n",
x, y, pressure, z1, z2);
/* Ignore out of range caculcations */
if (pressure > 0x0fff)
{
idbg("Dropped out-of-range pressure: %d\n", pressure);
pressure = 0;
}
} }
/* Save the measurements */ /* Save the measurements */
@@ -878,17 +946,27 @@ static ssize_t tsc2007_read(FAR struct file *filep, FAR char *buffer, size_t len
report->point[0].flags = TOUCH_UP | TOUCH_ID_VALID; report->point[0].flags = TOUCH_UP | TOUCH_ID_VALID;
} }
else if (sample.contact == CONTACT_DOWN) else
{ {
/* First contact */ if (sample.contact == CONTACT_DOWN)
{
/* First contact */
report->point[0].flags = TOUCH_DOWN | TOUCH_ID_VALID | TOUCH_POS_VALID | TOUCH_PRESSURE_VALID; report->point[0].flags = TOUCH_DOWN | TOUCH_ID_VALID | TOUCH_POS_VALID;
} }
else /* if (sample->contact == CONTACT_MOVE) */ else /* if (sample->contact == CONTACT_MOVE) */
{ {
/* Movement of the same contact */ /* Movement of the same contact */
report->point[0].flags = TOUCH_MOVE | TOUCH_ID_VALID | TOUCH_POS_VALID | TOUCH_PRESSURE_VALID; report->point[0].flags = TOUCH_MOVE | TOUCH_ID_VALID | TOUCH_POS_VALID;
}
/* A pressure measurement of zero means that pressure is not available */
if (report->point[0].pressure != 0)
{
report->point[0].flags |= TOUCH_PRESSURE_VALID;
}
} }
ret = SIZEOF_TOUCH_SAMPLE_S(1); ret = SIZEOF_TOUCH_SAMPLE_S(1);
@@ -1163,7 +1241,7 @@ int tsc2007_register(FAR struct i2c_dev_s *dev,
* waiting for a touch event. * waiting for a touch event.
*/ */
ret = tsc2007_transfer(priv, (TSC2007_CMD_12BIT | TSC2007_CMD_PWRDN_IRQEN)); ret = tsc2007_transfer(priv, TSC2007_ENABLE_PENIRQ);
if (ret < 0) if (ret < 0)
{ {
idbg("tsc2007_transfer failed: %d\n", ret); idbg("tsc2007_transfer failed: %d\n", ret);
+16 -6
View File
@@ -38,6 +38,7 @@
****************************************************************************/ ****************************************************************************/
#include <nuttx/config.h> #include <nuttx/config.h>
#include <nuttx/compiler.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
@@ -128,11 +129,15 @@ struct mmcsd_state_s
/* Memory card geometry (extracted from the CSD) */ /* Memory card geometry (extracted from the CSD) */
uint8_t blockshift; /* Log2 of blocksize */ uint8_t blockshift; /* Log2 of blocksize */
uint16_t blocksize; /* Read block length (== block size) */ uint16_t blocksize; /* Read block length (== block size) */
size_t nblocks; /* Number of blocks */ uint32_t nblocks; /* Number of blocks */
size_t capacity; /* Total capacity of volume */
#ifdef CONFIG_HAVE_LONG_LONG
uint64_t capacity; /* Total capacity of volume */
#else
uint32_t capacity; /* Total capacity of volume (Limited to 4Gb) */
#endif
/* Read-ahead and write buffering support */ /* Read-ahead and write buffering support */
#if defined(CONFIG_FS_WRITEBUFFER) || defined(CONFIG_FS_READAHEAD) #if defined(CONFIG_FS_WRITEBUFFER) || defined(CONFIG_FS_READAHEAD)
@@ -635,7 +640,11 @@ static void mmcsd_decodeCSD(FAR struct mmcsd_state_s *priv, uint32_t csd[4])
*/ */
uint32_t csize = ((csd[1] & 0x3f) << 16) | (csd[2] >> 16); uint32_t csize = ((csd[1] & 0x3f) << 16) | (csd[2] >> 16);
#ifdef CONFIG_HAVE_LONG_LONG
priv->capacity = ((uint64_t)(csize + 1)) << 19;
#else
priv->capacity = (csize + 1) << 19; priv->capacity = (csize + 1) << 19;
#endif
priv->blockshift = 9; priv->blockshift = 9;
priv->blocksize = 1 << 9; priv->blocksize = 1 << 9;
priv->nblocks = priv->capacity >> 9; priv->nblocks = priv->capacity >> 9;
@@ -802,8 +811,9 @@ static void mmcsd_decodeCSD(FAR struct mmcsd_state_s *priv, uint32_t csd[4])
fvdbg(" FILE_FORMAT: %d ECC: %d (MMC) CRC: %d\n", fvdbg(" FILE_FORMAT: %d ECC: %d (MMC) CRC: %d\n",
decoded.fileformat, decoded.mmcecc, decoded.crc); decoded.fileformat, decoded.mmcecc, decoded.crc);
fvdbg("Capacity: %dKb, Block size: %db, nblocks: %d wrprotect: %d\n", fvdbg("Capacity: %luKb, Block size: %db, nblocks: %d wrprotect: %d\n",
priv->capacity / 1024, priv->blocksize, priv->nblocks, priv->wrprotect); (unsigned long)(priv->capacity / 1024), priv->blocksize,
priv->nblocks, priv->wrprotect);
#endif #endif
} }
@@ -2759,7 +2769,7 @@ static int mmcsd_probe(FAR struct mmcsd_state_s *priv)
if (ret == OK) if (ret == OK)
{ {
/* Yes... */ /* Yes... */
fvdbg("Capacity: %lu Kbytes\n", (unsigned long)(priv->capacity / 1024)); fvdbg("Capacity: %lu Kbytes\n", (unsigned long)(priv->capacity / 1024));
priv->mediachanged = true; priv->mediachanged = true;
+42 -2
View File
@@ -129,10 +129,12 @@
*/ */
/* 446@0: Generally unused and zero; but may /* 446@0: Generally unused and zero; but may
* include IDM Boot Manager menu entry at 8@394 */ * include IDM Boot Manager menu entry at 8@394 */
#define PART_ENTRY(n) (446+((n) << 4)) /* n = 0,1,2,3 */
#define PART_ENTRY1 446 /* 16@446: Partition table, first entry */ #define PART_ENTRY1 446 /* 16@446: Partition table, first entry */
#define PART_ENTRY2 462 /* 16@462: Partition table, second entry */ #define PART_ENTRY2 462 /* 16@462: Partition table, second entry */
/* 32@478: Unused, should be zero */ #define PART_ENTRY3 478 /* 16@478: Partition table, third entry */
#define PART_SIGNATURE /* 2@510: Valid partitions have 0x55aa here */ #define PART_ENTRY4 494 /* 16@494: Partition table, fourth entry */
#define PART_SIGNATURE 510 /* 2@510: Valid partitions have 0x55aa here */
/**************************************************************************** /****************************************************************************
* These offsets describes one partition table entry. NOTE that ent entries * These offsets describes one partition table entry. NOTE that ent entries
@@ -147,6 +149,26 @@
#define PART_STARTSECTOR 8 /* 4@8: Starting sector */ #define PART_STARTSECTOR 8 /* 4@8: Starting sector */
#define PART_SIZE 12 /* 4@12: Partition size (in sectors) */ #define PART_SIZE 12 /* 4@12: Partition size (in sectors) */
/****************************************************************************
* Partition table types.
*/
#define PART_TYPE_NONE 0 /* No partition */
#define PART_TYPE_FAT12 1 /* FAT12 */
#define PART_TYPE_FAT16A 4 /* FAT16 (Partition smaller than 32MB) */
#define PART_TYPE_EXT 5 /* Extended MS-DOS Partition */
#define PART_TYPE_FAT16B 6 /* FAT16 (Partition larger than 32MB) */
#define PART_TYPE_FAT32 11 /* FAT32 (Partition up to 2048Gb) */
#define PART_TYPE_FAT32X 12 /* Same as 11, but uses LBA1 0x13 extensions */
#define PART_TYPE_FAT16X 14 /* Same as 6, but uses LBA1 0x13 extensions */
#define PART_TYPE_EXTX 15 /* Same as 5, but uses LBA1 0x13 extensions */
/****************************************************************************
* Each FAT "short" 8.3 file name directory entry is 32-bytes long.
*
* Sizes and limits
*/
/**************************************************************************** /****************************************************************************
* Each FAT "short" 8.3 file name directory entry is 32-bytes long. * Each FAT "short" 8.3 file name directory entry is 32-bytes long.
* *
@@ -329,8 +351,11 @@
#define MBR_GETBOOTSIG16(p) UBYTE_VAL(p,BS16_BOOTSIG) #define MBR_GETBOOTSIG16(p) UBYTE_VAL(p,BS16_BOOTSIG)
#define MBR_GETBOOTSIG32(p) UBYTE_VAL(p,BS32_BOOTSIG) #define MBR_GETBOOTSIG32(p) UBYTE_VAL(p,BS32_BOOTSIG)
#define PART_GETTYPE(n,p) UBYTE_VAL(p,PART_ENTRY(n)+PART_TYPE)
#define PART1_GETTYPE(p) UBYTE_VAL(p,PART_ENTRY1+PART_TYPE) #define PART1_GETTYPE(p) UBYTE_VAL(p,PART_ENTRY1+PART_TYPE)
#define PART2_GETTYPE(p) UBYTE_VAL(p,PART_ENTRY2+PART_TYPE) #define PART2_GETTYPE(p) UBYTE_VAL(p,PART_ENTRY2+PART_TYPE)
#define PART3_GETTYPE(p) UBYTE_VAL(p,PART_ENTRY3+PART_TYPE)
#define PART4_GETTYPE(p) UBYTE_VAL(p,PART_ENTRY4+PART_TYPE)
#define DIR_GETATTRIBUTES(p) UBYTE_VAL(p,DIR_ATTRIBUTES) #define DIR_GETATTRIBUTES(p) UBYTE_VAL(p,DIR_ATTRIBUTES)
#define DIR_GETNTRES(p) UBYTE_VAL(p,DIR_NTRES) #define DIR_GETNTRES(p) UBYTE_VAL(p,DIR_NTRES)
@@ -351,8 +376,11 @@
#define MBR_PUTBOOTSIG16(p,v) UBYTE_PUT(p,BS16_BOOTSIG,v) #define MBR_PUTBOOTSIG16(p,v) UBYTE_PUT(p,BS16_BOOTSIG,v)
#define MBR_PUTBOOTSIG32(p,v) UBYTE_PUT(p,BS32_BOOTSIG,v) #define MBR_PUTBOOTSIG32(p,v) UBYTE_PUT(p,BS32_BOOTSIG,v)
#define PART_PUTTYPE(n,p,v) UBYTE_PUT(p,PART_ENTRY(n)+PART_TYPE,v)
#define PART1_PUTTYPE(p,v) UBYTE_PUT(p,PART_ENTRY1+PART_TYPE,v) #define PART1_PUTTYPE(p,v) UBYTE_PUT(p,PART_ENTRY1+PART_TYPE,v)
#define PART2_PUTTYPE(p,v) UBYTE_PUT(p,PART_ENTRY2+PART_TYPE,v) #define PART2_PUTTYPE(p,v) UBYTE_PUT(p,PART_ENTRY2+PART_TYPE,v)
#define PART3_PUTTYPE(p,v) UBYTE_PUT(p,PART_ENTRY3+PART_TYPE,v)
#define PART4_PUTTYPE(p,v) UBYTE_PUT(p,PART_ENTRY4+PART_TYPE,v)
#define DIR_PUTATTRIBUTES(p,v) UBYTE_PUT(p,DIR_ATTRIBUTES,v) #define DIR_PUTATTRIBUTES(p,v) UBYTE_PUT(p,DIR_ATTRIBUTES,v)
#define DIR_PUTNTRES(p,v) UBYTE_PUT(p,DIR_NTRES,v) #define DIR_PUTNTRES(p,v) UBYTE_PUT(p,DIR_NTRES,v)
@@ -378,10 +406,16 @@
#define MBR_GETVOLID16(p) fat_getuint32(UBYTE_PTR(p,BS16_VOLID)) #define MBR_GETVOLID16(p) fat_getuint32(UBYTE_PTR(p,BS16_VOLID))
#define MBR_GETVOLID32(p) fat_getuint32(UBYTE_PTR(p,BS32_VOLID)) #define MBR_GETVOLID32(p) fat_getuint32(UBYTE_PTR(p,BS32_VOLID))
#define PART_GETSTARTSECTOR(n,p) fat_getuint32(UBYTE_PTR(p,PART_ENTRY(n)+PART_STARTSECTOR))
#define PART_GETSIZE(n,p) fat_getuint32(UBYTE_PTR(p,PART_ENTRY(n)+PART_SIZE))
#define PART1_GETSTARTSECTOR(p) fat_getuint32(UBYTE_PTR(p,PART_ENTRY1+PART_STARTSECTOR)) #define PART1_GETSTARTSECTOR(p) fat_getuint32(UBYTE_PTR(p,PART_ENTRY1+PART_STARTSECTOR))
#define PART1_GETSIZE(p) fat_getuint32(UBYTE_PTR(p,PART_ENTRY1+PART_SIZE)) #define PART1_GETSIZE(p) fat_getuint32(UBYTE_PTR(p,PART_ENTRY1+PART_SIZE))
#define PART2_GETSTARTSECTOR(p) fat_getuint32(UBYTE_PTR(p,PART_ENTRY2+PART_STARTSECTOR)) #define PART2_GETSTARTSECTOR(p) fat_getuint32(UBYTE_PTR(p,PART_ENTRY2+PART_STARTSECTOR))
#define PART2_GETSIZE(p) fat_getuint32(UBYTE_PTR(p,PART_ENTRY2+PART_SIZE)) #define PART2_GETSIZE(p) fat_getuint32(UBYTE_PTR(p,PART_ENTRY2+PART_SIZE))
#define PART3_GETSTARTSECTOR(p) fat_getuint32(UBYTE_PTR(p,PART_ENTRY3+PART_STARTSECTOR))
#define PART3_GETSIZE(p) fat_getuint32(UBYTE_PTR(p,PART_ENTRY3+PART_SIZE))
#define PART4_GETSTARTSECTOR(p) fat_getuint32(UBYTE_PTR(p,PART_ENTRY4+PART_STARTSECTOR))
#define PART4_GETSIZE(p) fat_getuint32(UBYTE_PTR(p,PART_ENTRY4+PART_SIZE))
#define MBR_PUTBYTESPERSEC(p,v) fat_putuint16(UBYTE_PTR(p,BS_BYTESPERSEC),v) #define MBR_PUTBYTESPERSEC(p,v) fat_putuint16(UBYTE_PTR(p,BS_BYTESPERSEC),v)
#define MBR_PUTROOTENTCNT(p,v) fat_putuint16(UBYTE_PTR(p,BS_ROOTENTCNT),v) #define MBR_PUTROOTENTCNT(p,v) fat_putuint16(UBYTE_PTR(p,BS_ROOTENTCNT),v)
@@ -389,10 +423,16 @@
#define MBR_PUTVOLID16(p,v) fat_putuint32(UBYTE_PTR(p,BS16_VOLID),v) #define MBR_PUTVOLID16(p,v) fat_putuint32(UBYTE_PTR(p,BS16_VOLID),v)
#define MBR_PUTVOLID32(p,v) fat_putuint32(UBYTE_PTR(p,BS32_VOLID),v) #define MBR_PUTVOLID32(p,v) fat_putuint32(UBYTE_PTR(p,BS32_VOLID),v)
#define PART_PUTSTARTSECTOR(n,p,v) fat_putuint32(UBYTE_PTR(p,PART_ENTRY(n)+PART_STARTSECTOR),v)
#define PART_PUTSIZE(n,p,v) fat_putuint32(UBYTE_PTR(p,PART_ENTRY(n)+PART_SIZE),v)
#define PART1_PUTSTARTSECTOR(p,v) fat_putuint32(UBYTE_PTR(p,PART_ENTRY1+PART_STARTSECTOR),v) #define PART1_PUTSTARTSECTOR(p,v) fat_putuint32(UBYTE_PTR(p,PART_ENTRY1+PART_STARTSECTOR),v)
#define PART1_PUTSIZE(p,v) fat_putuint32(UBYTE_PTR(p,PART_ENTRY1+PART_SIZE),v) #define PART1_PUTSIZE(p,v) fat_putuint32(UBYTE_PTR(p,PART_ENTRY1+PART_SIZE),v)
#define PART2_PUTSTARTSECTOR(p,v) fat_putuint32(UBYTE_PTR(p,PART_ENTRY2+PART_STARTSECTOR),v) #define PART2_PUTSTARTSECTOR(p,v) fat_putuint32(UBYTE_PTR(p,PART_ENTRY2+PART_STARTSECTOR),v)
#define PART2_PUTSIZE(p,v) fat_putuint32(UBYTE_PTR(p,PART_ENTRY2+PART_SIZE),v) #define PART2_PUTSIZE(p,v) fat_putuint32(UBYTE_PTR(p,PART_ENTRY2+PART_SIZE),v)
#define PART3_PUTSTARTSECTOR(p,v) fat_putuint32(UBYTE_PTR(p,PART_ENTRY3+PART_STARTSECTOR),v)
#define PART3_PUTSIZE(p,v) fat_putuint32(UBYTE_PTR(p,PART_ENTRY3+PART_SIZE),v)
#define PART4_PUTSTARTSECTOR(p,v) fat_putuint32(UBYTE_PTR(p,PART_ENTRY4+PART_STARTSECTOR),v)
#define PART4_PUTSIZE(p,v) fat_putuint32(UBYTE_PTR(p,PART_ENTRY4+PART_SIZE),v)
#ifdef CONFIG_FAT_LFN #ifdef CONFIG_FAT_LFN
# define LDIR_PTRWCHAR1_5(p) UBYTE_PTR(p,LDIR_WCHAR1_5) # define LDIR_PTRWCHAR1_5(p) UBYTE_PTR(p,LDIR_WCHAR1_5)
+74 -29
View File
@@ -138,6 +138,10 @@ static int fat_checkbootrecord(struct fat_mountpt_s *fs)
if (MBR_GETSIGNATURE(fs->fs_buffer) != BOOT_SIGNATURE16 || if (MBR_GETSIGNATURE(fs->fs_buffer) != BOOT_SIGNATURE16 ||
MBR_GETBYTESPERSEC(fs->fs_buffer) != fs->fs_hwsectorsize) MBR_GETBYTESPERSEC(fs->fs_buffer) != fs->fs_hwsectorsize)
{ {
fdbg("ERROR: Signature: %04x FS sectorsize: %d HW sectorsize: %d\n",
MBR_GETSIGNATURE(fs->fs_buffer), MBR_GETBYTESPERSEC(fs->fs_buffer),
fs->fs_hwsectorsize);
return -ENODEV; return -ENODEV;
} }
@@ -172,6 +176,9 @@ static int fat_checkbootrecord(struct fat_mountpt_s *fs)
if (!fs->fs_nfatsects || fs->fs_nfatsects >= fs->fs_hwnsectors) if (!fs->fs_nfatsects || fs->fs_nfatsects >= fs->fs_hwnsectors)
{ {
fdbg("ERROR: fs_nfatsects %d fs_hwnsectors: %d\n",
fs->fs_nfatsects, fs->fs_hwnsectors);
return -ENODEV; return -ENODEV;
} }
@@ -189,6 +196,9 @@ static int fat_checkbootrecord(struct fat_mountpt_s *fs)
if (!fs->fs_fattotsec || fs->fs_fattotsec > fs->fs_hwnsectors) if (!fs->fs_fattotsec || fs->fs_fattotsec > fs->fs_hwnsectors)
{ {
fdbg("ERROR: fs_fattotsec %d fs_hwnsectors: %d\n",
fs->fs_fattotsec, fs->fs_hwnsectors);
return -ENODEV; return -ENODEV;
} }
@@ -197,6 +207,9 @@ static int fat_checkbootrecord(struct fat_mountpt_s *fs)
fs->fs_fatresvdseccount = MBR_GETRESVDSECCOUNT(fs->fs_buffer); fs->fs_fatresvdseccount = MBR_GETRESVDSECCOUNT(fs->fs_buffer);
if (fs->fs_fatresvdseccount > fs->fs_hwnsectors) if (fs->fs_fatresvdseccount > fs->fs_hwnsectors)
{ {
fdbg("ERROR: fs_fatresvdseccount %d fs_hwnsectors: %d\n",
fs->fs_fatresvdseccount, fs->fs_hwnsectors);
return -ENODEV; return -ENODEV;
} }
@@ -210,6 +223,9 @@ static int fat_checkbootrecord(struct fat_mountpt_s *fs)
ndatasectors = fs->fs_fattotsec - fs->fs_fatresvdseccount - ntotalfatsects - rootdirsectors; ndatasectors = fs->fs_fattotsec - fs->fs_fatresvdseccount - ntotalfatsects - rootdirsectors;
if (ndatasectors > fs->fs_hwnsectors) if (ndatasectors > fs->fs_hwnsectors)
{ {
fdbg("ERROR: ndatasectors %d fs_hwnsectors: %d\n",
ndatasectors, fs->fs_hwnsectors);
return -ENODEV; return -ENODEV;
} }
@@ -235,11 +251,14 @@ static int fat_checkbootrecord(struct fat_mountpt_s *fs)
} }
else if (!notfat32) else if (!notfat32)
{ {
fs->fs_fsinfo = fs->fs_fatbase + MBR_GETFSINFO(fs->fs_buffer); fs->fs_fsinfo = fs->fs_fatbase + MBR_GETFSINFO(fs->fs_buffer);
fs->fs_type = FSTYPE_FAT32; fs->fs_type = FSTYPE_FAT32;
} }
else else
{ {
fdbg("ERROR: notfat32: %d fs_nclusters: %d\n",
notfat32, fs->fs_nclusters);
return -ENODEV; return -ENODEV;
} }
@@ -550,37 +569,63 @@ int fat_mount(struct fat_mountpt_s *fs, bool writeable)
/* The contents of sector 0 is not a boot record. It could be a /* The contents of sector 0 is not a boot record. It could be a
* partition, however. Assume it is a partition and get the offset * partition, however. Assume it is a partition and get the offset
* into the partition table. This table is at offset MBR_TABLE and is * into the partition table. This table is at offset MBR_TABLE and is
* indexed by 16x the partition number. Here we support only * indexed by 16x the partition number.
* partition 0.
*
* Check if the partition exists and, if so, get the bootsector for that
* partition and see if we can find the boot record there.
*/ */
if (PART1_GETTYPE(fs->fs_buffer) == 0) int i;
{ for (i = 0; i < 4; i++)
fdbg("No MBR or partition\n"); {
goto errout_with_buffer; /* Check if the partition exists and, if so, get the bootsector for that
* partition and see if we can find the boot record there.
*/
uint8_t part = PART_GETTYPE(i, fs->fs_buffer);
fvdbg("Partition %d, offset %d, type %d\n", i, PART_ENTRY(i), part);
if (part == 0)
{
fvdbg("No partition %d\n", i);
continue;
}
/* There appears to be a partition, get the sector number of the
* partition (LBA)
*/
fs->fs_fatbase = PART_GETSTARTSECTOR(i, fs->fs_buffer);
/* Read the new candidate boot sector */
ret = fat_hwread(fs, fs->fs_buffer, fs->fs_fatbase, 1);
if (ret < 0)
{
/* Failed to read the sector */
goto errout_with_buffer;
}
/* Check if this is a boot record */
ret = fat_checkbootrecord(fs);
if (ret == OK)
{
/* Break out of the loop if a valid boot record is found */
fvdbg("MBR found in partition %d\n", i);
break;
}
/* Re-read sector 0 so that we can check the next partition */
fvdbg("Partition %d is not an MBR\n", i);
ret = fat_hwread(fs, fs->fs_buffer, 0, 1);
if (ret < 0)
{
goto errout_with_buffer;
}
} }
/* There appears to be a partition, get the sector number of the if (i > 3)
* partition (LBA)
*/
fs->fs_fatbase = PART1_GETSTARTSECTOR(fs->fs_buffer);
/* Read the new candidate boot sector */
ret = fat_hwread(fs, fs->fs_buffer, fs->fs_fatbase, 1);
if (ret < 0)
{
goto errout_with_buffer;
}
/* Check if this is a boot record */
ret = fat_checkbootrecord(fs);
if (ret != OK)
{ {
fdbg("No valid MBR\n"); fdbg("No valid MBR\n");
goto errout_with_buffer; goto errout_with_buffer;