コード例 #1
0
ファイル: qla_iocb.c プロジェクト: iPodLinux/linux-2.6.7-ipod
/**
 * qla2x00_build_scsi_iocbs_64() - Build IOCB command utilizing 64bit
 * capable IOCB types.
 *
 * @sp: SRB command to process
 * @cmd_pkt: Command type 3 IOCB
 * @tot_dsds: Total number of segments to transfer
 */
void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt,
    uint16_t tot_dsds)
{
	uint16_t	avail_dsds;
	uint32_t	*cur_dsd;
	scsi_qla_host_t	*ha;
	struct scsi_cmnd *cmd;

	cmd = sp->cmd;

	/* Update entry type to indicate Command Type 3 IOCB */
	*((uint32_t *)(&cmd_pkt->entry_type)) =
	    __constant_cpu_to_le32(COMMAND_A64_TYPE);

	/* No data transfer */
	if (cmd->request_bufflen == 0 || cmd->sc_data_direction == DMA_NONE) {
		cmd_pkt->byte_count = __constant_cpu_to_le32(0);
		return;
	}

	ha = sp->ha;

	cmd_pkt->control_flags |= cpu_to_le16(qla2x00_get_cmd_direction(cmd));

	/* Two DSDs are available in the Command Type 3 IOCB */
	avail_dsds = 2;
	cur_dsd = (uint32_t *)&cmd_pkt->dseg_0_address;

	/* Load data segments */
	if (cmd->use_sg != 0) {
		struct	scatterlist *cur_seg;
		struct	scatterlist *end_seg;

		cur_seg = (struct scatterlist *)cmd->request_buffer;
		end_seg = cur_seg + tot_dsds;
		while (cur_seg < end_seg) {
			dma_addr_t	sle_dma;
			cont_a64_entry_t *cont_pkt;

			/* Allocate additional continuation packets? */
			if (avail_dsds == 0) {
				/*
				 * Five DSDs are available in the Continuation
				 * Type 1 IOCB.
				 */
				cont_pkt = qla2x00_prep_cont_type1_iocb(ha);
				cur_dsd = (uint32_t *)cont_pkt->dseg_0_address;
				avail_dsds = 5;
			}

			sle_dma = sg_dma_address(cur_seg);
			*cur_dsd++ = cpu_to_le32(LSD(sle_dma));
			*cur_dsd++ = cpu_to_le32(MSD(sle_dma));
			*cur_dsd++ = cpu_to_le32(sg_dma_len(cur_seg));
			avail_dsds--;

			cur_seg++;
		}
	} else {
		dma_addr_t	req_dma;
		struct page	*page;
		unsigned long	offset;

		page = virt_to_page(cmd->request_buffer);
		offset = ((unsigned long)cmd->request_buffer & ~PAGE_MASK);
		req_dma = pci_map_page(ha->pdev, page, offset,
		    cmd->request_bufflen, cmd->sc_data_direction);

		sp->dma_handle = req_dma;

		*cur_dsd++ = cpu_to_le32(LSD(req_dma));
		*cur_dsd++ = cpu_to_le32(MSD(req_dma));
		*cur_dsd++ = cpu_to_le32(cmd->request_bufflen);
	}
}
コード例 #2
0
ファイル: qla_iocb.c プロジェクト: rcplay/snake-os
/**
 * qla24xx_build_scsi_iocbs() - Build IOCB command utilizing Command Type 7
 * IOCB types.
 *
 * @sp: SRB command to process
 * @cmd_pkt: Command type 3 IOCB
 * @tot_dsds: Total number of segments to transfer
 */
static inline void
qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt,
                         uint16_t tot_dsds)
{
    uint16_t	avail_dsds;
    uint32_t	*cur_dsd;
    scsi_qla_host_t	*ha;
    struct scsi_cmnd *cmd;

    cmd = sp->cmd;

    /* Update entry type to indicate Command Type 3 IOCB */
    *((uint32_t *)(&cmd_pkt->entry_type)) =
        __constant_cpu_to_le32(COMMAND_TYPE_7);

    /* No data transfer */
    if (cmd->request_bufflen == 0 || cmd->sc_data_direction == DMA_NONE) {
        cmd_pkt->byte_count = __constant_cpu_to_le32(0);
        return;
    }

    ha = sp->ha;

    /* Set transfer direction */
    if (cmd->sc_data_direction == DMA_TO_DEVICE)
        cmd_pkt->task_mgmt_flags =
            __constant_cpu_to_le16(TMF_WRITE_DATA);
    else if (cmd->sc_data_direction == DMA_FROM_DEVICE)
        cmd_pkt->task_mgmt_flags =
            __constant_cpu_to_le16(TMF_READ_DATA);

    /* One DSD is available in the Command Type 3 IOCB */
    avail_dsds = 1;
    cur_dsd = (uint32_t *)&cmd_pkt->dseg_0_address;

    /* Load data segments */
    if (cmd->use_sg != 0) {
        struct	scatterlist *cur_seg;
        struct	scatterlist *end_seg;

        cur_seg = (struct scatterlist *)cmd->request_buffer;
        end_seg = cur_seg + tot_dsds;
        while (cur_seg < end_seg) {
            dma_addr_t	sle_dma;
            cont_a64_entry_t *cont_pkt;

            /* Allocate additional continuation packets? */
            if (avail_dsds == 0) {
                /*
                 * Five DSDs are available in the Continuation
                 * Type 1 IOCB.
                 */
                cont_pkt = qla2x00_prep_cont_type1_iocb(ha);
                cur_dsd = (uint32_t *)cont_pkt->dseg_0_address;
                avail_dsds = 5;
            }

            sle_dma = sg_dma_address(cur_seg);
            *cur_dsd++ = cpu_to_le32(LSD(sle_dma));
            *cur_dsd++ = cpu_to_le32(MSD(sle_dma));
            *cur_dsd++ = cpu_to_le32(sg_dma_len(cur_seg));
            avail_dsds--;

            cur_seg++;
        }
    } else {
        *cur_dsd++ = cpu_to_le32(LSD(sp->dma_handle));
        *cur_dsd++ = cpu_to_le32(MSD(sp->dma_handle));
        *cur_dsd++ = cpu_to_le32(cmd->request_bufflen);
    }
}