cardread.c 2.1 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)
u32 __osBbCardSbErr;

static void
read_page(u32 dev, u32 addr, u32 which_buf) {
    IO_WRITE(PI_FLASH_ADDR_REG, addr << PI_FLASH_PAGE_ADDR_SHIFT);
    IO_WRITE(PI_FLASH_CTRL_REG, PI_FLASH_CTRL_START |
	    			PI_FLASH_CTRL_INTR  |
	    			PI_FLASH_CTRL_RDPH  |
				0xf << PI_FLASH_CTRL_ADPH_SHIFT |
				0x0 << PI_FLASH_CTRL_CMD_SHIFT |
				PI_FLASH_CTRL_WRDY |
				which_buf << PI_FLASH_CTRL_BUF_SHIFT |
				dev << PI_FLASH_CTRL_DEV_SHIFT |
				PI_FLASH_CTRL_ECC |
				528);
}

s32
osBbCardReadBlock(u32 dev, u16 block, void* addr, void* spare) {
    u32 x, i, b = 0;
    s32 rv, db = 0;
VERBOSE(osSyncPrintf("read block %d\n", block));
#ifdef _DEBUG
    if ((u32)addr&15) return BBCARD_ERR_INVALID;
#endif
    if ((rv = __osBbCardGetAccess()) < 0) return rv;
    if (spare) ((u8*)spare)[BB_FL_BLOCK_STATUS_OFF] = 0xff;
    for(i = 0; i < BB_FL_BLOCK_PAGES; i++) {
	read_page(dev, BB_FL_BYTE_TO_PAGE(BB_FL_BLOCK_TO_BYTE(block)+i*BB_FL_PAGE_SIZE), b);
	if (i) {
	    __osBbCardDmaCopy(b^1, addr+BB_FL_PAGE_SIZE*(i-1), OS_READ);
	    if (spare) {
		u32 addr = PI_BUFFER_0_OOB_START+(b^1)*(PI_BUFFER_OOB_SIZE>>1);
		((u8*)spare)[BB_FL_BLOCK_STATUS_OFF] &= IO_READ(addr+4) >> 8;
	    }
	}
	if ((rv = __osBbCardWaitEvent()) < 0) goto error;
	if ((x = IO_READ(PI_FLASH_CTRL_REG)) & PI_FLASH_CTRL_DBERR) {
#ifdef _DEBUG
#if 0
osSyncPrintf("double bit error block %d (page %d)\n", block, i);
#endif
#endif
	    db = BBCARD_ERR_FAIL;
	    if (!spare || i == BB_FL_BLOCK_PAGES-1)
	    goto error;
	}
	if (x & PI_FLASH_CTRL_SBERR) 
	    __osBbCardSbErr++;
	b ^= 1;
    }
    __osBbCardDmaCopy(b^1, addr+BB_FL_PAGE_SIZE*(i-1), OS_READ);
error:
    if (spare) {
	u8 *p = spare;
	u32 addr = PI_BUFFER_0_OOB_START+(b^1)*(PI_BUFFER_OOB_SIZE>>1);
	for(i = 0; i < BB_FL_SPARE_SIZE/4; i++) {
	    u32 x = IO_READ(addr+4*i);
	    p[0] = x >> 24;
	    p[1] = x >> 16;
	    if (i == 1) p[2] &= x >> 8;
	    else p[2] = x >> 8;
	    p[3] = x;
	    p += 4;
	}
    }
    __osBbCardRelAccess();
    return db ? db : rv;
}