如果 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); }