编写设备驱动程序

GLDv2 驱动程序需求

基于 GLDv2 的驱动程序必须包括头文件 <sys/gld.h>

基于 GLDv2 的驱动程序必须与 -N"misc/gld" 选项链接:

%ld -r -N"misc/gld" xx.o -o xx

GLDv2 代表特定于设备的驱动程序实现以下函数:

module_info(9S) 结构的 mi_idname 元素是用于指定驱动程序名称的字符串。此字符串必须与文件系统中定义的驱动程序模块的名称完全匹配。

读端 qinit(9S) 结构应该指定以下元素:

qi_putp

NULL

qi_srvp

gld_rsrv

qi_qopen

gld_open

qi_qclose

gld_close

写端 qinit(9S) 结构应该指定以下元素:

qi_putp

gld_wput

qi_srvp

gld_wsrv

qi_qopen

NULL

qi_qclose

NULL

dev_ops(9S) 结构的 devo_getinfo 元素应该将 gld_getinfo 指定为 getinfo(9E) 例程。

驱动程序的 attach(9E) 函数会将特定于硬件的设备驱动程序与 GLDv2 功能相关联。然后,attach() 将准备设备和驱动程序以供使用。

attach(9E) 函数使用 gld_mac_alloc() 分配 gld_mac_info(9S) 结构。通常,驱动程序需要针对每台设备保存的信息比在 macinfo 结构中定义的信息多。驱动程序应该分配其他必需的数据结构,并在 gld_mac_info(9S) 结构的 gldm_private 成员中保存指向该结构的指针。

attach(9E) 例程必须初始化 macinfo 结构,如 gld_mac_info(9S) 手册页中所述。然后,attach() 例程应该调用 gld_register() 以将驱动程序与 GLDv2 模块相链接。驱动程序应该在必要时映射寄存器,并在调用 gld_register() 之前完全初始化以准备接受中断。attach(9E) 函数应该添加中断,而不应该使设备生成这些中断。驱动程序应该在调用 gld_register() 之前重置硬件,以确保硬件处于停顿状态。不得将设备置于其可能会在调用 gld_register() 之前生成中断的状态。稍后会在 GLDv2 调用驱动程序的 gldm_start() 入口点时启动设备,相关内容在 gld(9E) 手册页中介绍。gld_register() 成功执行之后,GLDv2 可能会随时调用 gld(9E) 入口点。

如果 gld_register() 成功执行,则 attach(9E) 例程应该返回 DDI_SUCCESS。如果 gld_register() 失败,则会返回 DDI_FAILURE。如果出现故障,则 attach(9E) 例程应该解除分配在调用 gld_register() 之前分配的所有资源。然后,连接例程还应该返回 DDI_FAILURE。绝不能重新使用出现故障的 macinfo 结构。应该使用 gld_mac_free() 解除分配此类结构。

detach(9E) 函数应尝试通过调用 gld_unregister() 来尝试从 GLDv2 中取消注册驱动程序。有关 gld_unregister() 的更多信息,请参见 gld(9F) 手册页。detach(9E) 例程可以使用 ddi_get_driver_private(9F) 从设备的专用数据中获取指向所需 gld_mac_info(9S) 结构的指针。gld_unregister() 将检查可能要求不分离驱动程序的特定条件。如果检查失败,则 gld_unregister() 会返回 DDI_FAILURE,在这种情况下,驱动程序的 detach(9E) 例程必须保持设备处于运行状态并返回 DDI_FAILURE

如果检查成功,则 gld_unregister() 会确保停止设备中断。如有必要,则会调用驱动程序的 gldm_stop() 例程。驱动程序将与 GLDv2 框架解除链接。然后,gld_unregister() 会返回 DDI_SUCCESS。在这种情况下,detach(9E) 例程应该删除中断,并使用 gld_mac_free() 解除分配在 attach(9E) 例程中分配的所有 macinfo 数据结构。然后,detach() 例程应该返回 DDI_SUCCESS。此例程必须在调用 gld_mac_free() 之前删除中断。