编写设备驱动程序

detach() 入口点

内核调用驱动程序的 detach(9E) 入口点,通过电源管理来分离设备的某个实例或暂停对设 备某个实例的操作。本节讨论分离设备实例的操作。有关电源管理问题的讨论,请参阅第 12 章

调用驱动程序detach() 入口点以分离绑定到该驱动程序的设备的某个实例。该入口点是使用要分离的设备节点的实例和指定为该入口点的 cmd 参数的 DDI_DETACH 来调用的。

驱动程序需要取消或等待所有超时或回调完成,然后在返回前释放分配给设备实例的所有资源。如果由于某种原因,驱动程序无法取消未完成的回调以释放资源,则驱动程序需要将设备返回至其初始状态并从入口点返回 DDI_FAILURE,使设备实例保持连接状态。

有两种类型的回调例程: 可取消回调例程和不可取消回调例程。驱动程序在 detach(9E) 期间可以原子方式取消 timeout(9F)bufcall(9F) 回调例程。其他类型的回调例程,如 scsi_init_pkt(9F)ddi_dma_buf_bind_handle(9F),则不能被取消。驱动程序必须要么阻塞在 detach() 中直到回调完成,要么使分离请求失败。


示例 6–6 典型 detach() 入口点

/*
 * detach(9e)
 * free the resources that were allocated in attach(9e)
 */
static int
xxdetach(dev_info_t *dip, ddi_detach_cmd_t cmd)
{
    Pio     *pio_p;
    int     instance;

    switch (cmd) {
    case DDI_DETACH:

    instance = ddi_get_instance(dip);
    pio_p = ddi_get_soft_state(pio_softstate, instance);

    /*
     * turn off the device
     * free any resources allocated in attach
     */
    ddi_put8(pio_p->csr_handle, pio_p->csr, PIO_RESET);
    ddi_remove_minor_node(dip, NULL);
    ddi_regs_map_free(&pio_p->csr_handle);
    ddi_regs_map_free(&pio_p->data_handle);
    ddi_remove_intr(pio_p->dip, 0, pio_p->iblock_cookie);
    mutex_destroy(&pio_p->mutex);
    ddi_soft_state_free(pio_softstate, instance);
    return (DDI_SUCCESS);

    case DDI_SUSPEND:
    default:
    return (DDI_FAILURE);
    }
}