www.pudn.com > s3c2440_kernel2.4.18_module_mmc.rar > mmc_cs.c


/*
 * drivers/mmc/mmc_cs.c
 *
 * MMC core service routines
 *
 * Copyright (C) 2001-2003 MIZI Research, Inc.
 *
 * Author: Yong-iL Joh 
 * $Id: mmc_cs.c,v 1.1.1.1 2004/01/19 13:24:45 laputa Exp $
 *
 * Revision History:
 *
 * 2001-XX-XX Yong-iL Joh 
 * - initial release
 *
 * 2002-07-25 Chan Gyun Jeong 
 * - code cleanup 
 * 
 * 2002-12-07 Chan Gyun Jeong 
 * - rough restructuring for S3C2410 SD Controller
 *
 * 2003-01-17 Chan Gyun Jeong 
 * - remove unused code
 *
 */

#include 
#include 
#include 
#include 
#include 

#include "mmc.h"

/*====================================================================*/
/* Data Conversion utilities */

void mmc_str2cid(CID_regs *regs, __u8 *buff)
{
	int i;

	regs->mid = buff[0];
	regs->oid = (buff[1] << 8) | (buff[2]);
	for(i=0; i < 6; i++)
		regs->pnm[i] = buff[3+i];
	regs->pnm[6] = '\0';
	regs->prv = buff[9];
	regs->psn = (buff[10] << 24) | (buff[11] << 16) | 
		(buff[12] << 8) | buff[13];
	regs->mdt = buff[14];
}

void mmc_str2csd(CSD_regs *regs, __u8 *buff)
{
	regs->csd		= (buff[0] & 0xc0) >> 6;
	regs->spec_vers		= (buff[0] & 0x3c) >> 2;
	(regs->taac).man	= (buff[1] & 0x78) >> 3;
	(regs->taac).exp	= (buff[1]) & 0x07;
	regs->nsac		= buff[2];
	(regs->tran_speed).man = (buff[3] & 0x78) >> 3;
	(regs->tran_speed).exp = (buff[3]) & 0x07;
	regs->ccc		= (buff[4] << 4) | ((buff[5] & 0xf0) >> 4);
	regs->read_len	= (buff[5] & 0x0f);
	regs->read_part	= (buff[6] & 0x80) ? 1 : 0;
	regs->write_mis	= (buff[6] & 0x40) ? 1 : 0;
	regs->read_mis	= (buff[6] & 0x20) ? 1 : 0;
	regs->dsr		= (buff[6] & 0x10) ? 1 : 0;
	regs->c_size		= ((buff[6] & 0x03) << 10) |
		(buff[7] << 2) | ((buff[8] & 0xc0) >> 6);
	regs->vcc_r_min	= (buff[8] & 0x38) >> 3;
	regs->vcc_r_max	= (buff[8] & 0x07);
	regs->vcc_w_min	= (buff[9] & 0xe0) >> 5;
	regs->vcc_w_max	= (buff[9] & 0x1c) >> 2;
	regs->c_size_mult = ((buff[9] & 0x03) << 1) | ((buff[10] & 0x80) >> 7);
	regs->er_size     = (buff[10] & 0x7c) >> 2;
	regs->er_grp_size = ((buff[10] & 0x03) << 3) | 
		((buff[11] & 0xe0) >> 5);
	regs->wp_grp_size = (buff[11] & 0x1f);
	regs->wp_grp_en	= (buff[12] & 0x80) ? 1 : 0;
	regs->dflt_ecc	= (buff[12] & 0x60) >> 5;
	regs->r2w_factor = (buff[12] & 0x1c) >> 2;
	regs->write_len  = ((buff[12] & 0x03) << 2) | ((buff[13] & 0xc0) >> 6);
	regs->write_part = (buff[13] & 0x20) ? 1 : 0;
	regs->ffmt_grp   = (buff[14] & 0x80) ? 1 : 0;
	regs->copy		= (buff[14] & 0x40) ? 1 : 0;
	regs->perm_wp		= (buff[14] & 0x20) ? 1 : 0;
	regs->tmp_wp		= (buff[14] & 0x10) ? 1 : 0;
	regs->ffmt		= (buff[14] & 0x0c) >> 2;
	regs->ecc	= (buff[14] & 0x03);
}

/*====================================================================*/
/* Information collecting functions */

void mmc_get_CSD_info(struct mmc_slot *slot, CSD_regs *csd) 
{
	/* read/write block size */
	slot->read_len	= 0x0001 << (csd->read_len);
	slot->write_len	= 0x0001 << (csd->write_len);

	if (slot->read_len != slot->write_len) {
		DEBUG2(1, "read_len(%u) and write_len(%u) are not equal\n",
		       slot->read_len, slot->write_len);
	}

	/* partial block read/write I/O support */
	if (csd->read_part) slot->stat |= MMC_READ_PART;
	if (csd->write_part) slot->stat |= MMC_WRITE_PART;

	if (csd->wp_grp_en) slot->stat |= MMC_WP_GRP_EN;
	if (csd->perm_wp) slot->stat |= MMC_PERM_WP;
	if (csd->tmp_wp) slot->stat |= MMC_TMP_WP;

	/* calculate total card size in bytes */
	slot->size = (1 + csd->c_size) * 
		(0x01 << (csd->c_size_mult + 2)) * slot->read_len;
}