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

📄 mptscsih.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	info.buffer	= pbuf;	info.length	= len;	info.offset	= offset;	info.pos	= 0;	copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name);	copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);	copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts);	copy_info(&info, "MaxQ=%d\n", ioc->req_depth);	return ((info.pos > info.offset) ? info.pos - info.offset : 0);}#ifndef MPTSCSIH_DBG_TIMEOUTstatic int mptscsih_user_command(MPT_ADAPTER *ioc, char *pbuf, int len){	/* Not yet implemented */	return len;}#else#define is_digit(c)	((c) >= '0' && (c) <= '9')#define digit_to_bin(c)	((c) - '0')#define is_space(c)	((c) == ' ' || (c) == '\t')#define UC_DBG_TIMEOUT		0x01#define UC_DBG_HARDRESET	0x02static int skip_spaces(char *ptr, int len){	int cnt, c;	for (cnt = len; cnt > 0 && (c = *ptr++) && is_space(c); cnt --);	return (len - cnt);}static int get_int_arg(char *ptr, int len, ulong *pv){	int cnt, c;	ulong	v;	for (v =  0, cnt = len; cnt > 0 && (c=*ptr++) && is_digit(c); cnt --) {		v = (v * 10) + digit_to_bin(c);	}	if (pv)		*pv = v;	return (len - cnt);}static int is_keyword(char *ptr, int len, char *verb){	int verb_len = strlen(verb);	if (len >= strlen(verb) && !memcmp(verb, ptr, verb_len))		return verb_len;	else		return 0;}#define SKIP_SPACES(min_spaces)						\	if ((arg_len = skip_spaces(ptr,len)) < (min_spaces))		\		return -EINVAL;						\	ptr += arg_len;							\	len -= arg_len;#define GET_INT_ARG(v)							\	if (!(arg_len = get_int_arg(ptr,len, &(v))))			\		return -EINVAL;						\	ptr += arg_len;							\	len -= arg_len;static int mptscsih_user_command(MPT_ADAPTER *ioc, char *buffer, int length){	char *ptr = buffer;	char btmp[24];	/* REMOVE */	int arg_len;	int len	= length;	int cmd;	ulong number = 1;	ulong delta = 10;	if ((len > 0) && (ptr[len -1] == '\n'))		--len;	if (len < 22) {		strncpy(btmp, buffer, len);		btmp[len+1]='\0';	} else {		strncpy(btmp, buffer, 22);		btmp[23]='\0';	}	printk("user_command:  ioc %d, buffer %s, length %d\n",			ioc->id, btmp, length);	if ((arg_len = is_keyword(ptr, len, "timeout")) != 0)		cmd = UC_DBG_TIMEOUT;	else if ((arg_len = is_keyword(ptr, len, "hardreset")) != 0)		cmd = UC_DBG_HARDRESET;	else		return -EINVAL;	ptr += arg_len;	len -= arg_len;	switch(cmd) {		case UC_DBG_TIMEOUT:			SKIP_SPACES(1);			GET_INT_ARG(number);			SKIP_SPACES(1);			GET_INT_ARG(delta);			break;	}	printk("user_command: cnt=%ld delta=%ld\n", number, delta);	if (len)		return -EINVAL;	else {		if (cmd == UC_DBG_HARDRESET) {			ioc->timeout_hard = 1;		} else if (cmd == UC_DBG_TIMEOUT) {			/* process this command ...			 */			ioc->timeout_maxcnt = 0;			ioc->timeout_delta = delta < 2 ? 2 : delta;			ioc->timeout_cnt = 0;			ioc->timeout_maxcnt = number < 8 ? number: 8;		}	}	/* Not yet implemented */	return length;}#endif/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mptscsih_proc_info - Return information about MPT adapter * *	(linux scsi_host_template.info routine) * * 	buffer: if write, user data; if read, buffer for user * 	length: if write, return length; * 	offset: if write, 0; if read, the current offset into the buffer from * 		the previous read. * 	hostno: scsi host number *	func:   if write = 1; if read = 0 */int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,			int length, int func){	MPT_SCSI_HOST	*hd = (MPT_SCSI_HOST *)host->hostdata;	MPT_ADAPTER	*ioc = hd->ioc;	int size = 0;	if (func) {		size = mptscsih_user_command(ioc, buffer, length);	} else {		if (start)			*start = buffer;		size = mptscsih_host_info(ioc, buffer, offset, length);	}	return size;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/#define ADD_INDEX_LOG(req_ent)	do { } while(0)/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine. *	@SCpnt: Pointer to scsi_cmnd structure *	@done: Pointer SCSI mid-layer IO completion function * *	(linux scsi_host_template.queuecommand routine) *	This is the primary SCSI IO start routine.  Create a MPI SCSIIORequest *	from a linux scsi_cmnd request and send it to the IOC. * *	Returns 0. (rtn value discarded by linux scsi mid-layer) */intmptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)){	MPT_SCSI_HOST		*hd;	MPT_FRAME_HDR		*mf;	SCSIIORequest_t		*pScsiReq;	VirtDevice		*pTarget;	MPT_DONE_Q		*buffer;	unsigned long		 flags;	int	 target;	int	 lun;	u32	 datalen;	u32	 scsictl;	u32	 scsidir;	u32	 cmd_len;	int	 my_idx;	int	 ii;	int	 rc;	int	 did_errcode;	int	 issueCmd;	did_errcode = 0;	hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;	target = SCpnt->device->id;	lun = SCpnt->device->lun;	SCpnt->scsi_done = done;	pTarget = hd->Targets[target];	dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n",			(hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done));	if (hd->resetPending) {		/* Prevent new commands from being issued		 * while reloading the FW. Reset timer to 60 seconds,		 * as the FW can take some time to come ready.		 * For New EH, cmds on doneQ posted to FW.		 */		did_errcode = 1;		mod_timer(&SCpnt->eh_timeout, jiffies + (HZ * 60));		dtmprintk((MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n",			(hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt));		goto did_error;	}	/*	 *  Put together a MPT SCSI request...	 */	if ((mf = mpt_get_msg_frame(ScsiDoneCtx, hd->ioc)) == NULL) {		dprintk((MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",				hd->ioc->name));		did_errcode = 2;		goto did_error;	}	pScsiReq = (SCSIIORequest_t *) mf;	my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);	ADD_INDEX_LOG(my_idx);	/*  BUG FIX!  19991030 -sralston	 *    TUR's being issued with scsictl=0x02000000 (DATA_IN)!	 *    Seems we may receive a buffer (datalen>0) even when there	 *    will be no data transfer!  GRRRRR...	 */	if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) {		datalen = SCpnt->request_bufflen;		scsidir = MPI_SCSIIO_CONTROL_READ;	/* DATA IN  (host<--ioc<--dev) */	} else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) {		datalen = SCpnt->request_bufflen;		scsidir = MPI_SCSIIO_CONTROL_WRITE;	/* DATA OUT (host-->ioc-->dev) */	} else {		datalen = 0;		scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER;	}	/* Default to untagged. Once a target structure has been allocated,	 * use the Inquiry data to determine if device supports tagged.	 */	if (   pTarget	    && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)	    && (SCpnt->device->tagged_supported)) {		scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;	} else {		scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED;	}	/* Use the above information to set up the message frame	 */	pScsiReq->TargetID = (u8) target;	pScsiReq->Bus = (u8) SCpnt->device->channel;	pScsiReq->ChainOffset = 0;	pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;	pScsiReq->CDBLength = SCpnt->cmd_len;	pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;	pScsiReq->Reserved = 0;	pScsiReq->MsgFlags = mpt_msg_flags();	pScsiReq->LUN[0] = 0;	pScsiReq->LUN[1] = 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	 */	cmd_len = SCpnt->cmd_len;	for (ii=0; ii < cmd_len; ii++)		pScsiReq->CDB[ii] = SCpnt->cmnd[ii];	for (ii=cmd_len; ii < 16; ii++)		pScsiReq->CDB[ii] = 0;	/* DataLength */	pScsiReq->DataLength = cpu_to_le32(datalen);	/* SenseBuffer low address */	pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma					   + (my_idx * MPT_SENSE_BUFFER_ALLOC));	/* Now add the SG list	 * Always have a SGE even if null length.	 */	rc = SUCCESS;	if (datalen == 0) {		/* Add a NULL SGE */		mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0,			(dma_addr_t) -1);	} else {		/* Add a 32 or 64 bit SGE */		rc = mptscsih_AddSGE(hd, SCpnt, pScsiReq, my_idx);	}	if (rc == SUCCESS) {		hd->ScsiLookup[my_idx] = SCpnt;		SCpnt->host_scribble = NULL;		/* SCSI specific processing */		issueCmd = 1;		if (hd->is_spi) {			int dvStatus = hd->ioc->spi_data.dvStatus[target];			if (dvStatus || hd->ioc->spi_data.forceDv) {#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION				if ((dvStatus & MPT_SCSICFG_NEED_DV) ||					(hd->ioc->spi_data.forceDv & MPT_SCSICFG_NEED_DV)) {					unsigned long lflags;					/* Schedule DV if necessary */					spin_lock_irqsave(&dvtaskQ_lock, lflags);					if (!dvtaskQ_active) {						dvtaskQ_active = 1;						spin_unlock_irqrestore(&dvtaskQ_lock, lflags);						INIT_WORK(&mptscsih_dvTask, mptscsih_domainValidation, (void *) hd);						schedule_work(&mptscsih_dvTask);					} else {						spin_unlock_irqrestore(&dvtaskQ_lock, lflags);					}					hd->ioc->spi_data.forceDv &= ~MPT_SCSICFG_NEED_DV;				}				/* 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;				}				/* Set the DV flags.				 */				if (dvStatus & MPT_SCSICFG_DV_NOT_DONE)					mptscsih_set_dvflags(hd, pScsiReq);#endif			}		}#ifdef MPTSCSIH_DBG_TIMEOUT		if (hd->ioc->timeout_cnt < hd->ioc->timeout_maxcnt) {			foo_to[hd->ioc->timeout_cnt] = SCpnt;			hd->ioc->timeout_cnt++;			//mod_timer(&SCpnt->eh_timeout, jiffies + hd->ioc->timeout_delta);			issueCmd = 0;			printk(MYIOC_s_WARN_FMT				"to pendingQ: (sc=%p, mf=%p, time=%ld)\n",				hd->ioc->name, SCpnt, mf, jiffies);		}#endif		if (issueCmd) {			mpt_put_msg_frame(ScsiDoneCtx, hd->ioc, mf);			dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",					hd->ioc->name, SCpnt, mf, my_idx));		} else {			ddvtprintk((MYIOC_s_INFO_FMT "Pending cmd=%p idx %d\n",					hd->ioc->name, SCpnt, my_idx));			/* 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, 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)) {		dtmprintk((MYIOC_s_WARN_FMT "SCpnt=%p to doneQ\n",			(hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt));		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_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;	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_HD

⌨️ 快捷键说明

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