| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /******************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	(C)Copyright 1998,1999 SysKonnect, | 
					
						
							|  |  |  |  *	a business unit of Schneider & Koch & Co. Datensysteme GmbH. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	See the file "skfddi.c" for further information. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	This program is free software; you can redistribute it and/or modify | 
					
						
							|  |  |  |  *	it under the terms of the GNU General Public License as published by | 
					
						
							|  |  |  |  *	the Free Software Foundation; either version 2 of the License, or | 
					
						
							|  |  |  |  *	(at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	The information in this file is provided "AS IS" without warranty. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ******************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Timer Driver for FBI board (timer chip 82C54) | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Modifications: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	28-Jun-1994 sw	Edit v1.6. | 
					
						
							|  |  |  |  *			MCA: Added support for the SK-NET FDDI-FM2 adapter. The | 
					
						
							|  |  |  |  *			 following functions have been added(+) or modified(*): | 
					
						
							|  |  |  |  *			 hwt_start(*), hwt_stop(*), hwt_restart(*), hwt_read(*) | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "h/types.h"
 | 
					
						
							|  |  |  | #include "h/fddi.h"
 | 
					
						
							|  |  |  | #include "h/smc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef	lint
 | 
					
						
							|  |  |  | static const char ID_sccs[] = "@(#)hwt.c	1.13 97/04/23 (C) SK " ; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Prototypes of local functions. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | /* 28-Jun-1994 sw - Note: hwt_restart() is also used in module 'drvfbi.c'. */ | 
					
						
							|  |  |  | /*static void hwt_restart() ; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	hwt_start | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	Start hardware timer (clock ticks are 16us). | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	void hwt_start( | 
					
						
							|  |  |  |  *		struct s_smc *smc, | 
					
						
							|  |  |  |  *		u_long time) ; | 
					
						
							|  |  |  |  * In | 
					
						
							|  |  |  |  *	smc - A pointer to the SMT Context structure. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	time - The time in units of 16us to load the timer with. | 
					
						
							|  |  |  |  * Out | 
					
						
							|  |  |  |  *	Nothing. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************/ | 
					
						
							|  |  |  | #define	HWT_MAX	(65000)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hwt_start(struct s_smc *smc, u_long time) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	u_short	cnt ; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (time > HWT_MAX) | 
					
						
							|  |  |  | 		time = HWT_MAX ; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	smc->hw.t_start = time ; | 
					
						
							|  |  |  | 	smc->hw.t_stop = 0L ; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cnt = (u_short)time ; | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * if time < 16 us | 
					
						
							|  |  |  | 	 *	time = 16 us | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	if (!cnt) | 
					
						
							|  |  |  | 		cnt++ ; | 
					
						
							| 
									
										
										
										
											2007-07-24 01:30:36 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	outpd(ADDR(B2_TI_INI), (u_long) cnt * 200) ;	/* Load timer value. */ | 
					
						
							|  |  |  | 	outpw(ADDR(B2_TI_CRTL), TIM_START) ;		/* Start timer. */ | 
					
						
							| 
									
										
										
										
											2007-07-24 01:30:36 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	smc->hw.timer_activ = TRUE ; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	hwt_stop | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	Stop hardware timer. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	void hwt_stop( | 
					
						
							|  |  |  |  *		struct s_smc *smc) ; | 
					
						
							|  |  |  |  * In | 
					
						
							|  |  |  |  *	smc - A pointer to the SMT Context structure. | 
					
						
							|  |  |  |  * Out | 
					
						
							|  |  |  |  *	Nothing. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************/ | 
					
						
							|  |  |  | void hwt_stop(struct s_smc *smc) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	outpw(ADDR(B2_TI_CRTL), TIM_STOP) ; | 
					
						
							|  |  |  | 	outpw(ADDR(B2_TI_CRTL), TIM_CL_IRQ) ; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	smc->hw.timer_activ = FALSE ; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	hwt_init | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	Initialize hardware timer. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	void hwt_init( | 
					
						
							|  |  |  |  *		struct s_smc *smc) ; | 
					
						
							|  |  |  |  * In | 
					
						
							|  |  |  |  *	smc - A pointer to the SMT Context structure. | 
					
						
							|  |  |  |  * Out | 
					
						
							|  |  |  |  *	Nothing. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************/ | 
					
						
							|  |  |  | void hwt_init(struct s_smc *smc) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	smc->hw.t_start = 0 ; | 
					
						
							|  |  |  | 	smc->hw.t_stop	= 0 ; | 
					
						
							|  |  |  | 	smc->hw.timer_activ = FALSE ; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	hwt_restart(smc) ; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	hwt_restart | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	Clear timer interrupt. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	void hwt_restart( | 
					
						
							|  |  |  |  *		struct s_smc *smc) ; | 
					
						
							|  |  |  |  * In | 
					
						
							|  |  |  |  *	smc - A pointer to the SMT Context structure. | 
					
						
							|  |  |  |  * Out | 
					
						
							|  |  |  |  *	Nothing. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************/ | 
					
						
							|  |  |  | void hwt_restart(struct s_smc *smc) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hwt_stop(smc) ; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	hwt_read | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	Stop hardware timer and read time elapsed since last start. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	u_long hwt_read(smc) ; | 
					
						
							|  |  |  |  * In | 
					
						
							|  |  |  |  *	smc - A pointer to the SMT Context structure. | 
					
						
							|  |  |  |  * Out | 
					
						
							|  |  |  |  *	The elapsed time since last start in units of 16us. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************/ | 
					
						
							|  |  |  | u_long hwt_read(struct s_smc *smc) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	u_short	tr ; | 
					
						
							|  |  |  | 	u_long	is ; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (smc->hw.timer_activ) { | 
					
						
							|  |  |  | 		hwt_stop(smc) ; | 
					
						
							|  |  |  | 		tr = (u_short)((inpd(ADDR(B2_TI_VAL))/200) & 0xffff) ; | 
					
						
							| 
									
										
										
										
											2007-07-24 01:30:36 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		is = GET_ISR() ; | 
					
						
							|  |  |  | 		/* Check if timer expired (or wraparound). */ | 
					
						
							|  |  |  | 		if ((tr > smc->hw.t_start) || (is & IS_TIMINT)) { | 
					
						
							|  |  |  | 			hwt_restart(smc) ; | 
					
						
							|  |  |  | 			smc->hw.t_stop = smc->hw.t_start ; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			smc->hw.t_stop = smc->hw.t_start - tr ; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return (smc->hw.t_stop) ; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef	PCI
 | 
					
						
							|  |  |  | /************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	hwt_quick_read | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	Stop hardware timer and read timer value and start the timer again. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	u_long hwt_read(smc) ; | 
					
						
							|  |  |  |  * In | 
					
						
							|  |  |  |  *	smc - A pointer to the SMT Context structure. | 
					
						
							|  |  |  |  * Out | 
					
						
							|  |  |  |  *	current timer value in units of 80ns. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************/ | 
					
						
							|  |  |  | u_long hwt_quick_read(struct s_smc *smc) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	u_long interval ; | 
					
						
							|  |  |  | 	u_long time ; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	interval = inpd(ADDR(B2_TI_INI)) ; | 
					
						
							|  |  |  | 	outpw(ADDR(B2_TI_CRTL), TIM_STOP) ; | 
					
						
							|  |  |  | 	time = inpd(ADDR(B2_TI_VAL)) ; | 
					
						
							|  |  |  | 	outpd(ADDR(B2_TI_INI),time) ; | 
					
						
							|  |  |  | 	outpw(ADDR(B2_TI_CRTL), TIM_START) ; | 
					
						
							|  |  |  | 	outpd(ADDR(B2_TI_INI),interval) ; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return(time) ; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	hwt_wait_time(smc,start,duration) | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	This function returnes after the amount of time is elapsed | 
					
						
							|  |  |  |  *	since the start time. | 
					
						
							|  |  |  |  *  | 
					
						
							|  |  |  |  * para	start		start time | 
					
						
							|  |  |  |  *	duration	time to wait | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * NOTE: The fuction will return immediately, if the timer is not  | 
					
						
							|  |  |  |  *	 started | 
					
						
							|  |  |  |  ************************/ | 
					
						
							|  |  |  | void hwt_wait_time(struct s_smc *smc, u_long start, long int duration) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	long	diff ; | 
					
						
							|  |  |  | 	long	interval ; | 
					
						
							|  |  |  | 	int	wrapped ; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * check if timer is running | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	if (smc->hw.timer_activ == FALSE || | 
					
						
							|  |  |  | 		hwt_quick_read(smc) == hwt_quick_read(smc)) { | 
					
						
							|  |  |  | 		return ; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	interval = inpd(ADDR(B2_TI_INI)) ; | 
					
						
							|  |  |  | 	if (interval > duration) { | 
					
						
							|  |  |  | 		do { | 
					
						
							|  |  |  | 			diff = (long)(start - hwt_quick_read(smc)) ; | 
					
						
							|  |  |  | 			if (diff < 0) { | 
					
						
							|  |  |  | 				diff += interval ; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} while (diff <= duration) ; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		diff = interval ; | 
					
						
							|  |  |  | 		wrapped = 0 ; | 
					
						
							|  |  |  | 		do { | 
					
						
							|  |  |  | 			if (!wrapped) { | 
					
						
							|  |  |  | 				if (hwt_quick_read(smc) >= start) { | 
					
						
							|  |  |  | 					diff += interval ; | 
					
						
							|  |  |  | 					wrapped = 1 ; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							|  |  |  | 				if (hwt_quick_read(smc) < start) { | 
					
						
							|  |  |  | 					wrapped = 0 ; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} while (diff <= duration) ; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 |