PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
s147nand.c
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright ps2dev - http://www.ps2dev.org
7# Licenced under Academic Free License version 2.0
8# Review ps2sdk README & LICENSE files for further details.
9*/
10
11#include "irx_imports.h"
12#include <errno.h>
13#include <iop_mmio_hwport.h>
14#include <s147_mmio_hwport.h>
15#include <s147nand.h>
16#include <sys/fcntl.h>
17
18IRX_ID("S147NAN2", 5, 2);
19// Text section hash:
20// 7894f2d18e733e5f2422b6c61af3b0da
21
23{
24 int m_seek_cur;
25 int m_flags;
26 int m_seek_max;
27 int m_partition_offset;
29
30static int do_register_nand_to_mdev(const char *drv_name, const char *drv_desc);
31static int nand_mdev_op_init(iop_device_t *dev);
32static int nand_mdev_op_deinit(iop_device_t *dev);
33static int nand_mdev_op_open(iop_file_t *f, const char *name, int flags);
34static int nand_mdev_op_close(iop_file_t *f);
35static int nand_mdev_op_read(iop_file_t *f, void *ptr, int size);
36static int nand_mdev_op_write(iop_file_t *f, void *ptr, int size);
37static int nand_mdev_op_lseek(iop_file_t *f, int offset, int mode);
38static int do_nand_open_inner1(s147nand_mdev_privdata_t *privdat, int part, const char *name);
39static int do_nand_open_inner2(s147nand_mdev_privdata_t *privdat, const char *name);
40static u32 do_get_nand_direntry(s147nand_mdev_privdata_t *privdat, const char *name, int idx, char typ);
41static int do_nand_bytes2sector(int pageoffs, int byteoffs);
42static int do_nand_bytes2sector_remainder(int byteoffs);
43static int do_nand_sector_rw(void *ptr, int pageoffs, int byteoffs, int size);
44static int get_nand_partition_offset(int part);
45static int nand_mdev_open_special(iop_file_t *f, const char *name);
46static int nand_mdev_read_special(iop_file_t *f, void *ptr, int size);
47static int nand_mdev_write_special(iop_file_t *f, void *ptr, int size);
48static int do_nand_copy_seccode_from_buf(iop_file_t *f, void *ptr, int size);
49static int do_nand_copy_videomode_from_buf(iop_file_t *f, void *ptr, int size);
50static int nand_lowlevel_read_dma(void *ptr, int pageoffs, int byteoffs, int bytecnt);
51static int nand_lowlevel_read_pio(void *ptr, int pageoffs, int byteoffs, int bytecnt);
52static int nand_lowlevel_write_dma(void *ptr, int pageoffs, int byteoffs, int bytecnt);
53static int nand_lowlevel_write_pio(void *ptr, int pageoffs, int byteoffs, int bytecnt);
54static int nand_lowlevel_blockerase(int pageoffs);
55static int nand_lowlevel_readid(void *ptr);
56
57extern struct irx_export_table _exp_s147nand;
58
59IOMAN_RETURN_VALUE_IMPL(0);
60
61static iop_device_ops_t nand_mdev_ops = {
62 &nand_mdev_op_init,
63 &nand_mdev_op_deinit,
64 IOMAN_RETURN_VALUE(0),
65 &nand_mdev_op_open,
66 &nand_mdev_op_close,
67 &nand_mdev_op_read,
68 &nand_mdev_op_write,
69 &nand_mdev_op_lseek,
70 IOMAN_RETURN_VALUE(0),
71 IOMAN_RETURN_VALUE(0),
72 IOMAN_RETURN_VALUE(0),
73 IOMAN_RETURN_VALUE(0),
74 IOMAN_RETURN_VALUE(0),
75 IOMAN_RETURN_VALUE(0),
76 IOMAN_RETURN_VALUE(0),
77 IOMAN_RETURN_VALUE(0),
78 IOMAN_RETURN_VALUE(0),
79};
80// Unofficial: move to bss
81static void *g_nand_unaligned_buf;
82// Unofficial: move to bss
83static int g_nand_watchdog_enabled;
84// Unofficial: move to bss
85static s147nand_info_t g_nand_info;
86static iop_device_t g_drv;
87static void *g_nand_sector_buffer;
88static int g_sema_id_dev;
89static int g_sema_id_init;
90static s147nand_header_t g_nand_header __attribute__((__aligned__(16)));
91static u16 *g_logical_addr_tbl;
92static int g_sema_id_nand;
93static int g_thid;
94
95int _start(int ac, char **av)
96{
97 (void)ac;
98 (void)av;
99 Kprintf("\ns147nand.irx: System147 NAND-Flash File System Driver v%d.%d\n", 5, 2);
100 // Unofficial: init vars here instead
101 g_nand_info.m_page_size_noecc = 0x800;
102 g_nand_info.m_page_size_withecc = 0x840;
103 g_nand_info.m_pages_per_block = 0x40;
104 g_nand_info.m_block_size = 0x800;
105 g_nand_info.m_page_count = 0x20000;
106 if ( do_register_nand_to_mdev("nand", "NAND-Flash") )
107 return MODULE_NO_RESIDENT_END;
108 if ( RegisterLibraryEntries(&_exp_s147nand) )
109 {
110 Kprintf("s147nand.irx: RegisterLibraryEntries - Failed.\n");
111 return MODULE_NO_RESIDENT_END;
112 }
113 Kprintf("s147nand.irx: RegisterLibraryEntries - OK.\n");
114 return MODULE_RESIDENT_END;
115}
116
117static int do_register_nand_to_mdev(const char *drv_name, const char *drv_desc)
118{
119 iop_sema_t semaparam;
120
121 if ( s147nand_5_outerinit() < 0 )
122 return -1;
123 // Unofficial: make semaparam local var
124 semaparam.initial = 1;
125 semaparam.max = 1;
126 semaparam.attr = SA_THPRI;
127 semaparam.option = 0;
128 g_sema_id_dev = CreateSema(&semaparam);
129 if ( g_sema_id_dev < 0 )
130 {
131 Kprintf("s147nand.irx: CreateSema error (%d)\n", g_sema_id_dev);
132 return -1;
133 }
134 g_drv.name = drv_name;
135 g_drv.type = IOP_DT_FS;
136 g_drv.version = 0;
137 g_drv.desc = drv_desc;
138 g_drv.ops = &nand_mdev_ops;
139 s147mdev_5_delfs(0);
140 s147mdev_4_addfs(&g_drv, 0);
141 // Unofficial: remove redundant var
142 return 0;
143}
144
145static int nand_mdev_op_init(iop_device_t *dev)
146{
147 int state;
148
149 (void)dev;
150 Kprintf("s147nand.irx: SectorBuffer=%d, FileParam=%d\n", 0, 1);
151 CpuSuspendIntr(&state);
152 g_nand_sector_buffer = AllocSysMemory(ALLOC_FIRST, 2048, 0);
153 CpuResumeIntr(state);
154 if ( g_nand_sector_buffer )
155 return 0;
156 Kprintf("s147nand.irx: AllocSysMemory failed (s147file_Init)\n");
157 return -ENOMEM;
158}
159
160static int nand_mdev_op_deinit(iop_device_t *dev)
161{
162 int state;
163
164 (void)dev;
165 if ( g_nand_sector_buffer )
166 {
167 CpuSuspendIntr(&state);
168 FreeSysMemory(g_nand_sector_buffer);
169 CpuResumeIntr(state);
170 }
171 return 0;
172}
173
174static int nand_mdev_op_open(iop_file_t *f, const char *name, int flags)
175{
177 int state;
178 int retres;
179
180 (void)flags;
181 retres = 0;
182 WaitSema(g_sema_id_dev);
183 if ( f->unit == 9 )
184 {
185 retres = nand_mdev_open_special(f, name);
186 SignalSema(g_sema_id_dev);
187 return retres;
188 }
189 CpuSuspendIntr(&state);
190 f->privdata = AllocSysMemory(ALLOC_LAST, sizeof(s147nand_mdev_privdata_t), 0);
191 CpuResumeIntr(state);
192 if ( !f->privdata )
193 {
194 Kprintf("s147nand.irx: AllocSysMemory failed (Open)\n");
195 retres = -ENOMEM;
196 }
197 if ( retres >= 0 )
198 {
199 privdat = (s147nand_mdev_privdata_t *)f->privdata;
200 memset(privdat, 0, sizeof(s147nand_mdev_privdata_t));
201 retres = do_nand_open_inner1(privdat, f->unit, name);
202 }
203 if ( retres < 0 )
204 {
205 // Unofficial: check if not NULL
206 if ( f->privdata )
207 {
208 CpuSuspendIntr(&state);
209 FreeSysMemory(f->privdata);
210 CpuResumeIntr(state);
211 }
212 SignalSema(g_sema_id_dev);
213 return retres;
214 }
215 privdat->m_seek_cur = 0;
216 SignalSema(g_sema_id_dev);
217 return 0;
218}
219
220static int nand_mdev_op_close(iop_file_t *f)
221{
222 int state;
223
224 WaitSema(g_sema_id_dev);
225 if ( f->privdata )
226 {
227 CpuSuspendIntr(&state);
228 FreeSysMemory(f->privdata);
229 CpuResumeIntr(state);
230 f->privdata = 0;
231 }
232 SignalSema(g_sema_id_dev);
233 return 0;
234}
235
236static int nand_mdev_op_read(iop_file_t *f, void *ptr, int size)
237{
238 int xsize3;
240 int xsector1;
241 int xsector2;
242 int xsize2;
243 int cursz;
244
245 privdat = (s147nand_mdev_privdata_t *)f->privdata;
246 WaitSema(g_sema_id_dev);
247 if ( privdat->m_seek_cur >= privdat->m_seek_max )
248 {
249 SignalSema(g_sema_id_dev);
250 return 0;
251 }
252 xsize2 = (privdat->m_seek_max >= privdat->m_seek_cur + size) ? size : (privdat->m_seek_max - privdat->m_seek_cur);
253 if ( privdat->m_seek_cur < 0 || privdat->m_seek_max < 0 )
254 Kprintf(
255 "s147file: CallBack_Read -> Param=0x%08x Seek=%d/%d Count=%d CountEnd=%d\n",
256 privdat,
257 privdat->m_seek_cur,
258 privdat->m_seek_max,
259 size,
260 xsize2);
261 if ( f->unit == 9 )
262 {
263 int special;
264
265 special = nand_mdev_read_special(f, ptr, size);
266 SignalSema(g_sema_id_dev);
267 return special;
268 }
269 xsector1 = do_nand_bytes2sector(privdat->m_partition_offset, privdat->m_seek_cur + xsize2);
270 xsector2 = do_nand_bytes2sector_remainder(privdat->m_seek_cur + xsize2);
271 for ( cursz = 0; cursz < xsize2; cursz += xsize3 )
272 {
273 int pageoffs;
274
275 pageoffs = do_nand_bytes2sector(privdat->m_partition_offset, privdat->m_seek_cur);
276 xsize3 = ((pageoffs >= xsector1) ? xsector2 : 2048) - do_nand_bytes2sector_remainder(privdat->m_seek_cur);
277 do_nand_sector_rw(((char *)ptr) + cursz, pageoffs, do_nand_bytes2sector_remainder(privdat->m_seek_cur), xsize3);
278 privdat->m_seek_cur += xsize3;
279 }
280 SignalSema(g_sema_id_dev);
281 return xsize2;
282}
283
284static int nand_mdev_op_write(iop_file_t *f, void *ptr, int size)
285{
286 WaitSema(g_sema_id_dev);
287 if ( f->unit == 9 )
288 {
289 int retres;
290
291 retres = nand_mdev_write_special(f, ptr, size);
292 SignalSema(g_sema_id_dev);
293 return retres;
294 }
295 SignalSema(g_sema_id_dev);
296 return size;
297}
298
299static int nand_mdev_op_lseek(iop_file_t *f, int offset, int mode)
300{
302
303 privdat = (s147nand_mdev_privdata_t *)f->privdata;
304 WaitSema(g_sema_id_dev);
305 switch ( mode )
306 {
307 case SEEK_SET:
308 privdat->m_seek_cur = offset;
309 break;
310 case SEEK_CUR:
311 privdat->m_seek_cur += offset;
312 break;
313 case SEEK_END:
314 privdat->m_seek_cur = privdat->m_seek_max + offset;
315 break;
316 default:
317 SignalSema(g_sema_id_dev);
318 return -EINVAL;
319 }
320 if ( privdat->m_seek_max < privdat->m_seek_cur )
321 {
322 Kprintf("s147nand.irx: Out of range (seek=%d, filesize=%d)\n", privdat->m_seek_cur, privdat->m_seek_max);
323 privdat->m_seek_cur = privdat->m_seek_max;
324 SignalSema(g_sema_id_dev);
325 return -EINVAL;
326 }
327 SignalSema(g_sema_id_dev);
328 return privdat->m_seek_cur;
329}
330
331int s147nand_4_dumpprintinfo(int part)
332{
333 int hdrret;
334 int nand_partition_offset;
335 int i;
336 int j;
337 int dircnt;
338 int filcnt;
339 int finished;
340 char pathtmp[18];
341
342 hdrret = -1;
343 dircnt = 0;
344 filcnt = 0;
345 finished = 0;
346 nand_partition_offset = get_nand_partition_offset(part);
347 if ( nand_partition_offset < 0 )
348 return -ENODEV;
349 for ( i = 0; i < 64; i += 1 )
350 {
351 s147nand_7_multi_read_dma(g_nand_sector_buffer, nand_partition_offset + i, 1);
352 for ( j = 0; j < 64; j += 1 )
353 {
354 if ( (i << 6) - 1 + j == -1 )
355 {
356 const s147nand_dir_t *hdrbuf;
357
358 hdrbuf = (const s147nand_dir_t *)g_nand_sector_buffer;
359 if ( strncmp(hdrbuf->m_sig, "S147ROM", 8) )
360 {
361 // Unofficial: use g_drv.name
362 Kprintf(" \"%s%d:\" ... No data\n", g_drv.name, part);
363 Kprintf(" -----------------------------\n\n");
364 return -ENODEV;
365 }
366 hdrret = hdrbuf->m_entrycnt;
367 // Unofficial: use g_drv.name
368 Kprintf(" \"%s%d:\"\n", g_drv.name, part);
369 Kprintf(" -----------------------------\n");
370 }
371 else
372 {
373 const s147nand_direntry_t *dirbuf;
374
375 dirbuf = (const s147nand_direntry_t *)g_nand_sector_buffer;
376 if ( (i << 6) - 1 + j >= hdrret )
377 {
378 finished = 1;
379 break;
380 }
381 strcpy(pathtmp, dirbuf[j].m_name);
382 if ( dirbuf[j].m_type == 'D' )
383 {
384 strcat(pathtmp, "/");
385 dircnt += 1;
386 }
387 else
388 {
389 filcnt += 1;
390 }
391 Kprintf(" %9d %s\n", dirbuf[j].m_size, pathtmp);
392 }
393 }
394 if ( finished )
395 break;
396 }
397 Kprintf(" -----------------------------\n");
398 Kprintf(" %d directories, %d files\n", dircnt, filcnt);
399 Kprintf("\n");
400 return hdrret;
401}
402
403static int do_nand_open_inner1(s147nand_mdev_privdata_t *privdat, int part, const char *name)
404{
405 int nand_partition_offset;
406
407 nand_partition_offset = get_nand_partition_offset(part);
408 if ( nand_partition_offset < 0 )
409 {
410 Kprintf("s147nand.irx: Error invalid unit number\n");
411 return -ENODEV;
412 }
413 privdat->m_partition_offset = nand_partition_offset;
414 return do_nand_open_inner2(privdat, name + ((name[0] == '/') ? 1 : 0));
415}
416
417static int do_nand_open_inner2(s147nand_mdev_privdata_t *privdat, const char *name)
418{
419 int i;
420
421 for ( i = 0; name[i] && name[i] != '/'; i += 1 )
422 ;
423 if ( name[i] == '/' )
424 {
425 int nand_direntry;
426
427 nand_direntry = do_get_nand_direntry(privdat, name, i, 'D');
428 return (nand_direntry >= 0) ? do_nand_open_inner2(privdat, &name[i + 1]) : nand_direntry;
429 }
430 return do_get_nand_direntry(privdat, name, i, 'F');
431}
432
433static u32 do_get_nand_direntry(s147nand_mdev_privdata_t *privdat, const char *name, int idx, char typ)
434{
435 int lvtyp;
436 int size;
437 int hdrret;
438 int offscnt;
439 int i;
440 char name_trunc[18];
441
442 hdrret = -1;
443 size = (idx > (int)(sizeof(name_trunc) - 2)) ? (int)(sizeof(name_trunc) - 2) : idx;
444 strncpy(name_trunc, name, size);
445 name_trunc[size] = 0;
446 for ( offscnt = 0; offscnt < 64; offscnt += 1 )
447 {
448 s147nand_7_multi_read_dma(g_nand_sector_buffer, privdat->m_partition_offset + offscnt, 1);
449
450 for ( i = 0; i < 64; i += 1 )
451 {
452 if ( (offscnt << 6) - 1 + i == -1 )
453 {
454 const s147nand_dir_t *hdrbuf;
455
456 hdrbuf = (const s147nand_dir_t *)g_nand_sector_buffer;
457 if ( strncmp(hdrbuf->m_sig, "S147ROM", 8) )
458 {
459 Kprintf("s147nand.irx: No directory entries\n");
460 return -ENODEV;
461 }
462 if ( hdrbuf->m_ver >= 0x101 )
463 {
464 Kprintf("s147nand.irx: Version 0x%04x format is not supported\n", hdrbuf->m_ver);
465 return -ENODEV;
466 }
467 hdrret = hdrbuf->m_entrycnt;
468 }
469 else
470 {
471 const s147nand_direntry_t *dirbuf;
472
473 dirbuf = (const s147nand_direntry_t *)g_nand_sector_buffer;
474 if ( (offscnt << 6) - 1 + i >= hdrret )
475 return -ENOENT;
476 lvtyp = (char)dirbuf[i].m_type;
477 if (
478 (((lvtyp == 'D') && typ == 'D') || ((lvtyp == 'F' || lvtyp == '\x00') && typ == 'F'))
479 && (!strcmp(dirbuf[i].m_name, name_trunc)) )
480 {
481 privdat->m_seek_max = dirbuf[i].m_size;
482 privdat->m_partition_offset += dirbuf[i].m_offset;
483 return dirbuf[i].m_size;
484 }
485 }
486 }
487 }
488 return -ENOENT;
489}
490
491static int do_nand_bytes2sector(int pageoffs, int byteoffs)
492{
493 return pageoffs + byteoffs / 2048;
494}
495
496static int do_nand_bytes2sector_remainder(int byteoffs)
497{
498 return byteoffs % 2048;
499}
500
501int s147nand_5_outerinit(void)
502{
503 int initres;
504 iop_sema_t semaparam;
505
506 initres = s147nand_15_nandinit();
507 if ( initres )
508 {
509 Kprintf("s147nand.irx: NAND initialize failed (%d)\n", initres);
510 return -1;
511 }
512 // Unofficial: make semaparam local var
513 semaparam.initial = 1;
514 semaparam.max = 1;
515 semaparam.attr = SA_THPRI;
516 semaparam.option = 0;
517 g_sema_id_init = CreateSema(&semaparam);
518 if ( g_sema_id_init < 0 )
519 {
520 Kprintf("s147nand.irx: CreateSema error (%d)\n", g_sema_id_init);
521 return -1;
522 }
523 s147nand_6_checkformat();
524 return 0;
525}
526
527void s147nand_6_checkformat(void)
528{
529 int state;
530 s147nand_info_t *nandinf;
531
532 nandinf = s147nand_16_getnandinfo();
533 s147nand_20_nand_read_dma(&g_nand_header, 0, 0, sizeof(g_nand_header));
534 if ( strncmp(g_nand_header.m_sig, "S147NAND", 9) )
535 {
536 Kprintf("s147nand.irx: Unformatted device\n");
537 Kprintf("\n");
538 return;
539 }
540 Kprintf(
541 "s147nand.irx: BootSector format version = %d.%d\n",
542 g_nand_header.m_bootsector_ver_1,
543 g_nand_header.m_bootsector_ver_2);
544 if ( (u32)g_nand_header.m_bootsector_ver_1 < 2 )
545 {
546 Kprintf("s147nand.irx: Old version format, 256MB-NAND only\n");
547 }
548 else
549 {
550 Kprintf("s147nand.irx: %-.32s\n", g_nand_header.m_nand_desc);
551 CpuSuspendIntr(&state);
552 nandinf->m_page_size_noecc = g_nand_header.m_page_size_noecc;
553 nandinf->m_page_size_withecc = g_nand_header.m_page_size_withecc;
554 nandinf->m_pages_per_block = g_nand_header.m_pages_per_block;
555 nandinf->m_block_size = g_nand_header.m_block_size;
556 nandinf->m_page_count = g_nand_header.m_block_size * g_nand_header.m_pages_per_block;
557 CpuResumeIntr(state);
558 }
559 Kprintf(
560 "s147nand.irx: PageSize = %d + %d (Bytes)\n",
561 nandinf->m_page_size_noecc,
562 nandinf->m_page_size_withecc - nandinf->m_page_size_noecc);
563 Kprintf("s147nand.irx: Pages/Block = %d (Pages)\n", nandinf->m_pages_per_block);
564 Kprintf("s147nand.irx: BlockSize = %d (Blocks)\n", nandinf->m_block_size);
565 Kprintf("s147nand.irx: PageSize = %d (Pages)\n", nandinf->m_page_count);
566 Kprintf("\n");
567}
568
569static void do_update_acdelay(void)
570{
571 int state;
572
573 Kprintf("s147nand.irx: Update Acdelay\n", g_nand_header.m_bootsector_ver_1, g_nand_header.m_bootsector_ver_2);
574 DelayThread(10000);
575 if ( (u32)g_nand_header.m_bootsector_ver_1 < 2 )
576 {
577 Kprintf("s147nand.irx: Old version format, no update\n");
578 DelayThread(10000);
579 return;
580 }
581 if ( !g_nand_header.m_acmem_delay_val || (int)g_nand_header.m_acmem_delay_val == -1 )
582 {
583 Kprintf("s147nand.irx: AcMem = 0x%08x (Default)\n", g_nand_header.m_acmem_delay_val);
584 }
585 else
586 {
587 CpuSuspendIntr(&state);
588 SetAcMemDelayReg(g_nand_header.m_acmem_delay_val);
589 CpuResumeIntr(state);
590 Kprintf(
591 "s147nand.irx: AcMem = 0x%08x (DMA=%d, Read=%d, Write=%d)\n",
592 g_nand_header.m_acmem_delay_val,
593 ((g_nand_header.m_acmem_delay_val & 0xF000000) >> 24) + 1,
594 ((u8)(g_nand_header.m_acmem_delay_val & 0xF0) >> 4) + 1,
595 (g_nand_header.m_acmem_delay_val & 0xF) + 1);
596 }
597 DelayThread(10000);
598 if ( !g_nand_header.m_acio_delay_val || (int)g_nand_header.m_acio_delay_val == -1 )
599 {
600 Kprintf("s147nand.irx: AcIo = 0x%08x (Default)\n", g_nand_header.m_acio_delay_val);
601 }
602 else
603 {
604 CpuSuspendIntr(&state);
605 SetAcIoDelayReg(g_nand_header.m_acio_delay_val);
606 CpuResumeIntr(state);
607 Kprintf(
608 "s147nand.irx: AcIo = 0x%08x (DMA=%d, Read=%d, Write=%d)\n",
609 g_nand_header.m_acio_delay_val,
610 ((g_nand_header.m_acio_delay_val & 0xF000000) >> 24) + 1,
611 ((u8)(g_nand_header.m_acio_delay_val & 0xF0) >> 4) + 1,
612 (g_nand_header.m_acio_delay_val & 0xF) + 1);
613 }
614 DelayThread(10000);
615 Kprintf("\n");
616 DelayThread(10000);
617}
618
619static int do_nand_sector_rw(void *ptr, int pageoffs, int byteoffs, int size)
620{
621 int dma;
622
623 WaitSema(g_sema_id_init);
624 if ( ((uiptr)ptr & 3) != 0 || (byteoffs & 3) != 0 || (size & 3) != 0 )
625 {
626 dma = s147nand_20_nand_read_dma(
627 g_nand_unaligned_buf, s147nand_14_translate_pageoffs(pageoffs), 0, s147nand_16_getnandinfo()->m_page_size_noecc);
628 memcpy(ptr, (char *)g_nand_unaligned_buf + byteoffs, size);
629 }
630 else
631 {
632 dma = s147nand_20_nand_read_dma(ptr, s147nand_14_translate_pageoffs(pageoffs), byteoffs, size);
633 }
634 SignalSema(g_sema_id_init);
635 return dma;
636}
637
638int s147nand_7_multi_read_dma(void *ptr, int pageoffs, int pagecnt)
639{
640 int i;
641 int retres;
642
643 // Unofficial: initialize retres
644 retres = 0;
645 WaitSema(g_sema_id_init);
646 for ( i = 0; i < pagecnt; i += 1 )
647 {
648 retres = s147nand_20_nand_read_dma(
649 (char *)ptr + ((s147nand_16_getnandinfo()->m_page_size_noecc >> 2) << 2) * i,
650 s147nand_14_translate_pageoffs(pageoffs + i),
651 0,
652 s147nand_16_getnandinfo()->m_page_size_noecc);
653 if ( retres )
654 return retres;
655 }
656 SignalSema(g_sema_id_init);
657 return retres;
658}
659
660int s147nand_8_multi_write_dma(void *ptr, int pageoffs, int pagecnt)
661{
662 int i;
663 int retres;
664
665 // Unofficial: initialize retres
666 retres = 0;
667 for ( i = 0; i < pagecnt; i += 1 )
668 {
669 retres = s147nand_22_nand_write_dma(
670 (char *)ptr + ((s147nand_16_getnandinfo()->m_page_size_noecc >> 2) << 2) * i,
671 s147nand_14_translate_pageoffs(pageoffs + i),
672 0,
673 s147nand_16_getnandinfo()->m_page_size_noecc);
674 if ( retres )
675 return retres;
676 }
677 return retres;
678}
679
680int s147nand_9_get_nand_partition(int part)
681{
682 if ( part == 8 )
683 return g_nand_header.m_nand_partition_8_info.m_offset;
684 if ( part >= 0 && part < 8 )
685 return g_nand_header.m_nand_partition_info[part].m_offset;
686 return 0;
687}
688
689static int get_nand_partition_offset(int part)
690{
691 return s147nand_9_get_nand_partition(part) * g_nand_header.m_pages_per_block;
692}
693
694int s147nand_10_get_nand_partition_size(int part)
695{
696 if ( part == 8 )
697 return g_nand_header.m_nand_partition_8_info.m_size;
698 if ( part >= 0 && part < 8 )
699 return g_nand_header.m_nand_partition_info[part].m_size;
700 return 0;
701}
702
703static int nand_mdev_open_special(iop_file_t *f, const char *name)
704{
706 int state;
707
708 CpuSuspendIntr(&state);
709 f->privdata = AllocSysMemory(ALLOC_FIRST, sizeof(s147nand_mdev_privdata_t), 0);
710 CpuResumeIntr(state);
711 if ( !f->privdata )
712 {
713 Kprintf("s147nand.irx: AllocSysMemory failed (9:Open)\n");
714 // Unofficial: return early on error
715 return -ENOENT;
716 }
717 privdat = (s147nand_mdev_privdata_t *)f->privdata;
718 memset(privdat, 0, sizeof(s147nand_mdev_privdata_t));
719 privdat->m_seek_cur = 0;
720 if ( !strcmp(name, "watchdog-enable") )
721 {
722 s147nand_18_enable_nand_watchdog();
723 privdat->m_flags = 0;
724 privdat->m_seek_max = 0;
725 privdat->m_partition_offset = 0;
726 privdat->m_seek_cur = 0;
727 Kprintf("s147nand.irx: WatchDogTimer Enable\n");
728 DelayThread(10000);
729 }
730 else if ( !strcmp(name, "acdelay") )
731 {
732 do_update_acdelay();
733 privdat->m_flags = 0;
734 privdat->m_seek_max = 0;
735 privdat->m_partition_offset = 0;
736 privdat->m_seek_cur = 0;
737 }
738 else if ( !strcmp(name, "seccode") )
739 {
740 privdat->m_flags = 0x10000;
741 privdat->m_seek_max = 2;
742 privdat->m_partition_offset = 0;
743 privdat->m_seek_cur = 0;
744 }
745 else if ( !strcmp(name, "videomode") )
746 {
747 privdat->m_flags = 0x40000;
748 privdat->m_seek_max = 4;
749 privdat->m_partition_offset = 0;
750 privdat->m_seek_cur = 0;
751 }
752 else if ( !strcmp(name, "info") )
753 {
754 privdat->m_flags = 0x100000;
755 privdat->m_seek_max = 2048;
756 privdat->m_partition_offset = (s147nand_9_get_nand_partition(8) - 1) * g_nand_header.m_pages_per_block;
757 privdat->m_seek_cur = 0;
758 }
759 else if ( !strcmp(name, "romwrite-tmp") )
760 {
761 privdat->m_flags = 0x3000000;
762 privdat->m_seek_max = 0;
763 privdat->m_partition_offset = s147nand_9_get_nand_partition(8) * g_nand_header.m_pages_per_block;
764 privdat->m_seek_cur = 0;
765 }
766 else
767 {
768 CpuSuspendIntr(&state);
769 FreeSysMemory(f->privdata);
770 CpuResumeIntr(state);
771 return -ENOENT;
772 }
773 return 0;
774}
775
776static int nand_mdev_read_special(iop_file_t *f, void *ptr, int size)
777{
778 s147nand_mdev_privdata_t *privdata;
779 int retres1;
780
781 privdata = (s147nand_mdev_privdata_t *)f->privdata;
782 if ( (privdata->m_flags & 0x10000) != 0 )
783 return do_nand_copy_seccode_from_buf(f, ptr, size);
784 if ( (privdata->m_flags & 0x40000) != 0 )
785 return do_nand_copy_videomode_from_buf(f, ptr, size);
786 if ( (privdata->m_flags & 0x100000) != 0 )
787 {
788 retres1 = do_nand_sector_rw(ptr, privdata->m_partition_offset, privdata->m_seek_cur, size);
789 if ( retres1 < 0 )
790 return retres1;
791 privdata->m_seek_cur += size;
792 return size;
793 }
794 if ( (privdata->m_flags & 0x1000000) != 0 )
795 {
796 retres1 = do_nand_sector_rw(ptr, privdata->m_partition_offset, privdata->m_seek_cur, size);
797 if ( retres1 < 0 )
798 return retres1;
799 privdata->m_seek_cur += size;
800 return size;
801 }
802 return -ENOENT;
803}
804
805static int nand_mdev_write_special(iop_file_t *f, void *ptr, int size)
806{
807 s147nand_mdev_privdata_t *privdata;
808 int retres1;
809 int xsz;
810
811 privdata = (s147nand_mdev_privdata_t *)f->privdata;
812 xsz =
813 g_nand_header.m_nand_partition_8_info.m_size * g_nand_header.m_pages_per_block * g_nand_header.m_page_size_noecc;
814 if ( (privdata->m_flags & 0x1000000) == 0 )
815 return -EINVAL;
816 if ( xsz < privdata->m_seek_cur + size )
817 {
818 Kprintf("s147nand.irx: Out of rewritable partition, lseek(%d) > max(%d)\n", privdata->m_seek_cur + size, xsz);
819 return -EFBIG;
820 }
821 if ( (privdata->m_flags & 0x2000000) != 0 )
822 {
823 int i;
824
825 retres1 = 0;
826 for ( i = 0; i < g_nand_header.m_nand_partition_8_info.m_size; i += 1 )
827 retres1 = s147nand_11_erasetranslatepageoffs(
828 s147nand_27_blocks2pages(i + g_nand_header.m_nand_partition_8_info.m_offset));
829 privdata->m_flags &= ~0x2000000;
830 if ( retres1 )
831 return retres1;
832 }
833 if ( !g_nand_header.m_page_size_noecc )
834 __builtin_trap();
835 if ( g_nand_header.m_page_size_noecc == -1 && privdata->m_seek_cur == (int)0x80000000 )
836 __builtin_trap();
837 if ( !g_nand_header.m_page_size_noecc )
838 __builtin_trap();
839 if ( g_nand_header.m_page_size_noecc == -1 && size == (int)0x80000000 )
840 __builtin_trap();
841 retres1 = s147nand_8_multi_write_dma(
842 ptr,
843 privdata->m_seek_cur / g_nand_header.m_page_size_noecc + privdata->m_partition_offset,
844 size / g_nand_header.m_page_size_noecc);
845 if ( retres1 < 0 )
846 return retres1;
847 privdata->m_seek_cur += size;
848 privdata->m_seek_max = privdata->m_seek_cur;
849 return size;
850}
851
852static int do_nand_copy_seccode_from_buf(iop_file_t *f, void *ptr, int size)
853{
854 s147nand_mdev_privdata_t *privdata;
855 int xsize;
856
857 privdata = (s147nand_mdev_privdata_t *)f->privdata;
858 if ( privdata->m_seek_cur >= privdata->m_seek_max )
859 return 0;
860 xsize =
861 (privdata->m_seek_max >= (int)(privdata->m_seek_cur + size)) ? size : (privdata->m_seek_max - privdata->m_seek_cur);
862 memcpy(ptr, &g_nand_header.m_nand_seccode[privdata->m_seek_cur], xsize);
863 privdata->m_seek_cur += xsize;
864 return xsize;
865}
866
867static int do_nand_copy_videomode_from_buf(iop_file_t *f, void *ptr, int size)
868{
869 s147nand_mdev_privdata_t *privdata;
870 int xsize;
871
872 privdata = (s147nand_mdev_privdata_t *)f->privdata;
873 if ( privdata->m_seek_cur >= privdata->m_seek_max )
874 return 0;
875 xsize =
876 (privdata->m_seek_max >= (int)(privdata->m_seek_cur + size)) ? size : (privdata->m_seek_max - privdata->m_seek_cur);
877 memcpy(ptr, &g_nand_header.m_nand_vidmode[privdata->m_seek_cur], xsize);
878 privdata->m_seek_cur += xsize;
879 return xsize;
880}
881
882int s147nand_11_erasetranslatepageoffs(int pageoffs)
883{
884 return s147nand_24_eraseoffset(s147nand_14_translate_pageoffs(pageoffs));
885}
886
887int s147nand_12_load_logaddrtable(void)
888{
889 s147nand_header_t hdr __attribute__((__aligned__(16)));
890 int state;
891
892 s147nand_20_nand_read_dma(&hdr, 0, 0, sizeof(hdr));
893 if ( strncmp(hdr.m_sig, "S147NAND", 9) )
894 {
895 Kprintf("s147nand.irx: Unformatted device error.\n");
896 return -19;
897 }
898 CpuSuspendIntr(&state);
899 g_logical_addr_tbl = (u16 *)AllocSysMemory(ALLOC_FIRST, sizeof(u16) * hdr.m_block_size, 0);
900 CpuResumeIntr(state);
901 s147nand_19_logaddr_read(g_logical_addr_tbl, 1, sizeof(u16) * hdr.m_block_size);
902 CpuSuspendIntr(&state);
903 g_nand_unaligned_buf = AllocSysMemory(ALLOC_FIRST, s147nand_16_getnandinfo()->m_page_size_noecc, 0);
904 CpuResumeIntr(state);
905 if ( !g_nand_unaligned_buf )
906 {
907 Kprintf("s147nand.irx: AllocSysMemory failed (LogAddrTable)\n");
908 return -1;
909 }
910 // Unofficial: remove redundant var
911 return 0;
912}
913
914int s147nand_13_translate_blockoffs(int blockoffs)
915{
916 int tbladdr;
917
918 if ( blockoffs <= 0 || blockoffs >= s147nand_16_getnandinfo()->m_block_size )
919 {
920 Kprintf("s147nand.irx: Invalid logical block address %d\n", blockoffs);
921 return -1470010;
922 }
923 // Unofficial: check g_nand_unaligned_buf instead
924 if ( !g_nand_unaligned_buf )
925 {
926 int logaddrtable;
927
928 logaddrtable = s147nand_12_load_logaddrtable();
929 if ( logaddrtable < 0 )
930 return logaddrtable;
931 }
932 tbladdr = g_logical_addr_tbl[blockoffs];
933 switch ( tbladdr )
934 {
935 case 0xAAAA:
936 return blockoffs;
937 case 0xCCCC:
938 case 0xEEEE:
939 return -1470010;
940 default:
941 return tbladdr;
942 }
943}
944
945int s147nand_14_translate_pageoffs(int pageoffs)
946{
947 int tblockoffs;
948
949 tblockoffs = s147nand_13_translate_blockoffs(s147nand_28_pages2blocks(pageoffs));
950 if ( tblockoffs == -1470010 )
951 return -1470010;
952 if ( !g_nand_header.m_pages_per_block )
953 __builtin_trap();
954 if ( g_nand_header.m_pages_per_block == -1 && pageoffs == (int)0x80000000 )
955 __builtin_trap();
956 return s147nand_27_blocks2pages(tblockoffs) + (pageoffs % g_nand_header.m_pages_per_block);
957}
958
959static int dev9_intr_handler(void *unusd)
960{
961 (void)unusd;
962
963 iWakeupThread(g_thid);
964 return 1;
965}
966
967int s147nand_15_nandinit(void)
968{
969 int intrstate;
970 iop_sema_t semaparam;
971 USE_IOP_MMIO_HWPORT();
972
973 DisableIntr(IOP_IRQ_DMA_DEV9, &intrstate);
974 ReleaseIntrHandler(IOP_IRQ_DMA_DEV9);
975 // Unofficial: removed unused userdata var
976 RegisterIntrHandler(IOP_IRQ_DMA_DEV9, 1, dev9_intr_handler, NULL);
977 EnableIntr(IOP_IRQ_DMA_DEV9);
978 sceDisableDMAChannel(IOP_DMAC_DEV9);
979 sceSetDMAPriority(IOP_DMAC_DEV9, 7);
980 sceEnableDMAChannel(IOP_DMAC_DEV9);
981 // Unofficial: use uncached mirror
982 iop_mmio_hwport->ssbus2.ind_B_address = 0xB4000008;
983 // Unofficial: make semaparam local var
984 semaparam.initial = 1;
985 semaparam.max = 1;
986 semaparam.attr = SA_THPRI;
987 semaparam.option = 0;
988 g_sema_id_nand = CreateSema(&semaparam);
989 if ( g_sema_id_nand >= 0 )
990 return 0;
991 printf("nand_Init: CreateSema error (%d)\n", g_sema_id_nand);
992 return -1;
993}
994
995s147nand_info_t *s147nand_16_getnandinfo(void)
996{
997 return &g_nand_info;
998}
999
1000int s147nand_17_get_sema(void)
1001{
1002 return g_sema_id_nand;
1003}
1004
1005void s147nand_18_enable_nand_watchdog(void)
1006{
1007 g_nand_watchdog_enabled = 1;
1008}
1009
1010int s147nand_19_logaddr_read(u16 *tbl, int pageoffs, int bytecnt)
1011{
1012 int i;
1013 int pagecnt;
1014
1015 pagecnt = s147nand_30_bytes2pagesnoeccround(bytecnt);
1016 for ( i = 0; i < pagecnt; i += 1 )
1017 {
1018 int retres;
1019
1020 retres = s147nand_20_nand_read_dma(
1021 &tbl[((g_nand_info.m_page_size_noecc >> 2) << 1) * i], pageoffs + i, 0, g_nand_info.m_page_size_noecc);
1022 if ( retres )
1023 return retres;
1024 }
1025 return 0;
1026}
1027
1028int s147nand_20_nand_read_dma(void *ptr, int pageoffs, int byteoffs, int bytecnt)
1029{
1030 int retres;
1031
1032 WaitSema(g_sema_id_nand);
1033 retres = nand_lowlevel_read_dma(ptr, pageoffs, byteoffs, bytecnt);
1034 SignalSema(g_sema_id_nand);
1035 return retres;
1036}
1037
1038int s147nand_21_nand_read_pio(void *ptr, int pageoffs, int byteoffs, int bytecnt)
1039{
1040 int retres;
1041 int state;
1042
1043 WaitSema(g_sema_id_nand);
1044 CpuSuspendIntr(&state);
1045 retres = nand_lowlevel_read_pio(ptr, pageoffs, byteoffs, bytecnt);
1046 CpuResumeIntr(state);
1047 SignalSema(g_sema_id_nand);
1048 return retres;
1049}
1050
1051int s147nand_22_nand_write_dma(void *ptr, int pageoffs, int byteoffs, int bytecnt)
1052{
1053 int retres;
1054
1055 WaitSema(g_sema_id_nand);
1056 retres = nand_lowlevel_write_dma(ptr, pageoffs, byteoffs, bytecnt);
1057 SignalSema(g_sema_id_nand);
1058 return retres;
1059}
1060
1061int s147nand_23_nand_write_pio(void *ptr, int pageoffs, int byteoffs, int bytecnt)
1062{
1063 int retres;
1064 int state;
1065
1066 WaitSema(g_sema_id_nand);
1067 CpuSuspendIntr(&state);
1068 retres = nand_lowlevel_write_pio(ptr, pageoffs, byteoffs, bytecnt);
1069 CpuResumeIntr(state);
1070 SignalSema(g_sema_id_nand);
1071 return retres;
1072}
1073
1074int s147nand_24_eraseoffset(int pageoffs)
1075{
1076 int retres;
1077 int state;
1078 u8 val1;
1079 u8 val2;
1080
1081 s147nand_21_nand_read_pio(
1082 &val1,
1083 s147nand_27_blocks2pages(s147nand_28_pages2blocks(pageoffs)) + 0,
1084 g_nand_info.m_page_size_noecc,
1085 sizeof(val1));
1086 s147nand_21_nand_read_pio(
1087 &val2,
1088 s147nand_27_blocks2pages(s147nand_28_pages2blocks(pageoffs)) + 1,
1089 g_nand_info.m_page_size_noecc,
1090 sizeof(val2));
1091 if ( val1 != 255 || val2 != 255 )
1092 return -1470020;
1093 WaitSema(g_sema_id_nand);
1094 CpuSuspendIntr(&state);
1095 retres = nand_lowlevel_blockerase(pageoffs);
1096 CpuResumeIntr(state);
1097 SignalSema(g_sema_id_nand);
1098 return retres;
1099}
1100
1101int s147nand_25_nand_blockerase(int pageoffs)
1102{
1103 int retres;
1104 int state;
1105
1106 WaitSema(g_sema_id_nand);
1107 CpuSuspendIntr(&state);
1108 retres = nand_lowlevel_blockerase(pageoffs);
1109 CpuResumeIntr(state);
1110 SignalSema(g_sema_id_nand);
1111 return retres;
1112}
1113
1114int s147nand_26_nand_readid(void *ptr)
1115{
1116 int retres;
1117 int state;
1118
1119 WaitSema(g_sema_id_nand);
1120 CpuSuspendIntr(&state);
1121 retres = nand_lowlevel_readid(ptr);
1122 CpuResumeIntr(state);
1123 SignalSema(g_sema_id_nand);
1124 return retres;
1125}
1126
1127static int nand_lowlevel_read_dma(void *ptr, int pageoffs, int byteoffs, int bytecnt)
1128{
1129 int state;
1130 USE_S147_DEV9_MEM_MMIO();
1131 USE_S147MAMD_DEV9_IO_MMIO();
1132
1133 if ( pageoffs < 0 || pageoffs >= g_nand_info.m_page_count )
1134 return -1470010;
1135 if ( byteoffs < 0 || byteoffs >= g_nand_info.m_page_size_withecc )
1136 return -1470010;
1137 if ( bytecnt < 4 || g_nand_info.m_page_size_withecc < byteoffs + bytecnt )
1138 return -1470010;
1139 CpuSuspendIntr(&state);
1140 s147nand_dev9_io_mmio->m_nand_cmd_enable = 1;
1141 s147nand_dev9_io_mmio->m_nand_cmd_sel = 0;
1142 s147nand_dev9_io_mmio->m_nand_cmd_offs = (u16)(byteoffs);
1143 s147nand_dev9_io_mmio->m_nand_cmd_offs = (u16)(byteoffs & 0xF00) >> 8;
1144 s147nand_dev9_io_mmio->m_nand_cmd_offs = pageoffs;
1145 s147nand_dev9_io_mmio->m_nand_cmd_offs = (u16)(pageoffs & 0xFF00) >> 8;
1146 s147nand_dev9_io_mmio->m_nand_cmd_offs = (pageoffs & 0xFF0000) >> 16;
1147 s147nand_dev9_io_mmio->m_nand_cmd_sel = 0x30;
1148 CpuResumeIntr(state);
1149 while ( (s147nand_dev9_io_mmio->m_nand_waitflag & 1) != 0 )
1150 ;
1151 CpuSuspendIntr(&state);
1152 s147_dev9_mem_mmio->m_security_unlock_unlock = 0;
1153 sceSetSliceDMA(IOP_DMAC_DEV9, ptr, bytecnt >> 2, 1, 0);
1154 g_thid = GetThreadId();
1155 CpuResumeIntr(state);
1156 sceStartDMA(IOP_DMAC_DEV9);
1157 SleepThread();
1158 s147nand_dev9_io_mmio->m_nand_cmd_enable = 0;
1159 if ( g_nand_watchdog_enabled == 1 )
1160 s147_dev9_mem_mmio->m_watchdog_flag2 = 0;
1161 return 0;
1162}
1163
1164static int nand_lowlevel_read_pio(void *ptr, int pageoffs, int byteoffs, int bytecnt)
1165{
1166 int i;
1167 USE_S147_DEV9_MEM_MMIO();
1168 USE_S147MAMD_DEV9_IO_MMIO();
1169
1170 if ( pageoffs < 0 || pageoffs >= g_nand_info.m_page_count )
1171 return -1470010;
1172 if ( byteoffs < 0 || byteoffs >= g_nand_info.m_page_size_withecc )
1173 return -1470010;
1174 if ( bytecnt <= 0 || g_nand_info.m_page_size_withecc < byteoffs + bytecnt )
1175 return -1470010;
1176 while ( (s147nand_dev9_io_mmio->m_nand_waitflag & 1) != 0 )
1177 ;
1178 s147nand_dev9_io_mmio->m_nand_cmd_enable = 1;
1179 s147nand_dev9_io_mmio->m_nand_cmd_sel = 0;
1180 s147nand_dev9_io_mmio->m_nand_cmd_offs = byteoffs;
1181 s147nand_dev9_io_mmio->m_nand_cmd_offs = (u16)(byteoffs & 0xF00) >> 8;
1182 s147nand_dev9_io_mmio->m_nand_cmd_offs = pageoffs;
1183 s147nand_dev9_io_mmio->m_nand_cmd_offs = (u16)(pageoffs & 0xFF00) >> 8;
1184 s147nand_dev9_io_mmio->m_nand_cmd_offs = (pageoffs & 0xFF0000) >> 16;
1185 s147nand_dev9_io_mmio->m_nand_cmd_sel = 0x30;
1186 while ( (s147nand_dev9_io_mmio->m_nand_waitflag & 1) != 0 )
1187 ;
1188 for ( i = 0; i < bytecnt; i += 1 )
1189 ((u8 *)ptr)[i] = s147nand_dev9_io_mmio->m_nand_outbyte;
1190 s147nand_dev9_io_mmio->m_nand_cmd_enable = 0;
1191 if ( g_nand_watchdog_enabled == 1 )
1192 s147_dev9_mem_mmio->m_watchdog_flag2 = 0;
1193 return 0;
1194}
1195
1196static int nand_lowlevel_write_dma(void *ptr, int pageoffs, int byteoffs, int bytecnt)
1197{
1198 int state;
1199 u8 flgtmp;
1200 USE_S147_DEV9_MEM_MMIO();
1201 USE_S147MAMD_DEV9_IO_MMIO();
1202
1203 if ( pageoffs < 0 || pageoffs >= g_nand_info.m_page_count )
1204 return -1470010;
1205 if ( byteoffs < 0 || byteoffs >= g_nand_info.m_page_size_withecc )
1206 return -1470010;
1207 if ( bytecnt < 4 || g_nand_info.m_page_size_withecc < byteoffs + bytecnt )
1208 return -1470010;
1209 CpuSuspendIntr(&state);
1210 s147nand_dev9_io_mmio->m_nand_write_cmd_unlock = 0xA5;
1211 s147nand_dev9_io_mmio->m_nand_cmd_enable = 1;
1212 s147nand_dev9_io_mmio->m_nand_cmd_sel = 0x80;
1213 s147nand_dev9_io_mmio->m_nand_cmd_offs = (u16)(byteoffs);
1214 s147nand_dev9_io_mmio->m_nand_cmd_offs = (u16)(byteoffs & 0xF00) >> 8;
1215 s147nand_dev9_io_mmio->m_nand_cmd_offs = pageoffs;
1216 s147nand_dev9_io_mmio->m_nand_cmd_offs = (u16)(pageoffs & 0xFF00) >> 8;
1217 s147nand_dev9_io_mmio->m_nand_cmd_offs = (pageoffs & 0xFF0000) >> 16;
1218 s147_dev9_mem_mmio->m_security_unlock_unlock = 0;
1219 sceSetSliceDMA(IOP_DMAC_DEV9, ptr, bytecnt >> 2, 1, 1);
1220 g_thid = GetThreadId();
1221 CpuResumeIntr(state);
1222 sceStartDMA(IOP_DMAC_DEV9);
1223 SleepThread();
1224 s147nand_dev9_io_mmio->m_nand_cmd_sel = 0x10;
1225 while ( (s147nand_dev9_io_mmio->m_nand_waitflag & 1) != 0 )
1226 ;
1227 s147nand_dev9_io_mmio->m_nand_cmd_sel = 0x70;
1228 flgtmp = s147nand_dev9_io_mmio->m_nand_outbyte;
1229 s147nand_dev9_io_mmio->m_nand_cmd_enable = 0;
1230 s147nand_dev9_io_mmio->m_nand_write_cmd_unlock = 0;
1231 if ( g_nand_watchdog_enabled == 1 )
1232 s147_dev9_mem_mmio->m_watchdog_flag2 = 0;
1233 if ( (flgtmp & 0x80) == 0 )
1234 return -1470030;
1235 if ( (flgtmp & 1) != 0 )
1236 return -1470020;
1237 return 0;
1238}
1239
1240static int nand_lowlevel_write_pio(void *ptr, int pageoffs, int byteoffs, int bytecnt)
1241{
1242 u8 flgtmp;
1243 int i;
1244 USE_S147_DEV9_MEM_MMIO();
1245 USE_S147MAMD_DEV9_IO_MMIO();
1246
1247 if ( pageoffs < 0 || pageoffs >= g_nand_info.m_page_count )
1248 return -1470010;
1249 if ( byteoffs < 0 || byteoffs >= g_nand_info.m_page_size_withecc )
1250 return -1470010;
1251 if ( bytecnt <= 0 || g_nand_info.m_page_size_withecc < byteoffs + bytecnt )
1252 return -1470010;
1253 s147nand_dev9_io_mmio->m_nand_write_cmd_unlock = 0xA5;
1254 s147nand_dev9_io_mmio->m_nand_cmd_enable = 1;
1255 s147nand_dev9_io_mmio->m_nand_cmd_sel = 0x80;
1256 s147nand_dev9_io_mmio->m_nand_cmd_offs = byteoffs;
1257 s147nand_dev9_io_mmio->m_nand_cmd_offs = (u16)(byteoffs & 0xF00) >> 8;
1258 s147nand_dev9_io_mmio->m_nand_cmd_offs = pageoffs;
1259 s147nand_dev9_io_mmio->m_nand_cmd_offs = (u16)(pageoffs & 0xFF00) >> 8;
1260 s147nand_dev9_io_mmio->m_nand_cmd_offs = (pageoffs & 0xFF0000) >> 16;
1261 for ( i = 0; i < bytecnt; i += 1 )
1262 s147nand_dev9_io_mmio->m_nand_outbyte = ((u8 *)ptr)[i];
1263 s147nand_dev9_io_mmio->m_nand_cmd_sel = 0x10;
1264 while ( (s147nand_dev9_io_mmio->m_nand_waitflag & 1) != 0 )
1265 ;
1266 s147nand_dev9_io_mmio->m_nand_cmd_sel = 0x70;
1267 flgtmp = s147nand_dev9_io_mmio->m_nand_outbyte;
1268 s147nand_dev9_io_mmio->m_nand_cmd_enable = 0;
1269 s147nand_dev9_io_mmio->m_nand_write_cmd_unlock = 0;
1270 if ( g_nand_watchdog_enabled == 1 )
1271 s147_dev9_mem_mmio->m_watchdog_flag2 = 0;
1272 if ( (flgtmp & 0x80) == 0 )
1273 return -1470030;
1274 if ( (flgtmp & 1) != 0 )
1275 return -1470020;
1276 return 0;
1277}
1278
1279static int nand_lowlevel_blockerase(int pageoffs)
1280{
1281 u8 flgtmp;
1282 USE_S147_DEV9_MEM_MMIO();
1283 USE_S147MAMD_DEV9_IO_MMIO();
1284
1285 if ( pageoffs < 0 || pageoffs >= g_nand_info.m_page_count )
1286 return -1470010;
1287 s147nand_dev9_io_mmio->m_nand_write_cmd_unlock = 0xA5;
1288 s147nand_dev9_io_mmio->m_nand_cmd_enable = 1;
1289 s147nand_dev9_io_mmio->m_nand_cmd_sel = 0x60;
1290 s147nand_dev9_io_mmio->m_nand_cmd_offs = pageoffs & 0xC0;
1291 s147nand_dev9_io_mmio->m_nand_cmd_offs = (u16)(pageoffs & 0xFF00) >> 8;
1292 s147nand_dev9_io_mmio->m_nand_cmd_offs = (pageoffs & 0xFF0000) >> 16;
1293 s147nand_dev9_io_mmio->m_nand_cmd_sel = 0xD0;
1294 while ( (s147nand_dev9_io_mmio->m_nand_waitflag & 1) != 0 )
1295 ;
1296 s147nand_dev9_io_mmio->m_nand_cmd_sel = 0x70;
1297 flgtmp = s147nand_dev9_io_mmio->m_nand_outbyte;
1298 s147nand_dev9_io_mmio->m_nand_cmd_enable = 0;
1299 s147nand_dev9_io_mmio->m_nand_write_cmd_unlock = 0;
1300 if ( g_nand_watchdog_enabled == 1 )
1301 s147_dev9_mem_mmio->m_watchdog_flag2 = 0;
1302 if ( (flgtmp & 0x80) == 0 )
1303 return -1470030;
1304 if ( (flgtmp & 1) != 0 )
1305 return -1470020;
1306 return 0;
1307}
1308
1309static int nand_lowlevel_readid(void *ptr)
1310{
1311 int i;
1312 USE_S147_DEV9_MEM_MMIO();
1313 USE_S147MAMD_DEV9_IO_MMIO();
1314
1315 if ( !ptr )
1316 return -1470010;
1317 s147nand_dev9_io_mmio->m_nand_cmd_enable = 1;
1318 s147nand_dev9_io_mmio->m_nand_cmd_sel = 0x90;
1319 s147nand_dev9_io_mmio->m_nand_cmd_offs = 0;
1320 for ( i = 0; i < 5; i += 1 )
1321 ((u8 *)ptr)[i] = s147nand_dev9_io_mmio->m_nand_outbyte;
1322 s147nand_dev9_io_mmio->m_nand_cmd_enable = 0;
1323 if ( g_nand_watchdog_enabled == 1 )
1324 s147_dev9_mem_mmio->m_watchdog_flag2 = 0;
1325 return 0;
1326}
1327
1328int s147nand_27_blocks2pages(int blocks)
1329{
1330 return blocks * g_nand_info.m_pages_per_block;
1331}
1332
1333int s147nand_28_pages2blocks(int pages)
1334{
1335 if ( !g_nand_info.m_pages_per_block )
1336 __builtin_trap();
1337 if ( g_nand_info.m_pages_per_block == -1 && pages == (int)0x80000000 )
1338 __builtin_trap();
1339 return pages / g_nand_info.m_pages_per_block;
1340}
1341
1342int s147nand_29_pages2blockround(int pages)
1343{
1344 int blocks;
1345
1346 if ( !g_nand_info.m_pages_per_block )
1347 __builtin_trap();
1348 if ( g_nand_info.m_pages_per_block == -1 && pages == (int)0x80000000 )
1349 __builtin_trap();
1350 if ( !g_nand_info.m_pages_per_block )
1351 __builtin_trap();
1352 blocks = pages / g_nand_info.m_pages_per_block;
1353 if ( g_nand_info.m_pages_per_block == -1 && pages == (int)0x80000000 )
1354 __builtin_trap();
1355 return blocks + ((pages % g_nand_info.m_pages_per_block) ? 1 : 0);
1356}
1357
1358int s147nand_30_bytes2pagesnoeccround(int bytes)
1359{
1360 int pages;
1361
1362 if ( !g_nand_info.m_page_size_noecc )
1363 __builtin_trap();
1364 if ( g_nand_info.m_page_size_noecc == -1 && bytes == (int)0x80000000 )
1365 __builtin_trap();
1366 if ( !g_nand_info.m_page_size_noecc )
1367 __builtin_trap();
1368 pages = bytes / g_nand_info.m_page_size_noecc;
1369 if ( g_nand_info.m_page_size_noecc == -1 && bytes == (int)0x80000000 )
1370 __builtin_trap();
1371 return pages + ((bytes % g_nand_info.m_page_size_noecc) ? 1 : 0);
1372}
#define ENOENT
Definition errno.h:23
#define EINVAL
Definition errno.h:63
#define ENOMEM
Definition errno.h:43
#define ENODEV
Definition errno.h:57
#define EFBIG
Definition errno.h:73
int CpuResumeIntr(int state)
Definition intrman.c:227
int ReleaseIntrHandler(int irq)
Definition intrman.c:167
int DisableIntr(int irq, int *res)
Definition intrman.c:395
int CpuSuspendIntr(int *state)
Definition intrman.c:205
int RegisterIntrHandler(int irq, int mode, int(*handler)(void *arg), void *arg)
Definition intrman.c:125
int EnableIntr(int irq)
Definition intrman.c:346
unsigned int version
Definition ioman.h:68
void * privdata
Definition ioman.h:61
int unit
Definition ioman.h:57
typedef __attribute__
Definition tlbfunc.c:60