------------------------------------------
出處:------------------------------------------
一:前言
platform匯流排是kernel中最近加入的一種虛擬匯流排.在近版的2.6kernel中,很多驅動都用platform改寫了.只有在分析完platform匯流排之後,才能繼續深入下去分析.在分析完sysfs和裝置驅動模型之後,這部份應該很簡單了.閒言少敘.步入正題.go.go!以下的源**分析是基於2.6.25的.
二:platform概貌
在分析源**之前,先在核心**中找乙個platform架構的驅動程式.下面以i8042晶元的驅動為例進行分析.
在linux-2.6.25/drivers/input/serio/i8042.c的intel 8042的初始化入口中,有以下**分段:
static int __init i8042_init(void)
err = platform_device_add(i8042_platform_device);
if (err)
goto err_free_device;……}
我們在上面的程式片段中看到,驅動程式先註冊了乙個platform device.然後又新增了乙個platform device.這裡就涉及到了platform的兩個最主要的操作,乙個裝置驅動註冊,乙個裝置註冊.
要了解platform匯流排的來龍去脈.得從它的初始化開始.
三:platform初始化
platform匯流排的初始化是在linux-2.6.25/drivers/base/platform.c中的platform_bus_init()完成的,**如下:
int __init platform_bus_init(void)
上面**中呼叫的子函式在<
接著,這段初始化**又建立了乙個名為「platform」的匯流排.
platform_bus_type的定義如下:
struct bus_type platform_bus_type = ;
我們知道,在bus_type中包含了諸如裝置與驅動匹配.hotplug事件等很多重要的操作.這些操作在分析platform裝置註冊與platform驅動註冊的時候依次分析.
四:platform device註冊
在intel 8042的驅動**中,我們看到註冊乙個platform device分為了兩部分,一部份是建立乙個platform device結構,另一部份是將其註冊到匯流排中.先來看第乙個介面.
struct platform_device *platform_device_alloc(const char *name, int id)
return pa ? &pa->pdev : null;
}這段**主要初始化了封裝在struct platform_object中的struct device.
struct platform_object結構定義如下:
struct platform_object ;
在定義中,定義name為乙個長度.所以,才有了platform_device_alloc()中分配struct platform_object的時候多加了名稱的長度:
pa = kzalloc(sizeof(struct platform_object) + strlen(name), gfp_kernel);
struct device結構如下:
struct platform_device ;
在這個結構裡封裝了struct device.struct resource. struct resource這個結構在此之前沒有接觸過,這個結構表示裝置所擁有的資源.即i/o埠或者是i/o對映記憶體.
platform_device_add()**分段分析如下:
int platform_device_add(struct platform_device *pdev)
if (p && insert_resource(p, r))
}如果裝置指定了它所擁有的資源,將這些資源分配給它.如果分配失敗,則失敗退出.從**中可以看出.如果struct resource的flags域被指定為ioresource_mem.則所表示的資源為i/o對映記憶體.如果指定為ioresource_io.則所表示的資源為i/o埠.
pr_debug("registering platform device '%s'. parent at %s\n",
pdev->dev.bus_id, pdev->dev.parent->bus_id);
ret = device_add(&pdev->dev);
if (ret == 0)
return ret;
failed:
while (--i >= 0)
if (pdev->resource[i].flags & (ioresource_mem|ioresource_io))
release_resource(&pdev->resource[i]);
return ret;
}device_add()已經很熟悉了吧.沒錯,它就是將裝置註冊到指定的bus_type.
在分析linux裝置模型的時候,曾說過.呼叫device_add()會產生乙個hotplug事件.platform device的hotplug與一般的device事件相比.它還要它所屬bus_type的uevent().對這個流程不熟悉的可以參照<< linux裝置模型深探》.platform device所屬的bus_type為platform_bus_type.它的uevent()介面**如下:
static int platform_uevent(struct device *dev, struct kobj_uevent_env *env)
上面的**很簡單,它就是在環境變數中新增一項modalias.
五:platform driver的註冊
在intel 8024的驅動**中看到.platform driver註冊的介面為:
int platform_driver_register(struct platform_driver *drv)
struct platform_driver主要封裝了struct device_driver結構.如下:
struct platform_driver ;
在這個介面裡,它指定platform driver的所屬匯流排.如果在struct platform_driver指定了各項介面的操作,就會為struct device_driver中的相應介面賦值.
不要被上面的platform_drv_***嚇倒了,它們其實很簡單,就是將struct device轉換為struct platform_device和struct platform_driver.然後呼叫platform_driver中的相應介面函式
最後, platform_driver_register()將驅動註冊到匯流排上.
這樣,匯流排上有裝置,又有驅動,就會進行裝置與匹配的過程,呼叫的相應介面為:
bus ->match --- > bus->probe/driver->probe (如果匯流排的probe操作不存在,就會呼叫裝置的probe介面).
這樣,我們又回到platform_bus_type中的各項操作了.
對應的match介面如下:
static int platform_match(struct device *dev, struct device_driver *drv)
從**中看出.如果要匹配成功,那麼裝置與驅動的名稱必須要一致.
platform_bus_type中沒有指定probe介面,所以,會轉至驅動的probe介面,在platform_driver_register()中.將其probe介面指定為了platform_drv_probe.這個函式又會將操作回溯到struct platform_driver的probe介面中.
到這裡,platform driver的註冊過程就會析完了.
六:小結
在本小節裡,我們以linux裝置模型為基礎.分析虛擬匯流排platform的架構.對其hotplug事件,以及裝置與驅動的匹配過程做了非常詳細的分析.這部份知識是我們深入理解具體裝置驅動的基礎.
linux裝置模型之kobject
kobject 結構 在linux核心裡,kobject是組成linux裝置模型的基礎,乙個kobject對應sysfs裡的 乙個目錄。從物件導向的角度來說,kobject可以看作是所有裝置物件的基類,因為c 語言並沒有物件導向的語法,所以一般是把kobject內嵌到其他結構體裡來實現類似的 作用,...
Linux驅動之裝置模型 3
4 小結 4.1 kobject,kset和ktype kobject,kset和ktype就三個結構體,但是卻很容易讓人混淆,是由於它們內部相互交織。l kobject,是裝置模型中的基本物件,包含了引用計數,父子關係,目錄項等,通常會嵌入到其它的資料結構中,使其也具有kobject的特性 l k...
Linux驅動之裝置模型 5
6 裝置 6.1 裝置 l linux裝置模型中每乙個裝置用device結構來表示 struct device 6.2 裝置屬性 l 裝置屬性由device attribute來表示 structdevice attribute device attr name,mode,show,store l ...