📄 drvmmc.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 + -