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

📄 mptscsih.c

📁 上传linux-jx2410的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
				if (sg)					dest = (u8 *) (unsigned long)sg_dma_address(sg);			}			if (dest && mpt_sdev->sense_sz) {				memcpy(dest, mpt_sdev->CachedSense.data, mpt_sdev->sense_sz);#ifdef MPT_DEBUG				{					int  i;					u8  *sb;					sb = mpt_sdev->CachedSense.data;					if (sb && ((sb[0] & 0x70) == 0x70)) {						printk(KERN_WARNING MYNAM ": Returning last cached SCSI (hex) SenseData:\n");						printk(KERN_WARNING " ");						for (i = 0; i < (8 + sb[7]); i++)							printk("%s%02x", i == 13 ? "-" : " ", sb[i]);						printk("\n");					}				}#endif			}			SCpnt->resid = SCpnt->request_bufflen - mpt_sdev->sense_sz;			SCpnt->result = 0;/*			spin_lock(&io_request_lock);	*/			SCpnt->scsi_done(SCpnt);/*			spin_unlock(&io_request_lock);	*/			return 0;		}	}#endif	if ((mf = mpt_get_msg_frame(ScsiDoneCtx, hd->ioc->id)) == NULL) {/*		SCpnt->result = DID_SOFT_ERROR << 16;	*/		SCpnt->result = STS_BUSY;		SCpnt->scsi_done(SCpnt);/*		return 1;				*/		return 0;	}	pScsiReq = (SCSIIORequest_t *) mf;	my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);	ADD_INDEX_LOG(my_idx);	/* Map the data portion, if any. */	sges_left = SCpnt->use_sg;	if (sges_left) {		sges_left = pci_map_sg(hd->ioc->pcidev,				       (struct scatterlist *) SCpnt->request_buffer,				       sges_left,				       scsi_to_pci_dma_dir(SCpnt->sc_data_direction));	} else if (SCpnt->request_bufflen) {		dma_addr_t buf_dma_addr;		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. */		SCpnt->SCp.ptr = (char *)(unsigned long) buf_dma_addr;	}	/*	 *  Put together a MPT SCSI request...	 */	/* Assume SimpleQ, NO DATA XFER for now */	len = SCpnt->request_bufflen;	sgdir = 0x00000000;		/* SGL IN  (host<--ioc) */	scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER;	/*	 *  The scsi layer should be handling this stuff	 *  (In 2.3.x it does -DaveM)	 */	/*  BUG FIX!  19991030 -sralston	 *    TUR's being issued with scsictl=0x02000000 (DATA_IN)!	 *    Seems we may receive a buffer (len>0) even when there	 *    will be no data transfer!  GRRRRR...	 */	datadir = mptscsih_io_direction(SCpnt);	if (datadir < 0) {		scsidir = MPI_SCSIIO_CONTROL_READ;	/* DATA IN  (host<--ioc<--dev) */	} else if (datadir > 0) {		sgdir	= 0x04000000;			/* SGL OUT  (host-->ioc) */		scsidir = MPI_SCSIIO_CONTROL_WRITE;	/* DATA OUT (host-->ioc-->dev) */	} else {		len = 0;	}	qtag = MPI_SCSIIO_CONTROL_SIMPLEQ;	/*	 *  Attach tags to the devices	 */	if (SCpnt->device->tagged_supported) {		/*		 *  Some drives are too stupid to handle fairness issues		 *  with tagged queueing. We throw in the odd ordered		 *  tag to stop them starving themselves.		 */		if ((jiffies - hd->qtag_tick) > (5*HZ)) {			qtag = MPI_SCSIIO_CONTROL_ORDEREDQ;			hd->qtag_tick = jiffies;#if 0			/* These are ALWAYS zero!			 * (Because this is a place for the device driver to dynamically			 *  assign tag numbers any way it sees fit.  That's why -DaveM)			 */			dprintk((KERN_DEBUG MYNAM ": sc->device->current_tag = %08x\n",					SCpnt->device->current_tag));			dprintk((KERN_DEBUG MYNAM ": sc->tag                 = %08x\n",					SCpnt->tag));#endif		}#if 0		else {			/* Hmmm...  I always see value of 0 here,			 *  of which {HEAD_OF, ORDERED, SIMPLE} are NOT!  -sralston			 * (Because this is a place for the device driver to dynamically			 *  assign tag numbers any way it sees fit.  That's why -DaveM)			 *			 * if (SCpnt->tag == HEAD_OF_QUEUE_TAG)			 */			if (SCpnt->device->current_tag == HEAD_OF_QUEUE_TAG)				qtag = MPI_SCSIIO_CONTROL_HEADOFQ;			else if (SCpnt->tag == ORDERED_QUEUE_TAG)				qtag = MPI_SCSIIO_CONTROL_ORDEREDQ;		}#endif	}	scsictl = scsidir | qtag;	frm_sz = hd->ioc->req_sz;	/* Ack!	 * sge_spill1 = 9;	 */	sge_spill1 = (frm_sz - (sizeof(SCSIIORequest_t) - sizeof(SGEIOUnion_t) + sizeof(SGEChain32_t))) / 8;	/*  spill1: for req_sz == 128 (128-48==80, 80/8==10 SGEs max, first time!), --> use 9	 *  spill1: for req_sz ==  96 ( 96-48==48, 48/8== 6 SGEs max, first time!), --> use 5	 */	dsgprintk((KERN_INFO MYNAM ": SG: %x     spill1 = %d\n",		   my_idx, sge_spill1));#ifdef MPT_DEBUG	if (sges_left > max_sges) {		max_sges = sges_left;		dprintk((KERN_INFO MYNAM ": MPT_MaxSges = %d\n", max_sges));	}#endif#if 0	if (sges_left > max_num_sges) {		max_num_sges = sges_left;		printk(KERN_INFO MYNAM ": MPT_MaxNumSges = %d\n", max_num_sges);	}#endif	dsgprintk((KERN_INFO MYNAM ": SG: %x     sges_left = %d (initially)\n",		   my_idx, sges_left));	chain_offset = 0;	if (sges_left > (sge_spill1+1)) {#if 0		chain_offset = 0x1E;#endif		chain_offset = (frm_sz - 8) / 4;	}	pScsiReq->TargetID = SCpnt->target;	pScsiReq->Bus = hd->port;	pScsiReq->ChainOffset = chain_offset;	pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;	pScsiReq->CDBLength = SCpnt->cmd_len;/* We have 256 bytes alloc'd per IO; let's use it. *//*	pScsiReq->SenseBufferLength = SNS_LEN(SCpnt);	*/	pScsiReq->SenseBufferLength = 255;	pScsiReq->Reserved = 0;	pScsiReq->MsgFlags = 0;	pScsiReq->LUN[0] = 0;	pScsiReq->LUN[1] = SCpnt->lun;	pScsiReq->LUN[2] = 0;	pScsiReq->LUN[3] = 0;	pScsiReq->LUN[4] = 0;	pScsiReq->LUN[5] = 0;	pScsiReq->LUN[6] = 0;	pScsiReq->LUN[7] = 0;	pScsiReq->Control = cpu_to_le32(scsictl);	/*	 *  Write SCSI CDB into the message	 */	for (i = 0; i < 12; i++)		pScsiReq->CDB[i] = SCpnt->cmnd[i];	for (i = 12; i < 16; i++)		pScsiReq->CDB[i] = 0;	/* DataLength */	pScsiReq->DataLength = cpu_to_le32(len);	/* SenseBuffer low address */	pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_pool_dma + (my_idx * 256));	mptr = (u32 *) &pScsiReq->SGL;	/*	 *  Now fill in the SGList...	 *  NOTES: For 128 byte req_sz, we can hold up to 10 simple SGE's	 *  in the remaining request frame.  We -could- do unlimited chains	 *  but each chain buffer can only be req_sz bytes in size, and	 *  we lose one SGE whenever we chain.	 *  For 128 req_sz, we can hold up to 16 SGE's per chain buffer.	 *  For practical reasons, limit ourselves to 1 overflow chain buffer;	 *  giving us 9 + 16 == 25 SGE's max.	 *  At 4 Kb per SGE, that yields 100 Kb max transfer.	 *	 *  (This code needs to be completely changed when/if 64-bit DMA	 *   addressing is used, since we will be able to fit much less than	 *   10 embedded SG entries. -DaveM)	 */	if (sges_left) {		struct scatterlist *sg = (struct scatterlist *) SCpnt->request_buffer;		u32  v1, v2;		int  sge_spill2;		int  sge_cur_spill;		int  sgCnt;		u8  *pSgBucket;		int  chain_sz;		len = 0;		/*	sge_spill2 = 15;		 *  spill2: for req_sz == 128 (128/8==16 SGEs max, first time!), --> use 15		 *  spill2: for req_sz ==  96 ( 96/8==12 SGEs max, first time!), --> use 11		 */		sge_spill2 = frm_sz / 8 - 1;		dsgprintk((KERN_INFO MYNAM ": SG: %x     spill2 = %d\n",			   my_idx, sge_spill2));		pSgBucket = NULL;		sgCnt = 0;		sge_cur_spill = sge_spill1;		while (sges_left) {#if 0			if (sg_dma_len(sg) > max_sgent_len) {				max_sgent_len = sg_dma_len(sg);				printk(KERN_INFO MYNAM ": MPT_MaxSgentLen = %d\n", max_sgent_len);			}#endif			/* Write one simple SGE */			v1 = sgdir | 0x10000000 | sg_dma_len(sg);			len += sg_dma_len(sg);			v2 = sg_dma_address(sg);			dsgprintk((KERN_INFO MYNAM ": SG: %x     Writing SGE @%p: %08x %08x, sges_left=%d\n",				   my_idx, mptr, v1, v2, sges_left));			*mptr++ = cpu_to_le32(v1);			*mptr++ = cpu_to_le32(v2);			sg++;			sgCnt++;			if (--sges_left == 0) {				/* re-write 1st word of previous SGE with SIMPLE,				 * LE, EOB, and EOL bits!				 */				v1 = 0xD1000000 | sgdir | sg_dma_len(sg-1);				dsgprintk((KERN_INFO MYNAM ": SG: %x (re)Writing SGE @%p: %08x (VERY LAST SGE!)\n",					   my_idx, mptr-2, v1));				*(mptr - 2) = cpu_to_le32(v1);			} else {				if ((sges_left > 1) && ((sgCnt % sge_cur_spill) == 0)) {					dsgprintk((KERN_INFO MYNAM ": SG: %x     SG spill at modulo 0!\n",						   my_idx));					/* Fixup previous SGE with LE bit! */					v1 = sgdir | 0x90000000 | sg_dma_len(sg-1);					dsgprintk((KERN_INFO MYNAM ": SG: %x (re)Writing SGE @%p: %08x (LAST BUCKET SGE!)\n",						   my_idx, mptr-2, v1));					*(mptr - 2) = cpu_to_le32(v1);					chain_offset = 0;					/* Going to need another chain? */					if (sges_left > (sge_spill2+1)) {#if 0						chain_offset = 0x1E;#endif						chain_offset = (frm_sz - 8) / 4;						chain_sz = frm_sz;					} else {						chain_sz = sges_left * 8;					}					/* write chain SGE at mptr. */					v1 = 0x30000000 | chain_offset<<16 | chain_sz;					if (pSgBucket == NULL) {						pSgBucket = hd->SgHunks							+ (my_idx * frm_sz * MPT_SG_BUCKETS_PER_HUNK);					} else {						pSgBucket += frm_sz;					}					v2 = (hd->SgHunksDMA +					      ((u8 *)pSgBucket - (u8 *)hd->SgHunks));					dsgprintk((KERN_INFO MYNAM ": SG: %x     Writing SGE @%p: %08x %08x (CHAIN!)\n",						   my_idx, mptr, v1, v2));					*(mptr++) = cpu_to_le32(v1);					*(mptr) = cpu_to_le32(v2);					mptr = (u32 *) pSgBucket;					sgCnt = 0;					sge_cur_spill = sge_spill2;				}			}		}	} else {		dsgprintk((KERN_INFO MYNAM ": SG: non-SG for %p, len=%d\n",			   SCpnt, SCpnt->request_bufflen));		if (len > 0) {			dma_addr_t buf_dma_addr;			buf_dma_addr = (dma_addr_t) (unsigned long)SCpnt->SCp.ptr;			*(mptr++) = cpu_to_le32(0xD1000000|sgdir|SCpnt->request_bufflen);			*(mptr++) = cpu_to_le32(buf_dma_addr);		}	}#ifdef MPT_DEBUG	/* if (SCpnt->request_bufflen > max_xfer) */	if (len > max_xfer) {		max_xfer = len;		dprintk((KERN_INFO MYNAM ": MPT_MaxXfer = %d\n", max_xfer));	}#endif	hd->ScsiLookup[my_idx] = SCpnt;	/* Main banana... */	mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);	atomic_inc(&queue_depth);	if (atomic_read(&queue_depth) > max_qd) {		max_qd = atomic_read(&queue_depth);		dprintk((KERN_INFO MYNAM ": Queue depth now %d.\n", max_qd));	}	dmfprintk((KERN_INFO MYNAM ": Issued SCSI cmd (%p)\n", SCpnt));	return 0;}#ifdef MPT_SCSI_USE_NEW_EH		/* { *//*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//*    mptscsih_abort    Returns: 0=SUCCESS, else FAILED*//*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mptscsih_abort - Abort linux Scsi_Cmnd routine, new_eh variant *	@SCpnt: Pointer to Scsi_Cmnd structure, IO to be aborted * *	(linux Scsi_Host_Template.eh_abort_handler routine) * *	Returns SUCCESS or FAILED.   */intmptscsih_abort(Scsi_Cmnd * SCpnt){	MPT_FRAME_HDR	*mf;	SCSITaskMgmt_t	*pScsiTm;	MPT_SCSI_HOST	*hd;	u32		*msg;	u32		 ctx2abort;	int		 i;	unsigned long	 flags;	printk(KERN_WARNING MYNAM ": Attempting _ABORT SCSI IO (=%p)\n", SCpnt);	printk(KERN_WARNING MYNAM ": IOs outstanding = %d\n", atomic_read(&queue_depth));	hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata;	if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc->id)) == NULL) {/*		SCpnt->result = DID_SOFT_ERROR << 16;	*/		SCpnt->result = STS_BUSY;		SCpnt->scsi_done(SCpnt);		return FAILED;	}	pScsiTm = (SCSITaskMgmt_t *) mf;	msg = (u32 *) mf;	pScsiTm->TargetID = SCpnt->target;	pScsiTm->Bus = hd->port;	pScsiTm->ChainOffset = 0;	pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;	pScsiTm->Reserved = 0;	pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK;	pScsiTm->Reserved1 = 0;	pScsiTm->MsgFlags = 0;	for (i = 0; i < 8; i++) {		u8 val = 0;		if (i == 1)			val = SCpnt->lun;		pScsiTm->LUN[i] = val;	}	for (i = 0; i < 7; i++)		pScsiTm->Reserved2[i] = 0;	/* Most important!  Set TaskMsgContext to SCpnt's MsgContext!	 * (the IO to be ABORT'd)	 *	 * NOTE: Since we do not byteswap MsgContext, we do not	 *	 swap it here either.  It is an opaque cookie to	 *	 the controller, so it does not matter. -DaveM	 */	ctx2abort = SCPNT_TO_MSGCTX(SCpnt);	if (ctx2abort == -1) {		printk(KERN_ERR MYNAM ": ERROR - ScsiLookup fail(#2) for SCpnt=%p\n", SCpnt);		SCpnt->result = DID_SOFT_ERROR << 16;		spin_lock_irqsave(&io_request_lock, flags);		SCpnt->scsi_done(SCpnt);		spin_unlock_irqrestore(&io_request_lock, flags);		mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);	} else {		dprintk((KERN_INFO MYNAM ":DbG: ctx2abort = %08x\n", ctx2abort));		pScsiTm->TaskMsgContext = ctx2abort;		/* MPI v0.10 requires SCSITaskMgmt requests be sent via Doorbell/handshake			mpt_put_msg_frame(hd->ioc->id, mf);		*/		if ((i = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id,					sizeof(SCSITaskMgmt_t), msg))		    != 0) {			printk(KERN_WARNING MYNAM					": WARNING[2] - IOC error (%d) processing TaskMgmt request (mf=%p:sc=%p)\n",					i, mf, SCpnt);			SCpnt->result = DID_SOFT_ERROR << 16;			spin_lock_irqsave(&io_request_lock, flags);			SCpnt->scsi_done(SCpnt);			spin_unlock_irqrestore(&io_request_lock, flags);			mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);		}

⌨️ 快捷键说明

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