⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 drvmmc.c

📁 最近在國外網站抓到的作業系統 以Arm為基礎去開發的
💻 C
字号:
/*
 * Block driver for media (i.e., flash cards)
 *
 * Copyright (c) 2004 ASIC of SOUTHEAST UNIVERSITY
 *
 * Many thanks to PESIA!
 *
 * Based strongly on code by:
 *
 * Author: jzp
 *
 * Date  : $Date: 2004/12/22 10:02:10 $ 
 *
 * Versation : 1.0 $
 *          
 */
 
#include "mmccore.h" 
#include "mmcprotocal.h"
#include "pcdisk.h"

int g_busy = 0;
static UINT16 mmc_opencount = 0;

#define MMC_CFG_CARD_DELAY 10
#define MMC_CHK_STATUS_DELAY 10
#define MMCINIT  0x1FFF0000

static struct mmc_request g_req;

#if 0
/* SRC DEST SIZE */  /* NOT USED */
U32 DMA_CFG[3][3][3] = 
{
	/* SRC = 0x8 */
	{
		/* DEST = 0x8 */
		{ 
			0x01B, /* SIZE = 0x 4 */
			0x02D, /* SIZE = 0x 8 */
			0x03F, /* SIZE = 0x 16 */
		},
		/* DEST = 0x16 */
		{
			0xFFF, /* SIZE = 0x 4 */
			0x21D, /* SIZE = 0x 8 */
			0x22F, /* SIZE = 0x 16 */
		},
		/* DEST = 0x32 */
		{
			0xFFF, /* SIZE = 0x 4 */
			0xFFF, /* SIZE = 0x 8 */
			0x41F, /* SIZE = 0x 16 */
		},
	},

	/* SRC = 0x16 */
	{
		/* DEST = 0x8 */
		{ 
			0x06B, /* SIZE = 0x 4 */
			0x07D, /* SIZE = 0x 8 */
			0xFFF, /* SIZE = 0x 16 */
		},
		/* DEST = 0x16 */
		{
			0x25B, /* SIZE = 0x 4 */
			0x26D, /* SIZE = 0x 8 */
			0x27F, /* SIZE = 0x 16 */
		},
		/* DEST = 0x32*/
		{
			0x01B, /* SIZE = 0x 4 */
			0x02D, /* SIZE = 0x 8 */
			0x03F, /* SIZE = 0x 16 */
		},
	},

	/* SRC = 0x32 */
	{
		/* DEST = 0x8 */
		{ 
			0x01B, /* SIZE = 0x 4 */
			0x02D, /* SIZE = 0x 8 */
			0x03F, /* SIZE = 0x 16 */
		},
		/* DEST = 0x16 */
		{
			0x01B, /* SIZE = 0x 4 */
			0x02D, /* SIZE = 0x 8 */
			0x03F, /* SIZE = 0x 16 */
		},
		/* DEST = 0x32 */
		{
			0x01B, /* SIZE = 0x 4 */
			0x02D, /* SIZE = 0x 8 */
			0x03F, /* SIZE = 0x 16 */
		},
	}
};
#endif

static int mmc_init(void) 
{
	register int i;
	U32 *p = (U32*)(MMCINIT);
	
	for(i = 0; i < 0x100; i++){
		*(U32*)(p++) = 0xABCDEF;
	}

	return 0;
}

static int mmc_exit(void)
{
	return 0;
}

int mmc_open(UINT16 driveno)
{
	/* We don't use drive no. You could have multiple drives if wanted */
	driveno = driveno;

	/* mmc is useing now ,return; */
	if ( g_busy )
		return(NO);

	mmc_init( );

	mmc_opencount += 1;
	return(YES);

}

int  mmc_close(UINT16 driveno) 
{
	/* We don't use drive no. You could have multiple drives if wanted */
	driveno = driveno;
	
	if ( g_busy )
		return(NO);

	if (mmc_opencount)
		--mmc_opencount;

	mmc_exit();
	
	return(YES);
}

static int mmc_configure_card(int clkrate )
{
	register int i;

	*(RP)MMCC_STR_STP_CLK = 0X5;       
	for ( i = MMC_CFG_CARD_DELAY; i > 0; i--)  {;}
	
	*(RP)MMCC_CLK_RATE = clkrate;
	for ( i = MMC_CFG_CARD_DELAY; i > 0; i--)  {;}
	
	*(RP)MMCC_STR_STP_CLK =0XE ; 
	for ( i = MMC_CFG_CARD_DELAY; i > 0; i--)  {;}
}

static void check_mmccard_status( void )
{
	U32 retval;
	register int i;
	
	while(1){	
		*(RP)MMCC_ARG = 0x10000;  
		*(RP)MMCC_BLK_LEN = (U32)0;
		*(RP)MMCC_NOB = (U32)0;
		*(RP)MMCC_CMD_DAT_CONT= 0x85; 
		*(RP)MMCC_CMD = MMC_SEND_STATUS;  
		*(RP)MMCC_DAT_COUNT = (U32)0;  
		*(RP)MMCC_INT_MASK = (U32)0xF;

		while(1){
			for(i =0; i < MMC_CHK_STATUS_DELAY; i++) {;}
			
			retval = *(RP)MMCC_STATUS;
			if(retval & 0x00000800)
				break;
		}
	
		// read the card status and check if the card ready for data
		retval = *(RP)MMCC_RESPONSE3;  
		if( retval & R1_READY_FOR_DATA)
			break;
        }
}

static void HA_DMA_TRANS_RX(void)
{
	//Parameters Notes:
	//sourcewidth: byte/halfword/word
	//destwidth: byte/halfword/word
	//sourcesize:	1,4,8,16
	//channelnum:  0-5 general channel
	//transnum: number of to be transed data,by source data width
	//		
	//note: destsize is omitted,because sourcewidth*sourcesize
	//	      must=destwidth*destsize
	register U32 temp;
	register U32 addr;
	
	//These 4 temp regiser address rariable are used to replase registers
	//of registers of channel which is used now 

	addr = DMACbase + 0x1000 + 1*0x100;//src
	*(RP)addr = (U32)MMCC_READ_BUFER_ACCESS;
	
	//replase registers of channel to be used;
	addr += 4; //dest
	*(RP)addr = (U32)MMCINIT;

	//8th and 9th bit set to 1:srcadd and destadd are increasing during transaction;
	temp = (0x00000080 << 2) + 0x2;  
	temp <<= 12; //set trans number,10th--21bit,(<4k)
	//21th--10th bits determine total transcation data size;
	/* (srcwidth == 0x32)&&(destwidth == 0x32)&&(srcsize == 0x4) */
	temp += 0x49b;
	
	//19 transcation patterns altogether,change with sourcewith,destwith,
	//      sourcesize and destsize.
	//0th --7th bits determine which pattern is to be used;
	
	// Set the control register;
	addr += 8; //control
	*(RP)addr = temp;
	//Channel enable: memory-->memory,mask error interrupt and accomplishment
	//interrupt;DMAC control;transcation begin now;	
	addr += 4; //config
	*(RP)addr = 0x39d;

	temp = *(RP)addr;
}

static void HA_DMA_TRANS_TX(void)
{
	//Parameters Notes:
	//sourcewidth:	byte/halfword/word
	//destwidth:	byte/halfword/word
	//sourcesize:	1,4,8,16
	//channelnum:   0-5 general channel
	//transnum:	number of to be transed data,by source data width
	//		
	//note:		destsize is omitted,because sourcewidth*sourcesize
	//must=destwidth*destsize
	register U32 temp;
	register U32 addr;
	
	//These 4 temp regiser address rariable are used to replase registers
	//of registers of channel which is used now 

	addr = DMACbase + 0x1000 + 1*0x100;//src
	*(RP)addr = (U32)MMCINIT;
	
	//replase registers of channel to be used;
	addr += 4; //dest
	*(RP)addr = (U32)MMCC_WRITE_BUFER_ACCESS;
	
	//8th and 9th bit set to 1:srcadd and destadd are increasing during transaction;
	temp = (0x00000080 << 2) + 0x1;  
	//set trans number,10th--21bit,(<4k)
	//21th--10th bits determine total transcation data size;
	temp <<= 12;
	/* (srcwidth == 0x32)&&(destwidth == 0x32)&&(srcsize == 0x4) */
	temp += 0x49b;
	
	//19 transcation patterns altogether,change with sourcewith,destwith,
	//      sourcesize and destsize.
	//0th --7th bits determine which pattern is to be used;

	addr += 8; //control
	*(RP)addr = temp;
	//Channel enable: memory-->memory,mask error interrupt and accomplishment
	//interrupt;DMAC control;transcation begin now;	
	addr += 4; //config
	*(RP)addr = 0x381b;
	temp = *(RP)addr;
}

static void swap_data(U32 dst, U32 src)
{
	register char *psrc, *pdst, *q;
	register i;

	psrc = (char *)src;
	pdst = (char *)dst;
	
	for(i = 0; i < 128; i++){
		psrc += 3;
		q = psrc;

		*pdst++ = *q--;
		*pdst++ = *q--;
		*pdst++ = *q--;
		*pdst++ = *q--;
		
		psrc++;
	}
}

int  mmc_cmd_to_reg( struct mmc_request *request )
{    
	U32 status, value;
	U8 *pbuf;
	
	mmc_configure_card(0x7);	
	check_mmccard_status();
	mmc_configure_card(0x0);
   
	*(RP)MMCC_ARG = (U32)request->arg;
	*(RP)MMCC_BLK_LEN = (U32)request->block_len;
	*(RP)MMCC_NOB =  (U32)request->nob;

	if( request->cmd == MMC_READ_SINGLE_BLOCK )
		*(RP)MMCC_CMD_DAT_CONT= (U32)0x0000048d;
	else
		*(RP)MMCC_CMD_DAT_CONT= (U32)0x0000009d;

	*(RP)MMCC_DAT_COUNT  = (U32)0x00000200;
	*(RP)MMCC_INT_MASK = 0x0000000F; 

	pbuf = request->buffer;
	
	if( request->cmd == MMC_READ_SINGLE_BLOCK ){
		/* MMCC_READ_BUFER_ACCESS,MMCINIT,0x32,0x32,0x4,0x1,0x80 */
		HA_DMA_TRANS_RX();
		value = (U32)0x00001200;
	}else{
		swap_data(MMCINIT, (U32)pbuf);
		
		/* MMCINIT,MMCC_WRITE_BUFER_ACCESS,0X32,0X32,0X4,0X1,0X80 */
		HA_DMA_TRANS_TX();
		value = (U32)0x00002400;
	}

	//send it
	*(RP)MMCC_CMD =  (U32) request->cmd;	

	//waiting....
	do {
		status = *(RP)MMCC_STATUS;
		if ( status & value )
			break;
	}while(1);
	
	if( request->cmd == MMC_READ_SINGLE_BLOCK ){
		if(status&0x1000) 
			return 0;/*error*/
		
		swap_data((U32)pbuf, MMCINIT);
	}else{
		if(status&0x2000)
	 		return 0;/*error*/
	}
	
	return  1;/*ok*/
}

int mmc_io(U16 driveno, U32 block, void *buffer, U32 count,int reading)
{
	struct mmc_request *preq;
	int retval;
	U32 psr;

	if ( g_busy )
		return(NO);

	g_busy = 1;

	preq = &g_req;
	while (count--){
		preq->cmd = reading? MMC_READ_SINGLE_BLOCK : MMC_WRITE_BLOCK;
		preq->arg = (U32)(block << 9);
		preq->nob = 1;
		preq->block_len = 512;
		preq->buffer    = (U8*) buffer;

		psr = ent_cri();
		retval = mmc_cmd_to_reg( preq);
		ret_cri(psr);
		
		if ( retval == 0x0 ){
			g_busy = 0;
			return 0; /*NO*/
		}
	
		(U8*)buffer += 512;
		block ++;
	}	

	g_busy = 0;
	
	return 1; /*YES*/
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -