Writing Device Drivers

Allocation and Initialization of a scsi_pkt(9S) Structure

The tran_init_pkt(9E) entry point must allocate a scsi_pkt(9S) structure if pkt is NULL through scsi_hba_pkt_alloc(9F).

scsi_hba_pkt_alloc(9F) allocates the following:

The scsi_pkt(9S) structure members, as well as pkt itself, must be initialized to zero except for the following members: pkt_scbp (status completion), pkt_cdbp (CDB), pkt_ha_private (HBA driver private data), pkt_private (target driver private data). These members are pointers to memory space where the values of the fields are stored, as illustrated in Figure 14-5. For more information, refer to "scsi_pkt Structure".

Figure 14-5 scsi_pkt(9S) Structure Pointers

Graphic

Example 14-4 provides an example of allocation and initialization of a scsi_pkt(9S) structure.


Example 14-4 HBA Driver Initialization of a SCSI Packet Structure

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