ドライバの割り込みハンドラを登録する場合、ドライバは通常、その attach(9E) エントリポイントで次の段階を実行します。
ddi_intr_get_supported_types(9F) を使用して、サポートされている割り込みのタイプを判定します。
ddi_intr_get_nintrs(9F) を使用して、サポートされている割り込みタイプの数を判定します。
kmem_zalloc(9F) を使用して、DDI 割り込みハンドルにメモリーを割り当てます。
割り当てる割り込みタイプごとに、次の手順を実行します。
ddi_intr_get_pri (9F) を使用して、割り込みの優先順位を取得します。
割り込みに新しい優先順位を設定する必要がある場合は、 ddi_intr_set_pri(9F) を使用します。
mutex_init(9F) を使用して、ロックを初期化します。
ddi_intr_add_handler(9F) を使用して、割り込みのハンドラを登録します。
ddi_intr_enable (9F) を使用して、割り込みを有効にします。
次の手順を実行して、各割り込みを解放します。
ddi_intr_disable (9F) を使用して、各割り込みを無効にします。
ddi_intr_remove_handler(9F) を使用して、割り込みハンドラを削除します。
mutex_destroy (9F) を使用して、ロックを削除します。
ddi_intr_free (9F) およびkmem_free(9F) を使用して DDI 割り込みハンドルに割り当てられたメモリーを解放し、割り込みを解放します。
次の例は、mydev というデバイスの割り込みハンドラをインストールする方法を示しています。この例では、mydev が 1 つの割り込みだけをサポートしていることを前提としています。
/* Determine which types of interrupts supported */
ret = ddi_intr_get_supported_types(mydevp->mydev_dip, &type);
if ((ret != DDI_SUCCESS) || (!(type & DDI_INTR_TYPE_FIXED))) {
cmn_err(CE_WARN, "Fixed type interrupt is not supported");
return (DDI_FAILURE);
}
/* Determine number of supported interrupts */
ret = ddi_intr_get_nintrs(mydevp->mydev_dip, DDI_INTR_TYPE_FIXED,
&count);
/*
* Fixed interrupts can only have one interrupt. Check to make
* sure that number of supported interrupts and number of
* available interrupts are both equal to 1.
*/
if ((ret != DDI_SUCCESS) || (count != 1)) {
cmn_err(CE_WARN, "No fixed interrupts");
return (DDI_FAILURE);
}
/* Allocate memory for DDI interrupt handles */
mydevp->mydev_htable = kmem_zalloc(sizeof (ddi_intr_handle_t),
KM_SLEEP);
ret = ddi_intr_alloc(mydevp->mydev_dip, mydevp->mydev_htable,
DDI_INTR_TYPE_FIXED, 0, count, &actual, 0);
if ((ret != DDI_SUCCESS) || (actual != 1)) {
cmn_err(CE_WARN, "ddi_intr_alloc() failed 0x%x", ret);
kmem_free(mydevp->mydev_htable, sizeof (ddi_intr_handle_t));
return (DDI_FAILURE);
}
/* Sanity check that count and available are the same. */
ASSERT(count == actual);
/* Get the priority of the interrupt */
if (ddi_intr_get_pri(mydevp->mydev_htable[0], &mydevp->mydev_intr_pri)) {
cmn_err(CE_WARN, "ddi_intr_alloc() failed 0x%x", ret);
(void) ddi_intr_free(mydevp->mydev_htable[0]);
kmem_free(mydevp->mydev_htable, sizeof (ddi_intr_handle_t));
return (DDI_FAILURE);
}
cmn_err(CE_NOTE, "Supported Interrupt pri = 0x%x", mydevp->mydev_intr_pri);
/* Test for high level mutex */
if (mydevp->mydev_intr_pri >= ddi_intr_get_hilevel_pri()) {
cmn_err(CE_WARN, "Hi level interrupt not supported");
(void) ddi_intr_free(mydevp->mydev_htable[0]);
kmem_free(mydevp->mydev_htable, sizeof (ddi_intr_handle_t));
return (DDI_FAILURE);
}
/* Initialize the mutex */
mutex_init(&mydevp->mydev_int_mutex, NULL, MUTEX_DRIVER,
DDI_INTR_PRI(mydevp->mydev_intr_pri));
/* Register the interrupt handler */
if (ddi_intr_add_handler(mydevp->mydev_htable[0], mydev_intr,
(caddr_t)mydevp, NULL) !=DDI_SUCCESS) {
cmn_err(CE_WARN, "ddi_intr_add_handler() failed");
mutex_destroy(&mydevp->mydev_int_mutex);
(void) ddi_intr_free(mydevp->mydev_htable[0]);
kmem_free(mydevp->mydev_htable, sizeof (ddi_intr_handle_t));
return (DDI_FAILURE);
}
/* Enable the interrupt */
if (ddi_intr_enable(mydevp->mydev_htable[0]) != DDI_SUCCESS) {
cmn_err(CE_WARN, "ddi_intr_enable() failed");
(void) ddi_intr_remove_handler(mydevp->mydev_htable[0]);
mutex_destroy(&mydevp->mydev_int_mutex);
(void) ddi_intr_free(mydevp->mydev_htable[0]);
kmem_free(mydevp->mydev_htable, sizeof (ddi_intr_handle_t));
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
使用例 8-6 レガシー割り込みの削除 次の例は、レガシー割り込みを削除する方法を示しています。
/* disable interrupt */ (void) ddi_intr_disable(mydevp->mydev_htable[0]); /* Remove interrupt handler */ (void) ddi_intr_remove_handler(mydevp->mydev_htable[0]); /* free interrupt handle */ (void) ddi_intr_free(mydevp->mydev_htable[0]); /* free memory */ kmem_free(mydevp->mydev_htable, sizeof (ddi_intr_handle_t));