summaryrefslogtreecommitdiff
path: root/firmware/target
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target')
-rw-r--r--firmware/target/arm/tms320dm320/creative-zvm/ata-creativezvm.c337
-rw-r--r--firmware/target/arm/tms320dm320/creative-zvm/ata-target.h24
2 files changed, 316 insertions, 45 deletions
diff --git a/firmware/target/arm/tms320dm320/creative-zvm/ata-creativezvm.c b/firmware/target/arm/tms320dm320/creative-zvm/ata-creativezvm.c
index 1732c5d2c4..5f325a5e54 100644
--- a/firmware/target/arm/tms320dm320/creative-zvm/ata-creativezvm.c
+++ b/firmware/target/arm/tms320dm320/creative-zvm/ata-creativezvm.c
@@ -31,7 +31,10 @@
31#include "ata.h" 31#include "ata.h"
32#include "string.h" 32#include "string.h"
33 33
34void sleep_ms(int ms) 34#undef ata_read_sectors
35#undef ata_write_sectors
36
37static void sleep_ms(int ms)
35{ 38{
36 sleep(ms*HZ/1000); 39 sleep(ms*HZ/1000);
37} 40}
@@ -99,7 +102,7 @@ bool ata_is_coldstart(void)
99void ata_device_init(void) 102void ata_device_init(void)
100{ 103{
101 IO_INTC_EINT1 |= INTR_EINT1_EXT2; /* enable GIO2 interrupt */ 104 IO_INTC_EINT1 |= INTR_EINT1_EXT2; /* enable GIO2 interrupt */
102 //TODO: mimic OF inits... 105 /* TODO: mimic OF inits... */
103 return; 106 return;
104} 107}
105 108
@@ -114,38 +117,308 @@ void GIO2(void)
114 117
115/* 118/*
116 --------------------------------------------------------------------------- 119 ---------------------------------------------------------------------------
117 Creative File Systems parsing code 120 CreativeFileSystem parsing/handling code
118 --------------------------------------------------------------------------- 121 ---------------------------------------------------------------------------
119 */ 122 */
120 123
124#define VFAT_SECTOR_SIZE ( (1*1024*1024*1024)/0x8000 ) /* 1GB array requires 80kB of RAM */
125
126extern int ata_read_sectors(IF_MV2(int drive,) unsigned long start, int count, void* buf);
127extern int ata_write_sectors(IF_MV2(int drive,) unsigned long start, int count, const void* buf);
128
121struct main_header 129struct main_header
122{ 130{
123 char mblk[4]; 131 char mblk[4];
124 unsigned char sector_size[4]; 132 unsigned int sector_size;
125 unsigned char disk_size[8]; 133 long long disk_size;
126 struct partition_header 134 struct partition_header
127 { 135 {
128 unsigned char end[4]; 136 unsigned long end;
129 unsigned char start[4]; 137 unsigned long start;
130 char name[8]; 138 char name[8];
131 } partitions[31]; 139 } partitions[31];
132}; 140};
133 141
142struct cfs_header
143{
144 unsigned int unk;
145 unsigned int unk2;
146 unsigned int sector_size;
147 unsigned int unk4;
148 unsigned int unk5;
149 char identifier[4];
150 unsigned int first_inode;
151 unsigned int unk8;
152 unsigned int unk9;
153 unsigned int unk10;
154 unsigned int unk11;
155};
156
157struct cfs_inode
158{
159 unsigned char magic[4];
160 unsigned int number;
161 unsigned int parent;
162 unsigned int unk;
163 unsigned int type;
164 unsigned int created_time;
165 unsigned int lastmodified_time;
166 unsigned int unk2;
167 unsigned int first_class_chain[12];
168 unsigned int unk3;
169 unsigned int unk4;
170 unsigned int second_class_chain_first_cluster;
171 unsigned int unk9;
172 unsigned int unk10;
173 unsigned int second_class_chain_second_cluster;
174 unsigned int unk11;
175 unsigned int unk12;
176 unsigned int unk13;
177 unsigned int filesize;
178 unsigned int serial_number;
179 unsigned int number_of_metadata_records;
180};
181
182struct cfs_direntry
183{
184 unsigned char identifier[4];
185 unsigned int unk;
186 unsigned int items;
187 unsigned int unk2;
188 unsigned char maxlen[2];
189 unsigned char padding[202];
190 /* struct cfs_direntry_item _items[items]; */
191};
192struct cfs_direntry_item
193{
194 unsigned int inode_number;
195 unsigned short strlen;
196 unsigned short bytesperchar;
197 char string[32];
198};
199
200static bool cfs_inited = false;
201static unsigned long cfs_start;
202static unsigned long sectors[VFAT_SECTOR_SIZE];
203
204#define CFS_START ( ((hdr->partitions[1].start*hdr->sector_size) & ~0xFFFF) + 0x10000 )
205#define CFS_CLUSTER2CLUSTER(x) ( CFS_START+((x)-1)*64 )
206
207/* Limited version of UCS -> ASCII */
208static char* ucs2letostring(unsigned char* s)
209{
210 static char res[256];
211 int i;
212
213 for(i=0; (s[i] == 0 && s[i+1] == 0); i++)
214 res[i] = s[i*2];
215
216 return (char*)&res;
217}
218
219static void cfs_init(void)
220{
221 struct main_header *hdr;
222 struct cfs_header *cfs;
223 struct cfs_inode *root_inode, *vfat_inode, *inode;
224 struct cfs_direntry *root_direntry, *vfat_direntry;
225 struct cfs_direntry_item *root_direntry_items, *vfat_direntry_items;
226 unsigned int i, j, k, vfat_inode_nr=0, vfat_inodes_nr[10], vfat_sector_count;
227 unsigned char sector[512];
228 static unsigned int vfat_data[2][0x8000];
229 static unsigned char sector2[0x8000];
230
231 if(cfs_inited)
232 return;
233
234 /* Read MBLK */
235 _ata_read_sectors(0, 1, &sector);
236 hdr = (struct main_header*)&sector;
237
238 //printf("CFS is at 0x%x", CFS_START);
239
240 /* Read CFS header */
241 _ata_read_sectors(CFS_START/512, 64, &sector2);
242 cfs = (struct cfs_header*)&sector2;
243
244 //printf("First inode = %d", cfs->first_inode);
245
246 /* Read root inode */
247 _ata_read_sectors(CFS_CLUSTER2CLUSTER(cfs->first_inode), 64, &sector2);
248 root_inode = (struct cfs_inode*)&sector2;
249
250 /* Read root inode's first sector */
251 _ata_read_sectors(CFS_CLUSTER2CLUSTER(root_inode->first_class_chain[0]), 64, &sector2);
252 root_direntry = (struct cfs_direntry*)&sector2;
253 root_direntry_items = (struct cfs_direntry_item*)(&sector2+sizeof(struct cfs_direntry));
254
255 /* Search VFAT inode */
256 for(i=0; i < root_direntry->items; i++)
257 {
258 //printf(" * [%s] at 0x%x\n", ucs2letostring(&root_direntry_items[i].string[0]), root_direntry_items[i].inode_number);
259 if(strcmp(ucs2letostring(&root_direntry_items[i].string[0]), "VFAT") == 0)
260 vfat_inode_nr = root_direntry_items[i].inode_number;
261 }
262
263 /* Read VFAT inode */
264 _ata_read_sectors(CFS_CLUSTER2CLUSTER(vfat_inode_nr), 64, &sector2);
265 vfat_inode = (struct cfs_inode*)&sector2;
266
267 /* Read VFAT inode's first sector */
268 _ata_read_sectors(CFS_CLUSTER2CLUSTER(vfat_inode->first_class_chain[0]), 64, &sector2);
269 vfat_direntry = (struct cfs_direntry*)&sector2;
270 vfat_direntry_items = (struct cfs_direntry_item*)(&sector2+sizeof(struct cfs_direntry));
271
272 /* Search for VFAT's subinodes */
273 for(i=0; i < vfat_direntry->items; i++)
274 {
275 //printf(" * [%s] at 0x%x\n", ucs2letostring(&vfat_direntry_items[i].string[0]), vfat_direntry_items[i].inode_number);
276 if(i > 0)
277 vfat_inodes_nr[i-1] = vfat_direntry_items[i].inode_number;
278 }
279
280 /* Read all data sectors' addresses in memory */
281 vfat_sector_count = 0;
282 memset(&sectors, 0, VFAT_SECTOR_SIZE*sizeof(unsigned int));
283 for(i=0; vfat_inodes_nr[i] != 0; i++)
284 {
285 _ata_read_sectors(CFS_CLUSTER2CLUSTER(vfat_inodes_nr[i]), 1, &sector);
286 inode = (struct cfs_inode*)&sector;
287
288 /* Read second & third class chain */
289 _ata_read_sectors(CFS_CLUSTER2CLUSTER(inode->second_class_chain_first_cluster), 64, &vfat_data[0]);
290 _ata_read_sectors(CFS_CLUSTER2CLUSTER(inode->second_class_chain_second_cluster), 64, &vfat_data[1]);
291
292 /* First class chain */
293 for(j=0; j<12; j++)
294 {
295 if( (inode->first_class_chain[j] & 0xFFFF) != 0xFFFF &&
296 inode->first_class_chain[j] != 0
297 )
298 sectors[vfat_sector_count++] = inode->first_class_chain[j];
299 }
300
301 /* Second class chain */
302 for(j=0; j<0x8000/4; j++)
303 {
304 if( (vfat_data[0][j] & 0xFFFF) != 0xFFFF &&
305 vfat_data[0][j] != 0
306 )
307 sectors[vfat_sector_count++] = vfat_data[0][j];
308 }
309
310 /* Third class chain */
311 for(j=0; j<0x8000/4; j++)
312 {
313 if( (vfat_data[1][j] & 0xFFFF) != 0xFFFF &&
314 vfat_data[1][j] != 0
315 )
316 {
317 memset(&vfat_data[0], 0, 0x8000*sizeof(unsigned int));
318
319 /* Read third class subchain(s) */
320 _ata_read_sectors(CFS_CLUSTER2CLUSTER(vfat_data[1][j]), 64, &vfat_data[0]);
321
322 for(k=0; k<0x8000/4; k++)
323 {
324 if( (vfat_data[0][k] & 0xFFFF) != 0xFFFF &&
325 vfat_data[0][k] != 0
326 )
327 sectors[vfat_sector_count++] = vfat_data[0][k];
328 }
329 }
330 }
331 }
332
333 //printf("Sector count: %d 0x%x", vfat_sector_count, vfat_sector_count);
334
335 cfs_inited = true;
336}
337
338static inline unsigned long map_sector(unsigned long sector)
339{
340 /*
341 * Sector mapping: start of CFS + FAT_SECTOR2CFS_SECTOR(sector) + missing part
342 * FAT works with sectors of 0x200 bytes, CFS with sectors of 0x8000 bytes.
343 */
344 return cfs_start+sectors[sector/64]*64+sector%64;
345}
346
347int ata_read_sectors(IF_MV2(int drive,) unsigned long start, int count, void* buf)
348{
349 if(!cfs_inited)
350 cfs_init();
351
352 /* Check if count is lesser than or equal to 1 native CFS sector */
353 if(count <= 64)
354 return _ata_read_sectors(IF_MV2(drive,) map_sector(start), count, buf);
355 else
356 {
357 int i, ret;
358 unsigned char* dest = (unsigned char*)buf;
359
360 /* Read sectors in parts of 0x8000 */
361 for(i=0; i<count; i+=64)
362 {
363 ret = _ata_read_sectors(IF_MV2(drive,) map_sector(start+i), (count-i >= 64 ? 64 : count-i), (void*)dest);
364 if(ret != 0)
365 return ret;
366
367 dest += (count-i >= 64 ? 0x8000 : (count-i)*512);
368 }
369
370 return ret;
371 }
372}
373
374int ata_write_sectors(IF_MV2(int drive,) unsigned long start, int count, const void* buf)
375{
376 if(!cfs_inited)
377 cfs_init();
378
379 /* Check if count is lesser than or equal to 1 native CFS sector */
380 if(count <= 64)
381 return _ata_write_sectors(IF_MV2(drive,) map_sector(start), count, buf);
382 else
383 {
384 int i, ret;
385 unsigned char* dest = (unsigned char*)buf;
386
387 /* Read sectors in parts of 0x8000 */
388 for(i=0; i<count; i+=64)
389 {
390 ret = _ata_write_sectors(IF_MV2(drive,) map_sector(start+i), (count-i >= 64 ? 64 : count-i), (const void*)dest);
391 if(ret != 0)
392 return ret;
393
394 dest += (count-i >= 64 ? 0x8000 : (count-i)*512);
395 }
396
397 return ret;
398 }
399}
400
401/*
402 ---------------------------------------------------------------------------
403 MiniFileSystem parsing code
404 ---------------------------------------------------------------------------
405 */
406
134struct minifs_file 407struct minifs_file
135{ 408{
136 char name[0x10]; 409 char name[0x10];
137 unsigned char unk[4]; 410 unsigned int unk;
138 unsigned char size[4]; 411 unsigned long size;
139 unsigned char chain1[4]; 412 unsigned int chain1;
140 unsigned char chain2[4]; 413 unsigned int chain2;
141}; 414};
142 415
143struct minifs_chain 416struct minifs_chain
144{ 417{
145 unsigned char unknown[4]; 418 unsigned int unknown;
146 unsigned char chain[2*0x27FE]; 419 unsigned short chain[0x27FE];
147 unsigned char unknown2[4]; 420 unsigned int unknown2;
148 unsigned char length[4]; 421 unsigned long length;
149}; 422};
150 423
151 424
@@ -160,16 +433,6 @@ struct minifs_chain
160#define CLUSTER_CHAIN_CHAIN 0x0002 433#define CLUSTER_CHAIN_CHAIN 0x0002
161 434
162 435
163static unsigned short le2int16(unsigned char* buf)
164{
165 return (buf[1] << 8) | buf[0];
166}
167
168static unsigned int le2int32(unsigned char* buf)
169{
170 return (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
171}
172
173int load_minifs_file(char* filename, unsigned char* location) 436int load_minifs_file(char* filename, unsigned char* location)
174{ 437{
175 struct main_header *hdr; 438 struct main_header *hdr;
@@ -180,13 +443,13 @@ int load_minifs_file(char* filename, unsigned char* location)
180 unsigned char sector[512]; 443 unsigned char sector[512];
181 static unsigned char chain_data[42*512]; /* stack overflow if not static */ 444 static unsigned char chain_data[42*512]; /* stack overflow if not static */
182 445
183 /* Reading MBLK */ 446 /* Read MBLK */
184 ata_read_sectors(0, 1, &sector); 447 _ata_read_sectors(0, 1, &sector);
185 hdr = (struct main_header*)&sector; 448 hdr = (struct main_header*)&sector;
186 449
187 /* Reading directory listing */ 450 /* Read directory listing */
188#define CLUSTER2SECTOR(x) ( (le2int32(hdr->partitions[0].start) + (x)*8) ) 451#define CLUSTER2SECTOR(x) ( (hdr->partitions[0].start + (x)*8) )
189 ata_read_sectors(CLUSTER2SECTOR(DIR_START), 8, &files); 452 _ata_read_sectors(CLUSTER2SECTOR(DIR_START), 8, &files);
190 453
191 for(i=0; i<127; i++) 454 for(i=0; i<127; i++)
192 { 455 {
@@ -200,17 +463,17 @@ int load_minifs_file(char* filename, unsigned char* location)
200#define GET_CHAIN(x) ( CLUSTER2SECTOR(CLUSTER_CHAIN_CHAIN)*512 + (x)*CLUSTER_CHAIN_SIZE ) 463#define GET_CHAIN(x) ( CLUSTER2SECTOR(CLUSTER_CHAIN_CHAIN)*512 + (x)*CLUSTER_CHAIN_SIZE )
201#define FILE2SECTOR(x) ( CLUSTER2SECTOR(DATASPACE_START + (x)) ) 464#define FILE2SECTOR(x) ( CLUSTER2SECTOR(DATASPACE_START + (x)) )
202 465
203 /* Reading chain list */ 466 /* Read chain list */
204 ata_read_sectors(GET_CHAIN(le2int32(files[found].chain1))/512, 41, &chain_data[0]); 467 _ata_read_sectors(GET_CHAIN(files[found].chain1)/512, 41, &chain_data[0]);
205 468
206 chain = (struct minifs_chain*)&chain_data[GET_CHAIN(le2int32(files[found].chain1))%512]; 469 chain = (struct minifs_chain*)&chain_data[GET_CHAIN(files[found].chain1)%512];
207 470
208 /* Copying data */ 471 /* Copy data */
209 for(i=0; i<le2int32(chain->length); i++) 472 for(i=0; i<chain->length; i++)
210 { 473 {
211 ata_read_sectors(FILE2SECTOR(le2int16(&chain->chain[i*2])), 8, location); 474 _ata_read_sectors(FILE2SECTOR(chain->chain[i]), 8, location);
212 location += 0x1000; 475 location += 0x1000;
213 } 476 }
214 477
215 return le2int32(files[found].size); 478 return files[found].size;
216} 479}
diff --git a/firmware/target/arm/tms320dm320/creative-zvm/ata-target.h b/firmware/target/arm/tms320dm320/creative-zvm/ata-target.h
index 6e5699e887..ba877a1496 100644
--- a/firmware/target/arm/tms320dm320/creative-zvm/ata-target.h
+++ b/firmware/target/arm/tms320dm320/creative-zvm/ata-target.h
@@ -22,6 +22,8 @@
22#ifndef ATA_TARGET_H 22#ifndef ATA_TARGET_H
23#define ATA_TARGET_H 23#define ATA_TARGET_H
24 24
25#include "ata.h"
26
25/* DMA optimized reading and writing */ 27/* DMA optimized reading and writing */
26#define ATA_OPTIMIZED_READING 28#define ATA_OPTIMIZED_READING
27#define ATA_OPTIMIZED_WRITING 29#define ATA_OPTIMIZED_WRITING
@@ -33,6 +35,12 @@
33void copy_read_sectors(const unsigned char* buf, int wordcount); 35void copy_read_sectors(const unsigned char* buf, int wordcount);
34void copy_write_sectors(const unsigned char* buf, int wordcount); 36void copy_write_sectors(const unsigned char* buf, int wordcount);
35 37
38/* Nasty hack, but Creative is nasty... */
39#define ata_read_sectors _ata_read_sectors
40#define ata_write_sectors _ata_write_sectors
41extern int _ata_read_sectors(IF_MV2(int drive,) unsigned long start, int count, void* buf);
42extern int _ata_write_sectors(IF_MV2(int drive,) unsigned long start, int count, const void* buf);
43
36/* General purpose memory region #1 */ 44/* General purpose memory region #1 */
37#define ATA_IOBASE 0x50FEE000 45#define ATA_IOBASE 0x50FEE000
38#define ATA_DATA (*((volatile unsigned short*)(ATA_IOBASE))) 46#define ATA_DATA (*((volatile unsigned short*)(ATA_IOBASE)))
@@ -52,15 +60,15 @@ void copy_write_sectors(const unsigned char* buf, int wordcount);
52#define STATUS_ERR 0x01 60#define STATUS_ERR 0x01
53#define ERROR_ABRT 0x04 61#define ERROR_ABRT 0x04
54 62
55#define WRITE_PATTERN1 0xa5 63#define WRITE_PATTERN1 0xa5
56#define WRITE_PATTERN2 0x5a 64#define WRITE_PATTERN2 0x5a
57#define WRITE_PATTERN3 0xaa 65#define WRITE_PATTERN3 0xaa
58#define WRITE_PATTERN4 0x55 66#define WRITE_PATTERN4 0x55
59 67
60#define READ_PATTERN1 0xa5 68#define READ_PATTERN1 0xa5
61#define READ_PATTERN2 0x5a 69#define READ_PATTERN2 0x5a
62#define READ_PATTERN3 0xaa 70#define READ_PATTERN3 0xaa
63#define READ_PATTERN4 0x55 71#define READ_PATTERN4 0x55
64 72
65#define READ_PATTERN1_MASK 0xff 73#define READ_PATTERN1_MASK 0xff
66#define READ_PATTERN2_MASK 0xff 74#define READ_PATTERN2_MASK 0xff