fore_command.c

来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 448 行

C
448
字号
/* * * =================================== * 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: fore_command.c,v 1.4 1998/12/04 22:54:45 archie Exp $ * *//* * FORE Systems 200-Series Adapter Support * --------------------------------------- * * Command queue management * */#include <dev/hfa/fore_include.h>#ifndef lint__RCSID("@(#) $Id: fore_command.c,v 1.4 1998/12/04 22:54:45 archie Exp $");#endif/* * Local variables */static struct t_atm_cause	fore_cause = {	T_ATM_ITU_CODING,	T_ATM_LOC_USER,	T_ATM_CAUSE_TEMPORARY_FAILURE,	{0, 0, 0, 0}};/* * Allocate Command Queue Data Structures * * Arguments: *	fup		pointer to device unit structure * * Returns: *	0		allocations successful *	else		allocation failed */intfore_cmd_allocate(fup)	Fore_unit	*fup;{	caddr_t		memp;	/*	 * Allocate non-cacheable memory for command status words	 */	memp = atm_dev_alloc(sizeof(Q_status) * CMD_QUELEN,			QSTAT_ALIGN, ATM_DEV_NONCACHE);	if (memp == NULL) {		return (1);	}	fup->fu_cmd_stat = (Q_status *) memp;	memp = DMA_GET_ADDR(fup->fu_cmd_stat, sizeof(Q_status) * CMD_QUELEN,			QSTAT_ALIGN, ATM_DEV_NONCACHE);	if (memp == NULL) {		return (1);	}	fup->fu_cmd_statd = (Q_status *) memp;	/*	 * Allocate memory for statistics buffer	 */	memp = atm_dev_alloc(sizeof(Fore_stats), FORE_STATS_ALIGN, 0);	if (memp == NULL) {		return (1);	}	fup->fu_stats = (Fore_stats *) memp;#ifdef FORE_PCI	/*	 * Allocate memory for PROM buffer	 */	memp = atm_dev_alloc(sizeof(Fore_prom), FORE_PROM_ALIGN, 0);	if (memp == NULL) {		return (1);	}	fup->fu_prom = (Fore_prom *) memp;#endif	return (0);}/* * Command Queue Initialization * * Allocate and initialize the host-resident command queue structures * and then initialize the CP-resident queue structures. *  * Called at interrupt level. * * Arguments: *	fup		pointer to device unit structure * * Returns: *	none */voidfore_cmd_initialize(fup)	Fore_unit	*fup;{	Aali		*aap = fup->fu_aali;	Cmd_queue	*cqp;	H_cmd_queue	*hcp;	Q_status	*qsp;	Q_status	*qsp_dma;	int		i;	/*	 * Point to CP-resident command queue	 */	cqp = (Cmd_queue *)(fup->fu_ram + CP_READ(aap->aali_cmd_q));	/*	 * Point to host-resident command queue structures	 */	hcp = fup->fu_cmd_q;	qsp = fup->fu_cmd_stat;	qsp_dma = fup->fu_cmd_statd;	/*	 * Loop thru all queue entries and do whatever needs doing	 */	for (i = 0; i < CMD_QUELEN; i++) {		/*		 * Set queue status word to free		 */		*qsp = QSTAT_FREE;		/*		 * Set up host queue entry and link into ring		 */		hcp->hcq_cpelem = cqp;		hcp->hcq_status = qsp;		if (i == (CMD_QUELEN - 1))			hcp->hcq_next = fup->fu_cmd_q;		else			hcp->hcq_next = hcp + 1;		/*		 * Now let the CP into the game		 */		cqp->cmdq_status = (CP_dma) CP_WRITE(qsp_dma);		/*		 * Bump all queue pointers		 */		hcp++;		qsp++;		qsp_dma++;		cqp++;	}	/*	 * Initialize queue pointers	 */	fup->fu_cmd_head = fup->fu_cmd_tail = fup->fu_cmd_q;	return;}/* * Drain Command Queue * * This function will process and free all completed entries at the head  * of the command queue.  * * May be called in interrupt state.   * Must be called with interrupts locked out. * * Arguments: *	fup		pointer to device unit structure * * Returns: *	none */voidfore_cmd_drain(fup)	Fore_unit	*fup;{	H_cmd_queue	*hcp;	Fore_vcc	*fvp;	/*	 * Process each completed entry	 */	while (*fup->fu_cmd_head->hcq_status & QSTAT_COMPLETED) {		hcp = fup->fu_cmd_head;		/*		 * Process command completion		 */		switch (hcp->hcq_code) {		case CMD_ACT_VCCIN:		case CMD_ACT_VCCOUT:			fvp = hcp->hcq_arg;			if (*hcp->hcq_status & QSTAT_ERROR) {				/*				 * VCC activation failed - just abort vcc				 */				if (fvp)					atm_cm_abort(fvp->fv_connvc,						&fore_cause);				fup->fu_pif.pif_cmderrors++;			} else {				/*				 * Successful VCC activation				 */				if (fvp) {					fvp->fv_state = CVS_ACTIVE;					fup->fu_open_vcc++;				}			}			break;		case CMD_DACT_VCCIN:		case CMD_DACT_VCCOUT:			fvp = hcp->hcq_arg;			if (*hcp->hcq_status & QSTAT_ERROR) {				/*				 * VCC dactivation failed - whine				 */				log(LOG_ERR, 				   "fore_cmd_drain: DACT failed, vcc=(%d,%d)\n",					fvp->fv_connvc->cvc_vcc->vc_vpi,					fvp->fv_connvc->cvc_vcc->vc_vci);				fup->fu_pif.pif_cmderrors++;			} else {				/*				 * Successful VCC dactivation - so what?				 */			}			break;		case CMD_GET_STATS:			if (*hcp->hcq_status & QSTAT_ERROR) {				/*				 * Couldn't get stats				 */				fup->fu_pif.pif_cmderrors++;				fup->fu_stats_ret = EIO;			} else {				/*				 * Stats are now in unit buffer				 */				fup->fu_stats_ret = 0;			}			DMA_FREE_ADDR(fup->fu_stats, fup->fu_statsd,				sizeof(Fore_cp_stats), 0);			fup->fu_flags &= ~FUF_STATCMD;			/*			 * Flush received stats data			 */#ifdef VAC			if (vac)				vac_pageflush((addr_t)fup->fu_stats);#endif#if BYTE_ORDER == LITTLE_ENDIAN			/*			 * Little endian machines receives the stats in			 * wrong byte order. Instead of swapping in user			 * land, swap here so that everything going out			 * of the kernel is in correct host order.			 */			{				u_long *bp = (u_long *)fup->fu_stats;				int	loop;				for ( loop = 0; loop < sizeof(Fore_cp_stats)/				    sizeof(long); loop++, bp++ )					*bp = ntohl(*bp);			}#endif	/* BYTE_ORDER == LITTLE_ENDIAN */			/*			 * Poke whoever is waiting on the stats			 */			wakeup((caddr_t)&fup->fu_stats);			break;#ifdef FORE_PCI		case CMD_GET_PROM:			if (*hcp->hcq_status & QSTAT_ERROR) {				/*				 * Couldn't get PROM data				 */				fup->fu_pif.pif_cmderrors++;				log(LOG_ERR, 				    "fore_cmd_drain: %s%d: GET_PROM failed\n",					fup->fu_pif.pif_name,					fup->fu_pif.pif_unit);			} else {				Fore_prom	*fp = fup->fu_prom;				/*				 * Flush received PROM data				 */#ifdef VAC				if (vac)					vac_pageflush((addr_t)fp);#endif				/*				 * Copy PROM info into config areas				 */				KM_COPY(&fp->pr_mac[2],					&fup->fu_pif.pif_macaddr,					sizeof(struct mac_addr));				fup->fu_config.ac_macaddr = 					fup->fu_pif.pif_macaddr;				snprintf(fup->fu_config.ac_hard_vers,				    sizeof(fup->fu_config.ac_hard_vers),					"%ld.%ld.%ld",					(fp->pr_hwver >> 16) & 0xff,					(fp->pr_hwver >> 8) & 0xff,					fp->pr_hwver & 0xff);				fup->fu_config.ac_serial = fp->pr_serno;			}			DMA_FREE_ADDR(fup->fu_prom, fup->fu_promd,				sizeof(Fore_prom), 0);			break;#endif	/* FORE_PCI */		default:			log(LOG_ERR, "fore_cmd_drain: unknown command %ld\n",				hcp->hcq_code);		}		/*		 * Mark this entry free for use and bump head pointer		 * to the next entry in the queue		 */		*hcp->hcq_status = QSTAT_FREE;		fup->fu_cmd_head = hcp->hcq_next;	}	return;}/* * Free Command Queue Data Structures * * Arguments: *	fup		pointer to device unit structure * * Returns: *	none */voidfore_cmd_free(fup)	Fore_unit	*fup;{	H_cmd_queue	*hcp;	/*	 * Deal with any commands left on the queue	 */	if (fup->fu_flags & CUF_INITED) {		while (*fup->fu_cmd_head->hcq_status != QSTAT_FREE) {			hcp = fup->fu_cmd_head;			switch (hcp->hcq_code) {			case CMD_GET_STATS:				/*				 * Just in case someone is sleeping on this				 */				fup->fu_stats_ret = EIO;				wakeup((caddr_t)&fup->fu_stats);				break;			}			*hcp->hcq_status = QSTAT_FREE;			fup->fu_cmd_head = hcp->hcq_next;		}	}	/*	 * Free the statistics buffer	 */	if (fup->fu_stats) {		atm_dev_free(fup->fu_stats);		fup->fu_stats = NULL;	}#ifdef FORE_PCI	/*	 * Free the PROM buffer	 */	if (fup->fu_prom) {		atm_dev_free(fup->fu_prom);		fup->fu_prom = NULL;	}#endif	/*	 * Free the status words	 */	if (fup->fu_cmd_stat) {		if (fup->fu_cmd_statd) {			DMA_FREE_ADDR(fup->fu_cmd_stat, fup->fu_cmd_statd,				sizeof(Q_status) * CMD_QUELEN,				ATM_DEV_NONCACHE);		}		atm_dev_free((void *)fup->fu_cmd_stat);		fup->fu_cmd_stat = NULL;		fup->fu_cmd_statd = NULL;	}	return;}

⌨️ 快捷键说明

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