如果 pkt 为 NULL,则 tran_init_pkt(9E) 入口点必须通过 scsi_hba_pkt_alloc(9F) 分配 scsi_pkt(9S) 结构。
scsi_hba_pkt_alloc(9F) 可为以下各项分配空间:
长度为 cmdlen 的 SCSI CDB
长度为 statuslen 的 SCSI 状态的完成区
长度为 tgtlen 的按包的目标驱动程序专用数据区
长度为 hbalen 的按包的 HBA 驱动程序专用数据区
除以下成员外,必须将 scsi_pkt(9S) 结构成员(包括 pkt)初始化为零:
pkt_scbp-状态完成
pkt_cdbp-CDB
pkt_ha_private-HBA 驱动程序专用数据
pkt_private-目标驱动程序专用数据
这些成员是指向存储字段值的内存空间的指针,如下图所示。有关更多信息,请参阅scsi_pkt 结构 (HBA)。

以下示例说明了 scsi_pkt 结构的分配和初始化。
static struct scsi_pkt *
isp_scsi_init_pkt(
struct scsi_address *ap,
struct scsi_pkt *pkt,
struct buf *bp,
int cmdlen,
int statuslen,
int tgtlen,
int flags,
int (*callback)(),
caddr_t arg)
{
struct isp_cmd *sp;
struct isp *isp;
struct scsi_pkt *new_pkt;
ASSERT(callback == NULL_FUNC || callback == SLEEP_FUNC);
isp = (struct isp *)ap->a_hba_tran->tran_hba_private;
/*
* First step of isp_scsi_init_pkt: pkt allocation
*/
if (pkt == NULL) {
pkt = scsi_hba_pkt_alloc(isp->isp_dip, ap, cmdlen,
statuslen, tgtlen, sizeof (struct isp_cmd),
callback, arg);
if (pkt == NULL) {
return (NULL);
}
sp = (struct isp_cmd *)pkt->pkt_ha_private;
/*
* Initialize the new pkt
*/
sp->cmd_pkt = pkt;
sp->cmd_flags = 0;
sp->cmd_scblen = statuslen;
sp->cmd_cdblen = cmdlen;
sp->cmd_dmahandle = NULL;
sp->cmd_ncookies = 0;
sp->cmd_cookie = 0;
sp->cmd_cookiecnt = 0;
sp->cmd_nwin = 0;
pkt->pkt_address = *ap;
pkt->pkt_comp = (void (*)())NULL;
pkt->pkt_flags = 0;
pkt->pkt_time = 0;
pkt->pkt_resid = 0;
pkt->pkt_statistics = 0;
pkt->pkt_reason = 0;
new_pkt = pkt;
} else {
sp = (struct isp_cmd *)pkt->pkt_ha_private;
new_pkt = NULL;
}
/*
* Second step of isp_scsi_init_pkt: dma allocation/move
*/
if (bp && bp->b_bcount != 0) {
if (sp->cmd_dmahandle == NULL) {
if (isp_i_dma_alloc(isp, pkt, bp,
flags, callback) == 0) {
if (new_pkt) {
scsi_hba_pkt_free(ap, new_pkt);
}
return ((struct scsi_pkt *)NULL);
}
} else {
ASSERT(new_pkt == NULL);
if (isp_i_dma_move(isp, pkt, bp) == 0) {
return ((struct scsi_pkt *)NULL);
}
}
}
return (pkt);
}