内核调用驱动程序的 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() 中直到回调完成,要么使分离请求失败。
/* * 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); } }