source: cmedia/trunk/Sblive/timer.c@ 354

Last change on this file since 354 was 354, checked in by stevenhl, 17 years ago

Import untested baseline cmedia sources, work products and binaries
Binaries and work products should be deleted from repository.
once new builds are verified to work.

File size: 4.5 KB
Line 
1/* $Id: timer.c,v 1.1 2000/04/23 14:55:46 ktk Exp $ */
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.