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

📄 mptctl.c

📁 linux2.6.16版本
💻 C
📖 第 1 页 / 共 5 页
字号:
	 * 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:	case MPI_FUNCTION_TOOLBOX:	case MPI_FUNCTION_SAS_IO_UNIT_CONTROL:		break;	case MPI_FUNCTION_SCSI_IO_REQUEST:		if (ioc->sh) {			SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;			VirtTarget	*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 &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH;			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_SMP_PASSTHROUGH:		/* Check mf->PassthruFlags to determine if		 * transfer is ImmediateMode or not.		 * Immediate mode returns data in the ReplyFrame.		 * Else, we are sending request and response data		 * in two SGLs at the end of the mf.		 */		break;	case MPI_FUNCTION_SATA_PASSTHROUGH:		if (!ioc->sh) {			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 &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH;			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;			}		}		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);	}	ioc->ioctl->wait_done = 0;	if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT) {		DBG_DUMP_TM_REQUEST_FRAME((u32 *)mf);		if (mpt_send_handshake_request(mptctl_id, ioc,			sizeof(SCSITaskMgmt_t), (u32*)mf,			CAN_SLEEP) != 0) {			dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"				" (ioc %p, mf %p) \n", ioc->name,				ioc, mf));			mptctl_free_tm_flags(ioc);			rc = -ENODATA;			goto done_free_mem;		}	} else		mpt_put_msg_frame(mptctl_id, ioc, mf);	/* Now wait for the command to complete */	timeout = (karg.timeout > 0) ? karg.timeout : MPT_IOCTL_DEFAULT_TIMEOUT;	timeout = wait_event_timeout(mptctl_wait,	     ioc->ioctl->wait_done == 1,	     HZ*timeout);	if(timeout <=0 && (ioc->ioctl->wait_done != 1 )) {	/* Now we need to reset the board */		if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT)			mptctl_free_tm_flags(ioc);		mptctl_timeout_expired(ioc->ioctl);		rc = -ENODATA;		goto done_free_mem;	}	mf = NULL;	/* 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 reply frame %p\n",				 __FILE__, __LINE__, karg.replyFrameBufPtr);				 rc =  -ENODATA;				 goto done_free_mem;			}		}	}	/* If valid sense data, copy to user.	 */	if (ioc->ioctl->status & MPT_IOCTL_STATUS_SENSE_VALID) {		sz = min(karg.maxSenseBytes, MPT_SENSE_BUFFER_SIZE);		if (sz > 0) {			if (copy_to_user(karg.senseDataPtr, ioc->ioctl->sense, sz)) {				printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "				"Unable to write sense data to user %p\n",				__FILE__, __LINE__,				karg.senseDataPtr);				rc =  -ENODATA;				goto done_free_mem;			}		}	}	/* If the overall status is _GOOD and data in, copy data	 * to user.	 */	if ((ioc->ioctl->status & MPT_IOCTL_STATUS_COMMAND_GOOD) &&				(karg.dataInSize > 0) && (bufIn.kptr)) {		if (copy_to_user(karg.dataInBufPtr,				 bufIn.kptr, karg.dataInSize)) {			printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "				"Unable to write data to user %p\n",				__FILE__, __LINE__,				karg.dataInBufPtr);			rc =  -ENODATA;		}	}done_free_mem:	ioc->ioctl->status &= ~(MPT_IOCTL_STATUS_COMMAND_GOOD |		MPT_IOCTL_STATUS_SENSE_VALID |		MPT_IOCTL_STATUS_RF_VALID );	/* Free the allocated memory.	 */	if (bufOut.kptr != NULL) {		pci_free_consistent(ioc->pcidev,			bufOut.len, (void *) bufOut.kptr, dma_addr_out);	}	if (bufIn.kptr != NULL) {		pci_free_consistent(ioc->pcidev,			bufIn.len, (void *) bufIn.kptr, dma_addr_in);	}	/* mf is null if command issued successfully	 * otherwise, failure occured after mf acquired.	 */	if (mf)		mpt_free_msg_frame(ioc, mf);	return rc;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

⌨️ 快捷键说明

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