diff options
Diffstat (limited to 'firmware/target/arm/gigabeat/meg-fx')
-rw-r--r-- | firmware/target/arm/gigabeat/meg-fx/ata-meg-fx.c | 35 |
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 361b9d4b6f..d098d83de0 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) | |||
54 | 54 | ||
55 | void copy_read_sectors(unsigned char* buf, int wordcount) | 55 | void copy_read_sectors(unsigned char* buf, int wordcount) |
56 | { | 56 | { |
57 | /* Unaligned transfer - slow copy */ | ||
58 | if ( (unsigned long)buf & 1) | ||
59 | { /* not 16-bit aligned, copy byte by byte */ | ||
60 | unsigned short tmp = 0; | ||
61 | unsigned char* bufend = buf + wordcount*2; | ||
62 | do | ||
63 | { | ||
64 | tmp = ATA_DATA; | ||
65 | *buf++ = tmp & 0xff; /* I assume big endian */ | ||
66 | *buf++ = tmp >> 8; /* and don't use the SWAB16 macro */ | ||
67 | } while (buf < bufend); /* tail loop is faster */ | ||
68 | return; | ||
69 | } | ||
57 | /* This should never happen, but worth watching for */ | 70 | /* This should never happen, but worth watching for */ |
58 | if(wordcount > (1 << 18)) | 71 | if(wordcount > (1 << 18)) |
59 | panicf("atd-meg-fx.c: copy_read_sectors: too many sectors per read!"); | 72 | panicf("atd-meg-fx.c: copy_read_sectors: too many sectors per read!"); |
60 | 73 | ||
61 | //#define GIGABEAT_DEBUG_ATA | 74 | //#define GIGABEAT_DEBUG_ATA |
62 | #ifdef GIGABEAT_DEBUG_ATA | 75 | #ifdef GIGABEAT_DEBUG_ATA |
63 | static int line = 0; | 76 | static int line = 0; |
64 | static char str[256]; | 77 | static char str[256]; |
65 | snprintf(str, sizeof(str), "ODD DMA to %08x, %d", buf, wordcount); | 78 | snprintf(str, sizeof(str), "ODD DMA to %08x, %d", buf, wordcount); |
66 | lcd_puts(10, line, str); | 79 | lcd_puts(10, line, str); |
67 | line = (line+1) % 32; | 80 | line = (line+1) % 32; |
68 | lcd_update(); | 81 | lcd_update(); |
69 | #endif | 82 | #endif |
70 | /* Reset the channel */ | 83 | /* Reset the channel */ |
71 | DMASKTRIG0 |= 4; | 84 | DMASKTRIG0 |= 4; |
@@ -87,17 +100,17 @@ void copy_read_sectors(unsigned char* buf, int wordcount) | |||
87 | /* Activate the channel */ | 100 | /* Activate the channel */ |
88 | DMASKTRIG0 = 0x2; | 101 | DMASKTRIG0 = 0x2; |
89 | 102 | ||
90 | invalidate_dcache_range((void *)buf, wordcount*2); | 103 | invalidate_dcache_range((void *)buf, wordcount*2); |
91 | 104 | ||
92 | INTMSK &= ~(1<<17); /* unmask the interrupt */ | 105 | INTMSK &= ~(1<<17); /* unmask the interrupt */ |
93 | SRCPND = (1<<17); /* clear any pending interrupts */ | 106 | SRCPND = (1<<17); /* clear any pending interrupts */ |
94 | /* Start DMA */ | 107 | /* Start DMA */ |
95 | DMASKTRIG0 |= 0x1; | 108 | DMASKTRIG0 |= 0x1; |
96 | 109 | ||
97 | /* Wait for transfer to complete */ | 110 | /* Wait for transfer to complete */ |
98 | while((DSTAT0 & 0x000fffff)) | 111 | while((DSTAT0 & 0x000fffff)) |
99 | CLKCON |= (1 << 2); /* set IDLE bit */ | 112 | CLKCON |= (1 << 2); /* set IDLE bit */ |
100 | /* Dump cache for the buffer */ | 113 | /* Dump cache for the buffer */ |
101 | } | 114 | } |
102 | 115 | ||
103 | void dma0(void) | 116 | void dma0(void) |