pci匯流排驅動及pci裝置驅動註冊
一、PCI匯流排註冊
1、pci匯流排註冊對應建構函式
static int __init pci_driver_init(void)
{
return bus_register(&pci_bus_type);
}
postcore_initcall(pci_driver_init);
#define postcore_initcall(fn) __define_initcall("2",fn)
#define __define_initcall(level,fn) \
static initcall_t __initcall_##fn __attribute_used__ \
__attribute__((__section__(".initcall" level ".init"))) = fn
start_kernel -->rest_init() -->kernel_init() --> do_basic_setup() -->do_initcalls()----》遍歷.initcall" level ".init,執行.initcall" level ".init對應的fn,最終pci_driver_init被執行
2、執行註冊
pci匯流排的ops結構體:
struct bus_type pci_bus_type = {
.name = "pci",
.match = pci_bus_match,
.hotplug = pci_hotplug,
.suspend = pci_device_suspend,
.resume = pci_device_resume,
.dev_attrs = pci_dev_attrs,
};
註冊pci驅動
int bus_register(struct bus_type * bus)
{
int retval;
retval = kobject_set_name(&bus->subsys.kset.kobj, "%s", bus->name); //設定pci_bus_type->subsys.kset.kobj->k_name為pci
subsys_set_kset(bus, bus_subsys); //pci_bus_type->subsys.kset.kobj.kset = &bus_subsys.kset (bus_subsys由buses_init調subsystem_register進行初始化)
retval = subsystem_register(&bus->subsys); //初始化X.kobj.entry、X.list連結串列頭部、將X.kobj->entry新增到X.kobj->kset->list,建立sys/bus目錄下pci目錄(X為pci_bus_type->subsys.kset)
kobject_set_name(&bus->devices.kobj, "devices");
bus->devices.subsys = &bus->subsys;
retval = kset_register(&bus->devices); //初始化X.kobj.entry、X.list連結串列頭部,X->kobj.parent為pci_bus_type->subsys.kset.kobj,建立sys/bus/pci目錄下devices目錄(X為pci_bus_type->devices)
kobject_set_name(&bus->drivers.kobj, "drivers");
bus->drivers.subsys = &bus->subsys;
bus->drivers.ktype = &ktype_driver;
retval = kset_register(&bus->drivers); //初始化X.kobj.entry、X.list連結串列頭部,X->kobj.parent為pci_bus_type->subsys.kset.kobj,建立sys/bus/pci目錄下drivers目錄(X為pci_bus_type->drivers)
.......
二、註冊pci裝置驅動
int pci_register_driver(struct pci_driver *drv)
{
int error;
/* initialize common driver fields */
drv->driver.name = drv->name;
drv->driver.bus = &pci_bus_type;
drv->driver.probe = pci_device_probe;
drv->driver.remove = pci_device_remove;
drv->driver.owner = drv->owner;
drv->driver.kobj.ktype = &pci_driver_kobj_type;
pci_init_dynids(&drv->dynids);
/* register with core */
error = driver_register(&drv->driver);
}
int driver_register(struct device_driver * drv)
{
INIT_LIST_HEAD(&drv->devices); //初始化pci裝置驅動的devices連結串列
init_MUTEX_LOCKED(&drv->unload_sem);
return bus_add_driver(drv);
}
int bus_add_driver(struct device_driver * drv)
{
struct bus_type * bus = get_bus(drv->bus);
int error = 0;
if (bus) {
pr_debug("bus %s: add driver %s\n", bus->name, drv->name);
error = kobject_set_name(&drv->kobj, "%s", drv->name); //設定drv->driver.kobj.name為pci裝置驅動名字
drv->kobj.kset = &bus->drivers; //drv->kobj.kset為pci_bus_type->drivers
error = kobject_register(&drv->kobj)); //初始化drv->kobj->entry連結串列、drv->kobj.parent為pci_bus_type->drivers->list,將drv->kobj->entry新增到pci_bus_type->drivers->list,以sys/bus/pci/drivers為目錄建立pci裝置驅動名的目錄
down_write(&bus->subsys.rwsem);
driver_attach(drv); //1、遍歷pci_bus_type->devices->list上的device調driver_probe_device,該函式調drv->driver.bus.match = &pci_bus_type.match =pci_bus_match將device的pci id與driver註冊的pci id進行匹配, 若匹配成功,調driver的probe函式
2、調device_bind_driver:dev->driver_list新增到dev->driver->devices,將sys/bus/pci/drivers/驅動名/pci_id與sys/bus/pci/devices/pci_id建立軟連結
注:subsys_initcall(pcibios_init)註冊pci初始化回撥,subsys_initcall也是__define_initcall的巨集定義,在系統初始化時回撥被呼叫,??該回撥執行pci_scan_bus進行pci裝置的bar空間讀取並新增裝置到pci_bus_type->devices->list??
up_write(&bus->subsys.rwsem);
module_add_driver(drv->owner, drv); //建立driver與module的軟連結
driver_add_attrs(bus, drv); //根據pci_dev_attrs建立軟連結
}
相關文章
- 【linux】驅動-6-匯流排-裝置-驅動Linux
- Linux驅動之I2C匯流排裝置以及驅動Linux
- PCI匯流排基本概念
- 基於匯流排裝置驅動模型的按鍵讀取驅動程式模型
- 【原創】Linux PCI驅動框架分析(一)Linux框架
- 【原創】Linux PCI驅動框架分析(二)Linux框架
- linux核心匯流排驅動模型-驅動篇Linux模型
- liunx驅動之字元裝置的註冊字元
- Windows驅動中的PCI, DMA, ISR, DPC, ScatterGater, MapRegsiter, CommonBuffer, ConfigSpaceWindows
- 字元裝置驅動 —— 字元裝置驅動框架字元框架
- 華清平臺匯流排驅動201208(不同平臺)
- PCIe掃盲——PCI匯流排的中斷和錯誤處理
- platform_driver驅動及裝置驅動匹配識別符號Platform符號
- Linux的匯流排-裝置-驅動三者之間的關係和框架的理解Linux框架
- linux nvidia驅動錯誤--NVRM: This PCI I/O region assigned to your NVIDIA device is invalidLinuxVRdev
- 驅動Driver-MISC雜項驅動裝置
- 【linux】驅動-7-平臺裝置驅動Linux
- LED字元裝置驅動字元
- Linux裝置驅動程式學習----1.裝置驅動程式簡介Linux
- 全志R16_SPI匯流排驅動的使用文件
- Linux驅動開發筆記(四):裝置驅動介紹、熟悉雜項裝置驅動和ubuntu開發雜項裝置DemoLinux筆記Ubuntu
- platform 裝置驅動實驗Platform
- 字元驅動裝置踩坑字元
- Linux驅動實踐:如何編寫【 GPIO 】裝置的驅動程式?Linux
- 05_雜項裝置驅動
- mtd裝置驅動(待學習)
- linux 裝置驅動基本概念Linux
- 在Linux中,什麼是裝置驅動程式?如何安裝和解除安裝裝置驅動程式?Linux
- windows驅動註冊中斷服務程式Windows
- 裝置驅動程式包可以刪除嗎 win10裝置驅動程式包能刪嗎Win10
- 非同步通知和MISC裝置驅動非同步
- linux裝置驅動編寫入門Linux
- iOS 裝置驅動 for windows 32&64iOSWindows
- 如何編寫一個簡單的Linux驅動(三)——完善裝置驅動Linux
- win10驅動未知裝置怎麼辦_win10裝置管理器驅動未知裝置處理方法Win10
- 無作業系統時的裝置驅動和有作業系統時的裝置驅動作業系統
- “訊息驅動、事件驅動、流 ”基礎概念解析事件
- 【Linux SPI】RFID RC522 裝置驅動Linux