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

📄 commsup.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
	hw_fib->header.Command = cpu_to_le16(command);	hw_fib->header.XferState |= cpu_to_le32(SentFromHost);	fibptr->hw_fib->header.Flags = 0;	/* 0 the flags field - internal only*/	/*	 *	Set the size of the Fib we want to send to the adapter	 */	hw_fib->header.Size = cpu_to_le16(sizeof(struct aac_fibhdr) + size);	if (le16_to_cpu(hw_fib->header.Size) > le16_to_cpu(hw_fib->header.SenderSize)) {		return -EMSGSIZE;	}                	/*	 *	Get a queue entry connect the FIB to it and send an notify	 *	the adapter a command is ready.	 */	hw_fib->header.XferState |= cpu_to_le32(NormalPriority);	/*	 *	Fill in the Callback and CallbackContext if we are not	 *	going to wait.	 */	if (!wait) {		fibptr->callback = callback;		fibptr->callback_data = callback_data;	}	fibptr->done = 0;	fibptr->flags = 0;	FIB_COUNTER_INCREMENT(aac_config.FibsSent);	dprintk((KERN_DEBUG "Fib contents:.\n"));	dprintk((KERN_DEBUG "  Command =               %d.\n", le32_to_cpu(hw_fib->header.Command)));	dprintk((KERN_DEBUG "  SubCommand =            %d.\n", le32_to_cpu(((struct aac_query_mount *)fib_data(fibptr))->command)));	dprintk((KERN_DEBUG "  XferState  =            %x.\n", le32_to_cpu(hw_fib->header.XferState)));	dprintk((KERN_DEBUG "  hw_fib va being sent=%p\n",fibptr->hw_fib));	dprintk((KERN_DEBUG "  hw_fib pa being sent=%lx\n",(ulong)fibptr->hw_fib_pa));	dprintk((KERN_DEBUG "  fib being sent=%p\n",fibptr));	q = &dev->queues->queue[AdapNormCmdQueue];	if(wait)		spin_lock_irqsave(&fibptr->event_lock, flags);	spin_lock_irqsave(q->lock, qflags);	if (dev->new_comm_interface) {		unsigned long count = 10000000L; /* 50 seconds */		list_add_tail(&fibptr->queue, &q->pendingq);		q->numpending++;		spin_unlock_irqrestore(q->lock, qflags);		while (aac_adapter_send(fibptr) != 0) {			if (--count == 0) {				if (wait)					spin_unlock_irqrestore(&fibptr->event_lock, flags);				spin_lock_irqsave(q->lock, qflags);				q->numpending--;				list_del(&fibptr->queue);				spin_unlock_irqrestore(q->lock, qflags);				return -ETIMEDOUT;			}			udelay(5);		}	} else {		u32 index;		unsigned long nointr = 0;		aac_queue_get( dev, &index, AdapNormCmdQueue, hw_fib, 1, fibptr, &nointr);		list_add_tail(&fibptr->queue, &q->pendingq);		q->numpending++;		*(q->headers.producer) = cpu_to_le32(index + 1);		spin_unlock_irqrestore(q->lock, qflags);		dprintk((KERN_DEBUG "fib_send: inserting a queue entry at index %d.\n",index));		if (!(nointr & aac_config.irq_mod))			aac_adapter_notify(dev, AdapNormCmdQueue);	}	/*	 *	If the caller wanted us to wait for response wait now. 	 */    	if (wait) {		spin_unlock_irqrestore(&fibptr->event_lock, flags);		/* Only set for first known interruptable command */		if (wait < 0) {			/*			 * *VERY* Dangerous to time out a command, the			 * assumption is made that we have no hope of			 * functioning because an interrupt routing or other			 * hardware failure has occurred.			 */			unsigned long count = 36000000L; /* 3 minutes */			while (down_trylock(&fibptr->event_wait)) {				if (--count == 0) {					spin_lock_irqsave(q->lock, qflags);					q->numpending--;					list_del(&fibptr->queue);					spin_unlock_irqrestore(q->lock, qflags);					if (wait == -1) {	        				printk(KERN_ERR "aacraid: fib_send: first asynchronous command timed out.\n"						  "Usually a result of a PCI interrupt routing problem;\n"						  "update mother board BIOS or consider utilizing one of\n"						  "the SAFE mode kernel options (acpi, apic etc)\n");					}					return -ETIMEDOUT;				}				udelay(5);			}		} else			down(&fibptr->event_wait);		if(fibptr->done == 0)			BUG();					if((fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)){			return -ETIMEDOUT;		} else {			return 0;		}	}	/*	 *	If the user does not want a response than return success otherwise	 *	return pending	 */	if (reply)		return -EINPROGRESS;	else		return 0;}/**  *	aac_consumer_get	-	get the top of the queue *	@dev: Adapter *	@q: Queue *	@entry: Return entry * *	Will return a pointer to the entry on the top of the queue requested that * 	we are a consumer of, and return the address of the queue entry. It does *	not change the state of the queue.  */int aac_consumer_get(struct aac_dev * dev, struct aac_queue * q, struct aac_entry **entry){	u32 index;	int status;	if (le32_to_cpu(*q->headers.producer) == le32_to_cpu(*q->headers.consumer)) {		status = 0;	} else {		/*		 *	The consumer index must be wrapped if we have reached		 *	the end of the queue, else we just use the entry		 *	pointed to by the header index		 */		if (le32_to_cpu(*q->headers.consumer) >= q->entries) 			index = 0;				else		        index = le32_to_cpu(*q->headers.consumer);		*entry = q->base + index;		status = 1;	}	return(status);}/** *	aac_consumer_free	-	free consumer entry *	@dev: Adapter *	@q: Queue *	@qid: Queue ident * *	Frees up the current top of the queue we are a consumer of. If the *	queue was full notify the producer that the queue is no longer full. */void aac_consumer_free(struct aac_dev * dev, struct aac_queue *q, u32 qid){	int wasfull = 0;	u32 notify;	if ((le32_to_cpu(*q->headers.producer)+1) == le32_to_cpu(*q->headers.consumer))		wasfull = 1;        	if (le32_to_cpu(*q->headers.consumer) >= q->entries)		*q->headers.consumer = cpu_to_le32(1);	else		*q->headers.consumer = cpu_to_le32(le32_to_cpu(*q->headers.consumer)+1);        	if (wasfull) {		switch (qid) {		case HostNormCmdQueue:			notify = HostNormCmdNotFull;			break;		case HostNormRespQueue:			notify = HostNormRespNotFull;			break;		default:			BUG();			return;		}		aac_adapter_notify(dev, notify);	}}        /** *	fib_adapter_complete	-	complete adapter issued fib *	@fibptr: fib to complete *	@size: size of fib * *	Will do all necessary work to complete a FIB that was sent from *	the adapter. */int fib_adapter_complete(struct fib * fibptr, unsigned short size){	struct hw_fib * hw_fib = fibptr->hw_fib;	struct aac_dev * dev = fibptr->dev;	struct aac_queue * q;	unsigned long nointr = 0;	unsigned long qflags;	if (hw_fib->header.XferState == 0) {		if (dev->new_comm_interface)			kfree (hw_fib);        	return 0;	}	/*	 *	If we plan to do anything check the structure type first.	 */ 	if ( hw_fib->header.StructType != FIB_MAGIC ) {		if (dev->new_comm_interface)			kfree (hw_fib);        	return -EINVAL;	}	/*	 *	This block handles the case where the adapter had sent us a	 *	command and we have finished processing the command. We	 *	call completeFib when we are done processing the command 	 *	and want to send a response back to the adapter. This will 	 *	send the completed cdb to the adapter.	 */	if (hw_fib->header.XferState & cpu_to_le32(SentFromAdapter)) {		if (dev->new_comm_interface) {			kfree (hw_fib);		} else {	       		u32 index;		        hw_fib->header.XferState |= cpu_to_le32(HostProcessed);			if (size) {				size += sizeof(struct aac_fibhdr);				if (size > le16_to_cpu(hw_fib->header.SenderSize)) 					return -EMSGSIZE;				hw_fib->header.Size = cpu_to_le16(size);			}			q = &dev->queues->queue[AdapNormRespQueue];			spin_lock_irqsave(q->lock, qflags);			aac_queue_get(dev, &index, AdapNormRespQueue, hw_fib, 1, NULL, &nointr);			*(q->headers.producer) = cpu_to_le32(index + 1);			spin_unlock_irqrestore(q->lock, qflags);			if (!(nointr & (int)aac_config.irq_mod))				aac_adapter_notify(dev, AdapNormRespQueue);		}	}	else 	{        	printk(KERN_WARNING "fib_adapter_complete: Unknown xferstate detected.\n");        	BUG();	}   	return 0;}/** *	fib_complete	-	fib completion handler *	@fib: FIB to complete * *	Will do all necessary work to complete a FIB. */ int fib_complete(struct fib * fibptr){	struct hw_fib * hw_fib = fibptr->hw_fib;	/*	 *	Check for a fib which has already been completed	 */	if (hw_fib->header.XferState == 0)        	return 0;	/*	 *	If we plan to do anything check the structure type first.	 */ 	if (hw_fib->header.StructType != FIB_MAGIC)	        return -EINVAL;	/*	 *	This block completes a cdb which orginated on the host and we 	 *	just need to deallocate the cdb or reinit it. At this point the	 *	command is complete that we had sent to the adapter and this	 *	cdb could be reused.	 */	if((hw_fib->header.XferState & cpu_to_le32(SentFromHost)) &&		(hw_fib->header.XferState & cpu_to_le32(AdapterProcessed)))	{		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){	char *cp = dev->printfbuf;	if (dev->printf_enabled)	{		int length = val & 0xffff;		int level = (val >> 16) & 0xffff;				/*		 *	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_AAC_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. */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;	struct scsi_device *device;	enum {		NOTHING,		DELETE,		ADD,		CHANGE	} device_config_needed;	/* Sniff for container changes */	if (!dev)		return;	container = (u32)-1;	/*	 *	We have set this up to try and minimize the number of	 * re-configures that take place. As a result of this when	 * certain AIF's come in we will set a flag waiting for another	 * type of AIF before setting the re-config flag.	 */	switch (le32_to_cpu(aifcmd->command)) {	case AifCmdDriverNotify:		switch (le32_to_cpu(((u32 *)aifcmd->data)[0])) {		/*		 *	Morph or Expand complete		 */		case AifDenMorphComplete:		case AifDenVolumeExtendComplete:			container = le32_to_cpu(((u32 *)aifcmd->data)[1]);			if (container >= dev->maximum_num_containers)				break;			/*			 *	Find the scsi_device associated with the SCSI			 * address. Make sure we have the right array, and if			 * so set the flag to initiate a new re-config once we			 * see an AifEnConfigChange AIF come through.			 */			if ((dev != NULL) && (dev->scsi_host_ptr != NULL)) {				device = scsi_device_lookup(dev->scsi_host_ptr, 					CONTAINER_TO_CHANNEL(container), 					CONTAINER_TO_ID(container), 					CONTAINER_TO_LUN(container));				if (device) {					dev->fsa_dev[container].config_needed = CHANGE;					dev->fsa_dev[container].config_waiting_on = AifEnConfigChange;					scsi_device_put(device);				}			}		}		/*		 *	If we are waiting on something and this happens to be		 * that thing then set the re-configure flag.		 */		if (container != (u32)-1) {			if (container >= dev->maximum_num_containers)				break;			if (dev->fsa_dev[container].config_waiting_on ==			    le32_to_cpu(*(u32 *)aifcmd->data))				dev->fsa_dev[container].config_waiting_on = 0;		} else for (container = 0;

⌨️ 快捷键说明

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