Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /******************************************************************************
  2  *
  3  *      (C)Copyright 1998,1999 SysKonnect,
  4  *      a business unit of Schneider & Koch & Co. Datensysteme GmbH.
  5  *
  6  *      See the file "skfddi.c" for further information.
  7  *
  8  *      This program is free software; you can redistribute it and/or modify
  9  *      it under the terms of the GNU General Public License as published by
 10  *      the Free Software Foundation; either version 2 of the License, or
 11  *      (at your option) any later version.
 12  *
 13  *      The information in this file is provided "AS IS" without warranty.
 14  *
 15  ******************************************************************************/
 16 
 17 /*
 18         SMT timer
 19 */
 20 
 21 #include "h/types.h"
 22 #include "h/fddi.h"
 23 #include "h/smc.h"
 24 
 25 #ifndef lint
 26 static const char ID_sccs[] = "@(#)smttimer.c   2.4 97/08/04 (C) SK " ;
 27 #endif
 28 
 29 static void timer_done(struct s_smc *smc, int restart);
 30 
 31 void smt_timer_init(struct s_smc *smc)
 32 {
 33         smc->t.st_queue = NULL;
 34         smc->t.st_fast.tm_active = FALSE ;
 35         smc->t.st_fast.tm_next = NULL;
 36         hwt_init(smc) ;
 37 }
 38 
 39 void smt_timer_stop(struct s_smc *smc, struct smt_timer *timer)
 40 {
 41         struct smt_timer        **prev ;
 42         struct smt_timer        *tm ;
 43 
 44         /*
 45          * remove timer from queue
 46          */
 47         timer->tm_active = FALSE ;
 48         if (smc->t.st_queue == timer && !timer->tm_next) {
 49                 hwt_stop(smc) ;
 50         }
 51         for (prev = &smc->t.st_queue ; (tm = *prev) ; prev = &tm->tm_next ) {
 52                 if (tm == timer) {
 53                         *prev = tm->tm_next ;
 54                         if (tm->tm_next) {
 55                                 tm->tm_next->tm_delta += tm->tm_delta ;
 56                         }
 57                         return ;
 58                 }
 59         }
 60 }
 61 
 62 void smt_timer_start(struct s_smc *smc, struct smt_timer *timer, u_long time,
 63                      u_long token)
 64 {
 65         struct smt_timer        **prev ;
 66         struct smt_timer        *tm ;
 67         u_long                  delta = 0 ;
 68 
 69         time /= 16 ;            /* input is uS, clock ticks are 16uS */
 70         if (!time)
 71                 time = 1 ;
 72         smt_timer_stop(smc,timer) ;
 73         timer->tm_smc = smc ;
 74         timer->tm_token = token ;
 75         timer->tm_active = TRUE ;
 76         if (!smc->t.st_queue) {
 77                 smc->t.st_queue = timer ;
 78                 timer->tm_next = NULL;
 79                 timer->tm_delta = time ;
 80                 hwt_start(smc,time) ;
 81                 return ;
 82         }
 83         /*
 84          * timer correction
 85          */
 86         timer_done(smc,0) ;
 87 
 88         /*
 89          * find position in queue
 90          */
 91         delta = 0 ;
 92         for (prev = &smc->t.st_queue ; (tm = *prev) ; prev = &tm->tm_next ) {
 93                 if (delta + tm->tm_delta > time) {
 94                         break ;
 95                 }
 96                 delta += tm->tm_delta ;
 97         }
 98         /* insert in queue */
 99         *prev = timer ;
100         timer->tm_next = tm ;
101         timer->tm_delta = time - delta ;
102         if (tm)
103                 tm->tm_delta -= timer->tm_delta ;
104         /*
105          * start new with first
106          */
107         hwt_start(smc,smc->t.st_queue->tm_delta) ;
108 }
109 
110 void smt_force_irq(struct s_smc *smc)
111 {
112         smt_timer_start(smc,&smc->t.st_fast,32L, EV_TOKEN(EVENT_SMT,SM_FAST)); 
113 }
114 
115 void smt_timer_done(struct s_smc *smc)
116 {
117         timer_done(smc,1) ;
118 }
119 
120 static void timer_done(struct s_smc *smc, int restart)
121 {
122         u_long                  delta ;
123         struct smt_timer        *tm ;
124         struct smt_timer        *next ;
125         struct smt_timer        **last ;
126         int                     done = 0 ;
127 
128         delta = hwt_read(smc) ;
129         last = &smc->t.st_queue ;
130         tm = smc->t.st_queue ;
131         while (tm && !done) {
132                 if (delta >= tm->tm_delta) {
133                         tm->tm_active = FALSE ;
134                         delta -= tm->tm_delta ;
135                         last = &tm->tm_next ;
136                         tm = tm->tm_next ;
137                 }
138                 else {
139                         tm->tm_delta -= delta ;
140                         delta = 0 ;
141                         done = 1 ;
142                 }
143         }
144         *last = NULL;
145         next = smc->t.st_queue ;
146         smc->t.st_queue = tm ;
147 
148         for ( tm = next ; tm ; tm = next) {
149                 next = tm->tm_next ;
150                 timer_event(smc,tm->tm_token) ;
151         }
152 
153         if (restart && smc->t.st_queue)
154                 hwt_start(smc,smc->t.st_queue->tm_delta) ;
155 }
156 
157 
  This page was automatically generated by the LXR engine.