⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mptscsih.c

📁 microwindows移植到S3C44B0的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
			if (dropCounter == DROP_THIS_CMD) {				dropCounter = 0;				/* If global is set, then we are already				 * doing something - so keep issuing commands.				 */				if (dropMfPtr == NULL) {					dropTestNum++;					dropMfPtr = mf;					atomic_inc(&queue_depth);					printk(MYIOC_s_INFO_FMT						"Dropped SCSI cmd (%p)\n",						hd->ioc->name, SCpnt);					printk("mf (%p) req (%4x) tot cmds (%d)\n",						mf, my_idx, numTotCmds);					return 0;				}			}		}#endif		/* SCSI specific processing */		issueCmd = 1;		if (hd->is_spi) {			int dvStatus = hd->ioc->spi_data.dvStatus[target];			if (dvStatus || hd->ioc->spi_data.forceDv) {				/* Write SDP1 on 1st I/O to this target */				if (dvStatus & MPT_SCSICFG_NEGOTIATE) {					mptscsih_writeSDP1(hd, 0, target, hd->negoNvram);					dvStatus &= ~MPT_SCSICFG_NEGOTIATE;					hd->ioc->spi_data.dvStatus[target] =  dvStatus;				}#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION				if ((dvStatus & MPT_SCSICFG_NEED_DV) || hd->ioc->spi_data.forceDv) {					unsigned long lflags;					/* Schedule DV if necessary */					spin_lock_irqsave(&dvtaskQ_lock, lflags);					if (!dvtaskQ_active) {						dvtaskQ_active = 1;						mptscsih_dvTask.sync = 0;						mptscsih_dvTask.routine = mptscsih_domainValidation;						mptscsih_dvTask.data = (void *) hd;						SCHEDULE_TASK(&mptscsih_dvTask);					}					hd->ioc->spi_data.forceDv = 0;					spin_unlock_irqrestore(&dvtaskQ_lock, lflags);				}				/* Trying to do DV to this target, extend timeout.				 * Wait to issue intil flag is clear 				 */				if (dvStatus & MPT_SCSICFG_DV_PENDING) {					mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ);					issueCmd = 0;				}#endif			}		}		if (issueCmd) {			mptscsih_put_msgframe(ScsiDoneCtx, hd->ioc->id, mf);			dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p)\n",					hd->ioc->name, SCpnt));		} else {			ddvtprintk((MYIOC_s_INFO_FMT "Pending SCSI cmd (%p)\n",					hd->ioc->name, SCpnt));			/* Place this command on the pendingQ if possible */			spin_lock_irqsave(&hd->freedoneQlock, flags);			if (!Q_IS_EMPTY(&hd->freeQ)) {				buffer = hd->freeQ.head;				Q_DEL_ITEM(buffer);				/* Save the mf pointer				 */				buffer->argp = (void *)mf;				/* Add to the pendingQ				 */				Q_ADD_TAIL(&hd->pendingQ.head, buffer, MPT_DONE_Q);				spin_unlock_irqrestore(&hd->freedoneQlock, flags);			} else {				spin_unlock_irqrestore(&hd->freedoneQlock, flags);				SCpnt->result = (DID_BUS_BUSY << 16);				SCpnt->scsi_done(SCpnt);			}		}	} else {		mptscsih_freeChainBuffers(hd, my_idx);		mpt_free_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);		did_errcode = 3;		goto did_error;	}	return 0;did_error:	dprintk((MYIOC_s_WARN_FMT "_qcmd did_errcode=%d (sc=%p)\n",			hd->ioc->name, did_errcode, SCpnt));	/* Just wish OS to issue a retry */	SCpnt->result = (DID_BUS_BUSY << 16);	spin_lock_irqsave(&hd->freedoneQlock, flags);	if (!Q_IS_EMPTY(&hd->freeQ)) {		buffer = hd->freeQ.head;		Q_DEL_ITEM(buffer);		/* Set the Scsi_Cmnd pointer		 */		buffer->argp = (void *)SCpnt;		/* Add to the doneQ		 */		Q_ADD_TAIL(&hd->doneQ.head, buffer, MPT_DONE_Q);		spin_unlock_irqrestore(&hd->freedoneQlock, flags);	} else {		spin_unlock_irqrestore(&hd->freedoneQlock, flags);		SCpnt->scsi_done(SCpnt);	}	return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *	mptscsih_Add32BitSGE - Add a 32Bit SGE (plus chain buffers) to the *	SCSIIORequest_t Message Frame. *	@hd: Pointer to MPT_SCSI_HOST structure *	@SCpnt: Pointer to Scsi_Cmnd structure *	@pReq: Pointer to SCSIIORequest_t structure * *	Returns ... */static intmptscsih_Add32BitSGE(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt,				 SCSIIORequest_t *pReq, int req_idx){	MptSge_t *psge;	MptChain_t  *chainSge;	struct scatterlist *sg;	int	 frm_sz;	int	 sges_left, sg_done;	int	 chain_idx = MPT_HOST_NO_CHAIN;	int	 sgeOffset;	int	 numSgeSlots, numSgeThisFrame;	u32	 sgflags, sgdir, len, thisxfer = 0;	int	 offset;	int	 newIndex;	int	 ii;	dma_addr_t v2;	sgdir = le32_to_cpu(pReq->Control) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK;	if (sgdir == MPI_SCSIIO_CONTROL_WRITE)  {		sgdir = MPT_TRANSFER_HOST_TO_IOC;	} else {		sgdir = MPT_TRANSFER_IOC_TO_HOST;	}	psge = (MptSge_t *) &pReq->SGL;	frm_sz = hd->ioc->req_sz;	/* Map the data portion, if any.	 * sges_left  = 0 if no data transfer.	 */	sges_left = SCpnt->use_sg;	if (SCpnt->use_sg) {		sges_left = pci_map_sg(hd->ioc->pcidev,			       (struct scatterlist *) SCpnt->request_buffer,			       SCpnt->use_sg,			       scsi_to_pci_dma_dir(SCpnt->sc_data_direction));	} else if (SCpnt->request_bufflen) {		dma_addr_t	 buf_dma_addr;		scPrivate	*my_priv;		buf_dma_addr = pci_map_single(hd->ioc->pcidev,				      SCpnt->request_buffer,				      SCpnt->request_bufflen,				      scsi_to_pci_dma_dir(SCpnt->sc_data_direction));		/* We hide it here for later unmap. */		my_priv = (scPrivate *) &SCpnt->SCp;		my_priv->p1 = (void *)(ulong) buf_dma_addr;		dsgprintk((MYIOC_s_INFO_FMT "SG: non-SG for %p, len=%d\n",				hd->ioc->name, SCpnt, SCpnt->request_bufflen));		/* 0xD1000000 = LAST | EOB | SIMPLE | EOL */		psge->FlagsLength = cpu_to_le32(				0xD1000000|sgdir|SCpnt->request_bufflen);		cpu_to_leXX(buf_dma_addr, psge->Address);		return SUCCESS;	}	/* Handle the SG case.	 */	sg = (struct scatterlist *) SCpnt->request_buffer;	sg_done  = 0;	sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION);	chainSge = NULL;	/* Prior to entering this loop - the following must be set	 * current MF:  sgeOffset (bytes)	 *              chainSge (Null if original MF is not a chain buffer)	 *              sg_done (num SGE done for this MF)	 */nextSGEset:	numSgeSlots = ((frm_sz - sgeOffset) / sizeof(MptSge_t));	numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots;	sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir;	/* Get first (num - 1) SG elements	 * Skip any SG entries with a length of 0	 * NOTE: at finish, sg and psge pointed to NEXT data/location positions	 */	for (ii=0; ii < (numSgeThisFrame-1); ii++) {		thisxfer = sg_dma_len(sg);		if (thisxfer == 0) {			sg ++; /* Get next SG element from the OS */			sg_done++;			continue;		}		len += thisxfer;		psge->FlagsLength = cpu_to_le32( sgflags | thisxfer );		v2 = sg_dma_address(sg);		cpu_to_leXX(v2, psge->Address);		sg++;		/* Get next SG element from the OS */		psge++;		/* Point to next SG location in this MF */		sgeOffset += sizeof(MptSge_t);		sg_done++;	}	if (numSgeThisFrame == sges_left) {		/* Add last element, end of buffer and end of list flags.		 */		sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT |				MPT_SGE_FLAGS_END_OF_BUFFER |				MPT_SGE_FLAGS_ADDRESSING |				MPT_SGE_FLAGS_END_OF_LIST;		/* Add last SGE and set termination flags.		 * Note: Last SGE may have a length of 0 - which should be ok.		 */		thisxfer = sg_dma_len(sg);		len += thisxfer;		psge->FlagsLength = cpu_to_le32( sgflags | thisxfer );		v2 = sg_dma_address(sg);		cpu_to_leXX(v2, psge->Address);		sg_done++;		if (chainSge) {			/* The current buffer is a chain buffer,			 * but there is not another one.			 * Update the chain element			 * Offset and Length fields.			 */			chainSge->NextChainOffset = 0;			sgeOffset += sizeof(MptSge_t);			chainSge->Length = cpu_to_le16(sgeOffset);		} else {			/* The current buffer is the original MF			 * and there is no Chain buffer.			 */			pReq->ChainOffset = 0;		}	} else {		/* At least one chain buffer is needed.		 * Complete the first MF		 *  - last SGE element, set the LastElement bit		 *  - set ChainOffset (words) for orig MF		 *             (OR finish previous MF chain buffer)		 *  - update MFStructPtr ChainIndex		 *  - Populate chain element		 * Also		 * Loop until done.		 */		dsgprintk((MYIOC_s_INFO_FMT "SG: Chain Required! sg done %d\n",				hd->ioc->name, sg_done));		/* Set LAST_ELEMENT flag for last non-chain element		 * in the buffer. Since psge points at the NEXT		 * SGE element, go back one SGE element, update the flags		 * and reset the pointer. (Note: sgflags & thisxfer are already		 * set properly).		 */		if (sg_done) {			psge--;			sgflags = le32_to_cpu (psge->FlagsLength);			sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT;			psge->FlagsLength = cpu_to_le32( sgflags );			psge++;		}		if (chainSge) {			/* The current buffer is a chain buffer.			 * chainSge points to the previous Chain Element.			 * Update its chain element Offset and Length (must			 * include chain element size) fields.			 * Old chain element is now complete.			 */			chainSge->NextChainOffset = (u8) (sgeOffset >> 2);			sgeOffset += sizeof(MptSge_t);			chainSge->Length = cpu_to_le16(sgeOffset);		} else {			/* The original MF buffer requires a chain buffer -			 * set the offset.			 * Last element in this MF is a chain element.			 */			pReq->ChainOffset = (u8) (sgeOffset >> 2);		}		sges_left -= sg_done;		/* NOTE: psge points to the beginning of the chain element		 * in current buffer. Get a chain buffer.		 */		if ((mptscsih_getFreeChainBuffer(hd, &newIndex)) == FAILED)			return FAILED;		/* Update the tracking arrays.		 * If chainSge == NULL, update ReqToChain, else ChainToChain		 */		if (chainSge) {			hd->ChainToChain[chain_idx] = newIndex;		} else {			hd->ReqToChain[req_idx] = newIndex;		}		chain_idx = newIndex;		offset = hd->ioc->req_sz * chain_idx;		/* Populate the chainSGE for the current buffer.		 * - Set chain buffer pointer to psge and fill		 *   out the Address and Flags fields.		 */		chainSge = (MptChain_t *) psge;		chainSge->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT;		cpu_to_leXX ((hd->ChainBufferDMA + offset), chainSge->Address);		dsgprintk((KERN_INFO "  Current buff @ %p (index 0x%x)",				psge, req_idx));		/* Start the SGE for the next buffer		 */		psge = (MptSge_t *) (hd->ChainBuffer + offset);		sgeOffset = 0;		sg_done = 0;		dsgprintk((KERN_INFO "  Chain buff @ %p (index 0x%x)\n",				psge, chain_idx));		/* Start the SGE for the next buffer		 */		goto nextSGEset;	}	return SUCCESS;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *	mptscsih_AddNullSGE - Add a NULL SGE to the SCSIIORequest_t *	Message Frame. *	@pReq: Pointer to SCSIIORequest_t structure */static voidmptscsih_AddNullSGE(SCSIIORequest_t *pReq){	MptSge_t *psge;	psge = (MptSge_t *) &pReq->SGL;	psge->FlagsLength = cpu_to_le32(MPT_SGE_FLAGS_SSIMPLE_READ | 0);	cpu_to_leXX( (dma_addr_t) -1, psge->Address);	return;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *	mptscsih_getFreeChainBuffes - Function to get a free chain *	from the MPT_SCSI_HOST FreeChainQ. *	@hd: Pointer to the MPT_SCSI_HOST instance *	@req_idx: Index of the SCSI IO request frame. (output) * *	return SUCCESS or FAILED */static intmptscsih_getFreeChainBuffer(MPT_SCSI_HOST *hd, int *retIndex){	MPT_FRAME_HDR *chainBuf = NULL;	unsigned long flags;	int rc = FAILED;	int chain_idx = MPT_HOST_NO_CHAIN;	//spin_lock_irqsave(&hd->FreeChainQlock, flags);	spin_lock_irqsave(&hd->ioc->FreeQlock, flags);	if (!Q_IS_EMPTY(&hd->FreeChainQ)) {		int offset;		chainBuf = hd->FreeChainQ.head;		Q_DEL_ITEM(&chainBuf->u.frame.linkage);		offset = (u8 *)chainBuf - (u8 *)hd->ChainBuffer;		chain_idx = offset / hd->ioc->req_sz;		rc = SUCCESS;	}	//spin_unlock_irqrestore(&hd->FreeChainQlock, flags);	spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);	*retIndex = chain_idx;	dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer (index %d), got buf=%p\n",			hd->ioc->name, *retIndex, chainBuf));	return rc;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *	mptscsih_freeChainBuffers - Function to free chain buffers associated *	with a SCSI IO request *	@hd: Pointer to the MPT_SCSI_HOST instance *	@req_idx: Index of the SCSI IO request frame. * *	Called if SG chain buffer allocation fails and mptscsih callbacks. *	No return. */static voidmptscsih_freeChainBuffers(MPT_SCSI_HOST *hd, int req_idx){	MPT_FRAME_HDR *chain = NULL;	unsigned long flags;	int chain_idx;	int next;	/* Get the first chain index and reset	 * tracker state.	 */	chain_idx = hd->ReqToChain[req_idx];	hd->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;	while (chain_idx != MPT_HOST_NO_CHAIN) {		/* Save the next chain buffer index */		next = hd->ChainToChain[chain_idx];		/* Free this chain buffer and reset		 * tracker		 */		hd->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;		chain = (MPT_FRAME_HDR *) (hd->ChainBuffe

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -