769 lines
21 KiB
C
769 lines
21 KiB
C
/*
|
|
cartlib.c - Flash Linker Advance support for uCON64
|
|
|
|
Copyright (c) 2001 Jeff Frohwein
|
|
Copyright (c) 2002 - 2004 dbjh
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
|
|
#ifdef USE_PARALLEL
|
|
|
|
// *** GBA flash cart support routines in GCC ***
|
|
// This library allows programming FA/Visoly (both Turbo
|
|
// and non-Turbo) and official Nintendo flash carts. They
|
|
// can be used with the Flash Linker or can be called
|
|
// from GBA code to allow in-system flash cart programming.
|
|
// NOTE: ALL OF THESE ROUTINES MUST BE LOCATED IN GBA RAM
|
|
// IF THIS LIBRARY IS USED FOR IN-SYSTEM PROGRAMMING.
|
|
//
|
|
// by Jeff Frohwein, Started 2001-Aug-29
|
|
//
|
|
// v1.0 - 2001-Sept-25 - Original release
|
|
// v1.1 - 2001-Nov-13 - Slightly modified SetVisolyBackupRWMode by removing >>1.
|
|
//
|
|
// Routines -
|
|
//
|
|
// void SetFAFlashRWMode (void)
|
|
//
|
|
// Used to enable modifications of FA/Visoly cart flash chip(s)
|
|
// and also used for CartTypeDetect routine. YOU MUST CALL THIS
|
|
// ROUTINE BEFORE USING ANY OF THE OTHER FA/VISOLY ROUTINES.
|
|
//
|
|
// u8 CartTypeDetect (void)
|
|
// Return a value indicating type of cart installed:
|
|
// 0x00 = Hudson Cart, 0x2e = Standard ROM
|
|
// 0xe2 = N Flash Cart, 0xff = Unknown
|
|
// 0x17 = FA 64M, 0x96 = Turbo FA 64M
|
|
// 0x18 = FA 128M, 0x97 = Turbo FA 128M
|
|
//
|
|
// u32 EraseNintendoFlashBlocks (u32 StartAddr, u32 BlockCount)
|
|
//
|
|
// Erase official Nintendo flash cart blocks.
|
|
// Ex: EraseNintendoFlashBlocks (0x8000000, 1); // erase block 1
|
|
// EraseNintendoFlashBlocks (0x8010000, 2); // erase blocks 2 & 3
|
|
//
|
|
// u32 EraseNonTurboFABlocks (u32 StartAddr, u32 BlockCount)
|
|
//
|
|
// Erase older (non-Turbo) Visoly flash cart blocks.
|
|
// Ex: EraseNonTurboFABlocks (0x8000000, 1); // erase block 1
|
|
// EraseNonTurboFABlocks (0x8020000, 2); // erase blocks 2 & 3
|
|
//
|
|
// u32 EraseTurboFABlocks (u32 StartAddr, u32 BlockCount)
|
|
//
|
|
// Erase newer (Turbo) Visoly flash cart blocks.
|
|
// Ex: EraseTurboFABlocks (0x8000000, 1); // erase block 1
|
|
// EraseTurboFABlocks (0x8040000, 2); // erase blocks 2 & 3
|
|
//
|
|
// u32 WriteNintendoFlashCart (u32 SrcAddr, u32 FlashAddr, u32 Length)
|
|
//
|
|
// Write 2 x Length bytes to official Nintendo flash cart.
|
|
// Ex: WriteNintendoFlashCart (SrcAddr, 0x8000000, 2) // write 4 bytes
|
|
//
|
|
// u32 WriteNonTurboFACart (u32 SrcAddr, u32 FlashAddr, u32 Length)
|
|
//
|
|
// Write 32 x Length bytes to older (non-Turbo) Visoly flash cart.
|
|
// Ex: WriteNonTurboFACart (SrcAddr, 0x8000000, 2) // write 64 bytes
|
|
//
|
|
// u32 WriteTurboFACart (u32 SrcAddr, u32 FlashAddr, u32 Length)
|
|
//
|
|
// Write 64 x Length bytes to newer (Turbo) Visoly flash cart.
|
|
// Ex: WriteTurboFACart (SrcAddr, 0x8000000, 2) // write 128 bytes
|
|
//
|
|
// To reduce the library size and remove support for any
|
|
// of the following types, comment out one or more of
|
|
// the following lines using //
|
|
#define NONTURBO_FA_SUPPORT 1 // Visoly Non-Turbo flash carts
|
|
#define TURBO_FA_SUPPORT 1 // Visoly Turbo flash carts
|
|
#define NOA_FLASH_CART_SUPPORT 1 // Official Nintendo flash carts
|
|
//#define SET_CL_SECTION 1 // Enable setting code section for cartlib
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
#ifdef TURBO_FA_SUPPORT
|
|
#define COMMON_FA_SUPPORT 1
|
|
#endif
|
|
#ifdef NONTURBO_FA_SUPPORT
|
|
#define COMMON_FA_SUPPORT 1
|
|
#endif
|
|
|
|
#ifdef FLINKER
|
|
// FLinker programming defines
|
|
#define _MEM_INC 1
|
|
#define FP_TIMEOUT1 0x4000
|
|
#define FP_TIMEOUT2 0x8000
|
|
#define FP_TIMEOUT3 0x80000
|
|
#define _CART_START 0
|
|
#define FLINKER_SET l40226c ()
|
|
#define READ_NTURBO_SR(a,b) WriteFlash (a, INTEL28F_READSR); \
|
|
outpb (SPPCtrlPort, 0); \
|
|
b = (PPReadWord() & 0xff)
|
|
#define READ_NTURBO_S(a) outpb (SPPCtrlPort, 0); \
|
|
a = (PPReadWord() & 0xff)
|
|
#define READ_TURBO_SR(a) WriteFlash (0, INTEL28F_READSR); \
|
|
PPWriteWord (INTEL28F_READSR); \
|
|
outpb (SPPCtrlPort, 0); \
|
|
a = PPReadWord() & 0xff; \
|
|
a += (PPReadWord() & 0xff) << 8
|
|
#define READ_TURBO_S(a) outpb (SPPCtrlPort, 0); \
|
|
a = PPReadWord() & 0xff; \
|
|
a += (PPReadWord() & 0xff) << 8
|
|
#define READ_TURBO_S2(a,b,c) outpb (SPPCtrlPort, 0); \
|
|
b = PPReadWord () & 0x80; \
|
|
c = PPReadWord () & 0x80
|
|
#define WRITE_FLASH_NEXT(a,b) PPWriteWord (b)
|
|
#define SET_CART_ADDR(a) SetCartAddr (a); \
|
|
l4021d0 (3)
|
|
#define CTRL_PORT_0 outpb (SPPCtrlPort, 0)
|
|
#define CTRL_PORT_1 outpb (SPPCtrlPort, 1)
|
|
|
|
void
|
|
WriteRepeat (int addr, int data, int count)
|
|
{
|
|
int i;
|
|
for (i = 0; i < count; i++)
|
|
WriteFlash (addr, data);
|
|
}
|
|
|
|
#else
|
|
// GBA in-system programming defines
|
|
#define _MEM_INC 2
|
|
#define FP_TIMEOUT1 0x4000 // Probably could be MUCH smaller
|
|
#define FP_TIMEOUT2 0x8000 // Probably could be MUCH smaller
|
|
#define FP_TIMEOUT3 0x80000 // Probably could be MUCH smaller
|
|
#define INTEL28F_BLOCKERASE 0x20
|
|
#define INTEL28F_CLEARSR 0x50
|
|
#define INTEL28F_CONFIRM 0xD0
|
|
#define INTEL28F_QUIRY 0x98
|
|
#define INTEL28F_READARRAY 0xff
|
|
#define INTEL28F_READSR 0x70
|
|
#define INTEL28F_RIC 0x90
|
|
#define INTEL28F_WRTOBUF 0xe8
|
|
|
|
#define SHARP28F_BLOCKERASE 0x20
|
|
#define SHARP28F_CONFIRM 0xD0
|
|
#define SHARP28F_WORDWRITE 0x10
|
|
#define SHARP28F_READARRAY 0xff
|
|
// typedef volatile unsigned char vu8;
|
|
// typedef volatile unsigned short int vu16;
|
|
// typedef volatile unsigned int vu32;
|
|
// typedef volatile unsigned long long int vu64;
|
|
|
|
// typedef unsigned char u8;
|
|
// typedef unsigned short int u16;
|
|
// typedef unsigned int u32;
|
|
// typedef unsigned long long int u64;
|
|
|
|
#define _CART_START 0x8000000
|
|
#define _BACKUP_START 0xe000000
|
|
#define FLINKER_SET {}
|
|
#define READ_NTURBO_SR(a,b) *(vu16 *)a = INTEL28F_READSR; \
|
|
b = *(vu16 *)a
|
|
#define READ_NTURBO_S(a) a = *(vu16 *)_CART_START
|
|
#define READ_TURBO_SR(a) *(vu16 *)_CART_START = INTEL28F_READSR; \
|
|
*(vu16 *)(_CART_START+2) = INTEL28F_READSR; \
|
|
a = *(vu16 *)_CART_START & 0xff; \
|
|
a += (*(vu16 *)(_CART_START+2) & 0xff) << 8
|
|
#define READ_TURBO_S(a) a = *(vu16 *)_CART_START & 0xff; \
|
|
a += (*(vu16 *)(_CART_START+2) & 0xff) << 8
|
|
#define READ_TURBO_S2(a,b,c) b = *(vu16 *)a & 0x80; \
|
|
c = *(vu16 *)(a+2) & 0x80
|
|
#define WRITE_FLASH_NEXT(a,b) WriteFlash (a, b)
|
|
#define SET_CART_ADDR(a) {}
|
|
#define CTRL_PORT_0 {}
|
|
#define CTRL_PORT_1 {}
|
|
#define CL_SECTION __attribute__ ((section (".iwram")))
|
|
|
|
#ifdef SET_CL_SECTION
|
|
// Prototypes to allow placing routines in any section
|
|
void
|
|
WriteFlash (u32 addr, u16 data)
|
|
CL_SECTION;
|
|
u16 ReadFlash (u32 addr) CL_SECTION;
|
|
void WriteRepeat (u32 addr, u16 data, u16 count) CL_SECTION;
|
|
void VisolyModePreamble (void) CL_SECTION;
|
|
void SetVisolyFlashRWMode (void) CL_SECTION;
|
|
void SetVisolyBackupRWMode (int i) CL_SECTION;
|
|
u8 CartTypeDetect (void) CL_SECTION;
|
|
u32 EraseNintendoFlashBlocks (u32 StartAddr, u32 BlockCount) CL_SECTION;
|
|
u32 EraseNonTurboFABlocks (u32 StartAddr, u32 BlockCount) CL_SECTION;
|
|
u32 EraseTurboFABlocks (u32 StartAddr, u32 BlockCount) CL_SECTION;
|
|
u32 WriteNintendoFlashCart (u32 SrcAddr, u32 FlashAddr,
|
|
u32 Length) CL_SECTION;
|
|
u32 WriteNonTurboFACart (u32 SrcAddr, u32 FlashAddr,
|
|
u32 Length) CL_SECTION;
|
|
u32 WriteTurboFACart (u32 SrcAddr, u32 FlashAddr, u32 Length) CL_SECTION;
|
|
#endif
|
|
|
|
void WriteFlash (u32 addr, u16 data)
|
|
{
|
|
*(vu16 *) addr = data;
|
|
}
|
|
|
|
u16
|
|
ReadFlash (u32 addr)
|
|
{
|
|
return (*(vu16 *) addr);
|
|
}
|
|
|
|
void
|
|
WriteRepeat (u32 addr, u16 data, u16 count)
|
|
{
|
|
u16 i;
|
|
for (i = 0; i < count; i++)
|
|
*(vu16 *) (_CART_START + (addr << 1)) = data;
|
|
}
|
|
#endif
|
|
|
|
#ifdef COMMON_FA_SUPPORT
|
|
void
|
|
VisolyModePreamble (void) // 402438
|
|
{
|
|
FLINKER_SET;
|
|
WriteRepeat (0x987654, 0x5354, 1);
|
|
WriteRepeat (0x12345, 0x1234, 500);
|
|
WriteRepeat (0x7654, 0x5354, 1);
|
|
WriteRepeat (0x12345, 0x5354, 1);
|
|
WriteRepeat (0x12345, 0x5678, 500);
|
|
WriteRepeat (0x987654, 0x5354, 1);
|
|
WriteRepeat (0x12345, 0x5354, 1);
|
|
WriteRepeat (0x765400, 0x5678, 1);
|
|
WriteRepeat (0x13450, 0x1234, 1);
|
|
WriteRepeat (0x12345, 0xabcd, 500);
|
|
WriteRepeat (0x987654, 0x5354, 1);
|
|
}
|
|
|
|
void
|
|
SetVisolyFlashRWMode (void)
|
|
{
|
|
VisolyModePreamble ();
|
|
WriteRepeat (0xf12345, 0x9413, 1);
|
|
}
|
|
|
|
void
|
|
SetVisolyBackupRWMode (int i) // 402550
|
|
{
|
|
VisolyModePreamble ();
|
|
WriteRepeat (0xa12345, i, 1);
|
|
}
|
|
#endif
|
|
|
|
// Cart Type Detect
|
|
// Return a value indicating type of cart installed:
|
|
// 0xdc = Hudson Cart, 0x2e = Standard ROM Cart
|
|
// 0xe2 = N Flash Cart, 0xff = Unknown
|
|
// 0x17 = FA 64M, 0x96 = Turbo FA 64M
|
|
// 0x18 = FA 128M, 0x97 = Turbo FA 128M
|
|
|
|
u8
|
|
CartTypeDetect (void)
|
|
{
|
|
u8 type = 0xff;
|
|
u16 Manuf, Device;
|
|
|
|
WriteFlash (_CART_START, INTEL28F_RIC); // Read Identifier codes from flash.
|
|
// Works for intel 28F640J3A & Sharp LH28F320BJE.
|
|
Manuf = ReadFlash (_CART_START);
|
|
Device = ReadFlash (_CART_START + _MEM_INC);
|
|
|
|
switch (Manuf)
|
|
{
|
|
case 0: // Hudson Cart
|
|
type = 0xdc;
|
|
break;
|
|
case 0x2e: // Standard ROM
|
|
type = (u8) Manuf;
|
|
break;
|
|
case 0x89: // Intel chips
|
|
switch (Device)
|
|
{
|
|
case 0x16: // i28F320J3A
|
|
case 0x17: // i28F640J3A
|
|
case 0x18: // i28F128J3A
|
|
type = (u8) Device;
|
|
break;
|
|
default:
|
|
// Check to see if this is a Visoly "Turbo" cart
|
|
Device = ReadFlash (_CART_START + _MEM_INC + _MEM_INC);
|
|
switch (Device)
|
|
{
|
|
case 0x16: // 2 x i28F320J3A
|
|
case 0x17: // 2 x i28F640J3A
|
|
case 0x18: // 2 x i28F128J3A
|
|
type = Device + 0x80;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case 0xb0: // Sharp chips
|
|
switch (Device)
|
|
{
|
|
case 0xe2:
|
|
type = (u8) Device;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
WriteFlash (_CART_START, INTEL28F_READARRAY); // Set flash to normal read mode
|
|
return type;
|
|
}
|
|
|
|
#ifdef NOA_FLASH_CART_SUPPORT
|
|
// Erase official Nintendo flash cart blocks
|
|
// Function returns true if erase was successful.
|
|
// Each block represents 64k bytes.
|
|
|
|
u32
|
|
EraseNintendoFlashBlocks (u32 StartAddr, u32 BlockCount)
|
|
{
|
|
int i = 0;
|
|
int j, k;
|
|
time_t starttime = time (NULL);
|
|
|
|
for (k = 0; k < (int) BlockCount; k++)
|
|
{
|
|
i = StartAddr + (k * 32768 * _MEM_INC);
|
|
|
|
do
|
|
{
|
|
READ_NTURBO_SR (i, j);
|
|
}
|
|
while ((j & 0x80) == 0);
|
|
WriteFlash (i, SHARP28F_BLOCKERASE); // Erase a 64k byte block
|
|
WriteFlash (i, SHARP28F_CONFIRM); // Comfirm block erase
|
|
ucon64_gauge (starttime, (k + 1) * 64 * 1024, BlockCount * 64 * 1024);
|
|
}
|
|
|
|
do
|
|
{
|
|
READ_NTURBO_SR (i, j);
|
|
}
|
|
while ((j & 0x80) == 0);
|
|
WriteFlash (i, SHARP28F_READARRAY); // Set normal read mode
|
|
return 1;
|
|
}
|
|
#endif
|
|
|
|
#ifdef NONTURBO_FA_SUPPORT
|
|
// Erase older (non-Turbo) FA/Visoly flash cart blocks
|
|
// (Single flash chip)
|
|
// Function returns true if erase was successful.
|
|
// Each block represents 128k bytes.
|
|
|
|
u32
|
|
EraseNonTurboFABlocks (u32 StartAddr, u32 BlockCount)
|
|
{
|
|
u16 k;
|
|
u16 Ready = 1;
|
|
u32 i = 0;
|
|
u32 Timeout;
|
|
time_t starttime = time (NULL);
|
|
|
|
for (k = 0; k < BlockCount; k++)
|
|
{
|
|
i = StartAddr + (k * 65536 * _MEM_INC);
|
|
|
|
Ready = 0;
|
|
Timeout = FP_TIMEOUT2;
|
|
|
|
while ((Ready == 0) && (Timeout != 0))
|
|
{
|
|
READ_NTURBO_SR (_CART_START, Ready);
|
|
Ready &= 0x80;
|
|
Timeout--;
|
|
}
|
|
|
|
if (Ready)
|
|
{
|
|
WriteFlash (i, INTEL28F_BLOCKERASE); // Erase a 128k byte block
|
|
Ready = 0;
|
|
Timeout = FP_TIMEOUT3;
|
|
|
|
while ((!Ready) && (Timeout != 0))
|
|
{
|
|
READ_NTURBO_S (Ready);
|
|
Ready = (Ready == 0x80);
|
|
Timeout--;
|
|
}
|
|
|
|
if (Ready)
|
|
{
|
|
WriteFlash (i, INTEL28F_CONFIRM); // Comfirm block erase
|
|
Ready = 0;
|
|
Timeout = FP_TIMEOUT3;
|
|
|
|
while ((!Ready) && (Timeout != 0))
|
|
{
|
|
READ_NTURBO_S (Ready);
|
|
Ready = (Ready == 0x80);
|
|
Timeout--;
|
|
}
|
|
|
|
if (Ready)
|
|
{
|
|
READ_NTURBO_SR (_CART_START, Ready);
|
|
Ready = (Ready == 0x80);
|
|
|
|
if (!Ready)
|
|
break;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
else
|
|
break;
|
|
ucon64_gauge (starttime, (k + 1) * 128 * 1024,
|
|
BlockCount * 128 * 1024);
|
|
}
|
|
|
|
if (!Ready)
|
|
{
|
|
WriteFlash (i, INTEL28F_CLEARSR); // Clear flash status register
|
|
}
|
|
|
|
WriteFlash (i, INTEL28F_READARRAY); // Set flash to normal read mode
|
|
WriteFlash (i, INTEL28F_READARRAY); // Set flash to normal read mode
|
|
|
|
return Ready != 0;
|
|
}
|
|
#endif
|
|
|
|
#ifdef TURBO_FA_SUPPORT
|
|
// Erase newer (Turbo) FA/Visoly flash cart blocks
|
|
// (Dual chip / Interleave)
|
|
// Function returns true if erase was successful.
|
|
// Each block represents 256k bytes.
|
|
|
|
u32
|
|
EraseTurboFABlocks (u32 StartAddr, u32 BlockCount)
|
|
{
|
|
u16 j, k;
|
|
u16 done1, done2;
|
|
u16 Ready = 1;
|
|
u32 i = 0;
|
|
u32 Timeout;
|
|
time_t starttime = time (NULL);
|
|
|
|
for (k = 0; k < BlockCount; k++)
|
|
{
|
|
i = StartAddr + (k * 131072 * _MEM_INC);
|
|
|
|
Ready = 0;
|
|
Timeout = FP_TIMEOUT2;
|
|
|
|
while ((!Ready) && (Timeout != 0))
|
|
{
|
|
READ_TURBO_SR (j);
|
|
Ready = (j == 0x8080);
|
|
Timeout--;
|
|
}
|
|
|
|
if (Ready)
|
|
{
|
|
done1 = 0;
|
|
done2 = 0;
|
|
Ready = 0;
|
|
Timeout = FP_TIMEOUT3;
|
|
|
|
while ((!Ready) && (Timeout != 0))
|
|
{
|
|
if (done1 == 0)
|
|
WriteFlash (i, INTEL28F_BLOCKERASE); // Erase a 128k byte block in flash #1
|
|
if (done2 == 0)
|
|
WriteFlash (i + _MEM_INC, INTEL28F_BLOCKERASE); // Erase a 128k byte block in flash #2
|
|
|
|
READ_TURBO_S2 (_CART_START, done1, done2);
|
|
Ready = ((done1 + done2) == 0x100);
|
|
|
|
Timeout--;
|
|
}
|
|
|
|
if (Ready)
|
|
{
|
|
WriteFlash (i, INTEL28F_CONFIRM); // Comfirm block erase in flash #1
|
|
WriteFlash (i + _MEM_INC, INTEL28F_CONFIRM); // Comfirm block erase in flash #2
|
|
|
|
Ready = 0;
|
|
Timeout = FP_TIMEOUT3;
|
|
j = 0;
|
|
|
|
while (((j & 0x8080) != 0x8080) && (Timeout != 0))
|
|
{
|
|
READ_TURBO_S (j);
|
|
Ready = (j == 0x8080);
|
|
|
|
Timeout--;
|
|
}
|
|
|
|
if (!Ready)
|
|
break;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
else
|
|
break;
|
|
ucon64_gauge (starttime, (k + 1) * 256 * 1024,
|
|
BlockCount * 256 * 1024);
|
|
}
|
|
|
|
if (!Ready)
|
|
{
|
|
WriteFlash (i, INTEL28F_CLEARSR);
|
|
WriteFlash (i + _MEM_INC, INTEL28F_CLEARSR);
|
|
}
|
|
|
|
WriteFlash (_CART_START, INTEL28F_READARRAY);
|
|
WriteFlash (_CART_START + _MEM_INC, INTEL28F_READARRAY);
|
|
WriteFlash (_CART_START, INTEL28F_READARRAY);
|
|
WriteFlash (_CART_START + _MEM_INC, INTEL28F_READARRAY);
|
|
|
|
return Ready != 0;
|
|
}
|
|
#endif
|
|
|
|
#ifdef NOA_FLASH_CART_SUPPORT
|
|
// Write 2 x Length bytes to official Nintendo flash cart.
|
|
// Function returns true if write was successful.
|
|
|
|
u32
|
|
WriteNintendoFlashCart (u32 SrcAddr, u32 FlashAddr, u32 Length)
|
|
{
|
|
int j;
|
|
int LoopCount = 0;
|
|
u16 *SrcAddr2 = (u16 *)
|
|
#ifdef __LP64__
|
|
(u64)
|
|
#endif
|
|
SrcAddr;
|
|
|
|
while (LoopCount < (int) Length)
|
|
{
|
|
do
|
|
{
|
|
READ_NTURBO_SR (FlashAddr, j);
|
|
}
|
|
while ((j & 0x80) == 0);
|
|
|
|
WriteFlash (FlashAddr, SHARP28F_WORDWRITE);
|
|
WriteFlash (FlashAddr, *SrcAddr2);
|
|
SrcAddr2 += 2;
|
|
FlashAddr += _MEM_INC;
|
|
LoopCount++;
|
|
}
|
|
|
|
do
|
|
{
|
|
READ_NTURBO_SR (FlashAddr, j);
|
|
}
|
|
while ((j & 0x80) == 0);
|
|
|
|
WriteFlash (_CART_START, SHARP28F_READARRAY);
|
|
// CTRL_PORT_0;
|
|
return 1;
|
|
}
|
|
#endif
|
|
|
|
#ifdef NONTURBO_FA_SUPPORT
|
|
// Write 32 x Length bytes to older (non-Turbo) FA/Visoly flash cart.
|
|
// Function returns true if write was successful.
|
|
|
|
u32
|
|
WriteNonTurboFACart (u32 SrcAddr, u32 FlashAddr, u32 Length)
|
|
{
|
|
int Ready = 0;
|
|
int Timeout = 0;
|
|
int LoopCount = 0;
|
|
u16 *SrcAddr2 = (u16 *)
|
|
#ifdef __LP64__
|
|
(u64)
|
|
#endif
|
|
SrcAddr;
|
|
|
|
while (LoopCount < (int) Length)
|
|
{
|
|
Ready = 0;
|
|
Timeout = FP_TIMEOUT1;
|
|
|
|
while ((Ready == 0) && (Timeout != 0))
|
|
{
|
|
WriteFlash (FlashAddr, INTEL28F_WRTOBUF);
|
|
READ_NTURBO_S (Ready);
|
|
Ready &= 0x80;
|
|
|
|
Timeout--;
|
|
}
|
|
|
|
if (Ready)
|
|
{
|
|
int i;
|
|
|
|
WriteFlash (FlashAddr, 15); // Write 15+1 16bit words
|
|
|
|
SET_CART_ADDR (FlashAddr);
|
|
|
|
for (i = 0; i < 16; i++)
|
|
{
|
|
WRITE_FLASH_NEXT (FlashAddr, *SrcAddr2);
|
|
SrcAddr2 += 2;
|
|
FlashAddr += _MEM_INC;
|
|
}
|
|
|
|
WRITE_FLASH_NEXT (FlashAddr, INTEL28F_CONFIRM);
|
|
|
|
Ready = 0;
|
|
Timeout = FP_TIMEOUT1;
|
|
|
|
while ((Ready == 0) && (Timeout != 0))
|
|
{
|
|
READ_NTURBO_SR (_CART_START, i);
|
|
Ready = i & 0x80;
|
|
|
|
Timeout--;
|
|
}
|
|
|
|
if (Ready)
|
|
{
|
|
if (i & 0x7f)
|
|
{
|
|
// One or more status register error bits are set
|
|
CTRL_PORT_1;
|
|
WriteFlash (0, INTEL28F_CLEARSR);
|
|
Ready = 0;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CTRL_PORT_1;
|
|
WriteFlash (0, INTEL28F_CLEARSR);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
|
|
LoopCount++;
|
|
}
|
|
WriteFlash (_CART_START, INTEL28F_READARRAY); // Set flash to normal read mode
|
|
WriteFlash (_CART_START, INTEL28F_READARRAY); // Set flash to normal read mode
|
|
return Ready != 0;
|
|
}
|
|
#endif
|
|
|
|
#ifdef TURBO_FA_SUPPORT
|
|
// Write 64 x Length bytes to newer (Turbo) FA/Visoly flash cart.
|
|
// Function returns true if write was successful.
|
|
|
|
u32
|
|
WriteTurboFACart (u32 SrcAddr, u32 FlashAddr, u32 Length)
|
|
{
|
|
int i, k;
|
|
int done1, done2;
|
|
int Timeout;
|
|
int Ready = 0;
|
|
int LoopCount = 0;
|
|
u16 *SrcAddr2 = (u16 *)
|
|
#ifdef __LP64__
|
|
(u64)
|
|
#endif
|
|
SrcAddr;
|
|
|
|
while (LoopCount < (int) Length)
|
|
{
|
|
done1 = 0;
|
|
done2 = 0;
|
|
Ready = 0;
|
|
Timeout = 0x4000;
|
|
|
|
while ((!Ready) && (Timeout != 0))
|
|
{
|
|
if (done1 == 0)
|
|
WriteFlash (FlashAddr, INTEL28F_WRTOBUF);
|
|
if (done2 == 0)
|
|
WriteFlash (FlashAddr + _MEM_INC, INTEL28F_WRTOBUF);
|
|
|
|
SET_CART_ADDR (FlashAddr);
|
|
READ_TURBO_S2 (FlashAddr, done1, done2);
|
|
|
|
Ready = ((done1 + done2) == 0x100);
|
|
|
|
Timeout--;
|
|
}
|
|
|
|
if (Ready)
|
|
{
|
|
WriteFlash (FlashAddr, 15); // Write 15+1 16bit words
|
|
WRITE_FLASH_NEXT (FlashAddr + _MEM_INC, 15); // Write 15+1 16bit words
|
|
|
|
SET_CART_ADDR (FlashAddr);
|
|
|
|
for (i = 0; i < 32; i++)
|
|
{
|
|
WRITE_FLASH_NEXT (FlashAddr, *SrcAddr2);
|
|
SrcAddr2 += 2;
|
|
FlashAddr += _MEM_INC;
|
|
}
|
|
WRITE_FLASH_NEXT (FlashAddr, INTEL28F_CONFIRM);
|
|
WRITE_FLASH_NEXT (FlashAddr + _MEM_INC, INTEL28F_CONFIRM);
|
|
|
|
Ready = 0;
|
|
Timeout = 0x4000;
|
|
k = 0;
|
|
|
|
while (((k & 0x8080) != 0x8080) && (Timeout != 0))
|
|
{
|
|
READ_TURBO_S (k);
|
|
Ready = (k == 0x8080);
|
|
|
|
Timeout--;
|
|
}
|
|
|
|
if (!Ready)
|
|
break;
|
|
}
|
|
else
|
|
break;
|
|
LoopCount++;
|
|
}
|
|
|
|
WriteFlash (_CART_START, INTEL28F_READARRAY);
|
|
CTRL_PORT_0;
|
|
WriteFlash (_CART_START + _MEM_INC, INTEL28F_READARRAY);
|
|
CTRL_PORT_0;
|
|
|
|
if (!Ready)
|
|
{
|
|
WriteFlash (_CART_START, INTEL28F_CLEARSR);
|
|
WriteFlash (_CART_START + _MEM_INC, INTEL28F_CLEARSR);
|
|
}
|
|
return Ready != 0;
|
|
}
|
|
#endif
|
|
|
|
#endif // USE_PARALLEL
|