summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg White <gwhite@rockbox.org>2007-01-06 01:26:36 +0000
committerGreg White <gwhite@rockbox.org>2007-01-06 01:26:36 +0000
commitebcd762fb24455b58c9aab79a004e93d04a5c6cd (patch)
tree3a9e4e84c8533f13771894519b22c176638a9c47
parente370776120cf87e0a92038d3e4399240b2cf2c3d (diff)
downloadrockbox-ebcd762fb24455b58c9aab79a004e93d04a5c6cd.zip
rockbox-ebcd762fb24455b58c9aab79a004e93d04a5c6cd.tar.gz
rockbox-ebcd762fb24455b58c9aab79a004e93d04a5c6cd.tar.bz2
rockbox-ebcd762fb24455b58c9aab79a004e93d04a5c6cd.tar.xz
Read byte by byte rather than DMA for unaligned transfer
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11927 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/target/arm/gigabeat/meg-fx/ata-meg-fx.c35
1 files changed, 24 insertions, 11 deletions
diff --git a/firmware/target/arm/gigabeat/meg-fx/ata-meg-fx.c b/firmware/target/arm/gigabeat/meg-fx/ata-meg-fx.c
index 361b9d4..d098d83 100644
--- a/firmware/target/arm/gigabeat/meg-fx/ata-meg-fx.c
+++ b/firmware/target/arm/gigabeat/meg-fx/ata-meg-fx.c
@@ -54,18 +54,31 @@ void ata_device_init(void)
void copy_read_sectors(unsigned char* buf, int wordcount)
{
+ /* Unaligned transfer - slow copy */
+ if ( (unsigned long)buf & 1)
+ { /* not 16-bit aligned, copy byte by byte */
+ unsigned short tmp = 0;
+ unsigned char* bufend = buf + wordcount*2;
+ do
+ {
+ tmp = ATA_DATA;
+ *buf++ = tmp & 0xff; /* I assume big endian */
+ *buf++ = tmp >> 8; /* and don't use the SWAB16 macro */
+ } while (buf < bufend); /* tail loop is faster */
+ return;
+ }
/* This should never happen, but worth watching for */
if(wordcount > (1 << 18))
panicf("atd-meg-fx.c: copy_read_sectors: too many sectors per read!");
//#define GIGABEAT_DEBUG_ATA
#ifdef GIGABEAT_DEBUG_ATA
- static int line = 0;
- static char str[256];
- snprintf(str, sizeof(str), "ODD DMA to %08x, %d", buf, wordcount);
- lcd_puts(10, line, str);
- line = (line+1) % 32;
- lcd_update();
+ static int line = 0;
+ static char str[256];
+ snprintf(str, sizeof(str), "ODD DMA to %08x, %d", buf, wordcount);
+ lcd_puts(10, line, str);
+ line = (line+1) % 32;
+ lcd_update();
#endif
/* Reset the channel */
DMASKTRIG0 |= 4;
@@ -87,17 +100,17 @@ void copy_read_sectors(unsigned char* buf, int wordcount)
/* Activate the channel */
DMASKTRIG0 = 0x2;
- invalidate_dcache_range((void *)buf, wordcount*2);
+ invalidate_dcache_range((void *)buf, wordcount*2);
- INTMSK &= ~(1<<17); /* unmask the interrupt */
- SRCPND = (1<<17); /* clear any pending interrupts */
+ INTMSK &= ~(1<<17); /* unmask the interrupt */
+ SRCPND = (1<<17); /* clear any pending interrupts */
/* Start DMA */
DMASKTRIG0 |= 0x1;
/* Wait for transfer to complete */
while((DSTAT0 & 0x000fffff))
- CLKCON |= (1 << 2); /* set IDLE bit */
- /* Dump cache for the buffer */
+ CLKCON |= (1 << 2); /* set IDLE bit */
+ /* Dump cache for the buffer */
}
void dma0(void)