dahdi wctdm24xxp 驱动学习笔记

编程入门 行业动态 更新时间:2024-10-08 12:43:53

dahdi wctdm24xxp 驱动<a href=https://www.elefans.com/category/jswz/34/1770117.html style=学习笔记"/>

dahdi wctdm24xxp 驱动学习笔记

wctdm24xxp.c

//wctdm24xxp 驱动学习笔记static struct pci_driver wctdm_driver = {.name = "wctdm24xxp",.probe = wctdm_init_one,.remove = __devexit_p(wctdm_remove_one),.shutdown = wctdm_shutdown,.suspend = wctdm_suspend,.id_table = wctdm_pci_tbl,
};module_init(wctdm_init);
//驱动注册过程
wctdm_init
-> res = dahdi_pci_module(&wctdm_driver);-> pci_register_driver(&wctdm_driver);-> __pci_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)-> drv->driver.name = drv->name;    // drv->driver 是struct device_driver 结构drv->driver.bus = &pci_bus_type; // [1] bus里的match后面会用到drv->driver.owner = owner;       drv->driver.mod_name = mod_name; // [2]        return driver_register(&drv->driver);    -> ret = bus_add_driver(drv);-> error = driver_attach(drv);-> return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);-> __driver_attach-> if (!driver_match_device(drv, dev)) return 0-> return drv->bus->match ? drv->bus->match(dev, drv) : 1;-> if (!dev->driver) driver_probe_device(drv, dev);-> ret = really_probe(dev, drv);-> if (dev->bus->probe) {  //如果dev->bus里定义了probe函数,则用 dev->bus->proberet = dev->bus->probe(dev);if (ret)goto probe_failed;} else if (drv->probe) { //否则 看是否定义了drv->probe; 从上面[2]可以看出此处没有定义ret = drv->probe(dev);if (ret)goto probe_failed;}-> 展开dev->bus->probe 先看pci_bus_type struct bus_type pci_bus_type = {.name		= "pci",.match		= pci_bus_match,.uevent		= pci_uevent,.probe		= pci_device_probe,.remove		= pci_device_remove,.shutdown	= pci_device_shutdown,.dev_groups	= pci_dev_groups,.bus_groups	= pci_bus_groups,.drv_groups	= pci_drv_groups,.pm		= PCI_PM_OPS_PTR,};pci_device_probe(struct device *dev)-> error = __pci_device_probe(drv, pci_dev);-> error = pci_call_probe(drv, pci_dev, id);-> error = local_pci_probe(&ddi);-> rc = pci_drv->probe(pci_dev, ddi->id); // pci_drv 是struct pci_driver 结构-> 也就是最终调用的是wctdm_driver.probe
// PCI 设备注册过程
struct pci_dev *pci_scan_single_device(struct pci_bus *bus, int devfn) //(drivers/pci/probe.c)
{struct pci_dev *dev;dev = pci_get_slot(bus, devfn);if (dev) {pci_dev_put(dev);return dev;}dev = pci_scan_device(bus, devfn);if (!dev)return NULL;pci_device_add(dev, bus);return dev;
} 
-> pci_device_add(dev, bus);-> ret = device_add(&dev->dev);-> bus_probe_device(dev);-> ret = device_attach(dev);-> ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);-> __device_attach-> return driver_probe_device(drv, dev);-> ret = really_probe(dev, drv);-> ret = dev->bus->probe(dev);-> 到这里和前面一样了
//probe 函数分悉
.probe = wctdm_init_one
-> return __wctdm_init_one(pdev, ent);-> pci_set_drvdata(pdev, wc); // 将wc结构关联到pci_dev中wc->vb.pdev = pdev;ret = voicebus_init(&wc->vb, wc->board_name); //voicebus_initcreate_sysfs_files(wc); // voicebus_start(&wc->vb); //wctdm_init_span(wc, curspan, curchan, wc->desc->ports, 0, pos);//wctdm24xxp_analog_span_ops 在里面引用 -> wctdm_init_chan()wc->ddev = dahdi_create_device(); // 这里ddev包含一个新的struct device devdahdi_register_device(wc->ddev, &wc->vb.pdev->dev)-> ret = _dahdi_register_device(ddev, parent);-> ret = dahdi_sysfs_add_device(ddev, parent);-> struct device *const dev = &ddev->dev;dev->parent = parent;dev->bus = &dahdi_device_bus; //[3]ret = device_add(dev);  //这个是ddev->dev 也就是wc->ddev->dev-> 之后跟上面基本一样,不过这里dev->bus->probe 没有定义,drv也应该没有,所以不会再probestatic struct bus_type dahdi_device_bus = {.name = "dahdi_devices",.uevent         = device_uevent,#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0).dev_attrs = dahdi_device_attrs,#else.dev_groups = dahdi_device_groups,#endif-> list_for_each_entry(s, &ddev->spans, device_node)ret = _dahdi_assign_span(s, 0, 0, 1); -> res = span_sysfs_create(span);-> span_device->bus = &spans_bus_type;span_device->parent = &span->parent->dev;dev_set_name(span_device, "span-%d", span->spanno);dev_set_drvdata(span_device, span);span_device->release = span_release;res = device_register(span_device);for (x = 0; x < span->channels; x++) {res = chan_sysfs_create(span->chans[x]);}->  span = chan->span;devt = MKDEV(MAJOR(dahdi_channels_devt), chan->channo); dev = &chan->chan_device;memset(dev, 0, sizeof(*dev));dev->devt = devt; // 与dahdi_init 时cdev_add的dev进行关联dev->bus = &chan_bus_type;dev->parent = span->span_device;/** FIXME: the name cannot be longer than KOBJ_NAME_LEN*/dev_set_name(dev, "dahdi!chan!%03d!%03d", span->spanno, chan->chanpos);dev_set_drvdata(dev, chan);dev->release = chan_release;res = device_register(dev); //注册设备}
}; 

再来看 dahdi_base.c ,wctdm24xxp.c 要依赖这个模块(dahdi.ko)

// dahdi_fops 
static const struct file_operations dahdi_fops = {.owner   = THIS_MODULE,.open    = dahdi_open,.release = dahdi_release,
#ifdef HAVE_UNLOCKED_IOCTL.unlocked_ioctl  = dahdi_unlocked_ioctl,
#ifdef HAVE_COMPAT_IOCTLpat_ioctl = dahdi_ioctl_compat,
#endif
#else.ioctl   = dahdi_ioctl,
#endif.poll    = dahdi_poll,.read    = dahdi_no_read,.write   = dahdi_no_write,
};
//-------------------------------------------------------------------------------module_init(dahdi_init);
-> static int __init dahdi_init(void)-> res = dahdi_sysfs_init(&dahdi_fops);-> res = bus_register(&dahdi_device_bus); // [1] 注册busres = register_chrdev(DAHDI_MAJOR, "dahdi", dahdi_fops); //注册一个字符设备,暂时不明白用途    res = dahdi_sysfs_chan_init(dahdi_fops); // [2] sysfs_chan_init -> res = bus_register(&chan_bus_type); res = driver_register(&chan_driver);dahdi_class = class_create(THIS_MODULE, "dahdi"); // dahdi_class 被 fixed_devfiles_create 引用res = fixed_devfiles_create(); //Creates /dev/dahdi/{ctl,timer,channel,pseudo}res = alloc_chrdev_region(&dahdi_channels_devt,0,DAHDI_MAX_CHANNELS,"dahdi_channels");cdev_init(&dahdi_channels_cdev, fops); //dahdi_channels_devt 被 chan_sysfs_create 引用res = cdev_add(&dahdi_channels_cdev, dahdi_channels_devt,DAHDI_MAX_CHANNELS);-> res = bus_register(&spans_bus_type);  // [3] res = driver_register(&dahdi_driver); 

笔记:
1.wctdm24xxp.c (wctdm24xxp.ko)主要注册了一个PCI 驱动,驱动实现PCI 设备的probe 函数,当系统扫描到匹配的PCI设备时,会调用probe 函数。probe函数进行设备的初始化,生成可以供应用层进行文件操作的字符设备文件。
2.wctdm24xxp.ko 依赖于dahdi.ko (其实还依赖于voice_bus.ko),所以驱动安装时要先安装dahdi.ko ,dahdi.ko 创建好/dev/dahdi 下的一些文件,并分配好 dahdi_channels_cdev。

时光如梭,已经是2019年了,加油继续前行!

更多推荐

dahdi wctdm24xxp 驱动学习笔记

本文发布于:2024-03-12 02:23:41,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1730477.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:学习笔记   dahdi   wctdm24xxp

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!