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

📄 commsup.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
		fib_dealloc(fibptr);	}	else if(hw_fib->header.XferState & cpu_to_le32(SentFromHost))	{		/*		 *	This handles the case when the host has aborted the I/O		 *	to the adapter because the adapter is not responding		 */		fib_dealloc(fibptr);	} else if(hw_fib->header.XferState & cpu_to_le32(HostOwned)) {		fib_dealloc(fibptr);	} else {		BUG();	}   	return 0;}/** *	aac_printf	-	handle printf from firmware *	@dev: Adapter *	@val: Message info * *	Print a message passed to us by the controller firmware on the *	Adaptec board */void aac_printf(struct aac_dev *dev, u32 val){	int length = val & 0xffff;	int level = (val >> 16) & 0xffff;	char *cp = dev->printfbuf;		/*	 *	The size of the printfbuf is set in port.c	 *	There is no variable or define for it	 */	if (length > 255)		length = 255;	if (cp[length] != 0)		cp[length] = 0;	if (level == LOG_HIGH_ERROR)		printk(KERN_WARNING "aacraid:%s", cp);	else		printk(KERN_INFO "aacraid:%s", cp);	memset(cp, 0,  256);}/** *	aac_handle_aif		-	Handle a message from the firmware *	@dev: Which adapter this fib is from *	@fibptr: Pointer to fibptr from adapter * *	This routine handles a driver notify fib from the adapter and *	dispatches it to the appropriate routine for handling. */#define CONTAINER_TO_BUS(cont)		(0)#define CONTAINER_TO_TARGET(cont)	((cont))#define CONTAINER_TO_LUN(cont)		(0)static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr){	struct hw_fib * hw_fib = fibptr->hw_fib;	struct aac_aifcmd * aifcmd = (struct aac_aifcmd *)hw_fib->data;	int busy;	u32 container;	/* Sniff for container changes */	dprintk ((KERN_INFO "AifCmdDriverNotify=%x\n", le32_to_cpu(*(u32 *)aifcmd->data)));	switch (le32_to_cpu(*(u32 *)aifcmd->data)) {	case AifDenMorphComplete:	case AifDenVolumeExtendComplete:	case AifEnContainerChange: /* Not really a driver notify Event */		busy = 0;		container = le32_to_cpu(((u32 *)aifcmd->data)[1]);		dprintk ((KERN_INFO "container=%d(%d,%d,%d,%d) ",		  container,		  (dev && dev->scsi_host_ptr)		    ? dev->scsi_host_ptr->host_no		    : -1,		  CONTAINER_TO_BUS(container),		  CONTAINER_TO_TARGET(container),		  CONTAINER_TO_LUN(container)));		/*		 *	Find the Scsi_Device associated with the SCSI address,		 * and mark it as changed, invalidating the cache. This deals		 * with changes to existing device IDs.		 */		if ((dev != (struct aac_dev *)NULL)		 && (dev->scsi_host_ptr != (struct Scsi_Host *)NULL)) {			Scsi_Device * device;			for (device = dev->scsi_host_ptr->host_queue;			  device != (Scsi_Device *)NULL;			  device = device->next) {				dprintk((KERN_INFO				  "aifd: device (%d,%d,%d,%d)?\n",				  dev->scsi_host_ptr->host_no,				  device->channel,				  device->id,				  device->lun));				if ((device->channel == CONTAINER_TO_BUS(container))				 && (device->id == CONTAINER_TO_TARGET(container))				 && (device->lun == CONTAINER_TO_LUN(container))) {					busy |= (device->access_count != 0);					if (busy == 0) {						device->removable = TRUE;					}				}			}		}		dprintk (("busy=%d\n", busy));		/*		 * if (busy == 0) {		 *	scan_scsis(dev->scsi_host_ptr, 1,		 *	  CONTAINER_TO_BUS(container),		 *	  CONTAINER_TO_TARGET(container),		 *	  CONTAINER_TO_LUN(container));		 * }		 * is not exported as accessible, so we need to go around it		 * another way. So, we look for the "proc/scsi/scsi" entry in		 * the proc filesystem (using proc_scsi as a shortcut) and send		 * it a message. This deals with new devices that have		 * appeared. If the device has gone offline, scan_scsis will		 * also discover this, but we do not want the device to		 * go away. We need to check the access_count for the		 * device since we are not wanting the devices to go away.		 */		if ((busy == 0)		 && (proc_scsi != (struct proc_dir_entry *)NULL)) {			struct proc_dir_entry * entry;			dprintk((KERN_INFO "proc_scsi=%p ", proc_scsi));			for (entry = proc_scsi->subdir;			  entry != (struct proc_dir_entry *)NULL;			  entry = entry->next) {				dprintk(("\"%.*s\"[%d]=%x ", entry->namelen,				  entry->name, entry->namelen, entry->low_ino));				if ((entry->low_ino != 0)				 && (entry->namelen == 4)				 && (memcmp ("scsi", entry->name, 4) == 0)) {					dprintk(("%p->write_proc=%p ", entry, entry->write_proc));					if (entry->write_proc != (int (*)(struct file *, const char *, unsigned long, void *))NULL) {						char buffer[80];						int length;						mm_segment_t fs;						sprintf (buffer,						  "scsi add-single-device %d %d %d %d\n",						  dev->scsi_host_ptr->host_no,						  CONTAINER_TO_BUS(container),						  CONTAINER_TO_TARGET(container),						  CONTAINER_TO_LUN(container));						length = strlen (buffer);						dprintk((KERN_INFO						  "echo %.*s > /proc/scsi/scsi\n",						  length-1,						  buffer));						fs = get_fs();						set_fs(get_ds());						length = entry->write_proc(						  NULL, buffer, length, NULL);						set_fs(fs);						dprintk((KERN_INFO						  "returns %d\n", length));					}					break;				}			}		}	}}/** *	aac_command_thread	-	command processing thread *	@dev: Adapter to monitor * *	Waits on the commandready event in it's queue. When the event gets set *	it will pull FIBs off it's queue. It will continue to pull FIBs off *	until the queue is empty. When the queue is empty it will wait for *	more FIBs. */ int aac_command_thread(struct aac_dev * dev){	struct hw_fib *hw_fib, *hw_newfib;	struct fib *fib, *newfib;	struct aac_queue_block *queues = dev->queues;	struct aac_fib_context *fibctx;	unsigned long flags;	DECLARE_WAITQUEUE(wait, current);	/*	 *	We can only have one thread per adapter for AIF's.	 */	if (dev->aif_thread)		return -EINVAL;	/*	 *	Set up the name that will appear in 'ps'	 *	stored in  task_struct.comm[16].	 */	sprintf(current->comm, "aacraid");	daemonize();	/*	 *	Let the DPC know it has a place to send the AIF's to.	 */	dev->aif_thread = 1;	add_wait_queue(&queues->queue[HostNormCmdQueue].cmdready, &wait);	set_current_state(TASK_INTERRUPTIBLE);	dprintk ((KERN_INFO "aac_command_thread start\n"));	while(1) 	{		spin_lock_irqsave(queues->queue[HostNormCmdQueue].lock, flags);		while(!list_empty(&(queues->queue[HostNormCmdQueue].cmdq))) {			struct list_head *entry;			struct aac_aifcmd * aifcmd;			set_current_state(TASK_RUNNING);			entry = queues->queue[HostNormCmdQueue].cmdq.next;			list_del(entry);				spin_unlock_irqrestore(queues->queue[HostNormCmdQueue].lock, flags);			fib = list_entry(entry, struct fib, fiblink);			/*			 *	We will process the FIB here or pass it to a 			 *	worker thread that is TBD. We Really can't 			 *	do anything at this point since we don't have			 *	anything defined for this thread to do.			 */			hw_fib = fib->hw_fib;						memset(fib, 0, sizeof(struct fib));			fib->type = FSAFS_NTC_FIB_CONTEXT;			fib->size = sizeof( struct fib );			fib->hw_fib = hw_fib;			fib->data = hw_fib->data;			fib->dev = dev;			/*			 *	We only handle AifRequest fibs from the adapter.			 */			aifcmd = (struct aac_aifcmd *) hw_fib->data;			if (aifcmd->command == cpu_to_le32(AifCmdDriverNotify)) {				/* Handle Driver Notify Events */				aac_handle_aif(dev, fib);				*(u32 *)hw_fib->data = cpu_to_le32(ST_OK);				fib_adapter_complete(fib, sizeof(u32));			} else {				struct list_head *entry;				/* The u32 here is important and intended. We are using				   32bit wrapping time to fit the adapter field */				   				u32 time_now, time_last;				unsigned long flagv;								/* Sniff events */				if (aifcmd->command == cpu_to_le32(AifCmdEventNotify))					aac_handle_aif(dev, fib);				time_now = jiffies/HZ;				spin_lock_irqsave(&dev->fib_lock, flagv);				entry = dev->fib_list.next;				/*				 * For each Context that is on the 				 * fibctxList, make a copy of the				 * fib, and then set the event to wake up the				 * thread that is waiting for it.				 */				while (entry != &dev->fib_list) {					/*					 * Extract the fibctx					 */					fibctx = list_entry(entry, struct aac_fib_context, next);					/*					 * Check if the queue is getting					 * backlogged					 */					if (fibctx->count > 20)					{						/*						 * It's *not* jiffies folks,						 * but jiffies / HZ, so do not						 * panic ...						 */						time_last = fibctx->jiffies;						/*						 * Has it been > 2 minutes 						 * since the last read off						 * the queue?						 */						if ((time_now - time_last) > 120) {							entry = entry->next;							aac_close_fib_context(dev, fibctx);							continue;						}					}					/*					 * Warning: no sleep allowed while					 * holding spinlock					 */					hw_newfib = kmalloc(sizeof(struct hw_fib), GFP_ATOMIC);					newfib = kmalloc(sizeof(struct fib), GFP_ATOMIC);					if (newfib && hw_newfib) {						/*						 * Make the copy of the FIB						 * FIXME: check if we need to fix other fields up						 */						memcpy(hw_newfib, hw_fib, sizeof(struct hw_fib));						memcpy(newfib, fib, sizeof(struct fib));						newfib->hw_fib = hw_newfib;						/*						 * Put the FIB onto the						 * fibctx's fibs						 */						list_add_tail(&newfib->fiblink, &fibctx->fib_list);						fibctx->count++;						/* 						 * Set the event to wake up the						 * thread that will waiting.						 */						up(&fibctx->wait_sem);					} else {						printk(KERN_WARNING "aifd: didn't allocate NewFib.\n");						if(newfib)							kfree(newfib);						if(hw_newfib)							kfree(hw_newfib);					}					entry = entry->next;				}				/*				 *	Set the status of this FIB				 */				*(u32 *)hw_fib->data = cpu_to_le32(ST_OK);				fib_adapter_complete(fib, sizeof(u32));				spin_unlock_irqrestore(&dev->fib_lock, flagv);			}			spin_lock_irqsave(queues->queue[HostNormCmdQueue].lock, flags);			kfree(fib);		}		/*		 *	There are no more AIF's		 */		spin_unlock_irqrestore(queues->queue[HostNormCmdQueue].lock, flags);		schedule();		if(signal_pending(current))			break;		set_current_state(TASK_INTERRUPTIBLE);	}	remove_wait_queue(&queues->queue[HostNormCmdQueue].cmdready, &wait);	dev->aif_thread = 0;	complete_and_exit(&dev->aif_completion, 0);}

⌨️ 快捷键说明

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