编写设备驱动程序

GLDv2 服务例程

本节提供 GLDv2 服务例程的语法和说明。

gld_mac_alloc() 函数

gld_mac_info_t *gld_mac_alloc(dev_info_t *dip);

gld_mac_alloc() 可分配新的 gld_mac_info(9S) 结构并返回指向此结构的指针。可能会在 gld_mac_alloc() 返回之前初始化此结构的某些 GLDv2 专用元素。所有其他元素均初始化为 0。在将指向 gld_mac_info 结构的指针传递给 gld_register() 之前,设备驱动程序必须初始化某些结构成员,如 gld_mac_info(9S) 手册页中所述。

gld_mac_free() 函数

void gld_mac_free(gld_mac_info_t *macinfo);

gld_mac_free() 可释放先前由 gld_mac_alloc() 所分配的 gld_mac_info(9S) 结构。

gld_register() 函数

int gld_register(dev_info_t *dip, char *name, gld_mac_info_t *macinfo);

可通过设备驱动程序的 attach(9E) 例程调用 gld_register()gld_register() 将基于 GLDv2 的设备驱动程序与 GLDv2 框架相链接。在调用 gld_register() 之前,设备驱动程序的 attach(9E) 例程使用 gld_mac_alloc() 来分配 gld_mac_info(9S) 结构,然后初始化若干结构元素。有关更多信息,请参见 gld_mac_info(9S)。成功调用 gld_register() 可执行以下操作:

传递给 gld_register() 的设备接口名称必须与存在于文件系统中的驱动程序模块的名称完全匹配。

如果 gld_register() 成功执行,则驱动程序的 attach(9E) 例程应该返回 DDI_SUCCESS。如果 gld_register() 没有返回 DDI_SUCCESS,则 attach(9E) 例程应该在调用 gld_register() 之前解除分配所有已分配的资源,然后返回 DDI_FAILURE

gld_unregister() 函数

int gld_unregister(gld_mac_info_t *macinfo);

gld_unregister() 由设备驱动程序的 detach(9E) 函数进行调用,如果成功,会执行以下任务:

如果 gld_unregister() 返回 DDI_SUCCESS,则 detach(9E) 例程应该解除分配在 attach( 9E) 例程中分配的所有数据结构,使用 gld_mac_free() 解除分配 macinfo 结构,并返回 DDI_SUCCESS。如果 gld_unregister() 没有返回 DDI_SUCCESS,则驱动程序的 detach(9E) 例程必须保持设备处于运行状态并返回 DDI_FAILURE

gld_recv() 函数

void gld_recv(gld_mac_info_t *macinfo, mblk_t *mp);

驱动程序的中断处理程序可调用 gld_recv() 以向上游传递已接收的包。驱动程序必须构造并传递包含原始包的 STREAMS M_DATA 消息。gld_recv() 可确定哪些 STREAMS 队列应该接收包的副本,并在必要时复制包。然后,gld_recv() 会在需要时设置 DL_UNITDATA_IND 消息的格式,并沿所有相应的流向上传递数据。

在调用 gld_recv() 期间,驱动程序应该避免持有互斥锁或其他锁。需要特别指出的是,在调用 gld_recv() 期间,不得持有传输线程可使用的锁。在某些情况下调用 gld_recv() 的中断线程可执行包括发送传出包的处理。传输包会导致调用驱动程序的 gldm_send() 例程。如果在调用 gld_recv()gldm_send() 尝试获取 gldm_intr() 持有的互斥锁,则会由于存在递归互斥锁入口操作而出现紧急情况。在调用 gld_recv() 时,如果其他驱动程序入口点尝试获取驱动程序所持有的互斥锁,则会导致死锁。

gld_sched() 函数

void gld_sched(gld_mac_info_t *macinfo);

设备驱动程序可调用 gld_sched() 来重新安排已延迟的外发包。当驱动程序的 gldm_send() 例程返回 GLD_NORESOURCES 时,驱动程序必须调用 gld_sched() 以通知 GLDv2 框架重试先前无法发送的包。当资源变得可用之后,应该尽快调用 gld_sched(),以便 GLDv2 继续将外发包传递给驱动程序的 gldm_send() 例程。(如果调用了驱动程序的 gldm_stop() 例程,则在 gldm_send 返回 GLD_NORESOURCES() 之前,驱动程序不需要重试。不过,再次调用 gld_sched() 也不会导致错误操作。)

gld_intr() 函数

uint_t gld_intr(caddr_t);

gld_intr() 是 GLDv2 的主要中断处理程序。通常,将 gld_intr() 指定为设备驱动程序的 ddi_add_intr(9F) 调用中的中断例程。将中断处理程序的参数指定为 ddi_add_intr(9F) 调用中的 int_handler_arg。此参数必须是指向 gld_mac_info(9S) 结构的指针。gld_intr() 会在适当的情况下调用设备驱动程序的 gldm_intr() 函数,并将该指针传递给 gld_mac_info(9S) 结构。但是,要使用高级中断,驱动程序必须提供自身的高级中断处理程序,并在处理程序中触发软中断。在这种情况下,通常会将 gld_intr() 指定为 ddi_add_softintr() 调用中的软中断处理程序。gld_intr() 将返回适用于中断处理程序的值。