Fuchsia 驅動程式是可在驅動程式代管程序中動態載入的共用程式庫 建立使用者空間中的處理程序驅動程式庫的載入程序是由 。詳情請見 裝置型號 有關駕駛座、驅動程式管理器以及驅動程式庫和裝置的詳細資訊 生命週期
目錄結構
駕駛人或許可在來源樹狀結構的 driver
子目錄中找到
指定區域中的
原始碼版面配置文件。大多數
您可以在 //src/devices/ 底下找到 Fuchsia 驅動程式。這些圖片會歸類在一起
動態調整驅動程式通訊協定的定義
ddk/include/lib/ddk/protodefs.h.適用對象
例如 USB 乙太網路驅動程式庫
//src/connectivity/ethernet/drivers/
而不是 //src/devices/usb/drivers/,因為
會實作乙太網路通訊協定。但實作 USB 堆疊的驅動程式
位於 //src/devices/usb/drivers/,原因是
實作 USB 通訊協定
在驅動程式庫的 BUILD.gn
中,應有 fuchsia_driver_component
目標。
為了讓驅動程式庫顯示在/boot/driver
底下,請將該司機納入內
如下方相關主面板檔案的 board_bootfs_labels
清單中
//boards。為了讓產品顯示在 /system/driver
中,內容應為
已加入含有 driver_package
建構目標的系統套件中
則由 //boards
中的相關董事會檔案參照。驅動程式管理器
會在 /boot/driver
中優先顯示,然後為 /system/driver/
載入可供載入的驅動程式。
建立新的驅動程式庫
可使用 建立工具。只要執行下列指令即可:
fx create driver --path <PATH> --lang cpp
這會建立 <PATH>
目錄,其中包含一個空白驅動程式庫,其中
<PATH>
的最後一個部分是驅動程式庫名稱和 GN 目標名稱。之後
指令執行,請執行下列步驟:
- 在以下位置加入
fuchsia_driver_component
或driver_package
建構目標: 將司機加入系統的正確位置 - 如果是封裝驅動程式,應將
driver_package
建構目標新增至 收到有關//boards
或//vendor/<foo>/boards
中的相關主面板檔案,xx_package_labels
GN 引數。 - 如果是啟動驅動程式,應新增
fuchsia_driver_component
建構目標 至//boards
或//vendor/<foo>/boards
中的相關主面板檔案,board_bootfs_labels
GN 引數。 - 在
<PATH>:tests
建構目標中加入tests
建構目標,即可取得 進行深入的整合 - 在
meta/<NAME>.bind
中新增適當的繫結規則。 - 在
meta/<NAME>-info.json
中新增驅動程式庫資訊。檔案必須包含short_description
和areas
至少符合以下列出的其中一個區域//build/drivers/areas.txt
。 - 編寫驅動程式庫的功能。
宣告驅動程式庫
驅動程式庫至少應包含驅動程式庫宣告並實作
bind()
驅動程式庫任務。
驅動程式管理器成功載入驅動程式並繫結至裝置
會尋找與裝置相符的驅動程式庫。駕駛人宣告自身的裝置
與透過繫結規則相容,因此應置於 .bind
檔案中
一起驅動程式庫。繫結編譯器會編譯這些規則,
驅動程式庫宣告巨集,包含 C 標頭檔案中的這些規則。
下列繫結規則會將
AHCI 驅動程式:
using fuchsia.pci;
using fuchsia.pci.massstorage;
fuchsia.BIND_PROTOCOL == fuchsia.pci.BIND_PROTOCOL.DEVICE;
fuchsia.BIND_PCI_CLASS == fuchsia.pci.BIND_PCI_CLASS.MASS_STORAGE;
fuchsia.BIND_PCI_SUBCLASS == fuchsia.pci.massstorage.BIND_PCI_SUBCLASS_SATA;
fuchsia.BIND_PCI_INTERFACE == 0x01;
fuchsia.BIND_COMPOSITE == 1;
這些繫結規則狀態表示驅動程式庫繫結至具有 BIND_PROTOCOL
的裝置
與 pci
命名空間中的 DEVICE
和指定 PCI 相符的屬性
class/subclass/interface已從 fucnsia.pci
匯入 pci
命名空間
第一行程式碼庫詳情請參閱繫結
說明文件。
如要產生包含這些繫結規則的驅動程式庫宣告巨集,
為對應的 bind_rules
建構目標。這應宣告依附元件
「使用」陳述式。
driver_bind_rules("bind") {
rules = "meta/ahci.bind"
bind_output = "ahci.bindbc"
deps = [
"//src/devices/bind/fuchsia.pci",
"//src/devices/bind/fuchsia.pci.massstorage",
]
}
驅動程式現在可包含產生的標頭,並使用
下方的巨集。"zircon"
是供應商 ID,"0.1"
則是驅動程式庫版本。
#include <lib/ddk/binding_driver.h>
...
ZIRCON_DRIVER(ahci, ahci_driver_ops, "zircon", "0.1");
PCI 驅動程式會發布 並包含下列屬性:
zx_device_str_prop_t pci_device_props[] = {
ddk::MakeStrProperty(bind_fuchsia::PCI_VID,
static_cast<uint32_t>(device.info.vendor_id)),
ddk::MakeStrProperty(bind_fuchsia::PCI_DID,
static_cast<uint32_t>(device.info.device_id)),
ddk::MakeStrProperty(bind_fuchsia::PCI_CLASS,
static_cast<uint32_t>(device.info.base_class)),
ddk::MakeStrProperty(bind_fuchsia::PCI_SUBCLASS,
static_cast<uint32_t>(device.info.sub_class)),
ddk::MakeStrProperty(bind_fuchsia::PCI_INTERFACE,
static_cast<uint32_t>(device.info.program_interface)),
ddk::MakeStrProperty(bind_fuchsia::PCI_REVISION,
static_cast<uint32_t>(device.info.revision_id)),
ddk::MakeStrProperty(bind_fuchsia::PCI_TOPO, pci_bind_topo),
};
目前,繫結變數和巨集已在
lib/ddk/binding.h.在不久的將來
所有節點屬性都會由 fuchsia.pci
等繫結程式庫定義。
程式庫匯入了如要推出新的裝置類別,
將新的節點屬性導入繫結標頭中
繫結程式庫。
節點屬性為 32 位元值。如果您的變數值必須大於
32 位元值,分成多個 32 位元變數。例如 ACPI
HID 值,長度為 8 個字元 (64 位元)。並分為
《BIND_ACPI_HID_0_3
》和《BIND_ACPI_HID_4_7
》。遷移作業進行繫結後
程式庫完成後,您就能使用其他資料類型,例如字串、
較大的數字和布林值
您可以在 bind_rules
建構規則中指定 disable_autobind = true
,
停用自動繫結行為在這種情況下,可以將驅動程式庫繫結至
裝置使用 fuchsia.device.Controller/Bind
FIDL 呼叫。
驅動程式繫結
當使用者與裝置配對時,系統會呼叫驅動程式的 bind()
函式。通用
驅動程式庫會初始化裝置所需的任何資料結構
初始化此函式中的硬體因此不應執行任何耗時
或封鎖這個函式,因為它是從驅動程式代管程序的
RPC 執行緒,且在此期間將無法服務其他要求。
而應產生新的執行緒來執行長時間的工作。
驅動程式不應假設
bind()
。可能需要重設硬體,或確保裝置處於已知狀態
時間。因為系統會藉由轉動驅動程式庫程式,從驅動程式庫中復原
主機,叫用 bind()
時硬體可能處於不明狀態。
bind()
通常有四個結果:
驅動程式會判斷裝置確實受到支援,因此不需要執行任何操作 需花費較多心力,因此推出
device_add()
的新裝置 (C/ddk::Device::DdkAdd()
的 DDKTL C++ 包裝函式程式庫並傳回 `ZX_OK。即使繫結規則相符,驅動程式仍會判斷 無法支援 (可能是因為檢查 hw 版本位元或不正確) 以及 傳回錯誤。
驅動程式需要先進一步初始化,裝置才會準備就緒,或是 但確定可以支援,因此會發布隱形裝置 實作
init()
掛鉤 啟動執行緒以繼續工作,同時將ZX_OK
傳回bind()
。 該執行緒最後會呼叫 C 中的device_init_reply()
,或ddk::InitTxn::Reply()
是 DDKTL C++ 包裝函式程式庫。在 已收到回覆。狀態會指出ZX_OK
是否能成功 裝置初始化成功,且應一律顯示在畫面上,或 錯誤訊息,指出應移除裝置。駕駛人代表有 0..n 子項的公車或控制器 會動態顯示或消失。在此情況下,它應該發布裝置 以代表公車或控制器,接著以動態方式發布 代表硬體上鎖的子項 (繫結至該下游驅動程式) 搭乘大眾運輸工具例如:AHCI/SATA、USB 等
裝置新增並設定為可偵測後,就可供 用戶端程序,並供相容驅動程式建立繫結。
Banjo 協定
驅動程式為裝置提供一組裝置作業,以及選用的通訊協定作業。 裝置作業會實作裝置生命週期方法和外部介面, 其他使用者空間應用程式和服務所呼叫的裝置。 通訊協定作業會為裝置呼叫的 其他驅動程式載入同一個驅動程式代管程序。
您可以在 device_add_args_t
中為裝置傳遞一組通訊協定作業。如果
裝置支援多種通訊協定,請實作 get_protocol()
裝置作業。A 罩杯
裝置只能有一個通訊協定 ID。通訊協定 ID 會與類別對應
裝置是在 devfs 底下發布
驅動程式作業
司機運作時,通常會處理兒童駕駛人發出的用戶端要求 或其他程序用來執行要求時 與家長溝通 (例如透過 MMIO) (例如將 USB 交易排入佇列)。
由驅動程式代管程序外部程序所發出的外部用戶端要求,會由 兒童駕駛人通常以相同程序完成 裝置類別對應的通訊協定。駕駛對驅動程式庫要求應 使用 banjo 通訊協定取代裝置作業
裝置只要呼叫
device_get_protocol()
。
裝置幹擾
裝置中斷是由中斷物件實作,這類物件屬於
核心物件駕駛人要求裝置的控制代碼導致裝置中斷
裝置通訊協定方法。傳回的帳號代碼將會繫結至
由家長驅動程式庫程式定義,導致裝置的適當中斷情形。適用對象
舉例來說,PCI 通訊協定會為 PCI 子項實作 map_interrupt()
。A 罩杯
驅動程式庫應產生執行緒,來等待中斷控點。
核心會自動處理遮蓋及解除遮蓋中斷情形,即
視情況而定
都屬於使用者層級對於層級觸發的硬體中斷
「zx_interrupt_wait()
」會套用遮罩
在再次呼叫之前,中斷狀態並取消遮蓋中斷情形
下次再接再厲針對邊緣觸發的中斷,中斷情形會保持解除遮罩。
中斷執行緒不應執行任何長時間執行的工作。對於有下列需求的駕駛 或執行長時間的工作,請使用背景工作執行緒。
你可以透過以下方式指出中斷控點:
zx_interrupt_trigger()
已開啟
要從 zx_interrupt_wait()
返回的運算單元 ZX_INTERRUPT_SLOT_USER
。這是
而在驅動程式庫清理期間關閉中斷執行緒。
FIDL 訊息
非驅動程式庫程序
要定義各裝置類別的訊息,請參閱
FIDL。每部裝置
實作零或多個 FIDL 通訊協定,每個管道都會透過多工處理
用戶端。駕駛人有機會理解 FIDL 訊息
message()
掛鉤。只有以下項目可存取非驅動程式庫元件:
開發 Kubernetes 叢集
其他程序中的驅動程式
如果驅動程式庫必須以獨立程序與驅動程式庫溝通, 而不是定義通訊協定作業,而必須代管傳出目錄,類似於 元件,其中應代管子項驅動程式庫程式會存取的所有 FIDL 通訊協定 在繫結。
通訊協定運算與 FIDL 訊息
通訊協定作業為裝置定義 In-Process API。FIDL 訊息會定義 用於獨立程序的 API。如果函式符合以下條件,請定義通訊協定運算 僅由其他駕駛人在相同程序中呼叫駕駛人應打電話給 以便使用這些功能。
隔離裝置
使用 DEVICE_ADD_MUST_ISOLATE
新增的裝置會產生新的驅動程式代管程序。
裝置必須有代管 FIDL 的傳出目錄
通訊協定繫結至裝置的驅動程式會載入至新裝置
驅動程式代管程序提供的 FIDL 通訊協定
並由父項驅動程式庫提供的傳出目錄
駕駛權
雖然駕駛人會在使用者空間處理程序中執行,但該程式對一組較嚴格的限制 額外權利。不允許驅動程式存取檔案系統 包括 devfs這表示驅動程式庫無法與任意裝置互動。如果 您的驅動程式庫需要執行此操作,請考慮改為編寫服務元件。適用對象 虛擬控制台是由 virtcon 元件。
特殊權限作業,例如 zx_vmo_create_contiguous()
和
zx_interrupt_create
需要
根資源控點這個帳號代碼僅供
系統驅動程式庫 (在 x86 系統上使用 ACPI,
平台)。裝置
要求其父項為該函式執行此類作業與
父項驅動程式庫。
同樣地,驅動程式庫也不得要求任意 MMIO 範圍,導致中斷 或 GPIOPCI 和平台等匯流排驅動程式只會傳回資源 正確連結。
進階主題和訣竅
初始化花費較長時間
如果裝置需要很長的時間才能完成初始化,該怎麼辦?先前提到
上方顯示 null_bind()
函式,表示系統成功傳回
驅動程式管理器,此驅動程式庫已與裝置建立關聯。我們無法透過
在繫結函式中長時間執行基本上應該將
發布裝置、加以發布,輕鬆完成
不過,裝置可能需要執行較長的初始化作業,例如 為:
- 列舉硬體點
- 載入韌體。
- 協商通訊協定
以此類推,這可能需要較長的時間
您可以將裝置發布為「隱藏」只要實作裝置「init()
」
吊人胃口的情節片段。系統會在透過 device_add()
新增裝置後執行 init()
掛鉤。
也可以用於安全存取裝置狀態及產生背景工作執行緒。
裝置會繼續顯示,而且保證在
系統會呼叫 device_init_reply()
,可以從任何執行緒完成。這符合
或是沒有人可使用您的裝置
(因為目前還沒有人知道這個地點)。現在你的裝置
可以透過背景執行緒執行長時間作業
當裝置準備好處理用戶端要求時,請呼叫 device_init_reply()
如此一來,路徑名稱空間就會顯示
省電
你的裝置依序提供兩則摘要 (suspend()
和 resume()
)
以便支援電力或其他資源節省功能。
兩者都接收到裝置結構定義指標和旗標引數,但是旗標引數 只有在暫停的情況下使用
檢舉 | 意義 |
---|---|
DEVICE_SUSPEND_FLAG_REBOOT |
驅動程式應自行關閉,準備重新啟動或關機 |
DEVICE_SUSPEND_FLAG_REBOOT_BOOTLOADER |
? |
DEVICE_SUSPEND_FLAG_REBOOT_RECOVERY |
? |
DEVICE_SUSPEND_FLAG_POWEROFF |
駕駛人應自行關機準備關機 |
DEVICE_SUSPEND_FLAG_MEXEC |
驅動程式應自行關閉以準備柔性重新啟動 |
DEVICE_SUSPEND_FLAG_SUSPEND_RAM |
驅動程式應排列,以便從 RAM 重新啟動 |
參考資料:支援函式
本節列出提供給驅動程式使用的支援功能。
存取子函式
傳遞內容區塊,做為第一個引數傳遞至驅動程式通訊協定 函式是一種不透明的資料結構。這表示為了存取 資料元素,您需呼叫存取子函式:
函式 | 目的 |
---|---|
device_get_name() |
擷取裝置名稱 |
管理功能
以下函式可用於管理裝置:
函式 | 目的 |
---|---|
device_add() |
將裝置新增至家長 |
device_async_remove() |
安排裝置及所有子項的移除作業 |