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

📄 mptscsih.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
		    "Free'd ScsiLookup (%d) memory\n",		    hd->ioc->name, sz1));		/* NULL the Scsi_Host pointer		 */		hd->ioc->sh = NULL;	}	scsi_host_put(host);	mpt_scsi_hosts--;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *	mptscsih_shutdown - reboot notifier * */static voidmptscsih_shutdown(struct device * dev){	MPT_ADAPTER 		*ioc = pci_get_drvdata(to_pci_dev(dev));	struct Scsi_Host 	*host = ioc->sh;	MPT_SCSI_HOST		*hd;	if(!host)		return;	hd = (MPT_SCSI_HOST *)host->hostdata;	/* Flush the cache of this adapter	 */	if(hd != NULL)		mptscsih_synchronize_cache(hd, 0);}#ifdef CONFIG_PM/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *	mptscsih_suspend - Fusion MPT scsie driver suspend routine. * * */static intmptscsih_suspend(struct pci_dev *pdev, u32 state){	mptscsih_shutdown(&pdev->dev);	return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *	mptscsih_resume - Fusion MPT scsi driver resume routine. * * */static intmptscsih_resume(struct pci_dev *pdev){	MPT_ADAPTER 		*ioc = pci_get_drvdata(pdev);	struct Scsi_Host 	*host = ioc->sh;	MPT_SCSI_HOST		*hd;	if(!host)		return 0;	hd = (MPT_SCSI_HOST *)host->hostdata;	if(!hd)		return 0;#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION	{	unsigned long lflags;	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);	}	}#endif	return 0;}#endifstatic struct mpt_pci_driver mptscsih_driver = {	.probe		= mptscsih_probe,	.remove		= mptscsih_remove,	.shutdown	= mptscsih_shutdown,#ifdef CONFIG_PM	.suspend	= mptscsih_suspend,	.resume		= mptscsih_resume,#endif};/*  SCSI host fops start here...  *//*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mptscsih_init - Register MPT adapter(s) as SCSI host(s) with *	linux scsi mid-layer. * *	Returns 0 for success, non-zero for failure. */static int __initmptscsih_init(void){	show_mptmod_ver(my_NAME, my_VERSION);	ScsiDoneCtx = mpt_register(mptscsih_io_done, MPTSCSIH_DRIVER);	ScsiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSCSIH_DRIVER);	ScsiScanDvCtx = mpt_register(mptscsih_scandv_complete, MPTSCSIH_DRIVER);	if (mpt_event_register(ScsiDoneCtx, mptscsih_event_process) == 0) {		devtprintk((KERN_INFO MYNAM		  ": Registered for IOC event notifications\n"));	}	if (mpt_reset_register(ScsiDoneCtx, mptscsih_ioc_reset) == 0) {		dprintk((KERN_INFO MYNAM		  ": Registered for IOC reset notifications\n"));	}#ifdef MODULE	dinitprintk((KERN_INFO MYNAM		": Command Line Args: dv=%d max_width=%d "		"factor=0x%x saf_te=%d\n",		dv, width, factor, saf_te));	driver_setup.dv = (dv) ? 1 : 0;	driver_setup.max_width = (width) ? 1 : 0;	driver_setup.min_sync_factor = factor;	driver_setup.saf_te = (saf_te) ? 1 : 0;;#endif	if(mpt_device_driver_register(&mptscsih_driver,	  MPTSCSIH_DRIVER) != 0 ) {		dprintk((KERN_INFO MYNAM		": failed to register dd callbacks\n"));	}	return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mptscsih_exit - Unregisters MPT adapter(s) * */static void __exitmptscsih_exit(void){	mpt_device_driver_deregister(MPTSCSIH_DRIVER);	mpt_reset_deregister(ScsiDoneCtx);	dprintk((KERN_INFO MYNAM	  ": Deregistered for IOC reset notifications\n"));	mpt_event_deregister(ScsiDoneCtx);	dprintk((KERN_INFO MYNAM	  ": Deregistered for IOC event notifications\n"));	mpt_deregister(ScsiScanDvCtx);	mpt_deregister(ScsiTaskCtx);	mpt_deregister(ScsiDoneCtx);	if (info_kbuf != NULL)		kfree(info_kbuf);}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mptscsih_info - Return information about MPT adapter *	@SChost: Pointer to Scsi_Host structure * *	(linux scsi_host_template.info routine) * *	Returns pointer to buffer where information was written. */static const char *mptscsih_info(struct Scsi_Host *SChost){	MPT_SCSI_HOST *h;	int size = 0;	if (info_kbuf == NULL)		if ((info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)			return info_kbuf;	h = (MPT_SCSI_HOST *)SChost->hostdata;	info_kbuf[0] = '\0';	if (h) {		mpt_print_ioc_summary(h->ioc, info_kbuf, &size, 0, 0);		info_kbuf[size-1] = '\0';	}	return info_kbuf;}struct info_str {	char *buffer;	int   length;	int   offset;	int   pos;};static void copy_mem_info(struct info_str *info, char *data, int len){	if (info->pos + len > info->length)		len = info->length - info->pos;	if (info->pos + len < info->offset) {		info->pos += len;		return;	}	if (info->pos < info->offset) {	        data += (info->offset - info->pos);	        len  -= (info->offset - info->pos);	}	if (len > 0) {                memcpy(info->buffer + info->pos, data, len);                info->pos += len;	}}static int copy_info(struct info_str *info, char *fmt, ...){	va_list args;	char buf[81];	int len;	va_start(args, fmt);	len = vsprintf(buf, fmt, args);	va_end(args);	copy_mem_info(info, buf, len);	return len;}static int mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len){	struct info_str info;	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);}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	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 */static intmptscsih_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) {		/* 		 * write is not supported 		 */	} 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) */static intmptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)){	MPT_SCSI_HOST		*hd;	MPT_FRAME_HDR		*mf;	SCSIIORequest_t		*pScsiReq;	VirtDevice		*pTarget;	int	 target;	int	 lun;	u32	 datalen;	u32	 scsictl;	u32	 scsidir;	u32	 cmd_len;	int	 my_idx;	int	 ii;	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) {		dtmprintk((MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n",			(hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt));		return SCSI_MLQUEUE_HOST_BUSY;	}	/*	 *  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));		return SCSI_MLQUEUE_HOST_BUSY;	}	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.	 */	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 */		if (mptscsih_AddSGE(hd->ioc, SCpnt, pScsiReq, my_idx) != SUCCESS)			goto fail;	}	hd->ScsiLookup[my_idx] = SCpnt;	SCpnt->host_scribble = NULL;#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION	if (hd->ioc->bus_type == SCSI) {		int dvStatus = hd->ioc->spi_data.dvStatus[target];		int issueCmd = 1;		if (dvStatus || hd->ioc->spi_data.forceDv) {			if ((dvStatus & MPT_SCSICFG_NEED_DV) ||				(hd->ioc->spi_data.forceDv & MPT_SCSICFG_NEED_DV)) {				unsigned long lflags;

⌨️ 快捷键说明

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