カーネルは、デバイスのインスタンスを切り離すため、または電源管理によるデバイスのインスタンスに対する操作を中断するために、ドライバの detach(9E) エントリポイントを呼び出します。このセクションでは、デバイスインスタンスを切り離す操作について説明します。電源管理の問題の説明については、Chapter 12, Power Managementを参照してください。
ドライバの detach() エントリポイントは、そのドライバにバインドされたデバイスのインスタンスを切り離すために呼び出されます。このエントリポイントは、切り離されるデバイスノードのインスタンスと、このエントリポイントに対する cmd 引数として指定された DDI_DETACH を使用して呼び出されます。
ドライバは、すべてのタイムアウトまたはコールバックを取り消すか、または待機して完了したあと、戻る前にデバイスインスタンスに割り当てられたリソースをすべて解放する必要があります。ドライバが何らかの理由で、使用されていないリソースの未処理のコールバックを取り消すことができない場合、ドライバはデバイスを元の状態に戻し、エントリポイントから DDI_FAILURE を返す必要があります。これにより、デバイスインスタンスは接続された状態のままになります。
コールバックルーチンには、取り消すことができるコールバックと、取り消すことができないコールバックの 2 つのタイプがあります。timeout (9F) と bufcall (9F) のコールバックは、 detach(9E) 中にドライバが原子的に取り消すことができます。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);
}
}