扒完了 "字元設備" ,我們來看看平臺匯流排設備,平臺匯流排是Linux中的一種虛擬匯流排,我們知道, 匯流排+設備+驅動 是Linux驅動模型的三大組件,設計這樣的模型就是將驅動代碼和設備信息相分離,對於稍微複雜一點的驅動,都要使用這種結構,我在 ""Linux設備管理(一)_kobject, kset, ...
扒完了字元設備,我們來看看平臺匯流排設備,平臺匯流排是Linux中的一種虛擬匯流排,我們知道,匯流排+設備+驅動是Linux驅動模型的三大組件,設計這樣的模型就是將驅動代碼和設備信息相分離,對於稍微複雜一點的驅動,都要使用這種結構,我在"Linux設備管理(一)_kobject, kset,kobj_type分析"一文中提到過將一個設備或驅動掛載到匯流排就是將這個設備或驅動的kobject掛接到相應的匯流排kset下的設備kset或驅動kset中,本文就扒一扒內核中註冊一個平臺設備的源碼,驗證一下這個說法。整體的調用關係是:platform_device_register()->platform_device_add()->device_add()->kobject_add()
platform_device_register()
在平臺設備編程模型中,我們將我們數據封裝到一個platform_device結構中後,就可以將設備對象註冊到平臺匯流排上
platform_device_register()
--461--> device_initialize()初始化平臺設備的父類device結構
--463--> platform_device_add(pdev)將設備掛接到匯流排設備鏈表,即註冊
//drivers/base/platform.c
37 struct device platform_bus = {
38 .init_name = "platform",
39 };
459 int platform_device_register(struct platform_device *pdev)
460 {
461 device_initialize(&pdev->dev);
462 arch_setup_pdev_archdata(pdev);
463 return platform_device_add(pdev);
464 }
device_initialize()主要是對平臺設備的父類device結構進行一些初始化工作
device_initialize()
--702-->dev->kobj.kset = devices_kset;使用全局的devices_kset對象初始化設備的kset中
--703-->kobject_init(&dev->kobj, &device_ktype);使用全局的device_ktype對象初始化設備的kobj對應的kobj_type
--704-->INIT_LIST_HEAD(&dev->dma_pools);初始化設備list_head結構,用於後序的鏈接
//drivers/base/core.c
700 void device_initialize(struct device *dev)
701 {
702 dev->kobj.kset = devices_kset;
703 kobject_init(&dev->kobj, &device_ktype);
704 INIT_LIST_HEAD(&dev->dma_pools);
...
714 }
platform_device_add()
這個函數才開始真正把平臺設備對象掛接到平臺匯流排上
platform_device_add()
--353-->使新的設備的kobject->parent指向全局的平臺設備kobject對象
--355-->使設備的匯流排類型指針指向平臺匯流排對象
--403-->將設備掛接到相應的匯流排
//drivers/base/platform.c
345 int platform_device_add(struct platform_device *pdev)
346 {
347 int i, ret;
...
352 if (!pdev->dev.parent)
353 pdev->dev.parent = &platform_bus; //掛到平臺匯流排
354
355 pdev->dev.bus = &platform_bus_type;
...
403 ret = device_add(&pdev->dev);
404 if (ret == 0)
405 return ret;
...
421 }
device_add()
之前的工作已經準備好了一個平臺設備對象,接下來的工作就是將這個設備掛接到匯流排上,註冊任務就算完成了。
device_add()
--1074-->將設備的kobj掛接到之前填充好的parent的鏈表中,即平臺匯流排的鏈表。
//drivers/base/platform.c
1025 int device_add(struct device *dev)
1026 {
1027 struct device *parent = NULL;
1028 struct kobject *kobj;
1029 struct class_interface *class_intf;
1030 int error = -EINVAL;
1031
1032 dev = get_device(dev);
...
1071
1072 /* first, register with generic layer. */
1073 /* we require the name to be set before, and pass NULL */
1074 error = kobject_add(&dev->kobj, dev->kobj.parent, NULL);
...
1138 done:
1139 put_device(dev);
1140 return error;