patch-2.3.47 linux/drivers/net/skfp/hwt.c

Next file: linux/drivers/net/skfp/lnkstat.c
Previous file: linux/drivers/net/skfp/hwmtm.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.46/linux/drivers/net/skfp/hwt.c linux/drivers/net/skfp/hwt.c
@@ -0,0 +1,314 @@
+/******************************************************************************
+ *
+ *	(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(smc, time)
+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++ ;
+#ifndef	PCI
+	/*
+	 * 6.25MHz -> CLK0 : T0 (cnt0 = 16us)	-> OUT0
+	 *    OUT0 -> CLK1 : T1 (cnt1)	OUT1	-> ISRA(IS_TIMINT)
+	 */
+	OUT_82c54_TIMER(3,1<<6 | 3<<4 | 0<<1) ;	/* counter 1, mode 0 */
+	OUT_82c54_TIMER(1,cnt & 0xff) ;		/* LSB */
+	OUT_82c54_TIMER(1,(cnt>>8) & 0xff) ;	/* MSB */
+	/*
+	 * start timer by switching counter 0 to mode 3
+	 *	T0 resolution 16 us (CLK0=0.16us)
+	 */
+	OUT_82c54_TIMER(3,0<<6 | 3<<4 | 3<<1) ;	/* counter 0, mode 3 */
+	OUT_82c54_TIMER(0,100) ;		/* LSB */
+	OUT_82c54_TIMER(0,0) ;			/* MSB */
+#else	/* PCI */
+	outpd(ADDR(B2_TI_INI), (u_long) cnt * 200) ;	/* Load timer value. */
+	outpw(ADDR(B2_TI_CRTL), TIM_START) ;		/* Start timer. */
+#endif	/* PCI */
+	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(smc)
+struct s_smc *smc ;
+{
+#ifndef PCI
+	/* stop counter 0 by switching to mode 0 */
+	OUT_82c54_TIMER(3,0<<6 | 3<<4 | 0<<1) ;	/* counter 0, mode 0 */
+	OUT_82c54_TIMER(0,0) ;			/* LSB */
+	OUT_82c54_TIMER(0,0) ;			/* MSB */
+#else	/* PCI */
+	outpw(ADDR(B2_TI_CRTL), TIM_STOP) ;
+	outpw(ADDR(B2_TI_CRTL), TIM_CL_IRQ) ;
+#endif	/* PCI */
+
+	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(smc)
+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(smc)
+struct s_smc *smc ;
+{
+	hwt_stop(smc) ;
+#ifndef	PCI
+	OUT_82c54_TIMER(3,1<<6 | 3<<4 | 0<<1) ;	/* counter 1, mode 0 */
+	OUT_82c54_TIMER(1,1 ) ;			/* LSB */
+	OUT_82c54_TIMER(1,0 ) ;			/* MSB */
+#endif
+}
+
+/************************
+ *
+ *	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(smc)
+struct s_smc *smc ;
+{
+	u_short	tr ;
+#ifndef	PCI
+	u_short	is ;
+#else
+	u_long	is ;
+#endif
+
+	if (smc->hw.timer_activ) {
+		hwt_stop(smc) ;
+#ifndef	PCI
+		OUT_82c54_TIMER(3,1<<6) ;	/* latch command */
+		tr = IN_82c54_TIMER(1) & 0xff ;
+		tr += (IN_82c54_TIMER(1) & 0xff)<<8 ;
+#else	/* PCI */
+		tr = (u_short)((inpd(ADDR(B2_TI_VAL))/200) & 0xffff) ;
+#endif	/* PCI */
+		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(smc)
+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 immediatly, if the timer is not 
+ *	 started
+ ************************/
+void hwt_wait_time(smc,start,duration)
+struct s_smc *smc ;
+u_long	start ;
+long	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

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)