管理帧缓冲孔径的所有权

图形设备可能由不同的驱动程序支持,但任何给定时间只能有一个驱动程序处于活动状态。许多系统在启动过程的早期会加载通用图形驱动程序,例如 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 帧缓冲区或控制台。如果您有一个 VGA 兼容的 PCI 图形设备,其帧缓冲区位于非 BAR 位置,这将非常有用。驱动程序应该获取这些内存区域的所有权,然后调用此助手函数来释放剩余的 VGA 设备。

如果您的硬件的帧缓冲区可以通过 PCI BAR 访问,请改用 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 的任何内存 BAR 内孔径的设备。 该函数假设具有阴影 ROM 的 PCI 设备驱动主显示器,因此也会踢出 vga16fb。

返回

成功时为 0,否则为负 errno 代码