コード例 #1
0
static void pvscsi_unmap_buffers(const struct pvscsi_adapter *adapter,
				 struct pvscsi_ctx *ctx)
{
	struct scsi_cmnd *cmd;
	unsigned bufflen;

	cmd = ctx->cmd;
	bufflen = scsi_bufflen(cmd);

	if (bufflen != 0) {
		unsigned count = scsi_sg_count(cmd);

		if (count != 0) {
			scsi_dma_unmap(cmd);
			if (ctx->sglPA) {
				pci_unmap_single(adapter->dev, ctx->sglPA,
						 SGL_SIZE, PCI_DMA_TODEVICE);
				ctx->sglPA = 0;
			}
		} else
			pci_unmap_single(adapter->dev, ctx->dataPA, bufflen,
					 cmd->sc_data_direction);
	}
	if (cmd->sense_buffer)
		pci_unmap_single(adapter->dev, ctx->sensePA,
				 SCSI_SENSE_BUFFERSIZE, PCI_DMA_FROMDEVICE);
}
コード例 #2
0
static int sym_scatter(struct sym_hcb *np, struct sym_ccb *cp, struct scsi_cmnd *cmd)
{
	int segment;
	int use_sg;

	cp->data_len = 0;

	use_sg = scsi_dma_map(cmd);
	if (use_sg > 0) {
		struct scatterlist *sg;
		struct sym_tcb *tp = &np->target[cp->target];
		struct sym_tblmove *data;

		if (use_sg > SYM_CONF_MAX_SG) {
			scsi_dma_unmap(cmd);
			return -1;
		}

		data = &cp->phys.data[SYM_CONF_MAX_SG - use_sg];

		scsi_for_each_sg(cmd, sg, use_sg, segment) {
			dma_addr_t baddr = sg_dma_address(sg);
			unsigned int len = sg_dma_len(sg);

			if ((len & 1) && (tp->head.wval & EWS)) {
				len++;
				cp->odd_byte_adjustment++;
			}

			sym_build_sge(np, &data[segment], baddr, len);
			cp->data_len += len;
		}
	} else {
コード例 #3
0
ファイル: hptiop.c プロジェクト: cilynx/dd-wrt
static void hptiop_host_request_callback(struct hptiop_hba *hba, u32 tag)
{
	struct hpt_iop_request_scsi_command *req;
	struct scsi_cmnd *scp;

	req = (struct hpt_iop_request_scsi_command *)hba->reqs[tag].req_virt;
	dprintk("hptiop_host_request_callback: req=%p, type=%d, "
			"result=%d, context=0x%x tag=%d\n",
			req, req->header.type, req->header.result,
			req->header.context, tag);

	BUG_ON(!req->header.result);
	BUG_ON(req->header.type != cpu_to_le32(IOP_REQUEST_TYPE_SCSI_COMMAND));

	scp = hba->reqs[tag].scp;

	if (HPT_SCP(scp)->mapped)
		scsi_dma_unmap(scp);

	switch (le32_to_cpu(req->header.result)) {
	case IOP_RESULT_SUCCESS:
		scp->result = (DID_OK<<16);
		break;
	case IOP_RESULT_BAD_TARGET:
		scp->result = (DID_BAD_TARGET<<16);
		break;
	case IOP_RESULT_BUSY:
		scp->result = (DID_BUS_BUSY<<16);
		break;
	case IOP_RESULT_RESET:
		scp->result = (DID_RESET<<16);
		break;
	case IOP_RESULT_FAIL:
		scp->result = (DID_ERROR<<16);
		break;
	case IOP_RESULT_INVALID_REQUEST:
		scp->result = (DID_ABORT<<16);
		break;
	case IOP_RESULT_MODE_SENSE_CHECK_CONDITION:
		scp->result = SAM_STAT_CHECK_CONDITION;
		memset(&scp->sense_buffer,
				0, sizeof(scp->sense_buffer));
		memcpy(&scp->sense_buffer, &req->sg_list,
				min(sizeof(scp->sense_buffer),
					le32_to_cpu(req->dataxfer_length)));
		break;

	default:
		scp->result = ((DRIVER_INVALID|SUGGEST_ABORT)<<24) |
					(DID_ABORT<<16);
		break;
	}

	dprintk("scsi_done(%p)\n", scp);
	scp->scsi_done(scp);
	free_req(hba, &hba->reqs[tag]);
}
コード例 #4
0
/*
 *  Complete a pending CAM CCB.
 */
void sym_xpt_done(struct sym_hcb *np, struct scsi_cmnd *cmd)
{
	struct sym_ucmd *ucmd = SYM_UCMD_PTR(cmd);
	BUILD_BUG_ON(sizeof(struct scsi_pointer) < sizeof(struct sym_ucmd));

	if (ucmd->eh_done)
		complete(ucmd->eh_done);

	scsi_dma_unmap(cmd);
	cmd->scsi_done(cmd);
}
コード例 #5
0
ファイル: aha1542.c プロジェクト: avagin/linux
static void aha1542_free_cmd(struct scsi_cmnd *cmd)
{
	struct aha1542_cmd *acmd = scsi_cmd_priv(cmd);
	struct device *dev = cmd->device->host->dma_dev;
	size_t len = scsi_sg_count(cmd) * sizeof(struct chain);

	if (acmd->chain) {
		dma_unmap_single(dev, acmd->chain_handle, len, DMA_TO_DEVICE);
		kfree(acmd->chain);
	}

	acmd->chain = NULL;
	scsi_dma_unmap(cmd);
}
コード例 #6
0
ファイル: wd719x.c プロジェクト: avagin/linux
/* finish a SCSI command, unmap buffers */
static void wd719x_finish_cmd(struct wd719x_scb *scb, int result)
{
	struct scsi_cmnd *cmd = scb->cmd;
	struct wd719x *wd = shost_priv(cmd->device->host);

	list_del(&scb->list);

	dma_unmap_single(&wd->pdev->dev, scb->phys,
			sizeof(struct wd719x_scb), DMA_BIDIRECTIONAL);
	scsi_dma_unmap(cmd);
	dma_unmap_single(&wd->pdev->dev, cmd->SCp.dma_handle,
			 SCSI_SENSE_BUFFERSIZE, DMA_FROM_DEVICE);

	cmd->result = result << 16;
	cmd->scsi_done(cmd);
}
コード例 #7
0
/*
 * Unmap the data buffer and sense buffer for an io_req,
 * also unmap and free the device-private scatter/gather list.
 */
static void fnic_release_ioreq_buf(struct fnic *fnic,
				   struct fnic_io_req *io_req,
				   struct scsi_cmnd *sc)
{
	if (io_req->sgl_list_pa)
		pci_unmap_single(fnic->pdev, io_req->sgl_list_pa,
				 sizeof(io_req->sgl_list[0]) * io_req->sgl_cnt,
				 PCI_DMA_TODEVICE);
	scsi_dma_unmap(sc);

	if (io_req->sgl_cnt)
		mempool_free(io_req->sgl_list_alloc,
			     fnic->io_sgl_pool[io_req->sgl_type]);
	if (io_req->sense_buf_pa)
		pci_unmap_single(fnic->pdev, io_req->sense_buf_pa,
				 SCSI_SENSE_BUFFERSIZE, PCI_DMA_FROMDEVICE);
}
コード例 #8
0
ファイル: esas2r_main.c プロジェクト: Anjali05/linux
int esas2r_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
{
	struct esas2r_adapter *a =
		(struct esas2r_adapter *)cmd->device->host->hostdata;
	struct esas2r_request *rq;
	struct esas2r_sg_context sgc;
	unsigned bufflen;

	/* Assume success, if it fails we will fix the result later. */
	cmd->result = DID_OK << 16;

	if (unlikely(test_bit(AF_DEGRADED_MODE, &a->flags))) {
		cmd->result = DID_NO_CONNECT << 16;
		cmd->scsi_done(cmd);
		return 0;
	}

	rq = esas2r_alloc_request(a);
	if (unlikely(rq == NULL)) {
		esas2r_debug("esas2r_alloc_request failed");
		return SCSI_MLQUEUE_HOST_BUSY;
	}

	rq->cmd = cmd;
	bufflen = scsi_bufflen(cmd);

	if (likely(bufflen != 0)) {
		if (cmd->sc_data_direction == DMA_TO_DEVICE)
			rq->vrq->scsi.flags |= cpu_to_le32(FCP_CMND_WRD);
		else if (cmd->sc_data_direction == DMA_FROM_DEVICE)
			rq->vrq->scsi.flags |= cpu_to_le32(FCP_CMND_RDD);
	}

	memcpy(rq->vrq->scsi.cdb, cmd->cmnd, cmd->cmd_len);
	rq->vrq->scsi.length = cpu_to_le32(bufflen);
	rq->target_id = cmd->device->id;
	rq->vrq->scsi.flags |= cpu_to_le32(cmd->device->lun);
	rq->sense_buf = cmd->sense_buffer;
	rq->sense_len = SCSI_SENSE_BUFFERSIZE;

	esas2r_sgc_init(&sgc, a, rq, NULL);

	sgc.length = bufflen;
	sgc.cur_offset = NULL;

	sgc.cur_sgel = scsi_sglist(cmd);
	sgc.exp_offset = NULL;
	sgc.num_sgel = scsi_dma_map(cmd);
	sgc.sgel_count = 0;

	if (unlikely(sgc.num_sgel < 0)) {
		esas2r_free_request(a, rq);
		return SCSI_MLQUEUE_HOST_BUSY;
	}

	sgc.get_phys_addr = (PGETPHYSADDR)get_physaddr_from_sgc;

	if (unlikely(!esas2r_build_sg_list(a, rq, &sgc))) {
		scsi_dma_unmap(cmd);
		esas2r_free_request(a, rq);
		return SCSI_MLQUEUE_HOST_BUSY;
	}

	esas2r_debug("start request %p to %d:%d\n", rq, (int)cmd->device->id,
		     (int)cmd->device->lun);

	esas2r_start_request(a, rq);

	return 0;
}
コード例 #9
0
ファイル: cciss_scsi.c プロジェクト: lineuman/linux
static void complete_scsi_command(CommandList_struct *c, int timeout,
	__u32 tag)
{
	struct scsi_cmnd *cmd;
	ctlr_info_t *h;
	ErrorInfo_struct *ei;

	ei = c->err_info;

	/* First, see if it was a message rather than a command */
	if (c->Request.Type.Type == TYPE_MSG)  {
		c->cmd_type = CMD_MSG_DONE;
		return;
	}

	cmd = (struct scsi_cmnd *) c->scsi_cmd;
	h = hba[c->ctlr];

	scsi_dma_unmap(cmd);
	if (c->Header.SGTotal > h->max_cmd_sgentries)
		cciss_unmap_sg_chain_block(h, c);

	cmd->result = (DID_OK << 16); 		/* host byte */
	cmd->result |= (COMMAND_COMPLETE << 8);	/* msg byte */
	/* cmd->result |= (GOOD < 1); */		/* status byte */

	cmd->result |= (ei->ScsiStatus);
	/* printk("Scsistatus is 0x%02x\n", ei->ScsiStatus);  */

	/* copy the sense data whether we need to or not. */

	memcpy(cmd->sense_buffer, ei->SenseInfo, 
		ei->SenseLen > SCSI_SENSE_BUFFERSIZE ?
			SCSI_SENSE_BUFFERSIZE : 
			ei->SenseLen);
	scsi_set_resid(cmd, ei->ResidualCnt);

	if(ei->CommandStatus != 0) 
	{ /* an error has occurred */ 
		switch(ei->CommandStatus)
		{
			case CMD_TARGET_STATUS:
				/* Pass it up to the upper layers... */
				if (!ei->ScsiStatus) {
					
	/* Ordinarily, this case should never happen, but there is a bug
	   in some released firmware revisions that allows it to happen
	   if, for example, a 4100 backplane loses power and the tape
	   drive is in it.  We assume that it's a fatal error of some
	   kind because we can't show that it wasn't. We will make it
	   look like selection timeout since that is the most common
	   reason for this to occur, and it's severe enough. */

					cmd->result = DID_NO_CONNECT << 16;
				}
			break;
			case CMD_DATA_UNDERRUN: /* let mid layer handle it. */
			break;
			case CMD_DATA_OVERRUN:
				dev_warn(&h->pdev->dev, "%p has"
					" completed with data overrun "
					"reported\n", c);
			break;
			case CMD_INVALID: {
				/* print_bytes(c, sizeof(*c), 1, 0);
				print_cmd(c); */
     /* We get CMD_INVALID if you address a non-existent tape drive instead
	of a selection timeout (no response).  You will see this if you yank 
	out a tape drive, then try to access it. This is kind of a shame
	because it means that any other CMD_INVALID (e.g. driver bug) will
	get interpreted as a missing target. */
				cmd->result = DID_NO_CONNECT << 16;
				}
			break;
			case CMD_PROTOCOL_ERR:
				cmd->result = DID_ERROR << 16;
				dev_warn(&h->pdev->dev,
					"%p has protocol error\n", c);
                        break;
			case CMD_HARDWARE_ERR:
				cmd->result = DID_ERROR << 16;
				dev_warn(&h->pdev->dev,
					"%p had hardware error\n", c);
                        break;
			case CMD_CONNECTION_LOST:
				cmd->result = DID_ERROR << 16;
				dev_warn(&h->pdev->dev,
					"%p had connection lost\n", c);
			break;
			case CMD_ABORTED:
				cmd->result = DID_ABORT << 16;
				dev_warn(&h->pdev->dev, "%p was aborted\n", c);
			break;
			case CMD_ABORT_FAILED:
				cmd->result = DID_ERROR << 16;
				dev_warn(&h->pdev->dev,
					"%p reports abort failed\n", c);
			break;
			case CMD_UNSOLICITED_ABORT:
				cmd->result = DID_ABORT << 16;
				dev_warn(&h->pdev->dev, "%p aborted due to an "
					"unsolicited abort\n", c);
			break;
			case CMD_TIMEOUT:
				cmd->result = DID_TIME_OUT << 16;
				dev_warn(&h->pdev->dev, "%p timedout\n", c);
			break;
			case CMD_UNABORTABLE:
				cmd->result = DID_ERROR << 16;
				dev_warn(&h->pdev->dev, "c %p command "
					"unabortable\n", c);
			break;
			default:
				cmd->result = DID_ERROR << 16;
				dev_warn(&h->pdev->dev,
					"%p returned unknown status %x\n", c,
						ei->CommandStatus); 
		}
	}
	cmd->scsi_done(cmd);
	scsi_cmd_free(h, c);
}