关闭

无法识别apacer CF(compact flash)

标签: flashstructidemodulefunctiontable
1515人阅读 评论(0) 收藏 举报
分类:

最近测试CF卡,发现apacer牌子的CF卡无法识别,于是跟踪原因 ,现把分析过程写下,以备参考。

kernel verison 2.6.25.8

在文件

linux-2.6.25.8/drivers/ide/legacy/ide-cs.c

里面注册 pcmcia driver,
static struct pcmcia_driver ide_cs_driver = {
    .owner        = THIS_MODULE,
    .drv        = {
        .name    = "ide-cs",
    },
    .probe        = ide_probe,
    .remove        = ide_detach,
    .id_table       = ide_ids,
};

static int __init init_ide_cs(void)
{
    return pcmcia_register_driver(&ide_cs_driver);
}


//pcmcia_register_driver 的实现。

在 linux-2.6.25.8/drivers/pcmcia/ds.c
int pcmcia_register_driver(struct pcmcia_driver *driver)
{
    int error;

    if (!driver)
        return -EINVAL;

    pcmcia_check_driver(driver);

    /* initialize common fields */
    driver->drv.bus = &pcmcia_bus_type;
    driver->drv.owner = driver->owner;
    spin_lock_init(&driver->dynids.lock);
    INIT_LIST_HEAD(&driver->dynids.list);

    ds_dbg(3, "registering driver %s\n", driver->drv.name);

    error = driver_register(&driver->drv);
    if (error < 0)
        return error;

    error = pcmcia_create_newid_file(driver);
    if (error)
        driver_unregister(&driver->drv);

    return error;

}


//pcmcia driver和device  对应bus 实现


struct bus_type pcmcia_bus_type = {
    .name = "pcmcia",
    .uevent = pcmcia_bus_uevent,
    .match = pcmcia_bus_match,
    .dev_attrs = pcmcia_dev_attrs,
    .probe = pcmcia_device_probe,
    .remove = pcmcia_device_remove,
    .suspend = pcmcia_dev_suspend,
    .resume = pcmcia_dev_resume,
};

//检查设备是否匹配
static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) {
 ................

    while (did && did->match_flags) {
        ds_dbg(3, "trying to match %s to %s\n", dev->bus_id,
               drv->name);
        if (pcmcia_devmatch(p_dev, did)) {
            ds_dbg(0, "matched %s to %s\n", dev->bus_id,
                   drv->name);
            return 1;
        }
        did++;
    }
....
}


//具体匹配函数,此函数会遍历 drivers/ide/legacy/ ide-cs.c 里面的 ide_ids


static inline int pcmcia_devmatch(struct pcmcia_device *dev,
                  struct pcmcia_device_id *did)
{

    if (did->match_flags & PCMCIA_DEV_ID_MATCH_MANF_ID) {
        if ((!dev->has_manf_id) || (dev->manf_id != did->manf_id))
            return 0;
    }

    if (did->match_flags & PCMCIA_DEV_ID_MATCH_CARD_ID) {
        if ((!dev->has_card_id) || (dev->card_id != did->card_id))
            return 0;
    }

    if (did->match_flags & PCMCIA_DEV_ID_MATCH_FUNCTION) {
        if (dev->func != did->function)
            return 0;
    }

    if (did->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID1) {
        if (!dev->prod_id[0])
            return 0;
        if (strcmp(did->prod_id[0], dev->prod_id[0]))
            return 0;
    }

    if (did->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID2) {
        if (!dev->prod_id[1])
            return 0;
        if (strcmp(did->prod_id[1], dev->prod_id[1]))
            return 0;
    }

    if (did->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID3) {
        if (!dev->prod_id[2])
            return 0;
        if (strcmp(did->prod_id[2], dev->prod_id[2]))
            return 0;
    }

    if (did->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID4) {
        if (!dev->prod_id[3])
            return 0;
        if (strcmp(did->prod_id[3], dev->prod_id[3]))
            return 0;
    }

    if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) {
        if (dev->device_no != did->device_no)
            return 0;
    }

    if (did->match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID) {
        if ((!dev->has_func_id) || (dev->func_id != did->func_id))
            return 0;

        /* if this is a pseudo-multi-function device,
         * we need explicit matches */
        if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO)
            return 0;
        if (dev->device_no)
            return 0;

        /* also, FUNC_ID matching needs to be activated by userspace
         * after it has re-checked that there is no possible module
         * with a prod_id/manf_id/card_id match.
         */
        ds_dbg(0, "skipping FUNC_ID match for %s until userspace "
               "interaction\n", dev->dev.bus_id);
        if (!dev->allow_func_id_match)
            return 0;
    }

    if (did->match_flags & PCMCIA_DEV_ID_MATCH_FAKE_CIS) {
        ds_dbg(0, "device %s needs a fake CIS\n", dev->dev.bus_id);
        if (!dev->socket->fake_cis)
            pcmcia_load_firmware(dev, did->cisfile);

        if (!dev->socket->fake_cis)
            return 0;
    }

    if (did->match_flags & PCMCIA_DEV_ID_MATCH_ANONYMOUS) {
        int i;
        for (i=0; i<4; i++)
            if (dev->prod_id[i])
                return 0;
        if (dev->has_manf_id || dev->has_card_id || dev->has_func_id)
            return 0;
    }

    dev->dev.driver_data = (void *) did;

    return 1;
}


//通过跟踪发现,apacer CF卡 无法匹配到任何的匹配方式,因为drivers/ide/legacy/ ide-cs.c 里面的 

ide_ids 没有对应的匹配项。


而通过如下命令
#cd /sys/devices/platform/pxa2xx-pcmcia/1.0/
#cat manf_id
0x00bf
#cat card_id

0x0001


可以查到device的 manufactute id 和 card id 可以查询出来。


故在static struct pcmcia_device_id ide_ids[] 添加如下一行

PCMCIA_DEVICE_MANF_CARD(0x00bf, 0x0001)

顺利实现匹配。目前需要进一步确认是否只有这种匹配方式,其它方式是否可行。



0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:143798次
    • 积分:1960
    • 等级:
    • 排名:千里之外
    • 原创:40篇
    • 转载:29篇
    • 译文:1篇
    • 评论:13条
    最新评论
    blog收藏