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

📄 mmc_core.c

📁 pxa270下的sd卡驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Core MMC driver functions * * Copyright 2002 Hewlett-Packard Company * * Use consistent with the GNU GPL is permitted, * provided that this copyright notice is * preserved in its entirety in all copies and derived works. * * HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED, * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS * FITNESS FOR ANY PARTICULAR PURPOSE. * * Many thanks to Alessandro Rubini and Jonathan Corbet! * * Author:  Andrew Christian *          6 May 2002 */#undef CONFIG_CEE#if defined(CONFIG_ARCH_OMAP) || defined(CONFIG_ARCH_MAINSTONE) || defined(CONFIG_ARCH_MX2ADS)#define CONFIG_CEE#endif#include <linux/config.h>#include <linux/module.h>#include <linux/version.h>#include <linux/proc_fs.h>#include <linux/init.h>#include <linux/interrupt.h>#include <linux/delay.h>#include <linux/list.h>#include <linux/sysctl.h>#include <linux/pm.h>#include "mmc_core.h"#define STATE_CMD_ACTIVE   (1<<0)#define STATE_CMD_DONE     (1<<1)#define STATE_INSERT       (1<<2)#define STATE_EJECT        (1<<3)static struct mmc_dev          g_mmc_dev;static struct proc_dir_entry  *proc_mmc_dir;#ifdef CONFIG_MMC_DEBUGint g_mmc_debug = CONFIG_MMC_DEBUG_VERBOSE;#elseint g_mmc_debug = 0;#endifEXPORT_SYMBOL(g_mmc_debug);/************************************************************************** * Debugging functions **************************************************************************/static char * mmc_result_strings[] = {	"NO_RESPONSE",	"NO_ERROR",	"ERROR_OUT_OF_RANGE",	"ERROR_ADDRESS",	"ERROR_BLOCK_LEN",	"ERROR_ERASE_SEQ",	"ERROR_ERASE_PARAM",	"ERROR_WP_VIOLATION",	"ERROR_CARD_IS_LOCKED",	"ERROR_LOCK_UNLOCK_FAILED",	"ERROR_COM_CRC",	"ERROR_ILLEGAL_COMMAND",	"ERROR_CARD_ECC_FAILED",	"ERROR_CC",	"ERROR_GENERAL",	"ERROR_UNDERRUN",	"ERROR_OVERRUN",	"ERROR_CID_CSD_OVERWRITE",	"ERROR_STATE_MISMATCH",	"ERROR_HEADER_MISMATCH",	"ERROR_TIMEOUT",	"ERROR_CRC",	"ERROR_DRIVER_FAILURE",};char * mmc_result_to_string( int i ){	return mmc_result_strings[i+1];}static char * card_state_strings[] = {	"empty",	"idle",	"ready",	"ident",	"stby",	"tran",	"data",	"rcv",	"prg",	"dis",};static inline char * card_state_to_string( int i ){	return card_state_strings[i+1];}/************************************************************************** * Utility functions **************************************************************************/#define PARSE_U32(_buf,_index) \	(((u32)_buf[_index]) << 24) | (((u32)_buf[_index+1]) << 16) | \        (((u32)_buf[_index+2]) << 8) | ((u32)_buf[_index+3]);#define PARSE_U16(_buf,_index) \	(((u16)_buf[_index]) << 8) | ((u16)_buf[_index+1]);int mmc_unpack_csd( struct mmc_request *request, struct mmc_csd *csd ){	u8 *buf = request->response;		if ( request->result ) return request->result;	csd->csd_structure      = (buf[1] & 0xc0) >> 6;	csd->spec_vers          = (buf[1] & 0x3c) >> 2;	csd->taac               = buf[2];	csd->nsac               = buf[3];	csd->tran_speed         = buf[4];	csd->ccc                = (((u16)buf[5]) << 4) | ((buf[6] & 0xf0) >> 4);	csd->read_bl_len        = buf[6] & 0x0f;	csd->read_bl_partial    = (buf[7] & 0x80) ? 1 : 0;	csd->write_blk_misalign = (buf[7] & 0x40) ? 1 : 0;	csd->read_blk_misalign  = (buf[7] & 0x20) ? 1 : 0;	csd->dsr_imp            = (buf[7] & 0x10) ? 1 : 0;	csd->c_size             = ((((u16)buf[7]) & 0x03) << 10) | (((u16)buf[8]) << 2) | (((u16)buf[9]) & 0xc0) >> 6;	csd->vdd_r_curr_min     = (buf[9] & 0x38) >> 3;	csd->vdd_r_curr_max     = buf[9] & 0x07;	csd->vdd_w_curr_min     = (buf[10] & 0xe0) >> 5;	csd->vdd_w_curr_max     = (buf[10] & 0x1c) >> 2;	csd->c_size_mult        = ((buf[10] & 0x03) << 1) | ((buf[11] & 0x80) >> 7);	switch ( csd->csd_structure ) {	case CSD_STRUCT_VER_1_0:	case CSD_STRUCT_VER_1_1:		csd->erase.v22.sector_size    = (buf[11] & 0x7c) >> 2;		csd->erase.v22.erase_grp_size = ((buf[11] & 0x03) << 3) | ((buf[12] & 0xe0) >> 5);		break;	case CSD_STRUCT_VER_1_2:	default:		csd->erase.v31.erase_grp_size = (buf[11] & 0x7c) >> 2;		csd->erase.v31.erase_grp_mult = ((buf[11] & 0x03) << 3) | ((buf[12] & 0xe0) >> 5);		break;	}	csd->wp_grp_size        = buf[12] & 0x1f;	csd->wp_grp_enable      = (buf[13] & 0x80) ? 1 : 0;	csd->default_ecc        = (buf[13] & 0x60) >> 5;	csd->r2w_factor         = (buf[13] & 0x1c) >> 2;	csd->write_bl_len       = ((buf[13] & 0x03) << 2) | ((buf[14] & 0xc0) >> 6);	csd->write_bl_partial   = (buf[14] & 0x20) ? 1 : 0;	csd->file_format_grp    = (buf[15] & 0x80) ? 1 : 0;	csd->copy               = (buf[15] & 0x40) ? 1 : 0;	csd->perm_write_protect = (buf[15] & 0x20) ? 1 : 0;	csd->tmp_write_protect  = (buf[15] & 0x10) ? 1 : 0;	csd->file_format        = (buf[15] & 0x0c) >> 2;	csd->ecc                = buf[15] & 0x03;	DEBUG(2,"  csd_structure=%d  spec_vers=%d  taac=%02x  nsac=%02x  tran_speed=%02x\n"	      "  ccc=%04x  read_bl_len=%d  read_bl_partial=%d  write_blk_misalign=%d\n"	      "  read_blk_misalign=%d  dsr_imp=%d  c_size=%d  vdd_r_curr_min=%d\n"	      "  vdd_r_curr_max=%d  vdd_w_curr_min=%d  vdd_w_curr_max=%d  c_size_mult=%d\n"	      "  wp_grp_size=%d  wp_grp_enable=%d  default_ecc=%d  r2w_factor=%d\n"	      "  write_bl_len=%d  write_bl_partial=%d  file_format_grp=%d  copy=%d\n"	      "  perm_write_protect=%d  tmp_write_protect=%d  file_format=%d  ecc=%d\n",	      csd->csd_structure, csd->spec_vers, 	      csd->taac, csd->nsac, csd->tran_speed,	      csd->ccc, csd->read_bl_len, 	      csd->read_bl_partial, csd->write_blk_misalign,	      csd->read_blk_misalign, csd->dsr_imp, 	      csd->c_size, csd->vdd_r_curr_min,	      csd->vdd_r_curr_max, csd->vdd_w_curr_min, 	      csd->vdd_w_curr_max, csd->c_size_mult,	      csd->wp_grp_size, csd->wp_grp_enable,	      csd->default_ecc, csd->r2w_factor, 	      csd->write_bl_len, csd->write_bl_partial,	      csd->file_format_grp, csd->copy, 	      csd->perm_write_protect, csd->tmp_write_protect,	      csd->file_format, csd->ecc);	switch (csd->csd_structure) {	case CSD_STRUCT_VER_1_0:	case CSD_STRUCT_VER_1_1:		DEBUG(2," V22 sector_size=%d erase_grp_size=%d\n", 		      csd->erase.v22.sector_size, 		      csd->erase.v22.erase_grp_size);		break;	case CSD_STRUCT_VER_1_2:	default:		DEBUG(2," V31 erase_grp_size=%d erase_grp_mult=%d\n", 		      csd->erase.v31.erase_grp_size,		      csd->erase.v31.erase_grp_mult);		break;			}	if ( buf[0] != 0x3f )  return MMC_ERROR_HEADER_MISMATCH;	return 0;}/* Wangzheng */int    sd_unpack_csd( struct mmc_request *request, struct sd_csd *csd ){	u8 *buf = request->response;		if ( request->result ) return request->result;	csd->csd_structure      = (buf[1] & 0xc0) >> 6;	csd->taac               = buf[2];	csd->nsac               = buf[3];	csd->tran_speed         = buf[4];	csd->ccc                = (((u16)buf[5]) << 4) | ((buf[6] & 0xf0) >> 4);	csd->read_bl_len        = buf[6] & 0x0f;	csd->read_bl_partial    = (buf[7] & 0x80) ? 1 : 0;	csd->write_blk_misalign = (buf[7] & 0x40) ? 1 : 0;	csd->read_blk_misalign  = (buf[7] & 0x20) ? 1 : 0;	csd->dsr_imp            = (buf[7] & 0x10) ? 1 : 0;	csd->c_size             = ((((u16)buf[7]) & 0x03) << 10) | (((u16)buf[8]) << 2) | (((u16)buf[9]) & 0xc0) >> 6;	csd->vdd_r_curr_min     = (buf[9] & 0x38) >> 3;	csd->vdd_r_curr_max     = buf[9] & 0x07;	csd->vdd_w_curr_min     = (buf[10] & 0xe0) >> 5;	csd->vdd_w_curr_max     = (buf[10] & 0x1c) >> 2;	csd->c_size_mult        = ((buf[10] & 0x03) << 1) | ((buf[11] & 0x80) >> 7);        csd->erase_blk_enable = (buf[11]&0x40)>>6;        csd->erase_sector_size = ((buf[11]&0x3f)<<1) | ((buf[12]&0x80)>>7);	csd->wp_grp_size = buf[12]&0x7f;	csd->wp_grp_enable = (buf[13]&0x80)>>7;	csd->r2w_factor         = (buf[13] & 0x1c) >> 2;	csd->write_bl_len       = ((buf[13] & 0x03) << 2) | ((buf[14] & 0xc0) >> 6);	csd->write_bl_partial   = (buf[14] & 0x20) ? 1 : 0;	csd->file_format_grp    = (buf[15] & 0x80) ? 1 : 0;	csd->copy               = (buf[15] & 0x40) ? 1 : 0;	csd->perm_write_protect = (buf[15] & 0x20) ? 1 : 0;	csd->tmp_write_protect  = (buf[15] & 0x10) ? 1 : 0;	csd->file_format        = (buf[15] & 0x0c) >> 2;	DEBUG(2,"  csd_structure=%d  spec_vers=%d  taac=%02x  nsac=%02x  tran_speed=%02x\n"	      "  ccc=%04x  read_bl_len=%d  read_bl_partial=%d  write_blk_misalign=%d\n"	      "  read_blk_misalign=%d  dsr_imp=%d  c_size=%d  vdd_r_curr_min=%d\n"	      "  vdd_r_curr_max=%d  vdd_w_curr_min=%d  vdd_w_curr_max=%d  c_size_mult=%d\n"	      "  erase_blk_enable=%d  erase_sector_size=%d  wp_grp_size=%d wp_grp_enable=%d r2w_factor=%d\n"	      "  write_bl_len=%d  write_bl_partial=%d  file_format_grp=%d  copy=%d\n"	      "  perm_write_protect=%d  tmp_write_protect=%d  file_format=%d\n",	      csd->csd_structure, csd->spec_vers, 	      csd->taac, csd->nsac, csd->tran_speed,	      csd->ccc, csd->read_bl_len, 	      csd->read_bl_partial, csd->write_blk_misalign,	      csd->read_blk_misalign, csd->dsr_imp, 	      csd->c_size, csd->vdd_r_curr_min,	      csd->vdd_r_curr_max, csd->vdd_w_curr_min, 	      csd->vdd_w_curr_max, csd->c_size_mult,	      csd->erase_blk_enable, csd->erase_sector_size,	      csd->wp_grp_size, csd->wp_grp_enable,	      csd->r2w_factor, 	      csd->write_bl_len, csd->write_bl_partial,	      csd->file_format_grp, csd->copy, 	      csd->perm_write_protect, csd->tmp_write_protect,	      csd->file_format);	if ( buf[0] != 0x3f )  return MMC_ERROR_HEADER_MISMATCH;	return 0;}int mmc_unpack_r1( struct mmc_request *request, struct mmc_response_r1 *r1, enum card_state state ){	u8 *buf = request->response;	if ( request->result )        return request->result;	r1->cmd    = buf[0];	r1->status = PARSE_U32(buf,1);	DEBUG(2," cmd=%d status=%08x\n", r1->cmd, r1->status);	if (R1_STATUS(r1->status)) {		if ( r1->status & R1_OUT_OF_RANGE )       return MMC_ERROR_OUT_OF_RANGE;		if ( r1->status & R1_ADDRESS_ERROR )      return MMC_ERROR_ADDRESS;		if ( r1->status & R1_BLOCK_LEN_ERROR )    return MMC_ERROR_BLOCK_LEN;		if ( r1->status & R1_ERASE_SEQ_ERROR )    return MMC_ERROR_ERASE_SEQ;		if ( r1->status & R1_ERASE_PARAM )        return MMC_ERROR_ERASE_PARAM;		if ( r1->status & R1_WP_VIOLATION )       return MMC_ERROR_WP_VIOLATION;		if ( r1->status & R1_CARD_IS_LOCKED )     return MMC_ERROR_CARD_IS_LOCKED;		if ( r1->status & R1_LOCK_UNLOCK_FAILED ) return MMC_ERROR_LOCK_UNLOCK_FAILED;		if ( r1->status & R1_COM_CRC_ERROR )      return MMC_ERROR_COM_CRC;		if ( r1->status & R1_ILLEGAL_COMMAND )    return MMC_ERROR_ILLEGAL_COMMAND;		if ( r1->status & R1_CARD_ECC_FAILED )    return MMC_ERROR_CARD_ECC_FAILED;		if ( r1->status & R1_CC_ERROR )           return MMC_ERROR_CC;		if ( r1->status & R1_ERROR )              return MMC_ERROR_GENERAL;		if ( r1->status & R1_UNDERRUN )           return MMC_ERROR_UNDERRUN;		if ( r1->status & R1_OVERRUN )            return MMC_ERROR_OVERRUN;		if ( r1->status & R1_CID_CSD_OVERWRITE )  return MMC_ERROR_CID_CSD_OVERWRITE;	}	if ( buf[0] != request->cmd ) return MMC_ERROR_HEADER_MISMATCH;	/* This should be last - it's the least dangerous error */	if ( R1_CURRENT_STATE(r1->status) != state ) return MMC_ERROR_STATE_MISMATCH;	return 0;}/* Wangzheng */int sd_unpack_r6( struct mmc_request *request, struct sd_response_r6 *r6, enum card_state state ){	u8 *buf = request->response;	if ( request->result )        return request->result;	r6->cmd    = buf[0];	r6->rca = PARSE_U16(buf,1);	r6->status = PARSE_U16(buf,3);	DEBUG(2," cmd=%d rca = %08x status=%08x\n", r6->cmd, r6->rca, r6->status);	if ( buf[0] != request->cmd ) return MMC_ERROR_HEADER_MISMATCH;	/* This should be last - it's the least dangerous error */	// if ( R1_CURRENT_STATE(r1->status) != state ) return MMC_ERROR_STATE_MISMATCH;	return 0;}int mmc_unpack_cid( struct mmc_request *request, struct mmc_cid *cid ){	u8 *buf = request->response;	int i;	if ( request->result ) return request->result;	cid->mid = buf[1];	cid->oid = PARSE_U16(buf,2);	for ( i = 0 ; i < 6 ; i++ )		cid->pnm[i] = buf[4+i];	cid->pnm[6] = 0;	cid->prv = buf[10];	cid->psn = PARSE_U32(buf,11);	cid->mdt = buf[15];		DEBUG(2," mid=%d oid=%d pnm=%s prv=%d.%d psn=%08x mdt=%d/%d\n",	      cid->mid, cid->oid, cid->pnm, 	      (cid->prv>>4), (cid->prv&0xf), 	      cid->psn, (cid->mdt>>4), (cid->mdt&0xf)+1997);	if ( buf[0] != 0x3f )  return MMC_ERROR_HEADER_MISMATCH;      	return 0;}/* Wangzheng */int sd_unpack_cid( struct mmc_request *request, struct sd_cid *cid ){	u8 *buf = request->response;	int i;	if ( request->result ) return request->result;	cid->mid = buf[1];	cid->oid = PARSE_U16(buf,2);	for ( i = 0 ; i < 5 ; i++ )		cid->pnm[i] = buf[4+i];	cid->pnm[5] = 0;	cid->prv = buf[10];	cid->psn = PARSE_U32(buf,10);	cid->mdt = (u16)((buf[14]&0xf)<<8) + buf[15] ;	

⌨️ 快捷键说明

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