summaryrefslogtreecommitdiffstats
path: root/drivers/net/fddi/skfp/hwt.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-10-25 13:25:22 +0200
committerLinus Torvalds <torvalds@linux-foundation.org>2011-10-25 13:25:22 +0200
commit8a9ea3237e7eb5c25f09e429ad242ae5a3d5ea22 (patch)
treea0a63398a9983667d52cbbbf4e2405b4f22b1d83 /drivers/net/fddi/skfp/hwt.c
parent1be025d3cb40cd295123af2c394f7229ef9b30ca (diff)
parent8b3408f8ee994973869d8ba32c5bf482bc4ddca4 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1745 commits) dp83640: free packet queues on remove dp83640: use proper function to free transmit time stamping packets ipv6: Do not use routes from locally generated RAs |PATCH net-next] tg3: add tx_dropped counter be2net: don't create multiple RX/TX rings in multi channel mode be2net: don't create multiple TXQs in BE2 be2net: refactor VF setup/teardown code into be_vf_setup/clear() be2net: add vlan/rx-mode/flow-control config to be_setup() net_sched: cls_flow: use skb_header_pointer() ipv4: avoid useless call of the function check_peer_pmtu TCP: remove TCP_DEBUG net: Fix driver name for mdio-gpio.c ipv4: tcp: fix TOS value in ACK messages sent from TIME_WAIT rtnetlink: Add missing manual netlink notification in dev_change_net_namespaces ipv4: fix ipsec forward performance regression jme: fix irq storm after suspend/resume route: fix ICMP redirect validation net: hold sock reference while processing tx timestamps tcp: md5: add more const attributes Add ethtool -g support to virtio_net ... Fix up conflicts in: - drivers/net/Kconfig: The split-up generated a trivial conflict with removal of a stale reference to Documentation/networking/net-modules.txt. Remove it from the new location instead. - fs/sysfs/dir.c: Fairly nasty conflicts with the sysfs rb-tree usage, conflicting with Eric Biederman's changes for tagged directories.
Diffstat (limited to 'drivers/net/fddi/skfp/hwt.c')
-rw-r--r--drivers/net/fddi/skfp/hwt.c269
1 files changed, 269 insertions, 0 deletions
diff --git a/drivers/net/fddi/skfp/hwt.c b/drivers/net/fddi/skfp/hwt.c
new file mode 100644
index 00000000000..c0798fd2ca6
--- /dev/null
+++ b/drivers/net/fddi/skfp/hwt.c
@@ -0,0 +1,269 @@
+/******************************************************************************
+ *
+ * (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++ ;
+
+ outpd(ADDR(B2_TI_INI), (u_long) cnt * 200) ; /* Load timer value. */
+ outpw(ADDR(B2_TI_CRTL), TIM_START) ; /* Start timer. */
+
+ 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) ;
+
+ 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 function 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
+