文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>VIVI中MTD驱动的实现(2)

VIVI中MTD驱动的实现(2)

时间:2010-05-17  来源:charming2440

上面一章分析了MTD的实现(未完)接上文
在完成了函数的初始化以后则是调用smc_insert()函数,这个函数包括两个部分
inline int smc_insert(struct nand_chip *this);
1:smc_init()函数的功能就是调用smc_scan()函数
2:然后就是给this结构内部数据申请内存:this->data_buf = mmalloc(sizeof(u_char) *(mymtd->oobblock + mymtd->oobsize));
第2部分很好理解(在vivi的第5部分heap_init中有关于mmalloc函数的源代码)
现在来分析第一部分,smc_scan()函数
在分析smc_scan函数之前,我们先来看一个nsnd_flash_dev结构,这个结构定义了一些常用的nand flash的基本信息:
static struct nand_flash_dev nand_flash_ids[] = {
    {"Toshiba TC5816BDC",     NAND_MFR_TOSHIBA, 0x64, 21, 1, 2, 0x1000},    // 2Mb 5V
    {"Toshiba TC58V16BDC",    NAND_MFR_TOSHIBA, 0xea, 21, 1, 2, 0x1000},    // 2Mb 3.3V
    {"Toshiba TC5832DC",      NAND_MFR_TOSHIBA, 0x6b, 22, 0, 2, 0x2000},    // 4Mb 5V
    {"Toshiba TC58V32DC",     NAND_MFR_TOSHIBA, 0xe5, 22, 0, 2, 0x2000},    // 4Mb 3.3V
    {"Toshiba TC58V64AFT/DC", NAND_MFR_TOSHIBA, 0xe6, 23, 0, 2, 0x2000},    // 8Mb 3.3V
    {"Toshiba TH58V128DC",    NAND_MFR_TOSHIBA, 0x73, 24, 0, 2, 0x4000},    // 16Mb
    {"Toshiba TC58256FT/DC",  NAND_MFR_TOSHIBA, 0x75, 25, 0, 2, 0x4000},    // 32Mb
    {"Toshiba TH58512FT",     NAND_MFR_TOSHIBA, 0x76, 26, 0, 3, 0x4000},    // 64Mb
    {"Toshiba TH58NS100/DC",  NAND_MFR_TOSHIBA, 0x79, 27, 0, 3, 0x4000},    // 128Mb
    {"Samsung KM29N16000",    NAND_MFR_SAMSUNG, 0x64, 21, 1, 2, 0x1000},    // 2Mb 5V
    {"Samsung KM29W16000",    NAND_MFR_SAMSUNG, 0xea, 21, 1, 2, 0x1000},    // 2Mb 3.3V
    {"Samsung unknown 4Mb",   NAND_MFR_SAMSUNG, 0x6b, 22, 0, 2, 0x2000},    // 4Mb 5V
    {"Samsung KM29W32000",    NAND_MFR_SAMSUNG, 0xe3, 22, 0, 2, 0x2000},    // 4Mb 3.3V
    {"Samsung unknown 4Mb",   NAND_MFR_SAMSUNG, 0xe5, 22, 0, 2, 0x2000},    // 4Mb 3.3V
    {"Samsung KM29U64000",    NAND_MFR_SAMSUNG, 0xe6, 23, 0, 2, 0x2000},    // 8Mb 3.3V
    {"Samsung KM29U128T",     NAND_MFR_SAMSUNG, 0x73, 24, 0, 2, 0x4000},    // 16Mb
    {"Samsung KM29U256T",     NAND_MFR_SAMSUNG, 0x75, 25, 0, 2, 0x4000},    // 32Mb
    {"Samsung K9D1208V0M",    NAND_MFR_SAMSUNG, 0x76, 26, 0, 3, 0x4000},    // 64Mb
    {"Samsung K9D1G08V0M",    NAND_MFR_SAMSUNG, 0x79, 27, 0, 3, 0x4000},    // 128Mb
    {NULL,}
};
先来分析smc_scan(struct mtd_info *mtd)函数的基本流程:
smc_scan-->nand_select()
        -->nand_command(mtd, NAND_CMD_READID, 0x00, -1)
        -->this->wait_for_ready();等待flash设备准备好
        -->在找到于上面结构匹配的flash之后则是对mtd_info结构赋值
        -->nand_deselect();
        -->解析填充MTD driver中的数据
在知道了大概的流程和功能后我们来对每一个函数进行具体的分析:
一:nand_select();
这个函数是用一个宏来定义的,具体定义如下
#define nand_select() this->hwcontrol(NAND_CTL_SETNCE); \
                        nand_command(mtd, NAND_CMD_RESET, -1, -1); \
                        udelay(10);
这个宏定义其实就是调用了3个函数,
第一个函数我们在第一章里面就说明了,其实就是调用smc_hwcontrol(NAND_CTL_SETNCE)函数,作用就是enable the chip select
第二个函数调用:nand_command()函数,现来看看nand_command函数的原型:
(vivi/drivers/mtd/nand/smc_core.c)
/*
 * Send command to NAND device
 */
static void
nand_command(struct mtd_info *mtd, unsigned command, int column, int page_addr)
{
    register struct nand_chip *this = mtd->priv;

    /* Begin command latch cycle */
    this->hwcontrol(NAND_CTL_SETCLE);

    this->hwcontrol(NAND_CTL_DAT_OUT);

    /*  
     * Write out the command to the device.
     */
    if (command != NAND_CMD_SEQIN)
        this->write_cmd(command);
    else {
        if (mtd->oobblock == 256 && column >= 256) {
            column -= 256;
            this->write_cmd(NAND_CMD_RESET);
            this->write_cmd(NAND_CMD_READOOB);
            this->write_cmd(NAND_CMD_SEQIN);
        } else if (mtd->oobblock == 512 && column >= 256) {
            if (column < 512) {
                column -= 256;
                this->write_cmd(NAND_CMD_READ1);
                this->write_cmd(NAND_CMD_SEQIN);
            } else {
                column -= 512;
                this->write_cmd(NAND_CMD_READOOB);
                this->write_cmd(NAND_CMD_SEQIN);
            }   
        } else {
            this->write_cmd(NAND_CMD_READ0);
            this->write_cmd(NAND_CMD_SEQIN);
        }   
    }   

    /* Set ALE and clear CLE to start address cycle */
    this->hwcontrol(NAND_CTL_CLRCLE);
    this->hwcontrol(NAND_CTL_SETALE);

    /* Serially input address */
    if (column != -1)
        this->write_addr(column);
    if (page_addr != -1) {
        this->write_addr((u_char)(page_addr & 0xff));
        this->write_addr((u_char)((page_addr >> 8) & 0xff));
        /* One more address cycle for higher density devices */
        if (mtd->size & 0x0c000000) {
            this->write_addr((u_char)((page_addr >> 16) & 0xff));
        }
    }

    /* Latch in address */
    this->hwcontrol(NAND_CTL_CLRALE);

    this->hwcontrol(NAND_CTL_DAT_IN);
    /* Pause for 15us */
    udelay(15);
 }
从这里可以看出是使得nand_flash重启,
3):延时.
二:nand_command(mtd, NAND_CMD_READID, 0x00, -1);
从上面的nand_command函数的原型中可以看出,这个函数的目的就是读取nand flash的设备ID
三:this->wait_for_ready();
四:遍历常用nand flash结构数组,找到匹配的设备,并且初始化mtd_info 和 nand_chip结构
五:nand_deselect();
这个函数的原型也有一个宏定义;
#define nand_deselect() this->hwcontrol(NAND_CTL_CLRNCE)   //disable chip select
继续填充MTD drivers中的数据(初始化各种数据和函数)
下面是vivi中smc_scan(struct mtd_info *mtd)的原型
/*
 * Scan for the SMC device
 */
int
smc_scan(struct mtd_info *mtd)
{
    int i, nand_maf_id, nand_dev_id;
    struct nand_chip *this = mtd->priv;

    /* Select the device */
    nand_select();

    /* Send the command for reading device ID */
    nand_command(mtd, NAND_CMD_READID, 0x00, -1);

    this->wait_for_ready();

    /* Read manufacturer and device IDs */
    nand_maf_id = this->read_data();
    nand_dev_id = this->read_data();

    /* Print and sotre flash device information */
    for (i = 0; nand_flash_ids[i].name != NULL; i++) {
        if (nand_maf_id == nand_flash_ids[i].manufacture_id &&
            nand_dev_id == nand_flash_ids[i].model_id) {
#ifdef USE_256BYTE_NAND_FLASH
            if (!mtd->size) {
                mtd->name = nand_flash_ids[i].name;
                mtd->erasesize = nand_flash_ids[i].erasesize;
                mtd->size = (1 << nand_flash_ids[i].chipshift);
                mtd->eccsize = 256;
                if (nand_flash_ids[i].page256) {
                    mtd->oobblock = 256;
                    mtd->oobsize = 8;
                    this->page_shift = 8;
                } else {
                    mtd->oobblock = 512;
                    mtd->oobsize = 16;
                    this->page_shift = 9;
                }
                this->dev = &nand_smc_info[GET_DI_NUM(nand_flash_ids[i].chipshift)];
            }
#else
            if (!(mtd->size) && !(nand_flash_ids[i].page256)) {
                mtd->name = nand_flash_ids[i].name;
                mtd->erasesize = nand_flash_ids[i].erasesize;
                mtd->size = (1 << nand_flash_ids[i].chipshift);
                mtd->eccsize = 256;
                mtd->oobblock = 512;
                mtd->oobsize = 16;
                this->page_shift = 9;
                this->dev = &nand_smc_info[GET_DI_NUM(nand_flash_ids[i].chipshift)];
            }
#endif
            printk("NAND device: Manufacture ID:" \
                " 0x%02x, Chip ID: 0x%02x (%s)\n",
                nand_maf_id, nand_dev_id, mtd->name);
            break;
        }
    }

    /* De-select the device */
    nand_deselect();

    /* Print warning message for no device */
    if (!mtd->size) {
        printk("No NAND device found!!!\n");
        return 1;
    }

    /* Fill in remaining MTD driver data */
    mtd->type = MTD_NANDFLASH;
    mtd->flags = MTD_CAP_NANDFLASH | MTD_ECC;
    mtd->module = NULL;
    mtd->ecctype = MTD_ECC_SW;
    mtd->erase = nand_erase;
    mtd->point = NULL;
    mtd->unpoint = NULL;
    mtd->read = nand_read;
    mtd->write = nand_write;
    mtd->read_ecc = nand_read_ecc;
    mtd->write_ecc = nand_write_ecc;
    mtd->read_oob = nand_read_oob;
    mtd->write_oob = nand_write_oob;
    mtd->lock = NULL;
    mtd->unlock = NULL;

    /* Return happy */
    return 0;
}
这是函数的整体的概括,后面会陆续分析具体函数的实现。从来彻底了解在vivi中MTD中间驱动层的概念(未完,待续!)
相关阅读 更多 +
排行榜 更多 +
奥丘树海之下小米服手游下载

奥丘树海之下小米服手游下载

角色扮演 下载
网络天才国际服手游下载

网络天才国际服手游下载

休闲益智 下载
御剑红尘手游官方版下载

御剑红尘手游官方版下载

角色扮演 下载