cardinit.c 5.3 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)
u8	    __osBbCardMultiplane;
u8          __osBbCardChange = 1;
u8	    __osBbCardInit;
u16	    __osBbCardBlocks;
#define _EPI_DMA
#ifdef _EPI_DMA
static OSPiHandle __osBbCardHandler;
static OSMesgQueue __osBbCardDmaQ;
static OSMesg __osBbCardDmaBuf;
#define DEVICE_TYPE_PI	6
#endif


const struct {
    u8 mfg;
    u8 dev;
    u16 blocks;
    u32 config;
} __osBbCardConfig[] = {
    			/* default */
    { 0x0,  0x0,  0x0,  0x7  << PI_FLASH_CONFIG_EO_CYC_T_SHIFT |
	                0x5  << PI_FLASH_CONFIG_RD_SAM_T_SHIFT |
			0x3e << PI_FLASH_CONFIG_RE_ACT_T_SHIFT |
			0x3e << PI_FLASH_CONFIG_WE_ACT_T_SHIFT |
			0xff << PI_FLASH_CONFIG_CA_ACT_T_SHIFT } ,
    			/* Samsung K9F1208U0M */
    { 0xec, 0x76, 4096, 0x4  << PI_FLASH_CONFIG_EO_CYC_T_SHIFT |
	                0x4  << PI_FLASH_CONFIG_RD_SAM_T_SHIFT |
			0x1f << PI_FLASH_CONFIG_RE_ACT_T_SHIFT |
			0x1f << PI_FLASH_CONFIG_WE_ACT_T_SHIFT |
			0x3f << PI_FLASH_CONFIG_CA_ACT_T_SHIFT } ,
    			/* Samsung K9K1G08U0M */
    { 0xec, 0x79, 8192, 0x4  << PI_FLASH_CONFIG_EO_CYC_T_SHIFT |
	                0x4  << PI_FLASH_CONFIG_RD_SAM_T_SHIFT |
			0x1f << PI_FLASH_CONFIG_RE_ACT_T_SHIFT |
			0x1f << PI_FLASH_CONFIG_WE_ACT_T_SHIFT |
			0x3f << PI_FLASH_CONFIG_CA_ACT_T_SHIFT } ,
    			/* Toshiba TC58512FT */
    { 0x98, 0x76, 4096, 0x7  << PI_FLASH_CONFIG_EO_CYC_T_SHIFT |
	                0x5  << PI_FLASH_CONFIG_RD_SAM_T_SHIFT |
			0x3e << PI_FLASH_CONFIG_RE_ACT_T_SHIFT |
			0x1f << PI_FLASH_CONFIG_WE_ACT_T_SHIFT |
			0x3f << PI_FLASH_CONFIG_CA_ACT_T_SHIFT } ,
    			/* ST NAND512-A */
    { 0x20, 0x76, 4096, 0x4  << PI_FLASH_CONFIG_EO_CYC_T_SHIFT |
	                0x4  << PI_FLASH_CONFIG_RD_SAM_T_SHIFT |
			0x1f << PI_FLASH_CONFIG_RE_ACT_T_SHIFT |
			0x1f << PI_FLASH_CONFIG_WE_ACT_T_SHIFT |
			0x3f << PI_FLASH_CONFIG_CA_ACT_T_SHIFT } ,
			/* end of table */
    { 0xff, 0xff, 0x0,  0xff }
};

u32
__osBbCardPresent(void) {
    /* hook to detect that card has changed even when we aren't explicitly
     * performing a card operation
     */
    if (__osBbCardFlushEvent())
	__osBbCardChange = 1;
    return (IO_READ(MI_EINTR_REG)&MI_EINTR_MD_STATUS) != MI_EINTR_MODULE_REMOVED;
}

/* Access queue used for mutual exclusion on PI FLASH */
#define NUM_ACCESS_MESG		1
static OSMesg	cardAccessBuf[NUM_ACCESS_MESG];
OSMesgQueue	__osBbCardAccessQueue;

void
__osBbCardRelAccess(void) {
    (void)osSendMesg(&__osBbCardAccessQueue, (OSMesg)0, OS_MESG_NOBLOCK);
}

s32
__osBbCardGetAccess(void) {
    (void)osRecvMesg(&__osBbCardAccessQueue, NULL, OS_MESG_BLOCK);
    if (!__osBbCardPresent() || __osBbCardChange) {
	/* cancel */
	__osBbCardRelAccess();
	return __osBbCardPresent() ? BBCARD_ERR_CHANGED : BBCARD_ERR_NO_CARD;
    }
    return 0;
}


void
osBbCardInit(void) {
    u32 type, mfg;
    if (!__osBbCardInit) {
	osCreateMesgQueue(&__osBbCardAccessQueue, cardAccessBuf, NUM_ACCESS_MESG);
	/* Initialize the access queue with a resource token */
	(void)osSendMesg(&__osBbCardAccessQueue, (OSMesg)0, OS_MESG_NOBLOCK);
	__osBbCardInitEvent();
	IO_WRITE(MI_INTR_EMASK_REG, MI_INTR_MASK_SET_FLASH|MI_INTR_MASK_SET_MD);
#ifdef _EPI_DMA
	__osBbCardHandler.type = DEVICE_TYPE_PI;
	__osBbCardHandler.baseAddress = 0;
	__osBbCardHandler.latency = 0;
	__osBbCardHandler.pulse = 0;
	__osBbCardHandler.pageSize = /*512*/0; /*XXXblythe doesn't get used*/
	__osBbCardHandler.relDuration = 0;
	__osBbCardHandler.domain = 0;
	__osBbCardHandler.speed = 0;
	bzero((void *)&(__osBbCardHandler.transferInfo),
	    sizeof(__osBbCardHandler.transferInfo));
	osEPiLinkHandle(&__osBbCardHandler);
	osCreateMesgQueue(&__osBbCardDmaQ, &__osBbCardDmaBuf, 1);
#endif
	__osBbCardInit = 1;
    }
    IO_WRITE(PI_FLASH_CTRL_REG, 0);
    __osBbCardChange = 0;
    /* flush queue */
    /*XXXblythe should probably be mutexed*/
    (void)__osBbCardFlushEvent();
    if ((IO_READ(MI_EINTR_REG)&MI_EINTR_MD_STATUS) != MI_EINTR_MODULE_REMOVED) {
	u16 i;
	s32 rv;
	IO_WRITE(PI_FLASH_CONFIG_REG, __osBbCardConfig[0].config);
	if ((rv = osBbCardReadId(0, &mfg, &type)) < 0) {
#ifdef DEBUG
	    osSyncPrintf("Read id failed %d\n", rv);
#endif
    }
	for(i = 0; __osBbCardConfig[i].mfg != 0xff; i++) {
	    if (__osBbCardConfig[i].mfg == mfg && __osBbCardConfig[i].dev == type) {
		__osBbCardBlocks = __osBbCardConfig[i].blocks;
		IO_WRITE(PI_FLASH_CONFIG_REG, __osBbCardConfig[i].config);
		break;
	    }
	}
    } else
	__osBbCardBlocks = 0;
}

void
__osBbCardDmaCopy(u32 which, void *addr, u32 dir) {
#ifdef _EPI_DMA
    OSIoMesg m;
    m.hdr.pri = OS_MESG_PRI_NORMAL;
    m.hdr.retQueue = &__osBbCardDmaQ;
    m.dramAddr = addr;
    m.size = 512;
    m.devAddr = which*512;
    if (dir == OS_WRITE) osWritebackDCache(addr, 512);
    osEPiStartDma(&__osBbCardHandler, &m, dir);
    osRecvMesg(&__osBbCardDmaQ, NULL, OS_MESG_BLOCK);
    if (dir == OS_READ) osInvalDCache(addr, 512);
#else
    __osPiGetAccess();
    IO_WRITE(PI_CART_ADDR_REG, which*512);
    IO_WRITE(PI_DRAM_ADDR_REG, osVirtualToPhysical(addr));
    if (dir == OS_READ) {
	IO_WRITE(PI_DMA_BUFFER_WR_REG, 511);
	while(IO_READ(PI_STATUS_REG)&PI_STATUS_DMA_BUSY)
	    ;
	osInvalDCache(addr, 512);
    } else {
	osWritebackDCache(addr, 512);
	IO_WRITE(PI_DMA_BUFFER_RD_REG, 511);
	while(IO_READ(PI_STATUS_REG)&PI_STATUS_DMA_BUSY)
	    ;
    }
    __osPiRelAccess();
#endif
}