11#include "irx_imports.h"
18IRX_ID(
"S147NAN2", 5, 2);
27 int m_partition_offset;
30static int do_register_nand_to_mdev(
const char *drv_name,
const char *drv_desc);
33static int nand_mdev_op_open(
iop_file_t *f,
const char *name,
int flags);
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);
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);
59IOMAN_RETURN_VALUE_IMPL(0);
64 IOMAN_RETURN_VALUE(0),
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),
81static void *g_nand_unaligned_buf;
83static int g_nand_watchdog_enabled;
87static void *g_nand_sector_buffer;
88static int g_sema_id_dev;
89static int g_sema_id_init;
91static u16 *g_logical_addr_tbl;
92static int g_sema_id_nand;
95int _start(
int ac,
char **av)
99 Kprintf(
"\ns147nand.irx: System147 NAND-Flash File System Driver v%d.%d\n", 5, 2);
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) )
110 Kprintf(
"s147nand.irx: RegisterLibraryEntries - Failed.\n");
111 return MODULE_NO_RESIDENT_END;
113 Kprintf(
"s147nand.irx: RegisterLibraryEntries - OK.\n");
114 return MODULE_RESIDENT_END;
117static int do_register_nand_to_mdev(
const char *drv_name,
const char *drv_desc)
121 if ( s147nand_5_outerinit() < 0 )
124 semaparam.initial = 1;
126 semaparam.attr = SA_THPRI;
127 semaparam.option = 0;
128 g_sema_id_dev = CreateSema(&semaparam);
129 if ( g_sema_id_dev < 0 )
131 Kprintf(
"s147nand.irx: CreateSema error (%d)\n", g_sema_id_dev);
134 g_drv.name = drv_name;
135 g_drv.type = IOP_DT_FS;
137 g_drv.desc = drv_desc;
138 g_drv.ops = &nand_mdev_ops;
140 s147mdev_4_addfs(&g_drv, 0);
150 Kprintf(
"s147nand.irx: SectorBuffer=%d, FileParam=%d\n", 0, 1);
152 g_nand_sector_buffer = AllocSysMemory(ALLOC_FIRST, 2048, 0);
154 if ( g_nand_sector_buffer )
156 Kprintf(
"s147nand.irx: AllocSysMemory failed (s147file_Init)\n");
165 if ( g_nand_sector_buffer )
168 FreeSysMemory(g_nand_sector_buffer);
174static int nand_mdev_op_open(
iop_file_t *f,
const char *name,
int flags)
182 WaitSema(g_sema_id_dev);
185 retres = nand_mdev_open_special(f, name);
186 SignalSema(g_sema_id_dev);
194 Kprintf(
"s147nand.irx: AllocSysMemory failed (Open)\n");
201 retres = do_nand_open_inner1(privdat, f->
unit, name);
212 SignalSema(g_sema_id_dev);
215 privdat->m_seek_cur = 0;
216 SignalSema(g_sema_id_dev);
224 WaitSema(g_sema_id_dev);
232 SignalSema(g_sema_id_dev);
236static int nand_mdev_op_read(
iop_file_t *f,
void *ptr,
int size)
246 WaitSema(g_sema_id_dev);
247 if ( privdat->m_seek_cur >= privdat->m_seek_max )
249 SignalSema(g_sema_id_dev);
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 )
255 "s147file: CallBack_Read -> Param=0x%08x Seek=%d/%d Count=%d CountEnd=%d\n",
265 special = nand_mdev_read_special(f, ptr, size);
266 SignalSema(g_sema_id_dev);
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 )
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;
280 SignalSema(g_sema_id_dev);
284static int nand_mdev_op_write(
iop_file_t *f,
void *ptr,
int size)
286 WaitSema(g_sema_id_dev);
291 retres = nand_mdev_write_special(f, ptr, size);
292 SignalSema(g_sema_id_dev);
295 SignalSema(g_sema_id_dev);
299static int nand_mdev_op_lseek(
iop_file_t *f,
int offset,
int mode)
304 WaitSema(g_sema_id_dev);
308 privdat->m_seek_cur = offset;
311 privdat->m_seek_cur += offset;
314 privdat->m_seek_cur = privdat->m_seek_max + offset;
317 SignalSema(g_sema_id_dev);
320 if ( privdat->m_seek_max < privdat->m_seek_cur )
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);
327 SignalSema(g_sema_id_dev);
328 return privdat->m_seek_cur;
331int s147nand_4_dumpprintinfo(
int part)
334 int nand_partition_offset;
346 nand_partition_offset = get_nand_partition_offset(part);
347 if ( nand_partition_offset < 0 )
349 for ( i = 0; i < 64; i += 1 )
351 s147nand_7_multi_read_dma(g_nand_sector_buffer, nand_partition_offset + i, 1);
352 for ( j = 0; j < 64; j += 1 )
354 if ( (i << 6) - 1 + j == -1 )
359 if ( strncmp(hdrbuf->m_sig,
"S147ROM", 8) )
362 Kprintf(
" \"%s%d:\" ... No data\n", g_drv.name, part);
363 Kprintf(
" -----------------------------\n\n");
366 hdrret = hdrbuf->m_entrycnt;
368 Kprintf(
" \"%s%d:\"\n", g_drv.name, part);
369 Kprintf(
" -----------------------------\n");
376 if ( (i << 6) - 1 + j >= hdrret )
381 strcpy(pathtmp, dirbuf[j].m_name);
382 if ( dirbuf[j].m_type ==
'D' )
384 strcat(pathtmp,
"/");
391 Kprintf(
" %9d %s\n", dirbuf[j].m_size, pathtmp);
397 Kprintf(
" -----------------------------\n");
398 Kprintf(
" %d directories, %d files\n", dircnt, filcnt);
405 int nand_partition_offset;
407 nand_partition_offset = get_nand_partition_offset(part);
408 if ( nand_partition_offset < 0 )
410 Kprintf(
"s147nand.irx: Error invalid unit number\n");
413 privdat->m_partition_offset = nand_partition_offset;
414 return do_nand_open_inner2(privdat, name + ((name[0] ==
'/') ? 1 : 0));
421 for ( i = 0; name[i] && name[i] !=
'/'; i += 1 )
423 if ( name[i] ==
'/' )
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;
430 return do_get_nand_direntry(privdat, name, i,
'F');
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 )
448 s147nand_7_multi_read_dma(g_nand_sector_buffer, privdat->m_partition_offset + offscnt, 1);
450 for ( i = 0; i < 64; i += 1 )
452 if ( (offscnt << 6) - 1 + i == -1 )
457 if ( strncmp(hdrbuf->m_sig,
"S147ROM", 8) )
459 Kprintf(
"s147nand.irx: No directory entries\n");
462 if ( hdrbuf->m_ver >= 0x101 )
464 Kprintf(
"s147nand.irx: Version 0x%04x format is not supported\n", hdrbuf->m_ver);
467 hdrret = hdrbuf->m_entrycnt;
474 if ( (offscnt << 6) - 1 + i >= hdrret )
476 lvtyp = (char)dirbuf[i].m_type;
478 (((lvtyp ==
'D') && typ ==
'D') || ((lvtyp ==
'F' || lvtyp ==
'\x00') && typ ==
'F'))
479 && (!strcmp(dirbuf[i].m_name, name_trunc)) )
481 privdat->m_seek_max = dirbuf[i].m_size;
482 privdat->m_partition_offset += dirbuf[i].m_offset;
483 return dirbuf[i].m_size;
491static int do_nand_bytes2sector(
int pageoffs,
int byteoffs)
493 return pageoffs + byteoffs / 2048;
496static int do_nand_bytes2sector_remainder(
int byteoffs)
498 return byteoffs % 2048;
501int s147nand_5_outerinit(
void)
506 initres = s147nand_15_nandinit();
509 Kprintf(
"s147nand.irx: NAND initialize failed (%d)\n", initres);
513 semaparam.initial = 1;
515 semaparam.attr = SA_THPRI;
516 semaparam.option = 0;
517 g_sema_id_init = CreateSema(&semaparam);
518 if ( g_sema_id_init < 0 )
520 Kprintf(
"s147nand.irx: CreateSema error (%d)\n", g_sema_id_init);
523 s147nand_6_checkformat();
527void s147nand_6_checkformat(
void)
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) )
536 Kprintf(
"s147nand.irx: Unformatted device\n");
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 )
546 Kprintf(
"s147nand.irx: Old version format, 256MB-NAND only\n");
550 Kprintf(
"s147nand.irx: %-.32s\n", g_nand_header.m_nand_desc);
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;
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);
569static void do_update_acdelay(
void)
573 Kprintf(
"s147nand.irx: Update Acdelay\n", g_nand_header.m_bootsector_ver_1, g_nand_header.m_bootsector_ver_2);
575 if ( (u32)g_nand_header.m_bootsector_ver_1 < 2 )
577 Kprintf(
"s147nand.irx: Old version format, no update\n");
581 if ( !g_nand_header.m_acmem_delay_val || (
int)g_nand_header.m_acmem_delay_val == -1 )
583 Kprintf(
"s147nand.irx: AcMem = 0x%08x (Default)\n", g_nand_header.m_acmem_delay_val);
588 SetAcMemDelayReg(g_nand_header.m_acmem_delay_val);
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);
598 if ( !g_nand_header.m_acio_delay_val || (
int)g_nand_header.m_acio_delay_val == -1 )
600 Kprintf(
"s147nand.irx: AcIo = 0x%08x (Default)\n", g_nand_header.m_acio_delay_val);
605 SetAcIoDelayReg(g_nand_header.m_acio_delay_val);
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);
619static int do_nand_sector_rw(
void *ptr,
int pageoffs,
int byteoffs,
int size)
623 WaitSema(g_sema_id_init);
624 if ( ((uiptr)ptr & 3) != 0 || (byteoffs & 3) != 0 || (size & 3) != 0 )
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);
632 dma = s147nand_20_nand_read_dma(ptr, s147nand_14_translate_pageoffs(pageoffs), byteoffs, size);
634 SignalSema(g_sema_id_init);
638int s147nand_7_multi_read_dma(
void *ptr,
int pageoffs,
int pagecnt)
645 WaitSema(g_sema_id_init);
646 for ( i = 0; i < pagecnt; i += 1 )
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),
652 s147nand_16_getnandinfo()->m_page_size_noecc);
656 SignalSema(g_sema_id_init);
660int s147nand_8_multi_write_dma(
void *ptr,
int pageoffs,
int pagecnt)
667 for ( i = 0; i < pagecnt; i += 1 )
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),
673 s147nand_16_getnandinfo()->m_page_size_noecc);
680int s147nand_9_get_nand_partition(
int part)
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;
689static int get_nand_partition_offset(
int part)
691 return s147nand_9_get_nand_partition(part) * g_nand_header.m_pages_per_block;
694int s147nand_10_get_nand_partition_size(
int part)
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;
703static int nand_mdev_open_special(
iop_file_t *f,
const char *name)
713 Kprintf(
"s147nand.irx: AllocSysMemory failed (9:Open)\n");
719 privdat->m_seek_cur = 0;
720 if ( !strcmp(name,
"watchdog-enable") )
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");
730 else if ( !strcmp(name,
"acdelay") )
733 privdat->m_flags = 0;
734 privdat->m_seek_max = 0;
735 privdat->m_partition_offset = 0;
736 privdat->m_seek_cur = 0;
738 else if ( !strcmp(name,
"seccode") )
740 privdat->m_flags = 0x10000;
741 privdat->m_seek_max = 2;
742 privdat->m_partition_offset = 0;
743 privdat->m_seek_cur = 0;
745 else if ( !strcmp(name,
"videomode") )
747 privdat->m_flags = 0x40000;
748 privdat->m_seek_max = 4;
749 privdat->m_partition_offset = 0;
750 privdat->m_seek_cur = 0;
752 else if ( !strcmp(name,
"info") )
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;
759 else if ( !strcmp(name,
"romwrite-tmp") )
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;
776static int nand_mdev_read_special(
iop_file_t *f,
void *ptr,
int size)
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 )
788 retres1 = do_nand_sector_rw(ptr, privdata->m_partition_offset, privdata->m_seek_cur, size);
791 privdata->m_seek_cur += size;
794 if ( (privdata->m_flags & 0x1000000) != 0 )
796 retres1 = do_nand_sector_rw(ptr, privdata->m_partition_offset, privdata->m_seek_cur, size);
799 privdata->m_seek_cur += size;
805static int nand_mdev_write_special(
iop_file_t *f,
void *ptr,
int size)
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 )
816 if ( xsz < privdata->m_seek_cur + size )
818 Kprintf(
"s147nand.irx: Out of rewritable partition, lseek(%d) > max(%d)\n", privdata->m_seek_cur + size, xsz);
821 if ( (privdata->m_flags & 0x2000000) != 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;
833 if ( !g_nand_header.m_page_size_noecc )
835 if ( g_nand_header.m_page_size_noecc == -1 && privdata->m_seek_cur == (
int)0x80000000 )
837 if ( !g_nand_header.m_page_size_noecc )
839 if ( g_nand_header.m_page_size_noecc == -1 && size == (
int)0x80000000 )
841 retres1 = s147nand_8_multi_write_dma(
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);
847 privdata->m_seek_cur += size;
848 privdata->m_seek_max = privdata->m_seek_cur;
852static int do_nand_copy_seccode_from_buf(
iop_file_t *f,
void *ptr,
int size)
858 if ( privdata->m_seek_cur >= privdata->m_seek_max )
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;
867static int do_nand_copy_videomode_from_buf(
iop_file_t *f,
void *ptr,
int size)
873 if ( privdata->m_seek_cur >= privdata->m_seek_max )
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;
882int s147nand_11_erasetranslatepageoffs(
int pageoffs)
884 return s147nand_24_eraseoffset(s147nand_14_translate_pageoffs(pageoffs));
887int s147nand_12_load_logaddrtable(
void)
892 s147nand_20_nand_read_dma(&hdr, 0, 0,
sizeof(hdr));
893 if ( strncmp(hdr.m_sig,
"S147NAND", 9) )
895 Kprintf(
"s147nand.irx: Unformatted device error.\n");
899 g_logical_addr_tbl = (u16 *)AllocSysMemory(ALLOC_FIRST,
sizeof(u16) * hdr.m_block_size, 0);
901 s147nand_19_logaddr_read(g_logical_addr_tbl, 1,
sizeof(u16) * hdr.m_block_size);
903 g_nand_unaligned_buf = AllocSysMemory(ALLOC_FIRST, s147nand_16_getnandinfo()->m_page_size_noecc, 0);
905 if ( !g_nand_unaligned_buf )
907 Kprintf(
"s147nand.irx: AllocSysMemory failed (LogAddrTable)\n");
914int s147nand_13_translate_blockoffs(
int blockoffs)
918 if ( blockoffs <= 0 || blockoffs >= s147nand_16_getnandinfo()->m_block_size )
920 Kprintf(
"s147nand.irx: Invalid logical block address %d\n", blockoffs);
924 if ( !g_nand_unaligned_buf )
928 logaddrtable = s147nand_12_load_logaddrtable();
929 if ( logaddrtable < 0 )
932 tbladdr = g_logical_addr_tbl[blockoffs];
945int s147nand_14_translate_pageoffs(
int pageoffs)
949 tblockoffs = s147nand_13_translate_blockoffs(s147nand_28_pages2blocks(pageoffs));
950 if ( tblockoffs == -1470010 )
952 if ( !g_nand_header.m_pages_per_block )
954 if ( g_nand_header.m_pages_per_block == -1 && pageoffs == (
int)0x80000000 )
956 return s147nand_27_blocks2pages(tblockoffs) + (pageoffs % g_nand_header.m_pages_per_block);
959static int dev9_intr_handler(
void *unusd)
963 iWakeupThread(g_thid);
967int s147nand_15_nandinit(
void)
971 USE_IOP_MMIO_HWPORT();
978 sceDisableDMAChannel(IOP_DMAC_DEV9);
979 sceSetDMAPriority(IOP_DMAC_DEV9, 7);
980 sceEnableDMAChannel(IOP_DMAC_DEV9);
982 iop_mmio_hwport->ssbus2.ind_B_address = 0xB4000008;
984 semaparam.initial = 1;
986 semaparam.attr = SA_THPRI;
987 semaparam.option = 0;
988 g_sema_id_nand = CreateSema(&semaparam);
989 if ( g_sema_id_nand >= 0 )
991 printf(
"nand_Init: CreateSema error (%d)\n", g_sema_id_nand);
1000int s147nand_17_get_sema(
void)
1002 return g_sema_id_nand;
1005void s147nand_18_enable_nand_watchdog(
void)
1007 g_nand_watchdog_enabled = 1;
1010int s147nand_19_logaddr_read(u16 *tbl,
int pageoffs,
int bytecnt)
1015 pagecnt = s147nand_30_bytes2pagesnoeccround(bytecnt);
1016 for ( i = 0; i < pagecnt; i += 1 )
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);
1028int s147nand_20_nand_read_dma(
void *ptr,
int pageoffs,
int byteoffs,
int bytecnt)
1032 WaitSema(g_sema_id_nand);
1033 retres = nand_lowlevel_read_dma(ptr, pageoffs, byteoffs, bytecnt);
1034 SignalSema(g_sema_id_nand);
1038int s147nand_21_nand_read_pio(
void *ptr,
int pageoffs,
int byteoffs,
int bytecnt)
1043 WaitSema(g_sema_id_nand);
1045 retres = nand_lowlevel_read_pio(ptr, pageoffs, byteoffs, bytecnt);
1047 SignalSema(g_sema_id_nand);
1051int s147nand_22_nand_write_dma(
void *ptr,
int pageoffs,
int byteoffs,
int bytecnt)
1055 WaitSema(g_sema_id_nand);
1056 retres = nand_lowlevel_write_dma(ptr, pageoffs, byteoffs, bytecnt);
1057 SignalSema(g_sema_id_nand);
1061int s147nand_23_nand_write_pio(
void *ptr,
int pageoffs,
int byteoffs,
int bytecnt)
1066 WaitSema(g_sema_id_nand);
1068 retres = nand_lowlevel_write_pio(ptr, pageoffs, byteoffs, bytecnt);
1070 SignalSema(g_sema_id_nand);
1074int s147nand_24_eraseoffset(
int pageoffs)
1081 s147nand_21_nand_read_pio(
1083 s147nand_27_blocks2pages(s147nand_28_pages2blocks(pageoffs)) + 0,
1084 g_nand_info.m_page_size_noecc,
1086 s147nand_21_nand_read_pio(
1088 s147nand_27_blocks2pages(s147nand_28_pages2blocks(pageoffs)) + 1,
1089 g_nand_info.m_page_size_noecc,
1091 if ( val1 != 255 || val2 != 255 )
1093 WaitSema(g_sema_id_nand);
1095 retres = nand_lowlevel_blockerase(pageoffs);
1097 SignalSema(g_sema_id_nand);
1101int s147nand_25_nand_blockerase(
int pageoffs)
1106 WaitSema(g_sema_id_nand);
1108 retres = nand_lowlevel_blockerase(pageoffs);
1110 SignalSema(g_sema_id_nand);
1114int s147nand_26_nand_readid(
void *ptr)
1119 WaitSema(g_sema_id_nand);
1121 retres = nand_lowlevel_readid(ptr);
1123 SignalSema(g_sema_id_nand);
1127static int nand_lowlevel_read_dma(
void *ptr,
int pageoffs,
int byteoffs,
int bytecnt)
1130 USE_S147_DEV9_MEM_MMIO();
1131 USE_S147MAMD_DEV9_IO_MMIO();
1133 if ( pageoffs < 0 || pageoffs >= g_nand_info.m_page_count )
1135 if ( byteoffs < 0 || byteoffs >= g_nand_info.m_page_size_withecc )
1137 if ( bytecnt < 4 || g_nand_info.m_page_size_withecc < byteoffs + bytecnt )
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;
1149 while ( (s147nand_dev9_io_mmio->m_nand_waitflag & 1) != 0 )
1152 s147_dev9_mem_mmio->m_security_unlock_unlock = 0;
1153 sceSetSliceDMA(IOP_DMAC_DEV9, ptr, bytecnt >> 2, 1, 0);
1154 g_thid = GetThreadId();
1156 sceStartDMA(IOP_DMAC_DEV9);
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;
1164static int nand_lowlevel_read_pio(
void *ptr,
int pageoffs,
int byteoffs,
int bytecnt)
1167 USE_S147_DEV9_MEM_MMIO();
1168 USE_S147MAMD_DEV9_IO_MMIO();
1170 if ( pageoffs < 0 || pageoffs >= g_nand_info.m_page_count )
1172 if ( byteoffs < 0 || byteoffs >= g_nand_info.m_page_size_withecc )
1174 if ( bytecnt <= 0 || g_nand_info.m_page_size_withecc < byteoffs + bytecnt )
1176 while ( (s147nand_dev9_io_mmio->m_nand_waitflag & 1) != 0 )
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 )
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;
1196static int nand_lowlevel_write_dma(
void *ptr,
int pageoffs,
int byteoffs,
int bytecnt)
1200 USE_S147_DEV9_MEM_MMIO();
1201 USE_S147MAMD_DEV9_IO_MMIO();
1203 if ( pageoffs < 0 || pageoffs >= g_nand_info.m_page_count )
1205 if ( byteoffs < 0 || byteoffs >= g_nand_info.m_page_size_withecc )
1207 if ( bytecnt < 4 || g_nand_info.m_page_size_withecc < byteoffs + bytecnt )
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();
1222 sceStartDMA(IOP_DMAC_DEV9);
1224 s147nand_dev9_io_mmio->m_nand_cmd_sel = 0x10;
1225 while ( (s147nand_dev9_io_mmio->m_nand_waitflag & 1) != 0 )
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 )
1235 if ( (flgtmp & 1) != 0 )
1240static int nand_lowlevel_write_pio(
void *ptr,
int pageoffs,
int byteoffs,
int bytecnt)
1244 USE_S147_DEV9_MEM_MMIO();
1245 USE_S147MAMD_DEV9_IO_MMIO();
1247 if ( pageoffs < 0 || pageoffs >= g_nand_info.m_page_count )
1249 if ( byteoffs < 0 || byteoffs >= g_nand_info.m_page_size_withecc )
1251 if ( bytecnt <= 0 || g_nand_info.m_page_size_withecc < byteoffs + bytecnt )
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 )
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 )
1274 if ( (flgtmp & 1) != 0 )
1279static int nand_lowlevel_blockerase(
int pageoffs)
1282 USE_S147_DEV9_MEM_MMIO();
1283 USE_S147MAMD_DEV9_IO_MMIO();
1285 if ( pageoffs < 0 || pageoffs >= g_nand_info.m_page_count )
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 )
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 )
1304 if ( (flgtmp & 1) != 0 )
1309static int nand_lowlevel_readid(
void *ptr)
1312 USE_S147_DEV9_MEM_MMIO();
1313 USE_S147MAMD_DEV9_IO_MMIO();
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;
1328int s147nand_27_blocks2pages(
int blocks)
1330 return blocks * g_nand_info.m_pages_per_block;
1333int s147nand_28_pages2blocks(
int pages)
1335 if ( !g_nand_info.m_pages_per_block )
1337 if ( g_nand_info.m_pages_per_block == -1 && pages == (
int)0x80000000 )
1339 return pages / g_nand_info.m_pages_per_block;
1342int s147nand_29_pages2blockround(
int pages)
1346 if ( !g_nand_info.m_pages_per_block )
1348 if ( g_nand_info.m_pages_per_block == -1 && pages == (
int)0x80000000 )
1350 if ( !g_nand_info.m_pages_per_block )
1352 blocks = pages / g_nand_info.m_pages_per_block;
1353 if ( g_nand_info.m_pages_per_block == -1 && pages == (
int)0x80000000 )
1355 return blocks + ((pages % g_nand_info.m_pages_per_block) ? 1 : 0);
1358int s147nand_30_bytes2pagesnoeccround(
int bytes)
1362 if ( !g_nand_info.m_page_size_noecc )
1364 if ( g_nand_info.m_page_size_noecc == -1 && bytes == (
int)0x80000000 )
1366 if ( !g_nand_info.m_page_size_noecc )
1368 pages = bytes / g_nand_info.m_page_size_noecc;
1369 if ( g_nand_info.m_page_size_noecc == -1 && bytes == (
int)0x80000000 )
1371 return pages + ((bytes % g_nand_info.m_page_size_noecc) ? 1 : 0);
int CpuResumeIntr(int state)
int ReleaseIntrHandler(int irq)
int DisableIntr(int irq, int *res)
int CpuSuspendIntr(int *state)
int RegisterIntrHandler(int irq, int mode, int(*handler)(void *arg), void *arg)