summaryrefslogtreecommitdiff
path: root/firmware/target/arm/tms320dm320/creative-zvm/ata-creativezvm.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/tms320dm320/creative-zvm/ata-creativezvm.c')
-rw-r--r--firmware/target/arm/tms320dm320/creative-zvm/ata-creativezvm.c970
1 files changed, 485 insertions, 485 deletions
diff --git a/firmware/target/arm/tms320dm320/creative-zvm/ata-creativezvm.c b/firmware/target/arm/tms320dm320/creative-zvm/ata-creativezvm.c
index 5670a65b47..a55cda4c14 100644
--- a/firmware/target/arm/tms320dm320/creative-zvm/ata-creativezvm.c
+++ b/firmware/target/arm/tms320dm320/creative-zvm/ata-creativezvm.c
@@ -1,489 +1,489 @@
1/*************************************************************************** 1/***************************************************************************
2 * __________ __ ___. 2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/ 7 * \/ \/ \/ \/ \/
8 * $Id$ 8 * $Id$
9 * 9 *
10 * Copyright (C) 2008 by Maurus Cuelenaere 10 * Copyright (C) 2008 by Maurus Cuelenaere
11 * 11 *
12 * This program is free software; you can redistribute it and/or 12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License 13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2 14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version. 15 * of the License, or (at your option) any later version.
16 * 16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied. 18 * KIND, either express or implied.
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21 21
22#include "config.h" 22#include "config.h"
23#include "cpu.h" 23#include "cpu.h"
24#include "kernel.h" 24#include "kernel.h"
25#include "thread.h" 25#include "thread.h"
26#include "system.h" 26#include "system.h"
27#include "power.h" 27#include "power.h"
28#include "panic.h" 28#include "panic.h"
29#include "ata-target.h" 29#include "ata-target.h"
30#include "dm320.h" 30#include "dm320.h"
31#include "ata.h" 31#include "ata.h"
32#include "string.h" 32#include "string.h"
33#include "buffer.h" 33#include "buffer.h"
34 34
35#undef ata_read_sectors 35#undef ata_read_sectors
36#undef ata_write_sectors 36#undef ata_write_sectors
37 37
38static void sleep_ms(int ms) 38static void sleep_ms(int ms)
39{ 39{
40 sleep(ms*HZ/1000); 40 sleep(ms*HZ/1000);
41} 41}
42 42
43void ide_power_enable(bool on) 43void ide_power_enable(bool on)
44{ 44{
45/* Disabled until figured out what's wrong */ 45/* Disabled until figured out what's wrong */
46#if 0 46#if 0
47 int old_level = disable_irq_save(); 47 int old_level = disable_irq_save();
48 if(on) 48 if(on)
49 { 49 {
50 IO_GIO_BITSET0 = (1 << 14); 50 IO_GIO_BITSET0 = (1 << 14);
51 ata_reset(); 51 ata_reset();
52 } 52 }
53 else 53 else
54 IO_GIO_BITCLR0 = (1 << 14); 54 IO_GIO_BITCLR0 = (1 << 14);
55 restore_irq(old_level); 55 restore_irq(old_level);
56#else 56#else
57 (void)on; 57 (void)on;
58#endif 58#endif
59} 59}
60 60
61inline bool ide_powered() 61inline bool ide_powered()
62{ 62{
63#if 0 63#if 0
64 return (IO_GIO_BITSET0 & (1 << 14)); 64 return (IO_GIO_BITSET0 & (1 << 14));
65#else 65#else
66 return true; 66 return true;
67#endif 67#endif
68} 68}
69 69
70void ata_reset(void) 70void ata_reset(void)
71{ 71{
72 int old_level = disable_irq_save(); 72 int old_level = disable_irq_save();
73 if(!ide_powered()) 73 if(!ide_powered())
74 { 74 {
75 ide_power_enable(true); 75 ide_power_enable(true);
76 sleep_ms(150); 76 sleep_ms(150);
77 } 77 }
78 else 78 else
79 { 79 {
80 IO_GIO_BITSET0 = (1 << 5); 80 IO_GIO_BITSET0 = (1 << 5);
81 IO_GIO_BITCLR0 = (1 << 3); 81 IO_GIO_BITCLR0 = (1 << 3);
82 sleep_ms(1); 82 sleep_ms(1);
83 } 83 }
84 IO_GIO_BITCLR0 = (1 << 5); 84 IO_GIO_BITCLR0 = (1 << 5);
85 sleep_ms(10); 85 sleep_ms(10);
86 IO_GIO_BITSET0 = (1 << 3); 86 IO_GIO_BITSET0 = (1 << 3);
87 while(!(ATA_COMMAND & STATUS_RDY)) 87 while(!(ATA_COMMAND & STATUS_RDY))
88 sleep_ms(10); 88 sleep_ms(10);
89 restore_irq(old_level); 89 restore_irq(old_level);
90} 90}
91 91
92void ata_enable(bool on) 92void ata_enable(bool on)
93{ 93{
94 (void)on; 94 (void)on;
95 return; 95 return;
96} 96}
97 97
98bool ata_is_coldstart(void) 98bool ata_is_coldstart(void)
99{ 99{
100 return true; 100 return true;
101} 101}
102 102
103void ata_device_init(void) 103void ata_device_init(void)
104{ 104{
105 IO_INTC_EINT1 |= INTR_EINT1_EXT2; /* enable GIO2 interrupt */ 105 IO_INTC_EINT1 |= INTR_EINT1_EXT2; /* enable GIO2 interrupt */
106 /* TODO: mimic OF inits... */ 106 /* TODO: mimic OF inits... */
107 return; 107 return;
108} 108}
109 109
110void GIO2(void) 110void GIO2(void)
111{ 111{
112#ifdef DEBUG 112#ifdef DEBUG
113 logf("GIO2 interrupt..."); 113 logf("GIO2 interrupt...");
114#endif 114#endif
115 IO_INTC_IRQ1 = INTR_IRQ1_EXT2; /* Mask GIO2 interrupt */ 115 IO_INTC_IRQ1 = INTR_IRQ1_EXT2; /* Mask GIO2 interrupt */
116 return; 116 return;
117} 117}
118 118
119/* 119/*
120 --------------------------------------------------------------------------- 120 ---------------------------------------------------------------------------
121 CreativeFileSystem parsing/handling code 121 CreativeFileSystem parsing/handling code
122 --------------------------------------------------------------------------- 122 ---------------------------------------------------------------------------
123 */ 123 */
124 124
125#define VFAT_SECTOR_SIZE(x) ( (x)/0x8000 ) /* 1GB array requires 80kB of RAM */ 125#define VFAT_SECTOR_SIZE(x) ( (x)/0x8000 ) /* 1GB array requires 80kB of RAM */
126 126
127extern int ata_read_sectors(IF_MV2(int drive,) unsigned long start, int count, void* buf); 127extern int ata_read_sectors(IF_MV2(int drive,) unsigned long start, int count, void* buf);
128extern int ata_write_sectors(IF_MV2(int drive,) unsigned long start, int count, const void* buf); 128extern int ata_write_sectors(IF_MV2(int drive,) unsigned long start, int count, const void* buf);
129 129
130struct main_header 130struct main_header
131{ 131{
132 char mblk[4]; 132 char mblk[4];
133 unsigned int sector_size; 133 unsigned int sector_size;
134 long long disk_size; 134 long long disk_size;
135 struct partition_header 135 struct partition_header
136 { 136 {
137 unsigned long end; 137 unsigned long end;
138 unsigned long start; 138 unsigned long start;
139 char name[8]; 139 char name[8];
140 } partitions[31]; 140 } partitions[31];
141}; 141};
142 142
143struct cfs_header 143struct cfs_header
144{ 144{
145 unsigned int unk; 145 unsigned int unk;
146 unsigned int unk2; 146 unsigned int unk2;
147 unsigned int sector_size; 147 unsigned int sector_size;
148 unsigned int unk4; 148 unsigned int unk4;
149 unsigned int unk5; 149 unsigned int unk5;
150 char identifier[4]; 150 char identifier[4];
151 unsigned int first_inode; 151 unsigned int first_inode;
152 unsigned int unk8; 152 unsigned int unk8;
153 unsigned int unk9; 153 unsigned int unk9;
154 unsigned int unk10; 154 unsigned int unk10;
155 unsigned int unk11; 155 unsigned int unk11;
156}; 156};
157 157
158struct cfs_inode 158struct cfs_inode
159{ 159{
160 unsigned char magic[4]; 160 unsigned char magic[4];
161 unsigned int number; 161 unsigned int number;
162 unsigned int parent; 162 unsigned int parent;
163 unsigned int unk; 163 unsigned int unk;
164 unsigned int type; 164 unsigned int type;
165 unsigned int created_time; 165 unsigned int created_time;
166 unsigned int lastmodified_time; 166 unsigned int lastmodified_time;
167 unsigned int unk2; 167 unsigned int unk2;
168 unsigned int first_class_chain[12]; 168 unsigned int first_class_chain[12];
169 unsigned int unk3; 169 unsigned int unk3;
170 unsigned int unk4; 170 unsigned int unk4;
171 unsigned int second_class_chain_first_cluster; 171 unsigned int second_class_chain_first_cluster;
172 unsigned int unk9; 172 unsigned int unk9;
173 unsigned int unk10; 173 unsigned int unk10;
174 unsigned int second_class_chain_second_cluster; 174 unsigned int second_class_chain_second_cluster;
175 unsigned int unk11; 175 unsigned int unk11;
176 unsigned int unk12; 176 unsigned int unk12;
177 unsigned int unk13; 177 unsigned int unk13;
178 unsigned int filesize; 178 unsigned int filesize;
179 unsigned int serial_number; 179 unsigned int serial_number;
180 unsigned int number_of_metadata_records; 180 unsigned int number_of_metadata_records;
181}; 181};
182 182
183struct cfs_direntry 183struct cfs_direntry
184{ 184{
185 unsigned char identifier[4]; 185 unsigned char identifier[4];
186 unsigned int unk; 186 unsigned int unk;
187 unsigned int items; 187 unsigned int items;
188 unsigned int unk2; 188 unsigned int unk2;
189 unsigned char maxlen[2]; 189 unsigned char maxlen[2];
190 unsigned char padding[202]; 190 unsigned char padding[202];
191 /* struct cfs_direntry_item _items[items]; */ 191 /* struct cfs_direntry_item _items[items]; */
192}; 192};
193struct cfs_direntry_item 193struct cfs_direntry_item
194{ 194{
195 unsigned int inode_number; 195 unsigned int inode_number;
196 unsigned short strlen; 196 unsigned short strlen;
197 unsigned short bytesperchar; 197 unsigned short bytesperchar;
198 char string[32]; 198 char string[32];
199}; 199};
200 200
201static bool cfs_inited = false; 201static bool cfs_inited = false;
202static unsigned long cfs_start; 202static unsigned long cfs_start;
203static unsigned long *sectors; 203static unsigned long *sectors;
204 204
205#define CFS_START ( ((hdr->partitions[1].start*hdr->sector_size) & ~0xFFFF) + 0x10000 ) 205#define CFS_START ( ((hdr->partitions[1].start*hdr->sector_size) & ~0xFFFF) + 0x10000 )
206#define CFS_CLUSTER2CLUSTER(x) ( CFS_START+((x)-1)*64 ) 206#define CFS_CLUSTER2CLUSTER(x) ( CFS_START+((x)-1)*64 )
207 207
208/* Limited version of UCS -> ASCII */ 208/* Limited version of UCS -> ASCII */
209static char* ucs2letostring(unsigned char* s) 209static char* ucs2letostring(unsigned char* s)
210{ 210{
211 static char res[256]; 211 static char res[256];
212 int i; 212 int i;
213 213
214 for(i=0; (s[i] == 0 && s[i+1] == 0); i++) 214 for(i=0; (s[i] == 0 && s[i+1] == 0); i++)
215 res[i] = s[i*2]; 215 res[i] = s[i*2];
216 216
217 return (char*)&res; 217 return (char*)&res;
218} 218}
219 219
220static void cfs_init(void) 220static void cfs_init(void)
221{ 221{
222 struct main_header *hdr; 222 struct main_header *hdr;
223 struct cfs_header *cfs; 223 struct cfs_header *cfs;
224 struct cfs_inode *root_inode, *vfat_inode, *inode; 224 struct cfs_inode *root_inode, *vfat_inode, *inode;
225 struct cfs_direntry *root_direntry, *vfat_direntry; 225 struct cfs_direntry *root_direntry, *vfat_direntry;
226 struct cfs_direntry_item *root_direntry_items, *vfat_direntry_items; 226 struct cfs_direntry_item *root_direntry_items, *vfat_direntry_items;
227 unsigned int i, j, k, vfat_inode_nr=0, vfat_inodes_nr[10], vfat_sector_count; 227 unsigned int i, j, k, vfat_inode_nr=0, vfat_inodes_nr[10], vfat_sector_count;
228 unsigned char sector[512]; 228 unsigned char sector[512];
229 static unsigned int vfat_data[2][0x8000]; 229 static unsigned int vfat_data[2][0x8000];
230 static unsigned char sector2[0x8000]; 230 static unsigned char sector2[0x8000];
231 231
232 if(cfs_inited) 232 if(cfs_inited)
233 return; 233 return;
234 234
235 /* Read MBLK */ 235 /* Read MBLK */
236 _ata_read_sectors(0, 1, &sector); 236 _ata_read_sectors(0, 1, &sector);
237 hdr = (struct main_header*)&sector; 237 hdr = (struct main_header*)&sector;
238 238
239 //printf("CFS is at 0x%x", CFS_START); 239 //printf("CFS is at 0x%x", CFS_START);
240 240
241 /* Read CFS header */ 241 /* Read CFS header */
242 _ata_read_sectors(CFS_START/512, 64, &sector2); 242 _ata_read_sectors(CFS_START/512, 64, &sector2);
243 cfs = (struct cfs_header*)&sector2; 243 cfs = (struct cfs_header*)&sector2;
244 244
245 //printf("First inode = %d", cfs->first_inode); 245 //printf("First inode = %d", cfs->first_inode);
246 246
247 /* Read root inode */ 247 /* Read root inode */
248 _ata_read_sectors(CFS_CLUSTER2CLUSTER(cfs->first_inode), 64, &sector2); 248 _ata_read_sectors(CFS_CLUSTER2CLUSTER(cfs->first_inode), 64, &sector2);
249 root_inode = (struct cfs_inode*)&sector2; 249 root_inode = (struct cfs_inode*)&sector2;
250 250
251 /* Read root inode's first sector */ 251 /* Read root inode's first sector */
252 _ata_read_sectors(CFS_CLUSTER2CLUSTER(root_inode->first_class_chain[0]), 64, &sector2); 252 _ata_read_sectors(CFS_CLUSTER2CLUSTER(root_inode->first_class_chain[0]), 64, &sector2);
253 root_direntry = (struct cfs_direntry*)&sector2; 253 root_direntry = (struct cfs_direntry*)&sector2;
254 root_direntry_items = (struct cfs_direntry_item*)(&sector2+sizeof(struct cfs_direntry)); 254 root_direntry_items = (struct cfs_direntry_item*)(&sector2+sizeof(struct cfs_direntry));
255 255
256 /* Search VFAT inode */ 256 /* Search VFAT inode */
257 for(i=0; i < root_direntry->items; i++) 257 for(i=0; i < root_direntry->items; i++)
258 { 258 {
259 //printf(" * [%s] at 0x%x\n", ucs2letostring(&root_direntry_items[i].string[0]), root_direntry_items[i].inode_number); 259 //printf(" * [%s] at 0x%x\n", ucs2letostring(&root_direntry_items[i].string[0]), root_direntry_items[i].inode_number);
260 if(strcmp(ucs2letostring(&root_direntry_items[i].string[0]), "VFAT") == 0) 260 if(strcmp(ucs2letostring(&root_direntry_items[i].string[0]), "VFAT") == 0)
261 vfat_inode_nr = root_direntry_items[i].inode_number; 261 vfat_inode_nr = root_direntry_items[i].inode_number;
262 } 262 }
263 263
264 /* Read VFAT inode */ 264 /* Read VFAT inode */
265 _ata_read_sectors(CFS_CLUSTER2CLUSTER(vfat_inode_nr), 64, &sector2); 265 _ata_read_sectors(CFS_CLUSTER2CLUSTER(vfat_inode_nr), 64, &sector2);
266 vfat_inode = (struct cfs_inode*)&sector2; 266 vfat_inode = (struct cfs_inode*)&sector2;
267 267
268 /* Read VFAT inode's first sector */ 268 /* Read VFAT inode's first sector */
269 _ata_read_sectors(CFS_CLUSTER2CLUSTER(vfat_inode->first_class_chain[0]), 64, &sector2); 269 _ata_read_sectors(CFS_CLUSTER2CLUSTER(vfat_inode->first_class_chain[0]), 64, &sector2);
270 vfat_direntry = (struct cfs_direntry*)&sector2; 270 vfat_direntry = (struct cfs_direntry*)&sector2;
271 vfat_direntry_items = (struct cfs_direntry_item*)(&sector2+sizeof(struct cfs_direntry)); 271 vfat_direntry_items = (struct cfs_direntry_item*)(&sector2+sizeof(struct cfs_direntry));
272 272
273 /* Search for VFAT's subinodes */ 273 /* Search for VFAT's subinodes */
274 for(i=0; i < vfat_direntry->items; i++) 274 for(i=0; i < vfat_direntry->items; i++)
275 { 275 {
276 //printf(" * [%s] at 0x%x\n", ucs2letostring(&vfat_direntry_items[i].string[0]), vfat_direntry_items[i].inode_number); 276 //printf(" * [%s] at 0x%x\n", ucs2letostring(&vfat_direntry_items[i].string[0]), vfat_direntry_items[i].inode_number);
277 if(i > 0) 277 if(i > 0)
278 vfat_inodes_nr[i-1] = vfat_direntry_items[i].inode_number; 278 vfat_inodes_nr[i-1] = vfat_direntry_items[i].inode_number;
279 } 279 }
280 280
281 /* Determine size of VFAT file */ 281 /* Determine size of VFAT file */
282 _ata_read_sectors(CFS_CLUSTER2CLUSTER(vfat_inodes_nr[1]), 1, &sector); 282 _ata_read_sectors(CFS_CLUSTER2CLUSTER(vfat_inodes_nr[1]), 1, &sector);
283 inode = (struct cfs_inode*)&sector; 283 inode = (struct cfs_inode*)&sector;
284 sectors = (unsigned long*)buffer_alloc(VFAT_SECTOR_SIZE(inode->filesize)); 284 sectors = (unsigned long*)buffer_alloc(VFAT_SECTOR_SIZE(inode->filesize));
285 285
286 //printf("VFAT file size: 0x%x", inode->filesize); 286 //printf("VFAT file size: 0x%x", inode->filesize);
287 287
288 /* Clear data sectors */ 288 /* Clear data sectors */
289 memset(&sectors, 0, VFAT_SECTOR_SIZE(inode->filesize)*sizeof(unsigned long)); 289 memset(&sectors, 0, VFAT_SECTOR_SIZE(inode->filesize)*sizeof(unsigned long));
290 290
291 /* Read all data sectors' addresses in memory */ 291 /* Read all data sectors' addresses in memory */
292 vfat_sector_count = 0; 292 vfat_sector_count = 0;
293 for(i=0; vfat_inodes_nr[i] != 0; i++) 293 for(i=0; vfat_inodes_nr[i] != 0; i++)
294 { 294 {
295 _ata_read_sectors(CFS_CLUSTER2CLUSTER(vfat_inodes_nr[i]), 1, &sector); 295 _ata_read_sectors(CFS_CLUSTER2CLUSTER(vfat_inodes_nr[i]), 1, &sector);
296 inode = (struct cfs_inode*)&sector; 296 inode = (struct cfs_inode*)&sector;
297 297
298 /* Read second & third class chain */ 298 /* Read second & third class chain */
299 _ata_read_sectors(CFS_CLUSTER2CLUSTER(inode->second_class_chain_first_cluster), 64, &vfat_data[0]); 299 _ata_read_sectors(CFS_CLUSTER2CLUSTER(inode->second_class_chain_first_cluster), 64, &vfat_data[0]);
300 _ata_read_sectors(CFS_CLUSTER2CLUSTER(inode->second_class_chain_second_cluster), 64, &vfat_data[1]); 300 _ata_read_sectors(CFS_CLUSTER2CLUSTER(inode->second_class_chain_second_cluster), 64, &vfat_data[1]);
301 301
302 /* First class chain */ 302 /* First class chain */
303 for(j=0; j<12; j++) 303 for(j=0; j<12; j++)
304 { 304 {
305 if( (inode->first_class_chain[j] & 0xFFFF) != 0xFFFF && 305 if( (inode->first_class_chain[j] & 0xFFFF) != 0xFFFF &&
306 inode->first_class_chain[j] != 0 306 inode->first_class_chain[j] != 0
307 ) 307 )
308 sectors[vfat_sector_count++] = inode->first_class_chain[j]; 308 sectors[vfat_sector_count++] = inode->first_class_chain[j];
309 } 309 }
310 310
311 /* Second class chain */ 311 /* Second class chain */
312 for(j=0; j<0x8000/4; j++) 312 for(j=0; j<0x8000/4; j++)
313 { 313 {
314 if( (vfat_data[0][j] & 0xFFFF) != 0xFFFF && 314 if( (vfat_data[0][j] & 0xFFFF) != 0xFFFF &&
315 vfat_data[0][j] != 0 315 vfat_data[0][j] != 0
316 ) 316 )
317 sectors[vfat_sector_count++] = vfat_data[0][j]; 317 sectors[vfat_sector_count++] = vfat_data[0][j];
318 } 318 }
319 319
320 /* Third class chain */ 320 /* Third class chain */
321 for(j=0; j<0x8000/4; j++) 321 for(j=0; j<0x8000/4; j++)
322 { 322 {
323 if( (vfat_data[1][j] & 0xFFFF) != 0xFFFF && 323 if( (vfat_data[1][j] & 0xFFFF) != 0xFFFF &&
324 vfat_data[1][j] != 0 324 vfat_data[1][j] != 0
325 ) 325 )
326 { 326 {
327 memset(&vfat_data[0], 0, 0x8000*sizeof(unsigned int)); 327 memset(&vfat_data[0], 0, 0x8000*sizeof(unsigned int));
328 328
329 /* Read third class subchain(s) */ 329 /* Read third class subchain(s) */
330 _ata_read_sectors(CFS_CLUSTER2CLUSTER(vfat_data[1][j]), 64, &vfat_data[0]); 330 _ata_read_sectors(CFS_CLUSTER2CLUSTER(vfat_data[1][j]), 64, &vfat_data[0]);
331 331
332 for(k=0; k<0x8000/4; k++) 332 for(k=0; k<0x8000/4; k++)
333 { 333 {
334 if( (vfat_data[0][k] & 0xFFFF) != 0xFFFF && 334 if( (vfat_data[0][k] & 0xFFFF) != 0xFFFF &&
335 vfat_data[0][k] != 0 335 vfat_data[0][k] != 0
336 ) 336 )
337 sectors[vfat_sector_count++] = vfat_data[0][k]; 337 sectors[vfat_sector_count++] = vfat_data[0][k];
338 } 338 }
339 } 339 }
340 } 340 }
341 } 341 }
342 342
343 //printf("Sector count: %d 0x%x", vfat_sector_count, vfat_sector_count); 343 //printf("Sector count: %d 0x%x", vfat_sector_count, vfat_sector_count);
344 344
345 cfs_inited = true; 345 cfs_inited = true;
346} 346}
347 347
348static inline unsigned long map_sector(unsigned long sector) 348static inline unsigned long map_sector(unsigned long sector)
349{ 349{
350 /* 350 /*
351 * Sector mapping: start of CFS + FAT_SECTOR2CFS_SECTOR(sector) + missing part 351 * Sector mapping: start of CFS + FAT_SECTOR2CFS_SECTOR(sector) + missing part
352 * FAT works with sectors of 0x200 bytes, CFS with sectors of 0x8000 bytes. 352 * FAT works with sectors of 0x200 bytes, CFS with sectors of 0x8000 bytes.
353 */ 353 */
354 return cfs_start+sectors[sector/64]*64+sector%64; 354 return cfs_start+sectors[sector/64]*64+sector%64;
355} 355}
356 356
357int ata_read_sectors(IF_MV2(int drive,) unsigned long start, int count, void* buf) 357int ata_read_sectors(IF_MV2(int drive,) unsigned long start, int count, void* buf)
358{ 358{
359 if(!cfs_inited) 359 if(!cfs_inited)
360 cfs_init(); 360 cfs_init();
361 361
362 /* Check if count is lesser than or equal to 1 native CFS sector */ 362 /* Check if count is lesser than or equal to 1 native CFS sector */
363 if(count <= 64) 363 if(count <= 64)
364 return _ata_read_sectors(IF_MV2(drive,) map_sector(start), count, buf); 364 return _ata_read_sectors(IF_MV2(drive,) map_sector(start), count, buf);
365 else 365 else
366 { 366 {
367 int i, ret; 367 int i, ret;
368 unsigned char* dest = (unsigned char*)buf; 368 unsigned char* dest = (unsigned char*)buf;
369 369
370 /* Read sectors in parts of 0x8000 */ 370 /* Read sectors in parts of 0x8000 */
371 for(i=0; i<count; i+=64) 371 for(i=0; i<count; i+=64)
372 { 372 {
373 ret = _ata_read_sectors(IF_MV2(drive,) map_sector(start+i), (count-i >= 64 ? 64 : count-i), (void*)dest); 373 ret = _ata_read_sectors(IF_MV2(drive,) map_sector(start+i), (count-i >= 64 ? 64 : count-i), (void*)dest);
374 if(ret != 0) 374 if(ret != 0)
375 return ret; 375 return ret;
376 376
377 dest += (count-i >= 64 ? 0x8000 : (count-i)*512); 377 dest += (count-i >= 64 ? 0x8000 : (count-i)*512);
378 } 378 }
379 379
380 return ret; 380 return ret;
381 } 381 }
382} 382}
383 383
384int ata_write_sectors(IF_MV2(int drive,) unsigned long start, int count, const void* buf) 384int ata_write_sectors(IF_MV2(int drive,) unsigned long start, int count, const void* buf)
385{ 385{
386 if(!cfs_inited) 386 if(!cfs_inited)
387 cfs_init(); 387 cfs_init();
388 388
389 /* Check if count is lesser than or equal to 1 native CFS sector */ 389 /* Check if count is lesser than or equal to 1 native CFS sector */
390 if(count <= 64) 390 if(count <= 64)
391 return _ata_write_sectors(IF_MV2(drive,) map_sector(start), count, buf); 391 return _ata_write_sectors(IF_MV2(drive,) map_sector(start), count, buf);
392 else 392 else
393 { 393 {
394 int i, ret; 394 int i, ret;
395 unsigned char* dest = (unsigned char*)buf; 395 unsigned char* dest = (unsigned char*)buf;
396 396
397 /* Read sectors in parts of 0x8000 */ 397 /* Read sectors in parts of 0x8000 */
398 for(i=0; i<count; i+=64) 398 for(i=0; i<count; i+=64)
399 { 399 {
400 ret = _ata_write_sectors(IF_MV2(drive,) map_sector(start+i), (count-i >= 64 ? 64 : count-i), (const void*)dest); 400 ret = _ata_write_sectors(IF_MV2(drive,) map_sector(start+i), (count-i >= 64 ? 64 : count-i), (const void*)dest);
401 if(ret != 0) 401 if(ret != 0)
402 return ret; 402 return ret;
403 403
404 dest += (count-i >= 64 ? 0x8000 : (count-i)*512); 404 dest += (count-i >= 64 ? 0x8000 : (count-i)*512);
405 } 405 }
406 406
407 return ret; 407 return ret;
408 } 408 }
409} 409}
410 410
411/* 411/*
412 --------------------------------------------------------------------------- 412 ---------------------------------------------------------------------------
413 MiniFileSystem parsing code 413 MiniFileSystem parsing code
414 --------------------------------------------------------------------------- 414 ---------------------------------------------------------------------------
415 */ 415 */
416 416
417struct minifs_file 417struct minifs_file
418{ 418{
419 char name[0x10]; 419 char name[0x10];
420 unsigned int unk; 420 unsigned int unk;
421 unsigned long size; 421 unsigned long size;
422 unsigned int chain1; 422 unsigned int chain1;
423 unsigned int chain2; 423 unsigned int chain2;
424}; 424};
425 425
426struct minifs_chain 426struct minifs_chain
427{ 427{
428 unsigned int unknown; 428 unsigned int unknown;
429 unsigned short chain[0x27FE]; 429 unsigned short chain[0x27FE];
430 unsigned int unknown2; 430 unsigned int unknown2;
431 unsigned long length; 431 unsigned long length;
432}; 432};
433 433
434 434
435#define DIR_BITMAP_START 0x0143 435#define DIR_BITMAP_START 0x0143
436#define DIR_START 0x0144 436#define DIR_START 0x0144
437#define DATASPACE_BITMAP_START 0x0145 437#define DATASPACE_BITMAP_START 0x0145
438#define DATASPACE_START 0x0146 438#define DATASPACE_START 0x0146
439 439
440#define CLUSTER_CHAIN_SIZE 0x5008 440#define CLUSTER_CHAIN_SIZE 0x5008
441#define CLUSTER_CHAIN_HEAD 0x0000 441#define CLUSTER_CHAIN_HEAD 0x0000
442#define CLUSTER_CHAIN_BITMAP 0x0001 442#define CLUSTER_CHAIN_BITMAP 0x0001
443#define CLUSTER_CHAIN_CHAIN 0x0002 443#define CLUSTER_CHAIN_CHAIN 0x0002
444 444
445 445
446int load_minifs_file(char* filename, unsigned char* location) 446int load_minifs_file(char* filename, unsigned char* location)
447{ 447{
448 struct main_header *hdr; 448 struct main_header *hdr;
449 static struct minifs_file files[128]; 449 static struct minifs_file files[128];
450 struct minifs_chain *chain; 450 struct minifs_chain *chain;
451 unsigned int i; 451 unsigned int i;
452 int found = -1; 452 int found = -1;
453 unsigned char sector[512]; 453 unsigned char sector[512];
454 static unsigned char chain_data[42*512]; /* stack overflow if not static */ 454 static unsigned char chain_data[42*512]; /* stack overflow if not static */
455 455
456 /* Read MBLK */ 456 /* Read MBLK */
457 _ata_read_sectors(0, 1, &sector); 457 _ata_read_sectors(0, 1, &sector);
458 hdr = (struct main_header*)&sector; 458 hdr = (struct main_header*)&sector;
459 459
460 /* Read directory listing */ 460 /* Read directory listing */
461#define CLUSTER2SECTOR(x) ( (hdr->partitions[0].start + (x)*8) ) 461#define CLUSTER2SECTOR(x) ( (hdr->partitions[0].start + (x)*8) )
462 _ata_read_sectors(CLUSTER2SECTOR(DIR_START), 8, &files); 462 _ata_read_sectors(CLUSTER2SECTOR(DIR_START), 8, &files);
463 463
464 for(i=0; i<127; i++) 464 for(i=0; i<127; i++)
465 { 465 {
466 if(strcmp(files[i].name, filename) == 0) 466 if(strcmp(files[i].name, filename) == 0)
467 found = i; 467 found = i;
468 } 468 }
469 469
470 if(found == -1) 470 if(found == -1)
471 return -1; 471 return -1;
472 472
473#define GET_CHAIN(x) ( CLUSTER2SECTOR(CLUSTER_CHAIN_CHAIN)*512 + (x)*CLUSTER_CHAIN_SIZE ) 473#define GET_CHAIN(x) ( CLUSTER2SECTOR(CLUSTER_CHAIN_CHAIN)*512 + (x)*CLUSTER_CHAIN_SIZE )
474#define FILE2SECTOR(x) ( CLUSTER2SECTOR(DATASPACE_START + (x)) ) 474#define FILE2SECTOR(x) ( CLUSTER2SECTOR(DATASPACE_START + (x)) )
475 475
476 /* Read chain list */ 476 /* Read chain list */
477 _ata_read_sectors(GET_CHAIN(files[found].chain1)/512, 41, &chain_data[0]); 477 _ata_read_sectors(GET_CHAIN(files[found].chain1)/512, 41, &chain_data[0]);
478 478
479 chain = (struct minifs_chain*)&chain_data[GET_CHAIN(files[found].chain1)%512]; 479 chain = (struct minifs_chain*)&chain_data[GET_CHAIN(files[found].chain1)%512];
480 480
481 /* Copy data */ 481 /* Copy data */
482 for(i=0; i<chain->length; i++) 482 for(i=0; i<chain->length; i++)
483 { 483 {
484 _ata_read_sectors(FILE2SECTOR(chain->chain[i]), 8, location); 484 _ata_read_sectors(FILE2SECTOR(chain->chain[i]), 8, location);
485 location += 0x1000; 485 location += 0x1000;
486 } 486 }
487 487
488 return files[found].size; 488 return files[found].size;
489} 489}