The routine scsi_init_pkt(9F) allocates space for a SCSI CDB, allocates DMA resources if necessary, and sets the pkt_flags field:
pkt = scsi_init_pkt(&sdp->sd_address, NULL, bp, CDB_GROUP0, 1, 0, 0, SLEEP_FUNC, NULL);
This example creates a new packet and allocates DMA resources as specified in the passed buf(9S) structure pointer. A SCSI CDB is allocated for a Group 0 (6-byte) command, the pkt_flags field is set to zero, but no space is allocated for the pkt_private field. This call to scsi_init_pkt(9F), because of the SLEEP_FUNC parameter, waits indefinitely for resources if none are currently available.
The next step is to initialize the SCSI CDB, using the scsi_setup_cdb(9F) function:
if (scsi_setup_cdb((union scsi_cdb *)pkt->pkt_cdbp, SCMD_READ, bp->b_blkno, bp->b_bcount >> DEV_BSHIFT, 0) == 0) goto failed;
This example builds a Group 0 command descriptor block and fills in the pkt_cdbp field as follows:
The command itself (byte 0) is set from the parameter (SCMD_READ).
The address field (bits 0-4 of byte 1 and bytes 2 and 3) is set from bp->b_blkno.
The count field (byte 4) is set from the last parameter. In this case it is set to bp->b_bcount >> DEV_BSHIFT, where DEV_BSHIFT is the byte count of the transfer converted to the number of blocks.
scsi_setup_cdb(9F) does not support setting a target device's logical unit number (LUN) in bits 5-7 of byte 1 of the SCSI command block, as defined by SCSI-1. For SCSI-1 devices requiring the LUN bits set in the command block, use makecom_g0(9F) (or equivalent) rather than scsi_setup_cdb(9F).
After initializing the SCSI CDB, initialize three other fields in the packet and store as a pointer to the packet in the state structure.
pkt->pkt_private = (opaque_t)bp; pkt->pkt_comp = xxcallback; pkt->pkt_time = 30; xsp->pkt = pkt;
The buf(9S) pointer is saved in the pkt_private field for later use in the completion routine.