Staging: dt3155: use the fbuffer pointer instead of looking it up
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / dt3155 / dt3155_isr.c
blob549186f41f275436e6922474e732ac5ae8100bf0
1 /*
3 Copyright 1996,2002,2005 Gregory D. Hager, Alfred A. Rizzi, Noah J. Cowan,
4 Jason Lapenta, Scott Smedley, Greg Sharp
6 This file is part of the DT3155 Device Driver.
8 The DT3155 Device Driver is free software; you can redistribute it
9 and/or modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of the
11 License, or (at your option) any later version.
13 The DT3155 Device Driver is distributed in the hope that it will be
14 useful, but WITHOUT ANY WARRANTY; without even the implied warranty
15 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with the DT3155 Device Driver; if not, write to the Free
20 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 MA 02111-1307 USA
23 File: dt3155_isr.c
24 Purpose: Buffer management routines, and other routines for the ISR
25 (the actual isr is in dt3155_drv.c)
27 -- Changes --
29 Date Programmer Description of changes made
30 -------------------------------------------------------------------
31 03-Jul-2000 JML n/a
32 02-Apr-2002 SS Mods to make work with separate allocator
33 module; Merged John Roll's mods to make work with
34 multiple boards.
35 10-Jul-2002 GCS Complete rewrite of setup_buffers to disallow
36 buffers which span a 4MB boundary.
37 24-Jul-2002 SS GPL licence.
38 30-Jul-2002 NJC Added support for buffer loop.
39 31-Jul-2002 NJC Complete rewrite of buffer management
40 02-Aug-2002 NJC Including slab.h instead of malloc.h (no warning).
41 Also, allocator_init() now returns allocator_max
42 so cleaned up allocate_buffers() accordingly.
43 08-Aug-2005 SS port to 2.6 kernel.
47 #include <asm/system.h>
48 #include <linux/gfp.h>
49 #include <linux/sched.h>
50 #include <linux/types.h>
52 #include "dt3155.h"
53 #include "dt3155_drv.h"
54 #include "dt3155_io.h"
55 #include "dt3155_isr.h"
56 #include "allocator.h"
58 #define FOUR_MB (0x0400000) /* Can't DMA accross a 4MB boundary!*/
59 #define UPPER_10_BITS (0x3FF<<22) /* Can't DMA accross a 4MB boundary!*/
62 /******************************************************************************
63 * Simple array based que struct
65 * Some handy functions using the buffering structure.
66 *****************************************************************************/
68 /***************************
69 * are_empty_buffers
70 ***************************/
71 bool are_empty_buffers(struct dt3155_fbuffer *fb)
73 return fb->empty_len;
76 /**************************
77 * push_empty
79 * This is slightly confusing. The number empty_len is the literal #
80 * of empty buffers. After calling, empty_len-1 is the index into the
81 * empty buffer stack. So, if empty_len == 1, there is one empty buffer,
82 * given by fb->empty_buffers[0].
83 * empty_buffers should never fill up, though this is not checked.
84 **************************/
85 void push_empty(struct dt3155_fbuffer *fb, int index)
87 fb->empty_buffers[fb->empty_len] = index;
88 fb->empty_len++;
91 /**************************
92 * pop_empty
93 **************************/
94 int pop_empty(struct dt3155_fbuffer *fb)
96 fb->empty_len--;
97 return fb->empty_buffers[fb->empty_len];
100 /*************************
101 * is_ready_buf_empty
102 *************************/
103 bool is_ready_buf_empty(struct dt3155_fbuffer *fb)
105 return fb->ready_len == 0;
108 /*************************
109 * is_ready_buf_full
111 * this should *never* be true if there are any active, locked or empty
112 * buffers, since it corresponds to nbuffers ready buffers!!
113 * 7/31/02: total rewrite. --NJC
114 *************************/
115 bool is_ready_buf_full(struct dt3155_fbuffer *fb)
117 return fb->ready_len == fb->nbuffers;
120 /*****************************************************
121 * push_ready
122 *****************************************************/
123 void push_ready(struct dt3155_fbuffer *fb, int index)
125 int head = fb->ready_head;
127 fb->ready_que[head] = index;
128 fb->ready_head = (head + 1) % fb->nbuffers;
129 fb->ready_len++;
132 /*****************************************************
133 * get_tail
135 * Simply comptutes the tail given the head and the length.
136 *****************************************************/
137 static int get_tail(struct dt3155_fbuffer *fb)
139 return (fb->ready_head - fb->ready_len + fb->nbuffers) % fb->nbuffers;
142 /*****************************************************
143 * pop_ready
145 * This assumes that there is a ready buffer ready... should
146 * be checked (e.g. with is_ready_buf_empty() prior to call.
147 *****************************************************/
148 int pop_ready(struct dt3155_fbuffer *fb)
150 int tail = get_tail(fb);
152 fb->ready_len--;
153 return fb->ready_que[tail];
156 /*****************************************************
157 * printques
158 *****************************************************/
159 void printques(struct dt3155_fbuffer *fb)
161 int i;
163 printk(KERN_INFO "\n R:");
164 for (i = get_tail(fb); i != fb->ready_head; i++, i %= fb->nbuffers)
165 printk(" %d ", fb->ready_que[i]);
167 printk(KERN_INFO "\n E:");
168 for (i = 0; i < fb->empty_len; i++)
169 printk(" %d ", fb->empty_buffers[i]);
171 printk(KERN_INFO "\n A: %d", fb->active_buf);
173 printk(KERN_INFO "\n L: %d\n", fb->locked_buf);
176 /*****************************************************
177 * adjust_4MB
179 * If a buffer intersects the 4MB boundary, push
180 * the start address up to the beginning of the
181 * next 4MB chunk (assuming bufsize < 4MB).
182 *****************************************************/
183 u32 adjust_4MB(u32 buf_addr, u32 bufsize)
185 if (((buf_addr+bufsize) & UPPER_10_BITS) != (buf_addr & UPPER_10_BITS))
186 return (buf_addr+bufsize) & UPPER_10_BITS;
187 else
188 return buf_addr;
192 /*****************************************************
193 * allocate_buffers
195 * Try to allocate enough memory for all requested
196 * buffers. If there is not enough free space
197 * try for less memory.
198 *****************************************************/
199 void allocate_buffers(u32 *buf_addr, u32* total_size_kbs,
200 u32 bufsize)
202 /* Compute the minimum amount of memory guaranteed to hold all
203 MAXBUFFERS such that no buffer crosses the 4MB boundary.
204 Store this value in the variable "full_size" */
206 u32 allocator_max;
207 u32 bufs_per_chunk = (FOUR_MB / bufsize);
208 u32 filled_chunks = (MAXBUFFERS-1) / bufs_per_chunk;
209 u32 leftover_bufs = MAXBUFFERS - filled_chunks * bufs_per_chunk;
211 u32 full_size = bufsize /* possibly unusable part of 1st chunk */
212 + filled_chunks * FOUR_MB /* max # of completely filled 4mb chunks */
213 + leftover_bufs * bufsize; /* these buffs will be in a partly filled
214 chunk at beginning or end */
216 u32 full_size_kbs = 1 + (full_size-1) / 1024;
217 u32 min_size_kbs = 2*ndevices*bufsize / 1024;
218 u32 size_kbs;
220 /* Now, try to allocate full_size. If this fails, keep trying for
221 less & less memory until it succeeds. */
222 #ifndef STANDALONE_ALLOCATOR
223 /* initialize the allocator */
224 allocator_init(&allocator_max);
225 #endif
226 size_kbs = full_size_kbs;
227 *buf_addr = 0;
228 printk(KERN_INFO "DT3155: We would like to get: %d KB\n", full_size_kbs);
229 printk(KERN_INFO "DT3155: ...but need at least: %d KB\n", min_size_kbs);
230 printk(KERN_INFO "DT3155: ...the allocator has: %d KB\n", allocator_max);
231 size_kbs = (full_size_kbs <= allocator_max ? full_size_kbs : allocator_max);
232 if (size_kbs > min_size_kbs) {
233 *buf_addr = allocator_allocate_dma(size_kbs, GFP_KERNEL);
234 if (*buf_addr != 0) {
235 printk(KERN_INFO "DT3155: Managed to allocate: %d KB\n",
236 size_kbs);
237 *total_size_kbs = size_kbs;
238 return;
241 /* If we got here, the allocation failed */
242 printk(KERN_INFO "DT3155: Allocator failed!\n");
243 *buf_addr = 0;
244 *total_size_kbs = 0;
245 return;
250 /*****************************************************
251 * dt3155_setup_buffers
253 * setup_buffers just puts the buffering system into
254 * a consistent state before the start of interrupts
256 * JML : it looks like all the buffers need to be
257 * continuous. So I'm going to try and allocate one
258 * continuous buffer.
260 * GCS : Fix DMA problems when buffer spans
261 * 4MB boundary. Also, add error checking. This
262 * function will return -ENOMEM when not enough memory.
263 *****************************************************/
264 u32 dt3155_setup_buffers(u32 *allocatorAddr)
267 struct dt3155_fbuffer *fb;
268 u32 index;
269 u32 rambuff_addr; /* start of allocation */
270 u32 rambuff_size; /* total size allocated to driver */
271 u32 rambuff_acm; /* accumlator, keep track of how much
272 is left after being split up*/
273 u32 rambuff_end; /* end of rambuff */
274 u32 numbufs; /* number of useful buffers allocated (per device) */
275 u32 bufsize = DT3155_MAX_ROWS * DT3155_MAX_COLS;
276 int minor;
278 /* zero the fbuffer status and address structure */
279 for (minor = 0; minor < ndevices; minor++) {
280 fb = &dt3155_status[minor].fbuffer;
281 memset(fb, 0, sizeof(*fb));
284 /* allocate a large contiguous chunk of RAM */
285 allocate_buffers(&rambuff_addr, &rambuff_size, bufsize);
286 printk(KERN_INFO "DT3155: mem info\n");
287 printk(KERN_INFO " - rambuf_addr = 0x%x\n", rambuff_addr);
288 printk(KERN_INFO " - length (kb) = %u\n", rambuff_size);
289 if (rambuff_addr == 0) {
290 printk(KERN_INFO
291 "DT3155: Error setup_buffers() allocator dma failed\n");
292 return -ENOMEM;
294 *allocatorAddr = rambuff_addr;
295 rambuff_end = rambuff_addr + 1024 * rambuff_size;
297 /* after allocation, we need to count how many useful buffers there
298 are so we can give an equal number to each device */
299 rambuff_acm = rambuff_addr;
300 for (index = 0; index < MAXBUFFERS; index++) {
301 /*avoid spanning 4MB bdry*/
302 rambuff_acm = adjust_4MB(rambuff_acm, bufsize);
303 if (rambuff_acm + bufsize > rambuff_end)
304 break;
305 rambuff_acm += bufsize;
307 /* Following line is OK, will waste buffers if index
308 * not evenly divisible by ndevices -NJC*/
309 numbufs = index / ndevices;
310 printk(KERN_INFO " - numbufs = %u\n", numbufs);
311 if (numbufs < 2) {
312 printk(KERN_INFO
313 "DT3155: Error setup_buffers() couldn't allocate 2 bufs/board\n");
314 return -ENOMEM;
317 /* now that we have board memory we spit it up */
318 /* between the boards and the buffers */
319 rambuff_acm = rambuff_addr;
320 for (minor = 0; minor < ndevices; minor++) {
321 fb = &dt3155_status[minor].fbuffer;
322 rambuff_acm = adjust_4MB(rambuff_acm, bufsize);
324 /* Save the start of this boards buffer space (for mmap). */
325 dt3155_status[minor].mem_addr = rambuff_acm;
327 for (index = 0; index < numbufs; index++) {
328 rambuff_acm = adjust_4MB(rambuff_acm, bufsize);
329 if (rambuff_acm + bufsize > rambuff_end) {
330 /* Should never happen */
331 printk(KERN_INFO "DT3155 PROGRAM ERROR (GCS)\n"
332 "Error distributing allocated buffers\n");
333 return -ENOMEM;
336 fb->frame_info[index].addr = rambuff_acm;
337 push_empty(fb, index);
338 /* printk(" - Buffer : %lx\n", fb->frame_info[index].addr); */
339 fb->nbuffers += 1;
340 rambuff_acm += bufsize;
343 /* Make sure there is an active buffer there. */
344 fb->active_buf = pop_empty(fb);
345 fb->even_happened = 0;
346 fb->even_stopped = 0;
348 /* make sure there is no locked_buf JML 2/28/00 */
349 fb->locked_buf = -1;
351 dt3155_status[minor].mem_size = rambuff_acm -
352 dt3155_status[minor].mem_addr;
354 /* setup the ready queue */
355 fb->ready_head = 0;
356 fb->ready_len = 0;
357 printk(KERN_INFO "Available buffers for device %d: %d\n",
358 minor, fb->nbuffers);
361 return 1;
364 /*****************************************************
365 * internal_release_locked_buffer
367 * The internal function for releasing a locked buffer.
368 * It assumes interrupts are turned off.
369 *****************************************************/
370 static void internal_release_locked_buffer(struct dt3155_fbuffer *fb)
372 if (fb->locked_buf >= 0) {
373 push_empty(fb, fb->locked_buf);
374 fb->locked_buf = -1;
378 /*****************************************************
379 * dt3155_release_locked_buffer
381 * The user function of the above.
382 *****************************************************/
383 void dt3155_release_locked_buffer(struct dt3155_fbuffer *fb)
385 unsigned long int flags;
387 local_save_flags(flags);
388 local_irq_disable();
389 internal_release_locked_buffer(fb);
390 local_irq_restore(flags);
393 /*****************************************************
394 * dt3155_flush
395 *****************************************************/
396 int dt3155_flush(struct dt3155_fbuffer *fb)
398 unsigned long int flags;
399 int index;
401 local_save_flags(flags);
402 local_irq_disable();
404 internal_release_locked_buffer(fb);
405 fb->empty_len = 0;
407 for (index = 0; index < fb->nbuffers; index++)
408 push_empty(fb, index);
410 /* Make sure there is an active buffer there. */
411 fb->active_buf = pop_empty(fb);
413 fb->even_happened = 0;
414 fb->even_stopped = 0;
416 /* setup the ready queue */
417 fb->ready_head = 0;
418 fb->ready_len = 0;
420 local_irq_restore(flags);
422 return 0;
425 /*****************************************************
426 * dt3155_get_ready_buffer
428 * get_ready_buffer will grab the next chunk of data
429 * if it is already there, otherwise it returns 0.
430 * If the user has a buffer locked it will unlock
431 * that buffer before returning the new one.
432 *****************************************************/
433 int dt3155_get_ready_buffer(struct dt3155_fbuffer *fb)
435 unsigned long int flags;
436 int frame_index;
438 local_save_flags(flags);
439 local_irq_disable();
441 #ifdef DEBUG_QUES_A
442 printques(fb);
443 #endif
445 internal_release_locked_buffer(fb);
447 if (is_ready_buf_empty(fb)) {
448 frame_index = -1;
449 } else {
450 frame_index = pop_ready(fb);
451 fb->locked_buf = frame_index;
454 #ifdef DEBUG_QUES_B
455 printques(fb);
456 #endif
458 local_irq_restore(flags);
460 return frame_index;