ホストバスアダプタドライバがコマンドを完了すると、ドライバはパケットの完了コールバックルーチンを呼び出します。ドライバは次に、scsi_pkt(9S) 構造体へのポインタをパラメータとして渡します。パケットのデコード後、完了ルーチンが適切な操作を実行します。
Example 17–5は、簡単な完了コールバックルーチンを表しています。このコードは、トランスポートの失敗をチェックします。失敗の場合、ルーチンはコマンドを再試行するのではなく、実行を断念します。ターゲットがビジー状態の場合、あとでコマンドを再送信するために、追加のコードが必要です。
コマンドがチェック条件になった場合、要求の自動検知が有効になっている場合を除き、ターゲットドライバが要求検知コマンドを送信する必要があります。
その他の場合、コマンドは成功したことになります。コマンドの処理の最後に、コマンドはパケットを破棄し、biodone (9F) を呼び出します。
バスのリセットやパリティーの問題など、トランスポートエラーが発生した場合、ターゲットドライバはscsi_transport (9F) を使用してパケットを再送信できます。再送信の前に、パケット内の値を変更する必要はありません。
次の例では、完了しなかったコマンドの再試行は試みていません。
static void
xxcallback(struct scsi_pkt *pkt)
{
struct buf *bp;
struct xxstate *xsp;
minor_t instance;
struct scsi_status *ssp;
/*
* Get a pointer to the buf(9S) structure for the command
* and to the per-instance data structure.
*/
bp = (struct buf *)pkt->pkt_private;
instance = getminor(bp->b_edev);
xsp = ddi_get_soft_state(statep, instance);
/*
* Figure out why this callback routine was called
*/
if (pkt->pkt_reason != CMP_CMPLT) {
bp->b_resid = bp->b_bcount;
bioerror(bp, EIO);
scsi_destroy_pkt(pkt); /* Release resources */
biodone(bp); /* Notify waiting threads */ ;
} else {
/*
* Command completed, check status.
* See scsi_status(9S)
*/
ssp = (struct scsi_status *)pkt->pkt_scbp;
if (ssp->sts_busy) {
/* error, target busy or reserved */
} else if (ssp->sts_chk) {
/* Send a request sense command. */
} else {
bp->b_resid = pkt->pkt_resid; /* Packet completed OK */
scsi_destroy_pkt(pkt);
biodone(bp);
}
}
}