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

📄 mptscsih.c

📁 microwindows移植到S3C44B0的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	MPT_FRAME_HDR	*chain;	u8		*mem;	unsigned long	flags;	int		sz, ii, numChain;        /* Chain buffer allocations	 * Allocate and initialize tracker structures	 */	if (hd->ioc->req_sz <= 64)		numChain = MPT_SG_REQ_64_SCALE * hd->ioc->req_depth;	else if (hd->ioc->req_sz <= 96)		numChain = MPT_SG_REQ_96_SCALE * hd->ioc->req_depth;	else		numChain = MPT_SG_REQ_128_SCALE * hd->ioc->req_depth;	sz = numChain * sizeof(int);	if (hd->ReqToChain == NULL) {		mem = kmalloc(sz, GFP_KERNEL);		if (mem == NULL)			return -1;		hd->ReqToChain = (int *) mem;	} else {		mem = (u8 *) hd->ReqToChain;	}	memset(mem, 0xFF, sz);	if (hd->ChainToChain == NULL) {		mem = kmalloc(sz, GFP_KERNEL);		if (mem == NULL)			return -1;		hd->ChainToChain = (int *) mem;	} else {		mem = (u8 *) hd->ChainToChain;	}	memset(mem, 0xFF, sz);	if (hd->ChainBuffer == NULL) {		/* Allocate free chain buffer pool		 */		sz = numChain * hd->ioc->req_sz;		mem = pci_alloc_consistent(hd->ioc->pcidev, sz, &hd->ChainBufferDMA);		if (mem == NULL)			return -1;		hd->ChainBuffer = (u8*)mem;	} else {		mem = (u8 *) hd->ChainBuffer;	}	memset(mem, 0, sz);	dprintk((KERN_INFO "  ChainBuffer    @ %p(%p), sz=%d\n",		 hd->ChainBuffer, (void *)(ulong)hd->ChainBufferDMA, sz));	/* Initialize the free chain Q.	 */	if (init) {		spin_lock_init(&hd->FreeChainQlock);	}	spin_lock_irqsave (&hd->FreeChainQlock, flags);	Q_INIT(&hd->FreeChainQ, MPT_FRAME_HDR);	/* Post the chain buffers to the FreeChainQ.	 */	mem = (u8 *)hd->ChainBuffer;	for (ii=0; ii < numChain; ii++) {		chain = (MPT_FRAME_HDR *) mem;		Q_ADD_TAIL(&hd->FreeChainQ.head, &chain->u.frame.linkage, MPT_FRAME_HDR);		mem += hd->ioc->req_sz;	}	spin_unlock_irqrestore(&hd->FreeChainQlock, flags);	return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *  Hack! It might be nice to report if a device is returning QUEUE_FULL *  but maybe not each and every time... */static long last_queue_full = 0;/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *	mptscsih_report_queue_full - Report QUEUE_FULL status returned *	from a SCSI target device. *	@sc: Pointer to Scsi_Cmnd structure *	@pScsiReply: Pointer to SCSIIOReply_t *	@pScsiReq: Pointer to original SCSI request * *	This routine periodically reports QUEUE_FULL status returned from a *	SCSI target device.  It reports this to the console via kernel *	printk() API call, not more than once every 10 seconds. */static voidmptscsih_report_queue_full(Scsi_Cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq){	long time = jiffies;	if (time - last_queue_full > 10 * HZ) {		char *ioc_str = "ioc?";		if (sc->host && sc->host->hostdata)			ioc_str = ((MPT_SCSI_HOST *)sc->host->hostdata)->ioc->name;		printk(MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",				ioc_str, 0, sc->target, sc->lun);		last_queue_full = time;	}}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/static int BeenHereDoneThat = 0;/*  SCSI host fops start here...  *//*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mptscsih_detect - Register MPT adapter(s) as SCSI host(s) with *	linux scsi mid-layer. *	@tpnt: Pointer to Scsi_Host_Template structure * *	(linux Scsi_Host_Template.detect routine) * *	Returns number of SCSI host adapters that were successfully *	registered with the linux scsi mid-layer via the scsi_register() *	API call. */intmptscsih_detect(Scsi_Host_Template *tpnt){	struct Scsi_Host	*sh = NULL;	MPT_SCSI_HOST		*hd = NULL;	MPT_ADAPTER		*this;	MPT_DONE_Q		*freedoneQ;	unsigned long		 flags;	int			 sz, ii;	int			 numSGE = 0;	int			 scale;	u8			*mem;	if (! BeenHereDoneThat++) {		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);#ifndef MPT_SCSI_USE_NEW_EH		spin_lock_init(&mytaskQ_lock);#endif		if (mpt_event_register(ScsiDoneCtx, mptscsih_event_process) == 0) {			dprintk((KERN_INFO MYNAM ": Registered for IOC event notifications\n"));		} else {			/* FIXME! */		}		if (mpt_reset_register(ScsiDoneCtx, mptscsih_ioc_reset) == 0) {			dprintk((KERN_INFO MYNAM ": Registered for IOC reset notifications\n"));		} else {			/* FIXME! */		}	}	dprintk((KERN_INFO MYNAM ": mpt_scsih_detect()\n"));#ifdef MODULE	/* Evaluate the command line arguments, if any */	if (mptscsih)		mptscsih_setup(mptscsih);#endif#ifndef MPT_SCSI_USE_NEW_EH	atomic_set(&mpt_taskQdepth, 0);#endif	this = mpt_adapter_find_first();	while (this != NULL) {		int	 portnum;		for (portnum=0; portnum < this->facts.NumberOfPorts; portnum++) {			/* 20010215 -sralston			 *  Added sanity check on SCSI Initiator-mode enabled			 *  for this MPT adapter.			 */			if (!(this->pfacts[portnum].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR)) {				printk(MYIOC_s_WARN_FMT "Skipping because SCSI Initiator mode is NOT enabled!\n",						this->name);				continue;			}			/* 20010202 -sralston			 *  Added sanity check on readiness of the MPT adapter.			 */			if (this->last_state != MPI_IOC_STATE_OPERATIONAL) {				printk(MYIOC_s_WARN_FMT "Skipping because it's not operational!\n",						this->name);				continue;			}#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)			tpnt->proc_dir = &proc_mpt_scsihost;#endif			sh = scsi_register(tpnt, sizeof(MPT_SCSI_HOST));			if (sh != NULL) {				save_flags(flags);				cli();				sh->io_port = 0;				sh->n_io_port = 0;				sh->irq = 0;				/* Yikes!  This is important!				 * Otherwise, by default, linux				 * only scans target IDs 0-7!				 * pfactsN->MaxDevices unreliable				 * (not supported in early				 *	versions of the FW).				 * max_id = 1 + actual max id,				 * max_lun = 1 + actual last lun,				 *	see hosts.h :o(				 */				if ((int)this->chip_type > (int)FC929)					sh->max_id = MPT_MAX_SCSI_DEVICES;				else {					/* For FC, increase the queue depth					 * from MPT_SCSI_CAN_QUEUE (31)					 * to MPT_FC_CAN_QUEUE (63).					 */					sh->can_queue = MPT_FC_CAN_QUEUE;					sh->max_id = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;				}				sh->max_lun = MPT_LAST_LUN + 1;				sh->this_id = this->pfacts[portnum].PortSCSIID;				/* OS entry to allow host drivers to force				 * a queue depth on a per device basis.				 */				sh->select_queue_depths = mptscsih_select_queue_depths;				/* Verify that we won't exceed the maximum				 * number of chain buffers				 * We can optimize:  ZZ = req_sz/sizeof(MptSge_t)				 * For 32bit SGE's:				 *  numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ				 *               + (req_sz - 64)/sizeof(MptSge_t)				 * A slightly different algorithm is required for				 * 64bit SGEs.				 */				scale = this->req_sz/sizeof(MptSge_t);				if (sizeof(MptSge_t) == sizeof(SGESimple32_t)) {					numSGE = 1 + (scale - 1) * (this->facts.MaxChainDepth-1) + scale +						(this->req_sz - 64) / (sizeof(MptSge_t));				} else if (sizeof(MptSge_t) == sizeof(SGESimple64_t)) {					numSGE = (scale - 1) * (this->facts.MaxChainDepth-1) + scale +						(this->req_sz - 60) / (sizeof(MptSge_t));				}				if (numSGE < sh->sg_tablesize) {					/* Reset this value */					dprintk((MYIOC_s_INFO_FMT						 "Resetting sg_tablesize to %d from %d\n",						 this->name, numSGE, sh->sg_tablesize));					sh->sg_tablesize = numSGE;				}				restore_flags(flags);				hd = (MPT_SCSI_HOST *) sh->hostdata;				hd->ioc = this;				if ((int)this->chip_type > (int)FC929)					hd->is_spi = 1;				if (DmpService &&				    (this->chip_type == FC919 || this->chip_type == FC929))					hd->is_multipath = 1;				hd->port = 0;		/* FIXME! */				/* SCSI needs Scsi_Cmnd lookup table!				 * (with size equal to req_depth*PtrSz!)				 */				sz = hd->ioc->req_depth * sizeof(void *);				mem = kmalloc(sz, GFP_KERNEL);				if (mem == NULL)					goto done;				memset(mem, 0, sz);				hd->ScsiLookup = (struct scsi_cmnd **) mem;				dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",					 this->name, hd->ScsiLookup, sz));				if (mptscsih_initChainBuffers(hd, 1) < 0)					goto done;				/* Allocate memory for free and doneQ's				 */				sz = sh->can_queue * sizeof(MPT_DONE_Q);				mem = kmalloc(sz, GFP_KERNEL);				if (mem == NULL)					goto done;				memset(mem, 0xFF, sz);				hd->memQ = mem;				/* Initialize the free, done and pending Qs.				 */				Q_INIT(&hd->freeQ, MPT_DONE_Q);				Q_INIT(&hd->doneQ, MPT_DONE_Q);				Q_INIT(&hd->pendingQ, MPT_DONE_Q);				spin_lock_init(&hd->freedoneQlock);				mem = hd->memQ;				for (ii=0; ii < sh->can_queue; ii++) {					freedoneQ = (MPT_DONE_Q *) mem;					Q_ADD_TAIL(&hd->freeQ.head, freedoneQ, MPT_DONE_Q);					mem += sizeof(MPT_DONE_Q);				}				/* Initialize this Scsi_Host				 * internal task Q.				 */				Q_INIT(&hd->taskQ, MPT_FRAME_HDR);				hd->taskQcnt = 0;				/* Allocate memory for the device structures.				 * A non-Null pointer at an offset				 * indicates a device exists.				 * max_id = 1 + maximum id (hosts.h)				 */				sz = sh->max_id * sizeof(void *);				mem = kmalloc(sz, GFP_KERNEL);				if (mem == NULL)					goto done;				memset(mem, 0, sz);				hd->Targets = (VirtDevice **) mem;				dprintk((KERN_INFO "  Targets @ %p, sz=%d\n", hd->Targets, sz));				/* Clear the TM flags				 */				hd->tmPending = 0;				hd->resetPending = 0;				hd->abortSCpnt = NULL;				hd->tmPtr = NULL;				hd->numTMrequests = 0;				/* Clear the pointer used to store				 * single-threaded commands, i.e., those				 * issued during a bus scan, dv and				 * configuration pages.				 */				hd->cmdPtr = NULL;				/* Attach the SCSI Host to the IOC structure				 */				this->sh = sh;				/* Initialize this SCSI Hosts' timers				 * To use, set the timer expires field				 * and add_timer				 */				init_timer(&hd->timer);				hd->timer.data = (unsigned long) hd;				hd->timer.function = mptscsih_timer_expired;				init_timer(&hd->TMtimer);				hd->TMtimer.data = (unsigned long) hd;				hd->TMtimer.function = mptscsih_taskmgmt_timeout;				hd->qtag_tick = jiffies;				/* Moved Earlier Pam D */				/* this->sh = sh;	*/				if (hd->is_spi) {					/* Update with the driver setup					 * values.					 */					if (hd->ioc->spi_data.maxBusWidth > driver_setup.max_width)						hd->ioc->spi_data.maxBusWidth = driver_setup.max_width;					if (hd->ioc->spi_data.minSyncFactor < driver_setup.min_sync_fac)						hd->ioc->spi_data.minSyncFactor = driver_setup.min_sync_fac;					if (hd->ioc->spi_data.minSyncFactor == MPT_ASYNC)						hd->ioc->spi_data.maxSyncOffset = 0;					hd->negoNvram = 0;#ifdef MPTSCSIH_DISABLE_DOMAIN_VALIDATION					hd->negoNvram = MPT_SCSICFG_USE_NVRAM;#endif					if (driver_setup.dv == 0)						hd->negoNvram = MPT_SCSICFG_USE_NVRAM;					hd->ioc->spi_data.forceDv = 0;					for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)						hd->ioc->spi_data.dvStatus[ii] = MPT_SCSICFG_NEGOTIATE;					ddvprintk((MYIOC_s_INFO_FMT						"dv %x width %x factor %x \n",						hd->ioc->name, driver_setup.dv,						driver_setup.max_width,						driver_setup.min_sync_fac));				}				mpt_scsi_hosts++;			}		}	/* for each adapter port */		this = mpt_adapter_find_next(this);	}done:	if (mpt_scsi_hosts > 0)		register_reboot_notifier(&mptscsih_notifier);	return mpt_scsi_hosts;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/    static char *info_kbuf = NULL;/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mptscsih_release - Unregister SCSI host from linux scsi mid-layer *	@host: Pointer to Scsi_Host structure * *	(linux Scsi_Host_Template.release routine) *	This routine releases all resources associated with the SCSI host *	adapter. * *	Returns 0 for success. */intmptscsih_release(struct Scsi_Host *host){	MPT_SCSI_HOST	*hd;	int 		 count;	unsigned long	 flags;	hd = (MPT_SCSI_HOST *) host->hostdata;#ifndef MPT_SCSI_USE_NEW_EH#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION	spin_lock_irqsave(&dvtaskQ_lock, flags);	dvtaskQ_release = 1;	spin_unlock_irqrestore(&dvtaskQ_lock, flags);#endif	spin_lock_irqsave(&mytaskQ_lock, flags);	if (mytaskQ_bh_active) {		count = 10 * HZ;		spin_unlock_irqrestore(&mytaskQ_lock, flags);		dprintk((KERN_INFO MYNAM ": Info: Zapping TaskMgmt thread!\n"));		clean_taskQ(hd);		while(mytaskQ_bh_active && --count) {			set_current_state(TASK_INTERRUPTIBLE);			schedule_timeout(1);		}

⌨️ 快捷键说明

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