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