source: sbliveos2/trunk/sblive/timer.c@ 205

Last change on this file since 205 was 142, checked in by ktk, 25 years ago

Import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 4.3 KB
Line 
1/* $Id: timer.c 142 2000-04-23 14:55:46Z ktk $ */
2
3
4/*
5 **********************************************************************
6 * timer.c
7 * Copyright (C) 1999, 2000 Creative Labs, inc.
8 *
9 **********************************************************************
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation; either version 2 of
14 * the License, or (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public
22 * License along with this program; if not, write to the Free
23 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
24 * USA.
25 *
26 **********************************************************************
27 */
28
29/* 3/6/2000 Improved support for different timer delays Rui Sousa */
30
31/* 4/3/2000 Implemented timer list using list.h Rui Sousa */
32
33#include "hwaccess.h"
34
35/* Try to schedule only once per fragment */
36
37void emu10k1_timer_irqhandler(struct emu10k1_card *card)
38{
39 struct emu_timer *t;
40 struct list_head *entry;
41
42 spin_lock(&card->timer_lock);
43
44 list_for_each(entry, &card->timers) {
45 t = list_entry(entry, struct emu_timer, list);
46
47 if (t->active) {
48 t->count++;
49 if (t->count == t->count_max) {
50 t->count = 0;
51 tasklet_hi_schedule(&t->tasklet);
52 }
53 }
54 }
55
56 spin_unlock(&card->timer_lock);
57
58 return;
59}
60
61struct emu_timer *emu10k1_timer_install(struct emu10k1_card *card, void (*func) (unsigned long), unsigned long data, u32 delay)
62{
63 struct emu_timer *timer;
64 struct emu_timer *t;
65 struct list_head *entry;
66 unsigned long flags;
67
68 if ((timer = (struct emu_timer *) kmalloc(sizeof(struct emu_timer), GFP_KERNEL)) == NULL)
69 return timer;
70
71 if (delay < 5)
72 delay = 5;
73
74 timer->delay = delay;
75 tasklet_init(&timer->tasklet, func, data);
76 timer->active = 0;
77
78 spin_lock_irqsave(&card->timer_lock, flags);
79
80 timer->count_max = timer->delay / (card->timer_delay < 1024 ? card->timer_delay : 1024);
81 timer->count = timer->count_max - 1;
82
83 list_add(&timer->list, &card->timers);
84
85 if (card->timer_delay > delay) {
86 if (card->timer_delay == TIMER_STOPPED)
87 emu10k1_irq_enable(card, INTE_INTERVALTIMERENB);
88
89 card->timer_delay = delay;
90 delay = (delay < 1024 ? delay : 1024);
91
92 WRITE_FN0(card, TIMER_RATE, delay);
93
94 list_for_each(entry, &card->timers) {
95 t = list_entry(entry, struct emu_timer, list);
96
97 t->count_max = t->delay / delay;
98 /* don't want to think much, just force scheduling
99 on the next interrupt */
100 t->count = t->count_max - 1;
101 }
102
103 DPD(2, "timer rate --> %u\n", delay);
104 }
105
106 spin_unlock_irqrestore(&card->timer_lock, flags);
107
108 return timer;
109}
110
111void emu10k1_timer_uninstall(struct emu10k1_card *card, struct emu_timer *timer)
112{
113 struct emu_timer *t;
114 struct list_head *entry;
115 u32 delay = TIMER_STOPPED;
116 unsigned long flags;
117
118 spin_lock_irqsave(&card->timer_lock, flags);
119
120 list_del(&timer->list);
121
122 list_for_each(entry, &card->timers) {
123 t = list_entry(entry, struct emu_timer, list);
124
125 if (t->delay < delay)
126 delay = t->delay;
127 }
128
129 if (card->timer_delay != delay) {
130 card->timer_delay = delay;
131
132 if (delay == TIMER_STOPPED)
133 emu10k1_irq_disable(card, INTE_INTERVALTIMERENB);
134 else {
135 delay = (delay < 1024 ? delay : 1024);
136
137 WRITE_FN0(card, TIMER_RATE, delay);
138
139 list_for_each(entry, &card->timers) {
140 t = list_entry(entry, struct emu_timer, list);
141
142 t->count_max = t->delay / delay;
143 t->count = t->count_max - 1;
144 }
145 }
146
147 DPD(2, "timer rate --> %u\n", delay);
148 }
149
150 spin_unlock_irqrestore(&card->timer_lock, flags);
151
152 tasklet_unlock_wait(&timer->tasklet);
153 kfree(timer);
154
155 return;
156}
157
158void emu10k1_timer_enable(struct emu10k1_card *card, struct emu_timer *timer)
159{
160 unsigned long flags;
161
162 spin_lock_irqsave(&card->timer_lock, flags);
163 timer->active = 1;
164 spin_unlock_irqrestore(&card->timer_lock, flags);
165
166 return;
167}
168
169void emu10k1_timer_disable(struct emu10k1_card *card, struct emu_timer *timer)
170{
171 unsigned long flags;
172
173 spin_lock_irqsave(&card->timer_lock, flags);
174 timer->active = 0;
175 spin_unlock_irqrestore(&card->timer_lock, flags);
176
177 return;
178}
Note: See TracBrowser for help on using the repository browser.