管理幀緩衝孔徑的所有權

一個圖形裝置可能被不同的驅動程式支援,但在任何給定時間只能有一個驅動程式處於活動狀態。許多系統在啟動過程的早期載入通用圖形驅動程式,例如 EFI-GOP 或 VESA。在後續的啟動階段,它們將通用驅動程式替換為專用的、特定於硬體的驅動程式。為了接管裝置,專用驅動程式首先必須刪除通用驅動程式。孔徑函式管理幀緩衝記憶體的所有權以及驅動程式之間的切換。

圖形驅動程式應在其探測函式的頂部呼叫 aperture_remove_conflicting_devices()。該函式刪除當前與給定幀緩衝記憶體關聯的任何通用驅動程式。下面顯示了平臺總線上圖形裝置的示例。

static int example_probe(struct platform_device *pdev)
{
        struct resource *mem;
        resource_size_t base, size;
        int ret;

        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!mem)
                return -ENODEV;
        base = mem->start;
        size = resource_size(mem);

        ret = aperture_remove_conflicting_devices(base, size, "example");
        if (ret)
                return ret;

        // Initialize the hardware
        ...

        return 0;
}

static const struct platform_driver example_driver = {
        .probe = example_probe,
        ...
};

給定的示例從裝置例項讀取平臺裝置的 I/O 記憶體範圍。活動幀緩衝將位於此範圍內。呼叫 aperture_remove_conflicting_devices() 會釋放先前宣告該範圍所有權且當前在幀緩衝上驅動輸出的驅動程式。如果成功,新的驅動程式可以接管裝置。

雖然給定的示例使用平臺裝置,但孔徑助手適用於每個具有可定址幀緩衝的匯流排。對於 PCI,裝置驅動程式還可以呼叫 aperture_remove_conflicting_pci_devices(),並讓該函式自動檢測孔徑。不知道幀緩衝位置的裝置驅動程式可以呼叫 aperture_remove_all_conflicting_devices(),它將刪除所有已知裝置。

容易被其他驅動程式刪除的驅動程式(例如通用 EFI 或 VESA 驅動程式)必須將自己註冊為其幀緩衝孔徑的所有者。幀緩衝記憶體的所有權透過呼叫 devm_aperture_acquire_for_platform_device() 實現。如果成功,則該驅動程式是幀緩衝範圍的所有者。如果幀緩衝已由另一個驅動程式擁有,則該函式將失敗。請參見下面的示例。

static int generic_probe(struct platform_device *pdev)
{
        struct resource *mem;
        resource_size_t base, size;

        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!mem)
                return -ENODEV;
        base = mem->start;
        size = resource_size(mem);

        ret = devm_aperture_acquire_for_platform_device(pdev, base, size);
        if (ret)
                return ret;

        // Initialize the hardware
        ...

        return 0;
}

static int generic_remove(struct platform_device *)
{
        // Hot-unplug the device
        ...

        return 0;
}

static const struct platform_driver generic_driver = {
        .probe = generic_probe,
        .remove = generic_remove,
        ...
};

與前面的示例類似,通用驅動程式從其探測函式宣告幀緩衝記憶體的所有權。如果記憶體範圍或其部分已由另一個驅動程式擁有,則此操作將失敗。

如果成功,則通用驅動程式現在可能會被另一個驅動程式強制刪除。這僅適用於支援熱插拔的平臺驅動程式。當驅動程式呼叫 aperture_remove_conflicting_devices() 等來註冊的幀緩衝範圍時,孔徑助手會呼叫 platform_device_unregister(),並且通用驅動程式會解除安裝自身。通用驅動程式還必須提供一個刪除函式才能使其工作。一旦從硬體上熱插拔,它可能無法再訪問裝置的暫存器、幀緩衝記憶體、ROM 等。

int aperture_remove_all_conflicting_devices(const char *name)

刪除所有現有的幀緩衝

引數

const char *name

請求驅動程式的描述性名稱

描述

此函式刪除所有圖形裝置驅動程式。在幀緩衝可以位於記憶體中任何位置的系統上使用此函式。

返回值

成功時返回 0,否則返回負 errno 程式碼

int devm_aperture_acquire_for_platform_device(struct platform_device *pdev, resource_size_t base, resource_size_t size)

代表平臺裝置獲取孔徑的所有權。

引數

struct platform_device *pdev

擁有孔徑的平臺裝置

resource_size_t base

孔徑在物理記憶體中的位元組偏移量

resource_size_t size

孔徑大小(以位元組為單位)

描述

將給定的裝置安裝為孔徑的新所有者。該函式希望孔徑由平臺裝置提供。如果另一個驅動程式接管孔徑的所有權,則孔徑助手將自動取消註冊平臺裝置。當底層裝置消失時,所有獲取的孔徑都會自動釋放。

如果孔徑或其部分當前由另一個裝置擁有,則該函式將失敗。要驅逐當前所有者,呼叫方應在使用此函式之前使用 remove_conflicting_devices() 等。

返回值

成功時返回 0,否則返回負 errno 值。

int aperture_remove_conflicting_devices(resource_size_t base, resource_size_t size, const char *name)

刪除給定範圍內的裝置

引數

resource_size_t base

孔徑在物理記憶體中的基地址

resource_size_t size

孔徑大小(以位元組為單位)

const char *name

請求驅動程式的描述性名稱

描述

此函式刪除擁有 basesize 中孔徑的裝置。

返回值

成功時返回 0,否則返回負 errno 程式碼

int __aperture_remove_legacy_vga_devices(struct pci_dev *pdev)

刪除 PCI 裝置的舊式 VGA 裝置

引數

struct pci_dev *pdev

PCI 裝置

描述

此函式刪除由 pdev 提供的 VGA 裝置,例如 VGA 幀緩衝或控制檯。如果您有一個具有非 BAR 位置的幀緩衝的 VGA 相容 PCI 圖形裝置,這將非常有用。驅動程式應獲取這些記憶體區域的所有權,然後呼叫此助手來釋放剩餘的 VGA 裝置。

如果您的硬體可以透過 PCI BARS 訪問其幀緩衝,請改用 aperture_remove_conflicting_pci_devices()。該函式將自動釋放任何 VGA 裝置。

警告:顯然我們必須在呼叫之前刪除圖形驅動程式

此助手。否則,如果我們配置了 vgacon,則 vga fbdev 驅動程式會崩潰。

返回值

成功時返回 0,否則返回負 errno 程式碼

int aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, const char *name)

刪除 PCI 裝置的現有幀緩衝

引數

struct pci_dev *pdev

PCI 裝置

const char *name

請求驅動程式的描述性名稱

描述

此函式刪除擁有 pdev 的任何記憶體條中的孔徑的裝置。該函式假設具有陰影 ROM 的 PCI 裝置驅動主顯示器,因此也踢出 vga16fb。

返回值

成功時返回 0,否則返回負 errno 程式碼