carderase.c 2.94 KB
#include <ultra64.h>
#include "bcp.h"
#include "bbnand.h"
#include "bbfs.h"
#include "os_bbcard.h"
#include "bbint.h"
#include "piint.h"

#define VERBOSE(x)

static void
erase_block(u32 dev, u32 addr) {
    IO_WRITE(PI_FLASH_ADDR_REG, addr << (PI_FLASH_PAGE_ADDR_SHIFT+PI_FLASH_PAGE_PER_BLOCK_POW2));
    IO_WRITE(PI_FLASH_CTRL_REG, PI_FLASH_CTRL_START |
				0xe << PI_FLASH_CTRL_ADPH_SHIFT |
				NAND_CMD_ERASE_0 << PI_FLASH_CTRL_CMD_SHIFT |
				dev << PI_FLASH_CTRL_DEV_SHIFT |
				PI_FLASH_CTRL_MCMD);
    do {
	if (IO_READ(MI_EINTR_REG)&(MI_EINTR_MODULE_REMOVED)) return /*1*/;
    } while(IO_READ(PI_FLASH_CTRL_REG)&PI_FLASH_CTRL_BUSY);
    IO_WRITE(PI_FLASH_CTRL_REG, PI_FLASH_CTRL_START |
	    			PI_FLASH_CTRL_INTR |
				0x0 << PI_FLASH_CTRL_ADPH_SHIFT |
				NAND_CMD_ERASE_1 << PI_FLASH_CTRL_CMD_SHIFT |
				PI_FLASH_CTRL_WRDY |
				dev << PI_FLASH_CTRL_DEV_SHIFT);
}

static void
erase_blocks(u32 dev, const u16 addr[], u32 n) {
    do {
	IO_WRITE(PI_FLASH_ADDR_REG, addr[--n] << (PI_FLASH_PAGE_ADDR_SHIFT+PI_FLASH_PAGE_PER_BLOCK_POW2));
	IO_WRITE(PI_FLASH_CTRL_REG, PI_FLASH_CTRL_START |
				    0xe << PI_FLASH_CTRL_ADPH_SHIFT |
				    NAND_CMD_ERASE_0 << PI_FLASH_CTRL_CMD_SHIFT |
				    dev << PI_FLASH_CTRL_DEV_SHIFT |
				    PI_FLASH_CTRL_MCMD);
	do {
	    if (IO_READ(MI_EINTR_REG)&(MI_EINTR_MODULE_REMOVED)) return /*1*/;
	} while(IO_READ(PI_FLASH_CTRL_REG)&PI_FLASH_CTRL_BUSY);
    } while(n > 0);
    IO_WRITE(PI_FLASH_CTRL_REG, PI_FLASH_CTRL_START |
	    			PI_FLASH_CTRL_INTR |
				0x0 << PI_FLASH_CTRL_ADPH_SHIFT |
				NAND_CMD_ERASE_1 << PI_FLASH_CTRL_CMD_SHIFT |
				PI_FLASH_CTRL_WRDY |
				dev << PI_FLASH_CTRL_DEV_SHIFT);
}

s32
osBbCardEraseBlock(u32 dev, u16 block) {
    s32 rv;
    u8 tmp;
VERBOSE(osSyncPrintf("erase block %d\n", block));
    if ((rv = __osBbCardGetAccess()) < 0) return rv;
    erase_block(dev, block);
    if ((rv = __osBbCardWaitEvent()) < 0 || __osBbCardStatus(dev, &tmp, 0))
	rv = BBCARD_ERR_CHANGED;
    else if (tmp != (NAND_STATUS_CMD_PASS|NAND_STATUS_READY|NAND_STATUS_WRITE_OK))
	rv = BBCARD_ERR_FAIL;
    __osBbCardRelAccess();
    return rv;
}

#define BLOCK_PLANE(baddr)	((baddr)&3)
#define BLOCK_SEG(baddr)	((baddr)>>12)
s32
osBbCardEraseBlocks(u32 dev, const u16 block[], u32 n) {
    u32 i = 0;
    s32 rv;
    u8 tmp;
VERBOSE(osSyncPrintf("erase blocks %d %d\n", block[0], n));
    if ((rv = __osBbCardGetAccess()) < 0) return rv;
    while(i < n) {
	int j = i+1;
        u32 plane = 1 << BLOCK_PLANE(block[i]);
	u32 seg = BLOCK_SEG(block[i]);
	while(__osBbCardMultiplane && j < n) {
	    int p = 1 << BLOCK_PLANE(block[j]);
	    if ((p & plane) || seg != BLOCK_SEG(block[j])) break;
	    plane |= p;
	    j++;
	}
	erase_blocks(dev, block+i, j-i);
	if ((rv = __osBbCardWaitEvent()) < 0) goto error;
	i = j;
    }
    if (__osBbCardStatus(dev, &tmp, 0))
	rv = BBCARD_ERR_CHANGED;
    else if (tmp != (NAND_STATUS_CMD_PASS|NAND_STATUS_READY|NAND_STATUS_WRITE_OK))
	rv = BBCARD_ERR_FAIL;
error:
    __osBbCardRelAccess();
    return rv;
}