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

📄 mss_sdio.c

📁 spi driver code one marve
💻 C
📖 第 1 页 / 共 2 页
字号:
/** @file if_sdio.c *  @brief This file contains SDIO IF (interface) module *  related functions. *  * (c) Copyright ?2003-2007, Marvell International Ltd.  * * This software file (the "File") is distributed by Marvell International  * Ltd. under the terms of the GNU General Public License Version 2, June 1991  * (the "License").  You may use, redistribute and/or modify this File in  * accordance with the terms and conditions of the License, a copy of which  * is available along with the File in the gpl.txt file or by writing to  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. * * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about  * this warranty disclaimer. * *//****************************************************Change log:	10/14/05: add Doxygen format comments 	01/05/06: add kernel 2.6.x support		  ****************************************************/#include <linux/config.h>#include <linux/module.h>#include <linux/sched.h>#include <linux/kernel.h> #include <linux/fs.h>     #include <linux/errno.h> #include <linux/types.h> #include <linux/fcntl.h> #include <linux/init.h>#include <linux/devfs_fs_kernel.h>#include <asm/system.h>#include <asm/uaccess.h>#include <asm/scatterlist.h>#include <linux/mm.h>
#include <asm/page.h>#include <linux/cdev.h>#include "mss_sdio.h"/* define Data block size for data Tx/Rx */#define CMMB_DATA_BLOCK_SIZE	512//#define	DEFAULT_DEBUG_MASK	    (0xffffffff & ~DBG_EVENT)#define SDIO_QUEUE_EXIT         (1 << 0)#define CMMB_FRAME_SIZE_MAX     131072				typedef struct{	struct cdev *cdev;	struct mss_card *card;	struct  class *sdio_class;	wait_queue_head_t wq;	unsigned char *databuf;	unsigned char *readp;	unsigned char *writep;	unsigned int  datalen;	unsigned int  flags;}sdio_dev;/********************************************************		Local Variables********************************************************///u32 drvdbg = DEFAULT_DEBUG_MASK;sdio_dev cmmb_dev;/********************************************************		Global Variables********************************************************//********************************************************		Local Functions********************************************************/static intsdio_rw(struct mss_card *card, u8 func, u32 reg, u32 blksz, u32 nob,        int opcode, u32 data, int rw){    struct mss_request mreq;    struct mss_rw_arg marg;    struct mss_rw_result mres;    struct scatterlist sg;    int ret;    memset(&mreq, 0x0, sizeof(mreq));    memset(&marg, 0x0, sizeof(marg));    memset(&mres, 0x0, sizeof(mres));    mreq.arg = &marg;    mreq.result = &mres;    mreq.card = card;    mreq.action = rw ? MSS_WRITE_MEM : MSS_READ_MEM;    marg.nob = nob;    marg.func = func;    marg.opcode = opcode;    marg.block_len = blksz;    marg.block = reg;    if (rw)        marg.val = data;    /* Read/Write one register */    if (blksz == 0 && nob == 1) {        marg.sg = NULL;        marg.sg_len = 0;    } else {        sg.page = virt_to_page((u8 *) data);        sg.offset = offset_in_page((u8 *) data);        sg.length = blksz * nob;        marg.sg = &sg;        marg.sg_len = 1;    }    ret = mss_send_request(&mreq);    if (ret) {        return -EIO;    }    if (blksz == 0 && nob == 1 && !rw)        *(u8 *) data = (u8) (mres.bytes_xfered);    return 0;}static inline intsdio_read_ioreg(struct mss_card *card, u8 func, u32 reg, u8 * data){    return sdio_rw(card, func, reg, 0, 1, 0, (u32) data, 0);}static inline intsdio_write_ioreg(struct mss_card *card, u8 func, u32 reg, u8 data){    return sdio_rw(card, func, reg, 0, 1, 0, data, 1);}static inline intsdio_read_iomem(struct mss_card *card, u8 func, u32 reg, u8 blockmode,                int opcode, u32 nob, u32 blksz, u8 * buf){    return sdio_rw(card, func, reg, blksz, nob, opcode, (u32) buf, 0);}static inline intsdio_write_iomem(struct mss_card *card, u8 func, u32 reg, u8 blockmode,                 int opcode, u32 nob, u32 blksz, u8 * buf){//      PRINTM(INFO, "iomem: func:%d, reg:%d, opcode:%d, nob:%d, blksz:%d\n", func, reg, opcode, nob, blksz);    return sdio_rw(card, func, reg, blksz, nob, opcode, (u32) buf, 1);}int sdio_media_read(void){    unsigned char lengthdata[3],tmp;    unsigned char *tmpbuf;    int len,readlen,i;    int ret;        ret = sdio_read_ioreg(cmmb_dev.card, FN1, FUNC1_DATA_COUNTER1_REG, &lengthdata[0]);    if (ret < 0)        return ret;    ret = sdio_read_ioreg(cmmb_dev.card, FN1, FUNC1_DATA_COUNTER2_REG, &lengthdata[1]);    if (ret < 0)        return ret;    ret = sdio_read_ioreg(cmmb_dev.card, FN1, FUNC1_DATA_COUNTER3_REG, &lengthdata[2]);    if (ret < 0)        return ret;    len = (lengthdata[2]<<16) + (lengthdata[1]<<8) + lengthdata[0];    if (len <= 0)        return 0;    //printk("read Functon 1 count register %x\n", len);        readlen = len;    while(readlen > CMMB_DATA_BLOCK_SIZE)    {        if (cmmb_dev.writep+CMMB_DATA_BLOCK_SIZE >= cmmb_dev.databuf+CMMB_FRAME_SIZE_MAX)//buffer end        {            //printk("into buffer end branch1\n");            tmpbuf = kzalloc(CMMB_DATA_BLOCK_SIZE, GFP_KERNEL);            if (tmpbuf == 0)            {                printk("kzalloc error\n");                goto ClearCounter;            }            ret = sdio_read_iomem(cmmb_dev.card, FN1, FUNC1_DATA_REG, BLOCK_MODE, FIXED_ADDRESS, 1, CMMB_DATA_BLOCK_SIZE, tmpbuf);            if (ret < 0)            {                printk("while read Functon 1 register FUNC1_DATA_REG error1\n");                kfree(tmpbuf);                goto ClearCounter;            }            else            {                i = cmmb_dev.databuf+CMMB_FRAME_SIZE_MAX-cmmb_dev.writep;                memcpy(cmmb_dev.writep, tmpbuf, i);                memcpy(cmmb_dev.databuf, tmpbuf+i, CMMB_DATA_BLOCK_SIZE-i);                cmmb_dev.writep = cmmb_dev.databuf+CMMB_DATA_BLOCK_SIZE-i;                readlen -= CMMB_DATA_BLOCK_SIZE;            }            kfree(tmpbuf);        }        else        {            ret = sdio_read_iomem(cmmb_dev.card, FN1, FUNC1_DATA_REG, BLOCK_MODE, FIXED_ADDRESS, 1, CMMB_DATA_BLOCK_SIZE, cmmb_dev.writep);            if (ret < 0)            {                printk("while read Functon 1 register FUNC1_DATA_REG error2\n");                goto ClearCounter;            }                        readlen -= CMMB_DATA_BLOCK_SIZE;            cmmb_dev.writep += CMMB_DATA_BLOCK_SIZE;        }    }            if (readlen > 0)    {        if (cmmb_dev.writep+readlen >= cmmb_dev.databuf+CMMB_FRAME_SIZE_MAX)        {            //printk("into buffer end branch2\n");            tmpbuf = kzalloc(readlen, GFP_KERNEL);            if (tmpbuf == 0)            {                printk("kzalloc error\n");                goto ClearCounter;            }            ret = sdio_read_iomem(cmmb_dev.card, FN1, FUNC1_DATA_REG, BLOCK_MODE, FIXED_ADDRESS, 1, readlen, tmpbuf);            if (ret < 0)            {                printk("while read Functon 1 register FUNC1_DATA_REG error3\n");            }            else            {                i = cmmb_dev.databuf+CMMB_FRAME_SIZE_MAX-cmmb_dev.writep;                memcpy(cmmb_dev.writep, tmpbuf, i);                memcpy(cmmb_dev.databuf, tmpbuf+i, readlen-i);                cmmb_dev.writep = cmmb_dev.writep+readlen-CMMB_FRAME_SIZE_MAX;            }            kfree(tmpbuf);        }        else        {            ret = sdio_read_iomem(cmmb_dev.card, FN1, FUNC1_DATA_REG, BLOCK_MODE, FIXED_ADDRESS, 1, readlen, cmmb_dev.writep);            if (ret < 0)            {                printk("read Functon 1 register FUNC1_DATA_REG error4 readlen %d\n",readlen);            }            else                cmmb_dev.writep += readlen;        }    }ClearCounter:    sdio_read_ioreg(cmmb_dev.card, FN1, FUNC1_INT_IDENTIFY_REG, &tmp);    sdio_write_ioreg(cmmb_dev.card, FN1, FUNC1_DATA_COUNTER1_REG, 0);    sdio_write_ioreg(cmmb_dev.card, FN1, FUNC1_DATA_COUNTER2_REG, 0);    sdio_write_ioreg(cmmb_dev.card, FN1, FUNC1_DATA_COUNTER3_REG, 0);    mss_set_sdio_int(cmmb_dev.card->slot->host, 1);        if (ret >= 0)        cmmb_dev.datalen += len;    return 0;}static int sdio_queue_thread(void *d){	DECLARE_WAITQUEUE(wait, current);	current->flags |= PF_MEMALLOC;	add_wait_queue(&cmmb_dev.wq, &wait);	do {		set_current_state(TASK_INTERRUPTIBLE);	    schedule();	    		if (cmmb_dev.flags & SDIO_QUEUE_EXIT)			break;			        if (signal_pending (current))             break;	    sdio_media_read();	} while (1);	remove_wait_queue(&cmmb_dev.wq, &wait);		return 0;}static int sdio_open(struct inode *inode, struct file *file){    unsigned char tmp;    int ret;        init_waitqueue_head(&cmmb_dev.wq);

⌨️ 快捷键说明

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