package yaffs2.platform.jop;
import yaffs2.utils.Yaffs1NANDInterfacePrimitives;
import yaffs2.utils.debug.communication.DebugSettings;
import com.jopdesign.sys.Native;
// XXX change to implement Yaffs1NANDInterface, add constructor for initialization
public class InternalNANDYaffs1NANDInterfacePrimitives implements Yaffs1NANDInterfacePrimitives
{
public static InternalNANDYaffs1NANDInterfacePrimitives instance =
new InternalNANDYaffs1NANDInterfacePrimitives();
static final int IO_NAND = 0x100000;
static final int CLE = 1; // command latch enable
static final int ALE = 2; // address latch enable
static final int RDY = 4; // ready signal
static final int COMMAND_ERASE = 0x60;
static final int COMMAND_ERASE_CONFIRM = 0xD0;
static final int COMMAND_PROGRAM = 0x80;
static final int COMMAND_PROGRAM_CONFIRM = 0x10;
static final int COMMAND_READA = 00;
static final int COMMAND_READB = 01;
static final int COMMAND_READC = 50;
static final int nPagesPerBlock = 32;
/**
*
* @return true if a Error is signalled by the error bit
*/
static boolean errorOccurred()
{
// 07: read status register command, 100000 address, 1 = A0 = CLE
Native.wrMem(0x70, IO_NAND+CLE/*0x100001*/);
// S0=error bit S6=controller inactive S7=wr protection S8=nReady/Busy Signal
return ((Native.rdMem(IO_NAND)&0x01) == 0x01) ? true : false;
}
/**
*
* waits until the nand is ready
*/
static void waitForNandReady(String msg)
{
int i = 0;
while(Native.rdMem(IO_NAND+RDY)==0) // wait if rdy signal is 0
{i++;}
}
/**
*
* writes data to nand at the address given
* returns true if error occurred
*/
public boolean writeChunkToNAND(int deviceGenericDevice,
int devicenDataBytesPerChunk, int chunkInNAND,
byte[] data, int dataIndex, byte[] spare, int spareIndex)
{
// TODO: data index is NOT used for the address!!!
// Set correct a0 and pointer
if (data != null) {
int column = 0, pointer = 0, addr0, addr1;
// (chunkInNAND % (PAGES_PER_BLOCK)) address in block
addr0 = (chunkInNAND % 32) & 0x1f;
// (chunkInNAND / (PAGES_PER_BLOCK) block address
addr0 = (addr0 & 0x1f) | (((chunkInNAND / 32) << 5) & 0xe0);
addr1 = ((chunkInNAND / 32) >>> 3) & 0xff;
Native.wrMem(pointer, IO_NAND + CLE); // pointer op.
Native.wrMem(COMMAND_PROGRAM, IO_NAND + CLE); // page program
// command
Native.wrMem(column, IO_NAND + ALE); // column address 0-7
Native.wrMem(addr0, IO_NAND + ALE); // page address 9-16
Native.wrMem(addr1, IO_NAND + ALE); // page address 17-24
for (int i = 0; i < devicenDataBytesPerChunk; i++)
Native.wrMem(data[dataIndex+i], IO_NAND + 0); // input data
Native.wrMem(COMMAND_PROGRAM_CONFIRM, IO_NAND + CLE); // confirm
// code,
waitForNandReady("data written.");
if (errorOccurred())
return false;
}
if (spare != null)
{
// waitForNandReady("data written."); shall we wait before writing?
int column = 0, pointer = 80, addr0, addr1;
// (chunkInNAND % (PAGES_PER_BLOCK)) address in block
addr0 = (chunkInNAND % 32) & 0x1f;
// (chunkInNAND / (PAGES_PER_BLOCK) block address
addr0 = (addr0 & 0x1f) | (((chunkInNAND / 32) << 5) & 0xe0);
addr1 = ((chunkInNAND / 32) >>> 3) & 0xff;
Native.wrMem(pointer, IO_NAND + CLE); // pointer op.
Native.wrMem(COMMAND_PROGRAM, IO_NAND + CLE); // page program command
Native.wrMem(column, IO_NAND + ALE); // column address 0-7
Native.wrMem(addr0, IO_NAND + ALE); // page address 9-16
Native.wrMem(addr1, IO_NAND + ALE); // page address 17-24
for (int i = 0; i < DebugSettings.SPARE_SERIALIZED_LENGTH /* XXX - 1 */; i++)
Native.wrMem(spare[spareIndex+i], IO_NAND + 0); // input data
Native.wrMem(COMMAND_PROGRAM_CONFIRM, IO_NAND + CLE); // confirm
// code,
waitForNandReady("spare written.");
if (errorOccurred())
return false;
}
return true;
}
public boolean eraseBlockInNAND(int deviceGenericDevice,
int devicenDataBytesPerChunk, int blockNumber)
{
int addr0 = (blockNumber & 0x07) << 5; // only A14-A26 matters: the block address
int addr1 = (blockNumber >>> 3) & 0xff;
/*
System.out.print("blockNumber: ");
System.out.println(blockNumber);
System.out.print("addr0: ");
System.out.println(Integer.toHexString(addr0));
System.out.print("addr1: ");
System.out.println(Integer.toHexString(addr1));
*/
Native.wrMem(COMMAND_ERASE, IO_NAND+CLE);
Native.wrMem(addr0, IO_NAND+ALE); // address 9-16
Native.wrMem(addr1, IO_NAND+ALE); // address 17-24
Native.wrMem(COMMAND_ERASE_CONFIRM, IO_NAND+CLE);
waitForNandReady("block erased.");
return !errorOccurred();
}
/*public byte[] readFromNAND(int chunkInNAND) */
public boolean readChunkFromNAND(int deviceGenericDevice,
int devicenDataBytesPerChunk, int chunkInNAND, byte[] data, int dataIndex,
byte[] spare, int spareIndex)
{
// TODO: data index is NOT used for the address!!!
// Set correct a0 and pointer
int column = 0, pointer = 0, addr0, addr1;
if (data != null) {
// (chunkInNAND % (PAGES_PER_BLOCK)) address in block
addr0 = (chunkInNAND % 32) & 0x1f;
// (chunkInNAND / (PAGES_PER_BLOCK) block address
addr0 = (addr0 & 0x1f) | (((chunkInNAND / 32) << 5) & 0xe0);
addr1 = ((chunkInNAND / 32) >>> 3) & 0xff;
Native.wrMem(pointer, IO_NAND + CLE); // Read A command
Native.wrMem(column, IO_NAND + ALE); // column address 0-7
Native.wrMem(addr0, IO_NAND + ALE); // page address 9-16
Native.wrMem(addr1, IO_NAND + ALE); // page address 17-24
// TODO conversion
waitForNandReady("data read.");
for (int i = 0; i < devicenDataBytesPerChunk /* XXX - 1 */; i++)
data[dataIndex+i] = (byte) (Native.rdMem(IO_NAND) & 0xff);
if (errorOccurred())
return false;
}
if (spare != null)
{
pointer = 80;
addr0 = (chunkInNAND % 32) & 0x1f;
addr0 = (addr0 & 0x1f) | (((chunkInNAND / 32) << 5) & 0xe0);
addr1 = ((chunkInNAND / 32) >>> 3) & 0xff;
Native.wrMem(pointer, IO_NAND + CLE); // Read A command
Native.wrMem(column, IO_NAND + ALE); // column address 0-7
Native.wrMem(addr0, IO_NAND + ALE); // page address 9-16
Native.wrMem(addr1, IO_NAND + ALE); // page address 17-24
waitForNandReady("spare read.");
for (int i = 0; i < DebugSettings.SPARE_SERIALIZED_LENGTH /* XXX - 1 */; i++)
spare[spareIndex+i] = (byte) (Native.rdMem(IO_NAND) & 0xff);
if (errorOccurred())
return false;
}
return true;
}
public boolean initialiseNAND(int deviceGenericDevice,
int devicenDataBytesPerChunk)
{
//CheckInit();
return true;
}
}