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

📄 eni_buffer.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
字号:
/* * * =================================== * HARP  |  Host ATM Research Platform * =================================== * * * This Host ATM Research Platform ("HARP") file (the "Software") is * made available by Network Computing Services, Inc. ("NetworkCS") * "AS IS".  NetworkCS does not provide maintenance, improvements or * support of any kind. * * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED, * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE. * In no event shall NetworkCS be responsible for any damages, including * but not limited to consequential damages, arising from or relating to * any use of the Software or related support. * * Copyright 1994-1998 Network Computing Services, Inc. * * Copies of this Software may be made, however, the above copyright * notice must be reproduced on all copies. * *	@(#) $Id: eni_buffer.c,v 1.2 1998/10/31 20:06:45 phk Exp $ * *//* * Efficient ENI Adapter Support * ----------------------------- * * Handle adapter memory buffers for ENI adapters * */#include <netatm/kern_include.h>#include <dev/hea/eni_stats.h>#include <dev/hea/eni.h>#include <dev/hea/eni_var.h>#ifndef lint__RCSID("@(#) $Id: eni_buffer.c,v 1.2 1998/10/31 20:06:45 phk Exp $");#endifstatic int	eni_test_memory __P((Eni_unit *));/* * The host is going to manage (that is, allocate and free) buffers * in the adapters RAM space. We are going to implement this as a * linked list describing FREE and INUSE memory segments. Initially, * the list contains one element with all memory marked free. As requests * are made, we search the list until we find the first free element * which can satisfy the request. If necessary, we will break the free * element into an INUSE element, and a new FREE element. When freeing * memory, we look at adjacent elements and if one or more are free, * we will combine into a single larger FREE element. *//* * This is for testing purposes. Since there are two versions of * the Efficient adapter with different memory sizes, this allows * us to fool an adapter with more memory into thinking it has less. */int	eni_mem_max = MAX_ENI_MEM;	/* Default to all available memory *//* * Size and test adapter RAM * * Walk through adapter RAM writing known patterns and reading back * for comparison. We write more than one pattern on the off chance * that we "get lucky" and read what we expected. * * Arguments: *	eup		pointer to device unit structure * * Returns *	size		memory size in bytes */static inteni_test_memory ( eup )	Eni_unit *eup;{	int	ram_size = 0;	int	i;	Eni_mem	mp;	/*	 * Walk through to maximum looking for RAM	 */	for ( i = 0; i < MAX_ENI_MEM; i += TEST_STEP ) {		mp = (Eni_mem)((int)eup->eu_ram + i);		/* write pattern */		*mp = (u_long)TEST_PAT;		/* read pattern, match? */		if ( *mp == (u_long)TEST_PAT ) {			/* yes - write inverse pattern */			*mp = (u_long)~TEST_PAT;			/* read pattern, match? */			if ( *mp == (u_long)~TEST_PAT ) {				/* yes - assume another 1K available */				ram_size = i + TEST_STEP;			} else			    break;		} else			break;	}	/*	 * Clear all RAM to initial value of zero.	 * This makes sure we don't leave anything funny in the	 * queues.	 */	KM_ZERO ( eup->eu_ram, ram_size );	/*	 * If we'd like to claim to have less memory, here's where	 * we do so. We take the minimum of what we'd like and what	 * we really found on the adapter.	 */	ram_size = MIN ( ram_size, eni_mem_max ); 	return ( ram_size );}/* * Initialize our memory allocator. * * Arguments: *	eup		Pointer to per unit structure * * Returns: *	size		Physical RAM size *	-1		failed to initialize memory * */inteni_init_memory ( eup )	Eni_unit *eup;{	/*	 * Have we (somehow) been called before?	 */	if ( eup->eu_memmap != NULL )	{		/* Oops  - it's already been initialized */		return -1;	}	/*	 * Allocate initial element which will hold all of memory	 */	if ( ( eup->eu_memmap = (Mbd *)KM_ALLOC(sizeof(Mbd), M_DEVBUF,	    M_NOWAIT ) ) == NULL )	{		/* Memory allocation error */		return -1;	}	/*	 * Test and size memory	 */	eup->eu_ramsize = eni_test_memory ( eup );	/*	 * Initialize a one element list which contains	 * all buffer memory	 */	eup->eu_memmap->prev = eup->eu_memmap->next = NULL;	eup->eu_memmap->base = (caddr_t)SEGBUF_BASE;	eup->eu_memmap->size = eup->eu_ramsize - SEGBUF_BASE;	eup->eu_memmap->state = MEM_FREE;	return ( eup->eu_ramsize );}/* * Allocate a buffer from adapter RAM. Due to constraints on the card, * we may roundup the size request to the next largest chunksize. Note * also that we must pay attention to address alignment within adapter * memory as well. * * Arguments: *	eup		pointer to per unit structure *	size		pointer to requested size - in bytes * * Returns: *	addr		address relative to adapter of allocated memory *	size		modified to reflect actual size of buffer * */caddr_teni_allocate_buffer ( eup, size )	Eni_unit *eup;	u_long	*size;{	int	nsize;	int	nclicks;	Mbd	*eptr = eup->eu_memmap;	/*	 * Initial size requested	 */	nsize = *size;	/*	 * Find the buffer size which will hold this request. There	 * are 8 possible sizes, each a power of two up, starting at	 * 256 words or 1024 bytes.	 */	for ( nclicks = 0; nclicks < ENI_BUF_NBIT; nclicks++ )		if ( ( 1 << nclicks ) * ENI_BUF_PGSZ >= nsize )			break;	/*	 * Request was for larger then the card supports	 */	if ( nclicks >= ENI_BUF_NBIT ) {		eup->eu_stats.eni_st_drv.drv_mm_toobig++;		/* Indicate 0 bytes allocated */		*size = 0;		/* Return NULL buffer */		return ( (caddr_t)NULL );	}	/*	 * New size will be buffer size	 */	nsize = ( 1 << nclicks ) * ENI_BUF_PGSZ;	/*	 * Look through memory for a segment large enough to	 * hold request	 */	while ( eptr ) {	    /*	     * State must be FREE and size must hold request	     */	    if ( eptr->state == MEM_FREE && eptr->size >= nsize )	    {		/*		 * Request will fit - now check if the		 * alignment needs fixing		 */		if ( ((u_int)eptr->base & (nsize-1)) != 0 )		{		    caddr_t	nbase;		    /*		     * Calculate where the buffer would have to		     * fall to be aligned.		     */		    nbase = (caddr_t)((u_int)( eptr->base + nsize ) &		        ~(nsize-1));		    /*		     * If we use this alignment, will it still fit?		     */		    if ( (eptr->size - (nbase - eptr->base)) >= 0 )		    {			Mbd	*etmp;			/* Yep - create a new segment */			etmp = (Mbd *)KM_ALLOC(sizeof(Mbd), M_DEVBUF,			    M_NOWAIT );			if ( etmp == (Mbd *)NULL ) {				/*				 * Couldn't allocate a new descriptor. Indicate 				 * failure and exit now or we'll start losing				 * memory.				 */				eup->eu_stats.eni_st_drv.drv_mm_nodesc++;				*size = 0;				return ( (caddr_t)NULL );			}			/* Place it in the list */			etmp->next = eptr->next;			if ( etmp->next )			    etmp->next->prev = etmp;			etmp->prev = eptr;			eptr->next = etmp;			/* Fill in new base and size */			etmp->base = nbase;			etmp->size = eptr->size - ( nbase - eptr->base );			/* Adjust old size */			eptr->size -= etmp->size;			/* Mark its state */			etmp->state = MEM_FREE;			eptr = etmp;			/* Done - outa here */			break;		    }		} else		    break;		/* Alignment is okay  - we're done */	    }	    /* Haven't found anything yet - keep looking */	    eptr = eptr->next;	}	if ( eptr != NULL )	{	    /* Found a usable segment - grab what we need */	    /* Exact fit? */	    if ( eptr->size == nsize )		/* Mark it as INUSE */		eptr->state = MEM_INUSE;	    else	    {		Mbd	*etmp;		/* larger then we need - split it */		etmp = (Mbd *)KM_ALLOC(sizeof(Mbd), M_DEVBUF, M_NOWAIT );		if ( etmp == (Mbd *)NULL ) {			/*			 * Couldn't allocate new descriptor. Indicate			 * failure and exit now or we'll start losing			 * memory.			 */			eup->eu_stats.eni_st_drv.drv_mm_nodesc++;			*size = 0;			return ( (caddr_t)NULL );		}		/* Place new element in list */		etmp->next = eptr->next;		if ( etmp->next )		    etmp->next->prev = etmp;		etmp->prev = eptr;		eptr->next = etmp;		/* Set new base, size and state */		etmp->base = eptr->base + nsize;		etmp->size = eptr->size - nsize;		etmp->state = MEM_FREE;		/* Adjust size and state of element we intend to use */		eptr->size = nsize;		eptr->state = MEM_INUSE;	    }	}	/* After all that, did we find a usable buffer? */	if ( eptr )	{		/* Record another inuse buffer of this size */		if ( eptr->base )			eup->eu_memclicks[nclicks]++;		/*		 * Return true size of allocated buffer		 */		*size = eptr->size;		/*		 * Make address relative to start of RAM since		 * its (the address) for use by the adapter, not		 * the host.		 */		return ((caddr_t)eptr->base);	} else {		eup->eu_stats.eni_st_drv.drv_mm_nobuf++;		/* No buffer to return - indicate zero length */		*size = 0;		/* Return NULL buffer */		return ( (caddr_t)NULL );	}}/* * Procedure to release a buffer previously allocated from adapter * RAM. When possible, we'll compact memory. * * Arguments: *	eup		pointer to per unit structure *	base		base adapter address of buffer to be freed * * Returns: *	none * */voideni_free_buffer ( eup, base )	Eni_unit *eup;	caddr_t	base;{	Mbd	*eptr = eup->eu_memmap;	int	nclicks;	/* Look through entire list */	while ( eptr )	{		/* Is this the buffer to be freed? */		if ( eptr->base == base )		{			/*			 * We're probably asking for trouble but,			 * assume this is it.			 */			if ( eptr->state != MEM_INUSE )			{				eup->eu_stats.eni_st_drv.drv_mm_notuse++;				/* Huh? Something's wrong */				return;			}			/* Reset state to FREE */			eptr->state = MEM_FREE;			/* Determine size for stats info */			for ( nclicks = 0; nclicks < ENI_BUF_NBIT; nclicks++ )			    if ( ( 1 << nclicks ) * ENI_BUF_PGSZ == eptr->size )				break;			/* Valid size? Yes - decrement inuse count */			if ( nclicks < ENI_BUF_NBIT )				eup->eu_memclicks[nclicks]--;			/* Try to compact neighbors */			/* with previous */			if ( eptr->prev )			    if ( eptr->prev->state == MEM_FREE )			    {				Mbd	*etmp = eptr;				/* Add to previous block */				eptr->prev->size += eptr->size;				/* Set prev block to skip this one */				eptr->prev->next = eptr->next;				/* Set next block to skip this one */				if ( eptr->next )					eptr->next->prev = eptr->prev;				/* Reset to where we want to be */				eptr = eptr->prev;				/* and free this element */				(void)KM_FREE(etmp, etmp->size, M_DEVBUF);			    }			/* with next */			if ( eptr->next )			    if ( eptr->next->state == MEM_FREE )			    {				Mbd	*etmp = eptr->next;				/* add following block in */				eptr->size += etmp->size;				/* set next next block to skip next block */				if ( etmp->next )					etmp->next->prev = eptr;				/* skip next block */				eptr->next = etmp->next;				/* and free next element */				(void)KM_FREE(etmp, etmp->size, M_DEVBUF);			    }			/*			 * We've freed the buffer and done any compaction,			 * we needn't look any further...			 */			return;		}		eptr = eptr->next;	}	if ( eptr == NULL )	{		/* Oops - failed to find the buffer. This is BAD */		eup->eu_stats.eni_st_drv.drv_mm_notfnd++;	}}

⌨️ 快捷键说明

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