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 through scsi_hba_pkt_alloc(9F) if pkt is NULL.

scsi_hba_pkt_alloc(9F) allocates space for the following items:

The scsi_pkt(9S) structure members, including pkt, must be initialized to zero except for the following members:

These members are pointers to memory space where the values of the fields are stored, as shown in the following figure. For more information, refer to scsi_pkt Structure (HBA).

Figure 18–5 scsi_pkt(9S) Structure Pointers

Diagram shows the scsi_pkt structure with those members
that point to values rather than being initialized to zero.

The following example shows allocation and initialization of a scsi_pkt structure.


Example 18–2 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);
}