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

📄 mptctl.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
	dma_addr_t	dma_addr_in;	dma_addr_t	dma_addr_out;	int		sgSize = 0;	/* Num SG elements */	int		iocnum, flagsLength;	int		sz, rc = 0;	int		msgContext;	int		tm_flags_set = 0;	u16		req_idx;	dctlprintk(("mptctl_do_mpt_command called.\n"));	bufIn.kptr = bufOut.kptr = NULL;	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||	    (ioc == NULL)) {		dctlprintk((KERN_ERR "%s::mptctl_do_mpt_command() @%d - ioc%d not found!\n",				__FILE__, __LINE__, iocnum));		return -ENODEV;	}	if (!ioc->ioctl) {		printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "			"No memory available during driver init.\n",				__FILE__, __LINE__);		return -ENOMEM;	} else if (ioc->ioctl->status & MPT_IOCTL_STATUS_DID_IOCRESET) {		printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "			"Busy with IOC Reset \n", __FILE__, __LINE__);		return -EBUSY;	}	/* Verify that the final request frame will not be too large.	 */	sz = karg.dataSgeOffset * 4;	if (karg.dataInSize > 0)		sz += sizeof(dma_addr_t) + sizeof(u32);	if (karg.dataOutSize > 0)		sz += sizeof(dma_addr_t) + sizeof(u32);	if (sz > ioc->req_sz) {		printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "			"Request frame too large (%d) maximum (%d)\n",				__FILE__, __LINE__, sz, ioc->req_sz);		return -EFAULT;	}	/* Get a free request frame and save the message context.	 */        if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL)                return -EAGAIN;	hdr = (MPIHeader_t *) mf;	msgContext = le32_to_cpu(hdr->MsgContext);	req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);	/* Copy the request frame	 * Reset the saved message context.	 * Request frame in user space	 */	if (copy_from_user(mf, mfPtr, karg.dataSgeOffset * 4)) {		printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "			"Unable to read MF from mpt_ioctl_command struct @ %p\n",			__FILE__, __LINE__, mfPtr);		rc = -EFAULT;		goto done_free_mem;	}	hdr->MsgContext = cpu_to_le32(msgContext);	/* Verify that this request is allowed.	 */	switch (hdr->Function) {	case MPI_FUNCTION_IOC_FACTS:	case MPI_FUNCTION_PORT_FACTS:		karg.dataOutSize  = karg.dataInSize = 0;		break;	case MPI_FUNCTION_CONFIG:	case MPI_FUNCTION_FC_COMMON_TRANSPORT_SEND:	case MPI_FUNCTION_FC_EX_LINK_SRVC_SEND:	case MPI_FUNCTION_FW_UPLOAD:	case MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR:	case MPI_FUNCTION_FW_DOWNLOAD:	case MPI_FUNCTION_FC_PRIMITIVE_SEND:		break;	case MPI_FUNCTION_SCSI_IO_REQUEST:		if (ioc->sh) {			SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;			VirtDevice	*pTarget = NULL;			MPT_SCSI_HOST	*hd = NULL;			int qtag = MPI_SCSIIO_CONTROL_UNTAGGED;			int scsidir = 0;			int target = (int) pScsiReq->TargetID;			int dataSize;			if ((target < 0) || (target >= ioc->sh->max_id)) {				printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "					"Target ID out of bounds. \n",					__FILE__, __LINE__);				rc = -ENODEV;				goto done_free_mem;			}			pScsiReq->MsgFlags = mpt_msg_flags();			/* verify that app has not requested			 *	more sense data than driver			 *	can provide, if so, reset this parameter			 * set the sense buffer pointer low address			 * update the control field to specify Q type			 */			if (karg.maxSenseBytes > MPT_SENSE_BUFFER_SIZE)				pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;			else				pScsiReq->SenseBufferLength = karg.maxSenseBytes;			pScsiReq->SenseBufferLowAddr =				cpu_to_le32(ioc->sense_buf_low_dma				   + (req_idx * MPT_SENSE_BUFFER_ALLOC));			if ((hd = (MPT_SCSI_HOST *) ioc->sh->hostdata)) {				if (hd->Targets)					pTarget = hd->Targets[target];			}			if (pTarget &&(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES))				qtag = MPI_SCSIIO_CONTROL_SIMPLEQ;			/* Have the IOCTL driver set the direction based			 * on the dataOutSize (ordering issue with Sparc).			 */			if (karg.dataOutSize > 0) {				scsidir = MPI_SCSIIO_CONTROL_WRITE;				dataSize = karg.dataOutSize;			} else {				scsidir = MPI_SCSIIO_CONTROL_READ;				dataSize = karg.dataInSize;			}			pScsiReq->Control = cpu_to_le32(scsidir | qtag);			pScsiReq->DataLength = cpu_to_le32(dataSize);			ioc->ioctl->reset = MPTCTL_RESET_OK;			ioc->ioctl->target = target;		} else {			printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "				"SCSI driver is not loaded. \n",					__FILE__, __LINE__);			rc = -EFAULT;			goto done_free_mem;		}		break;	case MPI_FUNCTION_RAID_ACTION:		/* Just add a SGE		 */		break;	case MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH:		if (ioc->sh) {			SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;			int qtag = MPI_SCSIIO_CONTROL_SIMPLEQ;			int scsidir = MPI_SCSIIO_CONTROL_READ;			int dataSize;			pScsiReq->MsgFlags = mpt_msg_flags();			/* verify that app has not requested			 *	more sense data than driver			 *	can provide, if so, reset this parameter			 * set the sense buffer pointer low address			 * update the control field to specify Q type			 */			if (karg.maxSenseBytes > MPT_SENSE_BUFFER_SIZE)				pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;			else				pScsiReq->SenseBufferLength = karg.maxSenseBytes;			pScsiReq->SenseBufferLowAddr =				cpu_to_le32(ioc->sense_buf_low_dma				   + (req_idx * MPT_SENSE_BUFFER_ALLOC));			/* All commands to physical devices are tagged			 */			/* Have the IOCTL driver set the direction based			 * on the dataOutSize (ordering issue with Sparc).			 */			if (karg.dataOutSize > 0) {				scsidir = MPI_SCSIIO_CONTROL_WRITE;				dataSize = karg.dataOutSize;			} else {				scsidir = MPI_SCSIIO_CONTROL_READ;				dataSize = karg.dataInSize;			}			pScsiReq->Control = cpu_to_le32(scsidir | qtag);			pScsiReq->DataLength = cpu_to_le32(dataSize);			ioc->ioctl->reset = MPTCTL_RESET_OK;			ioc->ioctl->target = pScsiReq->TargetID;		} else {			printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "				"SCSI driver is not loaded. \n",					__FILE__, __LINE__);			rc = -EFAULT;			goto done_free_mem;		}		break;	case MPI_FUNCTION_SCSI_TASK_MGMT:		{			MPT_SCSI_HOST *hd = NULL;			if ((ioc->sh == NULL) || ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL)) {				printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "					"SCSI driver not loaded or SCSI host not found. \n",					__FILE__, __LINE__);				rc = -EFAULT;				goto done_free_mem;			} else if (mptctl_set_tm_flags(hd) != 0) {				rc = -EPERM;				goto done_free_mem;			}			tm_flags_set = 1;		}		break;	case MPI_FUNCTION_IOC_INIT:		{			IOCInit_t	*pInit = (IOCInit_t *) mf;			u32		high_addr, sense_high;			/* Verify that all entries in the IOC INIT match			 * existing setup (and in LE format).			 */			if (sizeof(dma_addr_t) == sizeof(u64)) {				high_addr = cpu_to_le32((u32)((u64)ioc->req_frames_dma >> 32));				sense_high= cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32));			} else {				high_addr = 0;				sense_high= 0;			}			if ((pInit->Flags != 0) || (pInit->MaxDevices != ioc->facts.MaxDevices) ||				(pInit->MaxBuses != ioc->facts.MaxBuses) ||				(pInit->ReplyFrameSize != cpu_to_le16(ioc->reply_sz)) ||				(pInit->HostMfaHighAddr != high_addr) ||				(pInit->SenseBufferHighAddr != sense_high)) {				printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "					"IOC_INIT issued with 1 or more incorrect parameters. Rejected.\n",					__FILE__, __LINE__);				rc = -EFAULT;				goto done_free_mem;			}		}		break;	default:		/*		 * MPI_FUNCTION_PORT_ENABLE		 * MPI_FUNCTION_TARGET_CMD_BUFFER_POST		 * MPI_FUNCTION_TARGET_ASSIST		 * MPI_FUNCTION_TARGET_STATUS_SEND		 * MPI_FUNCTION_TARGET_MODE_ABORT		 * MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET		 * MPI_FUNCTION_IO_UNIT_RESET		 * MPI_FUNCTION_HANDSHAKE		 * MPI_FUNCTION_REPLY_FRAME_REMOVAL		 * MPI_FUNCTION_EVENT_NOTIFICATION		 *  (driver handles event notification)		 * MPI_FUNCTION_EVENT_ACK		 */		/*  What to do with these???  CHECK ME!!!			MPI_FUNCTION_FC_LINK_SRVC_BUF_POST			MPI_FUNCTION_FC_LINK_SRVC_RSP			MPI_FUNCTION_FC_ABORT			MPI_FUNCTION_LAN_SEND			MPI_FUNCTION_LAN_RECEIVE		 	MPI_FUNCTION_LAN_RESET		*/		printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "			"Illegal request (function 0x%x) \n",			__FILE__, __LINE__, hdr->Function);		rc = -EFAULT;		goto done_free_mem;	}	/* Add the SGL ( at most one data in SGE and one data out SGE )	 * In the case of two SGE's - the data out (write) will always	 * preceede the data in (read) SGE. psgList is used to free the	 * allocated memory.	 */	psge = (char *) (((int *) mf) + karg.dataSgeOffset);	flagsLength = 0;	/* bufIn and bufOut are used for user to kernel space transfers	 */	bufIn.kptr = bufOut.kptr = NULL;	bufIn.len = bufOut.len = 0;	if (karg.dataOutSize > 0)		sgSize ++;	if (karg.dataInSize > 0)		sgSize ++;	if (sgSize > 0) {		/* Set up the dataOut memory allocation */		if (karg.dataOutSize > 0) {			if (karg.dataInSize > 0) {				flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT |						MPI_SGE_FLAGS_END_OF_BUFFER |						MPI_SGE_FLAGS_DIRECTION |						mpt_addr_size() )						<< MPI_SGE_FLAGS_SHIFT;			} else {				flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;			}			flagsLength |= karg.dataOutSize;			bufOut.len = karg.dataOutSize;			bufOut.kptr = pci_alloc_consistent(					ioc->pcidev, bufOut.len, &dma_addr_out);			if (bufOut.kptr == NULL) {				rc = -ENOMEM;				goto done_free_mem;			} else {				/* Set up this SGE.				 * Copy to MF and to sglbuf				 */				mpt_add_sge(psge, flagsLength, dma_addr_out);				psge += (sizeof(u32) + sizeof(dma_addr_t));				/* Copy user data to kernel space.				 */				if (copy_from_user(bufOut.kptr,						karg.dataOutBufPtr,						bufOut.len)) {					printk(KERN_ERR						"%s@%d::mptctl_do_mpt_command - Unable "						"to read user data "						"struct @ %p\n",						__FILE__, __LINE__,karg.dataOutBufPtr);					rc =  -EFAULT;					goto done_free_mem;				}			}		}		if (karg.dataInSize > 0) {			flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;			flagsLength |= karg.dataInSize;			bufIn.len = karg.dataInSize;			bufIn.kptr = pci_alloc_consistent(ioc->pcidev,					bufIn.len, &dma_addr_in);			if (bufIn.kptr == NULL) {				rc = -ENOMEM;				goto done_free_mem;			} else {				/* Set up this SGE				 * Copy to MF and to sglbuf				 */				mpt_add_sge(psge, flagsLength, dma_addr_in);			}		}	} else  {		/* Add a NULL SGE		 */		mpt_add_sge(psge, flagsLength, (dma_addr_t) -1);	}	/* The request is complete. Set the timer parameters	 * and issue the request.	 */	if (karg.timeout > 0) {		ioc->ioctl->timer.expires = jiffies + HZ*karg.timeout;	} else {		ioc->ioctl->timer.expires = jiffies + HZ*MPT_IOCTL_DEFAULT_TIMEOUT;	}	ioc->ioctl->wait_done = 0;	ioc->ioctl->status |= MPT_IOCTL_STATUS_TIMER_ACTIVE;	add_timer(&ioc->ioctl->timer);	if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT) {		DBG_DUMP_TM_REQUEST_FRAME((u32 *)mf);		rc = mpt_send_handshake_request(mptctl_id, ioc,				sizeof(SCSITaskMgmt_t), (u32*)mf, CAN_SLEEP);		if (rc == 0) {			wait_event(mptctl_wait, ioc->ioctl->wait_done);		} else {			mptctl_free_tm_flags(ioc);			tm_flags_set= 0;			del_timer(&ioc->ioctl->timer);			ioc->ioctl->status &= ~MPT_IOCTL_STATUS_TIMER_ACTIVE;			ioc->ioctl->status |= MPT_IOCTL_STATUS_TM_FAILED;			mpt_free_msg_frame(ioc, mf);		}	} else {		mpt_put_msg_frame(mptctl_id, ioc, mf);		wait_event(mptctl_wait, ioc->ioctl->wait_done);	}	mf = NULL;	/* MF Cleanup:	 * If command failed and failure triggered a diagnostic reset	 * OR a diagnostic reset happens during command processing,	 * no data, messaging queues are reset (mf cannot be accessed),	 * and status is DID_IOCRESET	 *	 * If a user-requested bus reset fails to be handshaked, then	 * mf is returned to free queue and status is TM_FAILED.	 *	 * Otherise, the command completed and the mf was freed	 # by ISR (mf cannot be touched).	 */	if (ioc->ioctl->status & MPT_IOCTL_STATUS_DID_IOCRESET) {		/* The timer callback deleted the		 * timer and reset the adapter queues.		 */		printk(KERN_WARNING "%s@%d::mptctl_do_mpt_command - "			"Timeout Occurred on IOCTL! Reset IOC.\n", __FILE__, __LINE__);		tm_flags_set= 0;		rc = -ETIME;	} else if (ioc->ioctl->status & MPT_IOCTL_STATUS_TM_FAILED) {		/* User TM request failed! mf has not been freed.		 */		rc = -ENODATA;	} else {		/* If a valid reply frame, copy to the user.		 * Offset 2: reply length in U32's		 */		if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) {			if (karg.maxReplyBytes < ioc->reply_sz) {				 sz = min(karg.maxReplyBytes, 4*ioc->ioctl->ReplyFrame[2]);			} else {				 sz = min(ioc->reply_sz, 4*ioc->ioctl->ReplyFrame[2]);			}			if (sz > 0) {				if (copy_to_user(karg.replyFrameBufPtr,					 &ioc->ioctl->ReplyFrame, sz)){					 printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "					 "Unable to write out rep

⌨️ 快捷键说明

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