Merge commit 'kumar/next' into next
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / dt3155 / dt3155_drv.c
CommitLineData
aa337ef1
SS
1/*
2
3Copyright 1996,2002,2005 Gregory D. Hager, Alfred A. Rizzi, Noah J. Cowan,
4 Jason Lapenta, Scott Smedley, Greg Sharp
5
6This file is part of the DT3155 Device Driver.
7
8The DT3155 Device Driver is free software; you can redistribute it
9and/or modify it under the terms of the GNU General Public License as
10published by the Free Software Foundation; either version 2 of the
11License, or (at your option) any later version.
12
13The DT3155 Device Driver is distributed in the hope that it will be
14useful, but WITHOUT ANY WARRANTY; without even the implied warranty
15of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with the DT3155 Device Driver; if not, write to the Free
20Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21MA 02111-1307 USA
22
23-- Changes --
24
25 Date Programmer Description of changes made
26 -------------------------------------------------------------------
27 03-Jul-2000 JML n/a
28 10-Oct-2001 SS port to 2.4 kernel
29 02-Apr-2002 SS Mods to use allocator as a standalone module;
30 Merged John Roll's changes (john@cfa.harvard.edu)
31 to make work with multiple boards.
32 02-Jul-2002 SS Merged James Rose's chages (rosejr@purdue.edu) to:
33 * fix successive interrupt-driven captures
34 * add select/poll support.
35 10-Jul-2002 GCS Add error check when ndevices > MAXBOARDS.
36 02-Aug-2002 GCS Fix field mode so that odd (lower) field is stored
37 in lower half of buffer.
38 05-Aug-2005 SS port to 2.6 kernel.
39 26-Oct-2009 SS port to 2.6.30 kernel.
40
41-- Notes --
42
43** appended "mem=124" in lilo.conf to allow for 4megs free on my 128meg system.
44 * using allocator.c and allocator.h from o'reilly book (alessandro rubini)
45 ftp://ftp.systemy.it/pub/develop (see README.allocator)
46
47 + might want to get rid of MAXboards for allocating initial buffer.
48 confusing and not necessary
49
50 + in cleanup_module the MOD_IN_USE looks like it is check after it should
51
52 * GFP_DMA should not be set with a PCI system (pg 291)
53
54 - NJC why are only two buffers allowed? (see isr, approx line 358)
55
56*/
57
58extern void printques(int);
59
aa337ef1 60#include <linux/module.h>
aa337ef1 61#include <linux/interrupt.h>
aa337ef1
SS
62#include <linux/pci.h>
63#include <linux/types.h>
64#include <linux/poll.h>
ae7fd7b8 65#include <linux/sched.h>
b1f2ac07 66#include <linux/smp_lock.h>
aa337ef1
SS
67
68#include <asm/io.h>
69#include <asm/uaccess.h>
70
71#include "dt3155.h"
72#include "dt3155_drv.h"
73#include "dt3155_isr.h"
74#include "dt3155_io.h"
75#include "allocator.h"
76
74a92013
RD
77
78MODULE_LICENSE("GPL");
79
aa337ef1
SS
80/* Error variable. Zero means no error. */
81int dt3155_errno = 0;
82
83#ifndef PCI_DEVICE_ID_INTEL_7116
84#define PCI_DEVICE_ID_INTEL_7116 0x1223
85#endif
86
87#define DT3155_VENDORID PCI_VENDOR_ID_INTEL
88#define DT3155_DEVICEID PCI_DEVICE_ID_INTEL_7116
89#define MAXPCI 16
90
91#ifdef DT_DEBUG
92#define DT_3155_DEBUG_MSG(x,y) printk(x,y)
93#else
94#define DT_3155_DEBUG_MSG(x,y)
95#endif
96
97/* wait queue for interrupts */
d241fd58 98wait_queue_head_t dt3155_read_wait_queue[MAXBOARDS];
aa337ef1
SS
99
100#define DT_3155_SUCCESS 0
101#define DT_3155_FAILURE -EIO
102
103/* set to dynamicaly allocate, but it is tunable: */
104/* insmod DT_3155 dt3155 dt3155_major=XX */
105int dt3155_major = 0;
106
107/* The minor numbers are 0 and 1 ... they are not tunable.
108 * They are used as the indices for the structure vectors,
109 * and register address vectors
110 */
111
112/* Global structures and variables */
113
114/* Status of each device */
923c1244 115struct dt3155_status dt3155_status[MAXBOARDS];
aa337ef1
SS
116
117/* kernel logical address of the board */
d241fd58 118u8 *dt3155_lbase[MAXBOARDS] = { NULL
aa337ef1
SS
119#if MAXBOARDS == 2
120 , NULL
121#endif
122};
123/* DT3155 registers */
5d392111 124u8 *dt3155_bbase = NULL; /* kernel logical address of the *
aa337ef1 125 * buffer region */
d241fd58 126u32 dt3155_dev_open[MAXBOARDS] = {0
aa337ef1
SS
127#if MAXBOARDS == 2
128 , 0
129#endif
130};
131
dcff74ce 132u32 ndevices = 0;
3a8954e8 133u32 unique_tag = 0;;
aa337ef1
SS
134
135
136/*
137 * Stops interrupt generation right away and resets the status
138 * to idle. I don't know why this works and the other way doesn't.
139 * (James Rose)
140 */
141static void quick_stop (int minor)
142{
143 // TODO: scott was here
144#if 1
d241fd58 145 ReadMReg((dt3155_lbase[minor] + INT_CSR), int_csr_r.reg);
aa337ef1
SS
146 /* disable interrupts */
147 int_csr_r.fld.FLD_END_EVE_EN = 0;
148 int_csr_r.fld.FLD_END_ODD_EN = 0;
d241fd58 149 WriteMReg((dt3155_lbase[minor] + INT_CSR), int_csr_r.reg);
aa337ef1 150
d241fd58 151 dt3155_status[minor].state &= ~(DT3155_STATE_STOP|0xff);
aa337ef1 152 /* mark the system stopped: */
d241fd58
JB
153 dt3155_status[minor].state |= DT3155_STATE_IDLE;
154 dt3155_fbuffer[minor]->stop_acquire = 0;
155 dt3155_fbuffer[minor]->even_stopped = 0;
aa337ef1
SS
156#else
157 dt3155_status[minor].state |= DT3155_STATE_STOP;
158 dt3155_status[minor].fbuffer.stop_acquire = 1;
159#endif
160
161}
162
163
164/*****************************************************
165 * dt3155_isr() Interrupt service routien
166 *
167 * - looks like this isr supports IRQ sharing (or could) JML
168 * - Assumes irq's are disabled, via SA_INTERRUPT flag
169 * being set in request_irq() call from init_module()
170 *****************************************************/
e8afd402 171static void dt3155_isr(int irq, void *dev_id, struct pt_regs *regs)
aa337ef1
SS
172{
173 int minor = -1;
174 int index;
aa337ef1 175 unsigned long flags;
3a8954e8 176 u32 buffer_addr;
aa337ef1
SS
177
178 /* find out who issued the interrupt */
d241fd58
JB
179 for (index = 0; index < ndevices; index++) {
180 if(dev_id == (void*) &dt3155_status[index])
aa337ef1
SS
181 {
182 minor = index;
183 break;
184 }
185 }
186
187 /* hopefully we should not get here */
d241fd58 188 if (minor < 0 || minor >= MAXBOARDS) {
aa337ef1
SS
189 printk(KERN_ERR "dt3155_isr called with invalid dev_id\n");
190 return;
191 }
192
193 /* Check for corruption and set a flag if so */
d241fd58 194 ReadMReg((dt3155_lbase[minor] + CSR1), csr1_r.reg);
aa337ef1 195
d241fd58 196 if ((csr1_r.fld.FLD_CRPT_EVE) || (csr1_r.fld.FLD_CRPT_ODD))
aa337ef1
SS
197 {
198 /* TODO: this should probably stop acquisition */
199 /* and set some flags so that dt3155_read */
200 /* returns an error next time it is called */
201 dt3155_errno = DT_ERR_CORRUPT;
202 printk("dt3155: corrupt field\n");
203 return;
204 }
205
d241fd58 206 ReadMReg((dt3155_lbase[minor] + INT_CSR), int_csr_r.reg);
aa337ef1
SS
207
208 /* Handle the even field ... */
209 if (int_csr_r.fld.FLD_END_EVE)
210 {
d241fd58
JB
211 if ((dt3155_status[minor].state & DT3155_STATE_MODE) ==
212 DT3155_STATE_FLD)
aa337ef1 213 {
d241fd58 214 dt3155_fbuffer[minor]->frame_count++;
aa337ef1
SS
215 }
216
d241fd58 217 ReadI2C(dt3155_lbase[minor], EVEN_CSR, &i2c_even_csr.reg);
aa337ef1
SS
218
219 /* Clear the interrupt? */
220 int_csr_r.fld.FLD_END_EVE = 1;
221
222 /* disable the interrupt if last field */
d241fd58 223 if (dt3155_fbuffer[minor]->stop_acquire)
aa337ef1
SS
224 {
225 printk("dt3155: even stopped.\n");
d241fd58 226 dt3155_fbuffer[minor]->even_stopped = 1;
aa337ef1
SS
227 if (i2c_even_csr.fld.SNGL_EVE)
228 {
229 int_csr_r.fld.FLD_END_EVE_EN = 0;
230 }
231 else
232 {
233 i2c_even_csr.fld.SNGL_EVE = 1;
234 }
235 }
236
d241fd58 237 WriteMReg((dt3155_lbase[minor] + INT_CSR), int_csr_r.reg);
aa337ef1
SS
238
239 /* Set up next DMA if we are doing FIELDS */
d241fd58 240 if ((dt3155_status[minor].state & DT3155_STATE_MODE) ==
aa337ef1
SS
241 DT3155_STATE_FLD)
242 {
243 /* GCS (Aug 2, 2002) -- In field mode, dma the odd field
244 into the lower half of the buffer */
d241fd58
JB
245 const u32 stride = dt3155_status[minor].config.cols;
246 buffer_addr = dt3155_fbuffer[minor]->
247 frame_info[dt3155_fbuffer[minor]->active_buf].addr
aa337ef1 248 + (DT3155_MAX_ROWS / 2) * stride;
aa337ef1
SS
249 local_save_flags(flags);
250 local_irq_disable();
d241fd58 251 wake_up_interruptible(&dt3155_read_wait_queue[minor]);
aa337ef1
SS
252
253 /* Set up the DMA address for the next field */
aa337ef1 254 local_irq_restore(flags);
d241fd58 255 WriteMReg((dt3155_lbase[minor] + ODD_DMA_START), buffer_addr);
aa337ef1
SS
256 }
257
258 /* Check for errors. */
259 i2c_even_csr.fld.DONE_EVE = 1;
d241fd58 260 if (i2c_even_csr.fld.ERROR_EVE)
aa337ef1
SS
261 dt3155_errno = DT_ERR_OVERRUN;
262
d241fd58 263 WriteI2C(dt3155_lbase[minor], EVEN_CSR, i2c_even_csr.reg);
aa337ef1
SS
264
265 /* Note that we actually saw an even field meaning */
266 /* that subsequent odd field complete the frame */
d241fd58 267 dt3155_fbuffer[minor]->even_happened = 1;
aa337ef1
SS
268
269 /* recording the time that the even field finished, this should be */
270 /* about time in the middle of the frame */
d241fd58
JB
271 do_gettimeofday(&(dt3155_fbuffer[minor]->
272 frame_info[dt3155_fbuffer[minor]->
273 active_buf].time));
aa337ef1
SS
274 return;
275 }
276
277 /* ... now handle the odd field */
d241fd58 278 if (int_csr_r.fld.FLD_END_ODD)
aa337ef1 279 {
d241fd58 280 ReadI2C(dt3155_lbase[minor], ODD_CSR, &i2c_odd_csr.reg);
aa337ef1
SS
281
282 /* Clear the interrupt? */
283 int_csr_r.fld.FLD_END_ODD = 1;
284
d241fd58
JB
285 if (dt3155_fbuffer[minor]->even_happened ||
286 (dt3155_status[minor].state & DT3155_STATE_MODE) ==
aa337ef1
SS
287 DT3155_STATE_FLD)
288 {
d241fd58 289 dt3155_fbuffer[minor]->frame_count++;
aa337ef1
SS
290 }
291
d241fd58
JB
292 if (dt3155_fbuffer[minor]->stop_acquire &&
293 dt3155_fbuffer[minor]->even_stopped)
aa337ef1
SS
294 {
295 printk(KERN_DEBUG "dt3155: stopping odd..\n");
d241fd58 296 if (i2c_odd_csr.fld.SNGL_ODD)
aa337ef1
SS
297 {
298 /* disable interrupts */
299 int_csr_r.fld.FLD_END_ODD_EN = 0;
d241fd58 300 dt3155_status[minor].state &= ~(DT3155_STATE_STOP|0xff);
aa337ef1
SS
301
302 /* mark the system stopped: */
d241fd58
JB
303 dt3155_status[minor].state |= DT3155_STATE_IDLE;
304 dt3155_fbuffer[minor]->stop_acquire = 0;
305 dt3155_fbuffer[minor]->even_stopped = 0;
aa337ef1 306
dcff74ce 307 printk(KERN_DEBUG "dt3155: state is now %x\n",
3a8954e8 308 dt3155_status[minor].state);
aa337ef1
SS
309 }
310 else
311 {
312 i2c_odd_csr.fld.SNGL_ODD = 1;
313 }
314 }
315
d241fd58 316 WriteMReg((dt3155_lbase[minor] + INT_CSR), int_csr_r.reg);
aa337ef1
SS
317
318 /* if the odd field has been acquired, then */
319 /* change the next dma location for both fields */
320 /* and wake up the process if sleeping */
d241fd58
JB
321 if (dt3155_fbuffer[minor]->even_happened ||
322 (dt3155_status[minor].state & DT3155_STATE_MODE) ==
323 DT3155_STATE_FLD)
aa337ef1
SS
324 {
325
aa337ef1
SS
326 local_save_flags(flags);
327 local_irq_disable();
aa337ef1
SS
328
329#ifdef DEBUG_QUES_B
d241fd58 330 printques(minor);
aa337ef1 331#endif
d241fd58 332 if (dt3155_fbuffer[minor]->nbuffers > 2)
aa337ef1 333 {
d241fd58 334 if (!are_empty_buffers(minor))
aa337ef1
SS
335 {
336 /* The number of active + locked buffers is
337 * at most 2, and since there are none empty, there
338 * must be at least nbuffers-2 ready buffers.
339 * This is where we 'drop frames', oldest first. */
d241fd58 340 push_empty(pop_ready(minor), minor);
aa337ef1
SS
341 }
342
343 /* The ready_que can't be full, since we know
344 * there is one active buffer right now, so it's safe
345 * to push the active buf on the ready_que. */
d241fd58 346 push_ready(minor, dt3155_fbuffer[minor]->active_buf);
aa337ef1 347 /* There's at least 1 empty -- make it active */
d241fd58
JB
348 dt3155_fbuffer[minor]->active_buf = pop_empty(minor);
349 dt3155_fbuffer[minor]->
350 frame_info[dt3155_fbuffer[minor]->
351 active_buf].tag = ++unique_tag;
aa337ef1
SS
352 }
353 else /* nbuffers == 2, special case */
354 { /* There is 1 active buffer.
355 * If there is a locked buffer, keep the active buffer
356 * the same -- that means we drop a frame.
357 */
d241fd58 358 if (dt3155_fbuffer[minor]->locked_buf < 0)
aa337ef1 359 {
d241fd58
JB
360 push_ready(minor,
361 dt3155_fbuffer[minor]->active_buf);
362 if (are_empty_buffers(minor))
aa337ef1 363 {
d241fd58
JB
364 dt3155_fbuffer[minor]->active_buf =
365 pop_empty(minor);
aa337ef1
SS
366 }
367 else
368 { /* no empty or locked buffers, so use a readybuf */
d241fd58
JB
369 dt3155_fbuffer[minor]->active_buf =
370 pop_ready(minor);
aa337ef1
SS
371 }
372 }
373 }
374
375#ifdef DEBUG_QUES_B
d241fd58 376 printques(minor);
aa337ef1
SS
377#endif
378
d241fd58 379 dt3155_fbuffer[minor]->even_happened = 0;
aa337ef1 380
d241fd58 381 wake_up_interruptible(&dt3155_read_wait_queue[minor]);
aa337ef1 382
aa337ef1 383 local_irq_restore(flags);
aa337ef1
SS
384 }
385
386
387 /* Set up the DMA address for the next frame/field */
d241fd58
JB
388 buffer_addr = dt3155_fbuffer[minor]->
389 frame_info[dt3155_fbuffer[minor]->active_buf].addr;
390 if ((dt3155_status[minor].state & DT3155_STATE_MODE) ==
391 DT3155_STATE_FLD)
aa337ef1 392 {
d241fd58 393 WriteMReg((dt3155_lbase[minor] + EVEN_DMA_START), buffer_addr);
aa337ef1
SS
394 }
395 else
396 {
d241fd58 397 WriteMReg((dt3155_lbase[minor] + EVEN_DMA_START), buffer_addr);
aa337ef1 398
d241fd58
JB
399 WriteMReg((dt3155_lbase[minor] + ODD_DMA_START), buffer_addr
400 + dt3155_status[minor].config.cols);
aa337ef1
SS
401 }
402
403 /* Do error checking */
404 i2c_odd_csr.fld.DONE_ODD = 1;
d241fd58 405 if (i2c_odd_csr.fld.ERROR_ODD)
aa337ef1
SS
406 dt3155_errno = DT_ERR_OVERRUN;
407
d241fd58 408 WriteI2C(dt3155_lbase[minor], ODD_CSR, i2c_odd_csr.reg);
aa337ef1
SS
409
410 return;
411 }
412 /* If we get here, the Odd Field wasn't it either... */
d241fd58 413 printk("neither even nor odd. shared perhaps?\n");
aa337ef1
SS
414}
415
416/*****************************************************
417 * init_isr(int minor)
418 * turns on interupt generation for the card
419 * designated by "minor".
420 * It is called *only* from inside ioctl().
421 *****************************************************/
422static void dt3155_init_isr(int minor)
423{
d241fd58 424 const u32 stride = dt3155_status[minor].config.cols;
aa337ef1 425
d241fd58 426 switch (dt3155_status[minor].state & DT3155_STATE_MODE)
aa337ef1
SS
427 {
428 case DT3155_STATE_FLD:
429 {
d241fd58
JB
430 even_dma_start_r = dt3155_status[minor].
431 fbuffer.frame_info[dt3155_status[minor].fbuffer.active_buf].addr;
aa337ef1
SS
432 even_dma_stride_r = 0;
433 odd_dma_stride_r = 0;
434
d241fd58 435 WriteMReg((dt3155_lbase[minor] + EVEN_DMA_START),
aa337ef1 436 even_dma_start_r);
d241fd58 437 WriteMReg((dt3155_lbase[minor] + EVEN_DMA_STRIDE),
aa337ef1 438 even_dma_stride_r);
d241fd58 439 WriteMReg((dt3155_lbase[minor] + ODD_DMA_STRIDE),
aa337ef1
SS
440 odd_dma_stride_r);
441 break;
442 }
443
444 case DT3155_STATE_FRAME:
445 default:
446 {
d241fd58
JB
447 even_dma_start_r = dt3155_status[minor].
448 fbuffer.frame_info[dt3155_status[minor].fbuffer.active_buf].addr;
aa337ef1
SS
449 odd_dma_start_r = even_dma_start_r + stride;
450 even_dma_stride_r = stride;
451 odd_dma_stride_r = stride;
452
d241fd58 453 WriteMReg((dt3155_lbase[minor] + EVEN_DMA_START),
aa337ef1 454 even_dma_start_r);
d241fd58 455 WriteMReg((dt3155_lbase[minor] + ODD_DMA_START),
aa337ef1 456 odd_dma_start_r);
d241fd58 457 WriteMReg((dt3155_lbase[minor] + EVEN_DMA_STRIDE),
aa337ef1 458 even_dma_stride_r);
d241fd58 459 WriteMReg((dt3155_lbase[minor] + ODD_DMA_STRIDE),
aa337ef1
SS
460 odd_dma_stride_r);
461 break;
462 }
463 }
464
465 /* 50/60 Hz should be set before this point but let's make sure it is */
466 /* right anyway */
467
c8d1a126 468 ReadI2C(dt3155_lbase[minor], CSR2, &i2c_csr2.reg);
aa337ef1 469 i2c_csr2.fld.HZ50 = FORMAT50HZ;
c8d1a126 470 WriteI2C(dt3155_lbase[minor], CSR2, i2c_csr2.reg);
aa337ef1
SS
471
472 /* enable busmaster chip, clear flags */
473
474 /*
475 * TODO:
476 * shouldn't we be concered with continuous values of
477 * DT3155_SNAP & DT3155_ACQ here? (SS)
478 */
479
480 csr1_r.reg = 0;
481 csr1_r.fld.CAP_CONT_EVE = 1; /* use continuous capture bits to */
482 csr1_r.fld.CAP_CONT_ODD = 1; /* enable */
483 csr1_r.fld.FLD_DN_EVE = 1; /* writing a 1 clears flags */
484 csr1_r.fld.FLD_DN_ODD = 1;
485 csr1_r.fld.SRST = 1; /* reset - must be 1 */
486 csr1_r.fld.FIFO_EN = 1; /* fifo control - must be 1 */
487 csr1_r.fld.FLD_CRPT_EVE = 1; /* writing a 1 clears flags */
488 csr1_r.fld.FLD_CRPT_ODD = 1;
489
d241fd58 490 WriteMReg((dt3155_lbase[minor] + CSR1),csr1_r.reg);
aa337ef1
SS
491
492 /* Enable interrupts at the end of each field */
493
494 int_csr_r.reg = 0;
495 int_csr_r.fld.FLD_END_EVE_EN = 1;
496 int_csr_r.fld.FLD_END_ODD_EN = 1;
497 int_csr_r.fld.FLD_START_EN = 0;
498
d241fd58 499 WriteMReg((dt3155_lbase[minor] + INT_CSR), int_csr_r.reg);
aa337ef1
SS
500
501 /* start internal BUSY bits */
502
d241fd58 503 ReadI2C(dt3155_lbase[minor], CSR2, &i2c_csr2.reg);
aa337ef1
SS
504 i2c_csr2.fld.BUSY_ODD = 1;
505 i2c_csr2.fld.BUSY_EVE = 1;
d241fd58 506 WriteI2C(dt3155_lbase[minor], CSR2, i2c_csr2.reg);
aa337ef1
SS
507
508 /* Now its up to the interrupt routine!! */
509
510 return;
511}
512
513
514/*****************************************************
515 * ioctl()
516 *
517 *****************************************************/
dcff74ce
GKH
518static int dt3155_ioctl(struct inode *inode,
519 struct file *file,
520 unsigned int cmd,
521 unsigned long arg)
aa337ef1
SS
522{
523 int minor = MINOR(inode->i_rdev); /* What device are we ioctl()'ing? */
524
d241fd58 525 if (minor >= MAXBOARDS || minor < 0)
aa337ef1
SS
526 return -ENODEV;
527
528 /* make sure it is valid command */
529 if (_IOC_NR(cmd) > DT3155_IOC_MAXNR)
530 {
531 printk("DT3155: invalid IOCTL(0x%x)\n",cmd);
532 printk("DT3155: Valid commands (0x%x), (0x%x), (0x%x), (0x%x), (0x%x)\n",
f721ad7a
GKH
533 (unsigned int)DT3155_GET_CONFIG,
534 (unsigned int)DT3155_SET_CONFIG,
535 (unsigned int)DT3155_START,
536 (unsigned int)DT3155_STOP,
537 (unsigned int)DT3155_FLUSH);
aa337ef1
SS
538 return -EINVAL;
539 }
540
541 switch (cmd)
542 {
543 case DT3155_SET_CONFIG:
544 {
545 if (dt3155_status[minor].state != DT3155_STATE_IDLE)
546 return -EBUSY;
547
548 {
8b692e69 549 struct dt3155_config tmp;
aa337ef1
SS
550 if (copy_from_user((void *)&tmp, (void *) arg, sizeof(tmp)))
551 return -EFAULT;
552 /* check for valid settings */
553 if (tmp.rows > DT3155_MAX_ROWS ||
554 tmp.cols > DT3155_MAX_COLS ||
555 (tmp.acq_mode != DT3155_MODE_FRAME &&
556 tmp.acq_mode != DT3155_MODE_FIELD) ||
557 (tmp.continuous != DT3155_SNAP &&
558 tmp.continuous != DT3155_ACQ))
559 {
560 return -EINVAL;
561 }
562 dt3155_status[minor].config = tmp;
563 }
564 return 0;
565 }
566 case DT3155_GET_CONFIG:
567 {
568 if (copy_to_user((void *) arg, (void *) &dt3155_status[minor],
923c1244 569 sizeof(struct dt3155_status)))
aa337ef1
SS
570 return -EFAULT;
571 return 0;
572 }
573 case DT3155_FLUSH: /* Flushes the buffers -- ensures fresh data */
574 {
575 if (dt3155_status[minor].state != DT3155_STATE_IDLE)
576 return -EBUSY;
577 return dt3155_flush(minor);
578 }
579 case DT3155_STOP:
580 {
581 if (dt3155_status[minor].state & DT3155_STATE_STOP ||
582 dt3155_status[minor].fbuffer.stop_acquire)
583 return -EBUSY;
584
585 if (dt3155_status[minor].state == DT3155_STATE_IDLE)
586 return 0;
587
588 quick_stop(minor);
589 if (copy_to_user((void *) arg, (void *) &dt3155_status[minor],
923c1244 590 sizeof(struct dt3155_status)))
aa337ef1
SS
591 return -EFAULT;
592 return 0;
593 }
594 case DT3155_START:
595 {
596 if (dt3155_status[minor].state != DT3155_STATE_IDLE)
597 return -EBUSY;
598
599 dt3155_status[minor].fbuffer.stop_acquire = 0;
600 dt3155_status[minor].fbuffer.frame_count = 0;
601
602 /* Set the MODE in the status -- we default to FRAME */
603 if (dt3155_status[minor].config.acq_mode == DT3155_MODE_FIELD)
604 {
605 dt3155_status[minor].state = DT3155_STATE_FLD;
606 }
607 else
608 {
609 dt3155_status[minor].state = DT3155_STATE_FRAME;
610 }
611
612 dt3155_init_isr(minor);
d241fd58 613 if (copy_to_user((void *) arg, (void *) &dt3155_status[minor],
923c1244 614 sizeof(struct dt3155_status)))
aa337ef1
SS
615 return -EFAULT;
616 return 0;
617 }
618 default:
619 {
620 printk("DT3155: invalid IOCTL(0x%x)\n",cmd);
621 printk("DT3155: Valid commands (0x%x), (0x%x), (0x%x), (0x%x), (0x%x)\n",
f721ad7a
GKH
622 (unsigned int)DT3155_GET_CONFIG,
623 (unsigned int)DT3155_SET_CONFIG,
aa337ef1
SS
624 DT3155_START, DT3155_STOP, DT3155_FLUSH);
625 return -ENOSYS;
626 }
627 }
628 return -ENOSYS;
629}
630
631/*****************************************************
632 * mmap()
633 *
634 * only allow the user to mmap the registers and buffer
635 * It is quite possible that this is broken, since the
636 * addition of of the capacity for two cards!!!!!!!!
637 * It *looks* like it should work but since I'm not
638 * sure how to use it, I'm not actually sure. (NJC? ditto by SS)
639 *****************************************************/
640static int dt3155_mmap (struct file * file, struct vm_area_struct * vma)
641{
642 /* which device are we mmapping? */
643 int minor = MINOR(file->f_dentry->d_inode->i_rdev);
644 unsigned long offset;
aa337ef1
SS
645 offset = vma->vm_pgoff << PAGE_SHIFT;
646
647 if (offset >= __pa(high_memory) || (file->f_flags & O_SYNC))
648 vma->vm_flags |= VM_IO;
649
650 /* Don't try to swap out physical pages.. */
651 vma->vm_flags |= VM_RESERVED;
652
aa337ef1
SS
653 /* they are mapping the registers or the buffer */
654 if ((offset == dt3155_status[minor].reg_addr &&
655 vma->vm_end - vma->vm_start == PCI_PAGE_SIZE) ||
656 (offset == dt3155_status[minor].mem_addr &&
657 vma->vm_end - vma->vm_start == dt3155_status[minor].mem_size))
658 {
aa337ef1
SS
659 if (remap_pfn_range(vma,
660 vma->vm_start,
661 offset >> PAGE_SHIFT,
662 vma->vm_end - vma->vm_start,
2141ec62 663 vma->vm_page_prot)) {
aa337ef1
SS
664 printk("DT3155: remap_page_range() failed.\n");
665 return -EAGAIN;
666 }
667 }
668 else
669 {
670 printk("DT3155: dt3155_mmap() bad call.\n");
671 return -ENXIO;
672 }
673
674 return 0;
675}
676
677
678/*****************************************************
679 * open()
680 *
681 * Our special open code.
682 * MOD_INC_USE_COUNT make sure that the driver memory is not freed
683 * while the device is in use.
684 *****************************************************/
d241fd58 685static int dt3155_open(struct inode* inode, struct file* filep)
aa337ef1
SS
686{
687 int minor = MINOR(inode->i_rdev); /* what device are we opening? */
d241fd58 688 if (dt3155_dev_open[minor]) {
aa337ef1
SS
689 printk ("DT3155: Already opened by another process.\n");
690 return -EBUSY;
691 }
692
d241fd58 693 if (dt3155_status[minor].device_installed==0)
aa337ef1
SS
694 {
695 printk("DT3155 Open Error: No such device dt3155 minor number %d\n",
696 minor);
697 return -EIO;
698 }
699
d241fd58 700 if (dt3155_status[minor].state != DT3155_STATE_IDLE) {
dcff74ce 701 printk ("DT3155: Not in idle state (state = %x)\n",
d241fd58 702 dt3155_status[minor].state);
aa337ef1
SS
703 return -EBUSY;
704 }
705
706 printk("DT3155: Device opened.\n");
707
d241fd58 708 dt3155_dev_open[minor] = 1 ;
aa337ef1 709
d241fd58 710 dt3155_flush(minor);
aa337ef1
SS
711
712 /* Disable ALL interrupts */
713 int_csr_r.reg = 0;
d241fd58 714 WriteMReg((dt3155_lbase[minor] + INT_CSR), int_csr_r.reg);
aa337ef1 715
aa337ef1 716 init_waitqueue_head(&(dt3155_read_wait_queue[minor]));
aa337ef1
SS
717
718 return 0;
719}
720
721
722/*****************************************************
723 * close()
724 *
725 * Now decrement the use count.
726 *
727 *****************************************************/
d241fd58 728static int dt3155_close(struct inode *inode, struct file *filep)
aa337ef1
SS
729{
730 int minor;
731
732 minor = MINOR(inode->i_rdev); /* which device are we closing */
d241fd58 733 if (!dt3155_dev_open[minor])
aa337ef1
SS
734 {
735 printk("DT3155: attempt to CLOSE a not OPEN device\n");
736 }
737 else
738 {
d241fd58 739 dt3155_dev_open[minor] = 0;
aa337ef1 740
d241fd58 741 if (dt3155_status[minor].state != DT3155_STATE_IDLE)
aa337ef1
SS
742 {
743 quick_stop(minor);
744 }
745 }
746 return 0;
747}
748
749/*****************************************************
750 * read()
751 *
752 *****************************************************/
f721ad7a
GKH
753static ssize_t dt3155_read(struct file *filep, char __user *buf,
754 size_t count, loff_t *ppos)
aa337ef1
SS
755{
756 /* which device are we reading from? */
757 int minor = MINOR(filep->f_dentry->d_inode->i_rdev);
3a8954e8 758 u32 offset;
aa337ef1 759 int frame_index;
7f76c52f 760 struct frame_info *frame_info;
aa337ef1
SS
761
762 /* TODO: this should check the error flag and */
763 /* return an error on hardware failures */
5019d284 764 if (count != sizeof(struct dt3155_read))
aa337ef1
SS
765 {
766 printk("DT3155 ERROR (NJC): count is not right\n");
767 return -EINVAL;
768 }
769
770
771 /* Hack here -- I'm going to allow reading even when idle.
772 * this is so that the frames can be read after STOP has
773 * been called. Leaving it here, commented out, as a reminder
774 * for a short while to make sure there are no problems.
775 * Note that if the driver is not opened in non_blocking mode,
776 * and the device is idle, then it could sit here forever! */
777
778 /* if (dt3155_status[minor].state == DT3155_STATE_IDLE)*/
779 /* return -EBUSY;*/
780
aa337ef1
SS
781 /* non-blocking reads should return if no data */
782 if (filep->f_flags & O_NDELAY)
783 {
784 if ((frame_index = dt3155_get_ready_buffer(minor)) < 0) {
d241fd58 785 /*printk("dt3155: no buffers available (?)\n");*/
aa337ef1
SS
786 /* printques(minor); */
787 return -EAGAIN;
788 }
789 }
790 else
791 {
792 /*
793 * sleep till data arrives , or we get interrupted.
794 * Note that wait_event_interruptible() does not actually
795 * sleep/wait if it's condition evaluates to true upon entry.
796 */
797 wait_event_interruptible(dt3155_read_wait_queue[minor],
798 (frame_index = dt3155_get_ready_buffer(minor))
799 >= 0);
800
801 if (frame_index < 0)
802 {
803 printk ("DT3155: read: interrupted\n");
804 quick_stop (minor);
805 printques(minor);
806 return -EINTR;
807 }
808 }
809
7f76c52f 810 frame_info = &dt3155_status[minor].fbuffer.frame_info[frame_index];
aa337ef1
SS
811
812 /* make this an offset */
7f76c52f 813 offset = frame_info->addr - dt3155_status[minor].mem_addr;
aa337ef1
SS
814
815 put_user(offset, (unsigned int *) buf);
3a8954e8 816 buf += sizeof(u32);
d241fd58 817 put_user(dt3155_status[minor].fbuffer.frame_count, (unsigned int *) buf);
3a8954e8 818 buf += sizeof(u32);
aa337ef1 819 put_user(dt3155_status[minor].state, (unsigned int *) buf);
3a8954e8 820 buf += sizeof(u32);
7f76c52f 821 if (copy_to_user(buf, frame_info, sizeof(*frame_info)))
aa337ef1
SS
822 return -EFAULT;
823
5019d284 824 return sizeof(struct dt3155_read);
aa337ef1
SS
825}
826
827static unsigned int dt3155_poll (struct file * filp, poll_table *wait)
828{
829 int minor = MINOR(filp->f_dentry->d_inode->i_rdev);
830
831 if (!is_ready_buf_empty(minor))
832 return POLLIN | POLLRDNORM;
833
834 poll_wait (filp, &dt3155_read_wait_queue[minor], wait);
835
836 return 0;
837}
838
b1f2ac07
AB
839static long
840dt3155_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
841{
842 int ret;
843
844 lock_kernel();
845 ret = dt3155_ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
846 unlock_kernel();
847
848 return ret;
849}
aa337ef1
SS
850
851/*****************************************************
852 * file operations supported by DT3155 driver
853 * needed by init_module
854 * register_chrdev
855 *****************************************************/
856static struct file_operations dt3155_fops = {
b1f2ac07
AB
857 .read = dt3155_read,
858 .unlocked_ioctl = dt3155_unlocked_ioctl,
859 .mmap = dt3155_mmap,
860 .poll = dt3155_poll,
861 .open = dt3155_open,
862 .release = dt3155_close
aa337ef1
SS
863};
864
865
866/*****************************************************
867 * find_PCI();
868 *
869 * PCI has been totally reworked in 2.1..
870 *****************************************************/
871static int find_PCI (void)
872{
873 struct pci_dev *pci_dev = NULL;
874 int error, pci_index = 0;
875 unsigned short rev_device;
876 unsigned long base;
877 unsigned char irq;
878
6910dadf 879 while ((pci_dev = pci_get_device
aa337ef1
SS
880 (DT3155_VENDORID, DT3155_DEVICEID, pci_dev)) != NULL)
881 {
882 pci_index ++;
883
884 /* Is it really there? */
885 if ((error =
886 pci_read_config_word(pci_dev, PCI_CLASS_DEVICE, &rev_device)))
887 continue;
888
889 /* Found a board */
890 DT_3155_DEBUG_MSG("DT3155: Device number %d \n", pci_index);
891
892 /* Make sure the driver was compiled with enough buffers to handle
893 this many boards */
894 if (pci_index > MAXBOARDS) {
895 printk("DT3155: ERROR - found %d devices, but driver only configured "
896 "for %d devices\n"
897 "DT3155: Please change MAXBOARDS in dt3155.h\n",
898 pci_index, MAXBOARDS);
6910dadf 899 goto err;
aa337ef1
SS
900 }
901
902 /* Now, just go out and make sure that this/these device(s) is/are
903 actually mapped into the kernel address space */
d241fd58 904 if ((error = pci_read_config_dword(pci_dev, PCI_BASE_ADDRESS_0,
dcff74ce 905 (u32 *) &base)))
aa337ef1
SS
906 {
907 printk("DT3155: Was not able to find device \n");
6910dadf 908 goto err;
aa337ef1
SS
909 }
910
911 DT_3155_DEBUG_MSG("DT3155: Base address 0 for device is %lx \n", base);
912 dt3155_status[pci_index-1].reg_addr = base;
913
914 /* Remap the base address to a logical address through which we
915 * can access it. */
d241fd58
JB
916 dt3155_lbase[pci_index - 1] = ioremap(base,PCI_PAGE_SIZE);
917 dt3155_status[pci_index - 1].reg_addr = base;
f721ad7a
GKH
918 DT_3155_DEBUG_MSG("DT3155: New logical address is %p \n",
919 dt3155_lbase[pci_index-1]);
d241fd58 920 if (!dt3155_lbase[pci_index-1])
aa337ef1
SS
921 {
922 printk("DT3155: Unable to remap control registers\n");
6910dadf 923 goto err;
aa337ef1
SS
924 }
925
d241fd58 926 if ((error = pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &irq)))
aa337ef1
SS
927 {
928 printk("DT3155: Was not able to find device \n");
6910dadf 929 goto err;
aa337ef1
SS
930 }
931
932 DT_3155_DEBUG_MSG("DT3155: IRQ is %d \n",irq);
d241fd58 933 dt3155_status[pci_index-1].irq = irq;
aa337ef1 934 /* Set flag: kth device found! */
d241fd58 935 dt3155_status[pci_index-1].device_installed = 1;
f721ad7a 936 printk("DT3155: Installing device %d w/irq %d and address %p\n",
aa337ef1 937 pci_index,
3a8954e8 938 dt3155_status[pci_index-1].irq,
f721ad7a 939 dt3155_lbase[pci_index-1]);
aa337ef1
SS
940
941 }
942 ndevices = pci_index;
943
944 return DT_3155_SUCCESS;
6910dadf
SH
945
946err:
947 pci_dev_put(pci_dev);
948 return DT_3155_FAILURE;
aa337ef1
SS
949}
950
3a8954e8 951u32 allocatorAddr = 0;
aa337ef1
SS
952
953/*****************************************************
954 * init_module()
955 *****************************************************/
956int init_module(void)
957{
958 int index;
959 int rcode = 0;
d241fd58 960 char *devname[MAXBOARDS];
aa337ef1 961
d241fd58 962 devname[0] = "dt3155a";
aa337ef1 963#if MAXBOARDS == 2
d241fd58 964 devname[1] = "dt3155b";
aa337ef1
SS
965#endif
966
967 printk("DT3155: Loading module...\n");
968
969 /* Register the device driver */
d241fd58
JB
970 rcode = register_chrdev(dt3155_major, "dt3155", &dt3155_fops);
971 if(rcode < 0)
aa337ef1 972 {
d241fd58 973 printk(KERN_INFO "DT3155: register_chrdev failed \n");
aa337ef1
SS
974 return rcode;
975 }
976
d241fd58 977 if(dt3155_major == 0)
aa337ef1
SS
978 dt3155_major = rcode; /* dynamic */
979
980
981 /* init the status variables. */
982 /* DMA memory is taken care of in setup_buffers() */
d241fd58 983 for (index = 0; index < MAXBOARDS; index++)
aa337ef1 984 {
d241fd58
JB
985 dt3155_status[index].config.acq_mode = DT3155_MODE_FRAME;
986 dt3155_status[index].config.continuous = DT3155_ACQ;
987 dt3155_status[index].config.cols = DT3155_MAX_COLS;
988 dt3155_status[index].config.rows = DT3155_MAX_ROWS;
989 dt3155_status[index].state = DT3155_STATE_IDLE;
aa337ef1
SS
990
991 /* find_PCI() will check if devices are installed; */
992 /* first assume they're not: */
d241fd58
JB
993 dt3155_status[index].mem_addr = 0;
994 dt3155_status[index].mem_size = 0;
995 dt3155_status[index].state = DT3155_STATE_IDLE;
996 dt3155_status[index].device_installed = 0;
aa337ef1
SS
997 }
998
999 /* Now let's find the hardware. find_PCI() will set ndevices to the
1000 * number of cards found in this machine. */
aa337ef1 1001 {
d241fd58 1002 if ((rcode = find_PCI()) != DT_3155_SUCCESS)
aa337ef1
SS
1003 {
1004 printk("DT3155 error: find_PCI() failed to find dt3155 board(s)\n");
d241fd58 1005 unregister_chrdev(dt3155_major, "dt3155");
aa337ef1
SS
1006 return rcode;
1007 }
1008 }
1009
1010 /* Ok, time to setup the frame buffers */
d241fd58 1011 if((rcode = dt3155_setup_buffers(&allocatorAddr)) < 0)
aa337ef1
SS
1012 {
1013 printk("DT3155: Error: setting up buffer not large enough.");
d241fd58 1014 unregister_chrdev(dt3155_major, "dt3155");
aa337ef1
SS
1015 return rcode;
1016 }
1017
1018 /* If we are this far, then there is enough RAM */
1019 /* for the buffers: Print the configuration. */
d241fd58 1020 for( index = 0; index < ndevices; index++)
aa337ef1
SS
1021 {
1022 printk("DT3155: Device = %d; acq_mode = %d; "
1023 "continuous = %d; cols = %d; rows = %d;\n",
1024 index ,
d241fd58
JB
1025 dt3155_status[index].config.acq_mode,
1026 dt3155_status[index].config.continuous,
1027 dt3155_status[index].config.cols,
1028 dt3155_status[index].config.rows);
aa337ef1 1029 printk("DT3155: m_addr = 0x%x; m_size = %ld; "
dcff74ce 1030 "state = %d; device_installed = %d\n",
d241fd58
JB
1031 dt3155_status[index].mem_addr,
1032 (long int)dt3155_status[index].mem_size,
1033 dt3155_status[index].state,
1034 dt3155_status[index].device_installed);
aa337ef1
SS
1035 }
1036
1037 /* Disable ALL interrupts */
1038 int_csr_r.reg = 0;
d241fd58 1039 for( index = 0; index < ndevices; index++)
aa337ef1 1040 {
d241fd58
JB
1041 WriteMReg((dt3155_lbase[index] + INT_CSR), int_csr_r.reg);
1042 if(dt3155_status[index].device_installed)
aa337ef1
SS
1043 {
1044 /*
1045 * This driver *looks* like it can handle sharing interrupts,
1046 * but I can't actually test myself. I've had reports that it
1047 * DOES work so I'll enable it for now. This comment will remain
1048 * as a reminder in case any problems arise. (SS)
1049 */
1050 /* in older kernels flags are: SA_SHIRQ | SA_INTERRUPT */
d241fd58
JB
1051 rcode = request_irq(dt3155_status[index].irq, (void *)dt3155_isr,
1052 IRQF_SHARED | IRQF_DISABLED, devname[index],
aa337ef1 1053 (void*) &dt3155_status[index]);
d241fd58 1054 if(rcode < 0)
aa337ef1
SS
1055 {
1056 printk("DT3155: minor %d request_irq failed for IRQ %d\n",
1057 index, dt3155_status[index].irq);
d241fd58 1058 unregister_chrdev(dt3155_major, "dt3155");
aa337ef1
SS
1059 return rcode;
1060 }
1061 }
1062 }
1063
1064 printk("DT3155: finished loading\n");
1065
1066 return 0;
1067}
1068
1069/*****************************************************
1070 * cleanup_module(void)
1071 *
1072 *****************************************************/
1073void cleanup_module(void)
1074{
1075 int index;
1076
1077 printk("DT3155: cleanup_module called\n");
1078
1079 /* removed DMA allocated with the allocator */
1080#ifdef STANDALONE_ALLOCATOR
1081 if (allocatorAddr != 0)
1082 allocator_free_dma(allocatorAddr);
1083#else
1084 allocator_cleanup();
1085#endif
1086
d241fd58 1087 unregister_chrdev(dt3155_major, "dt3155");
aa337ef1 1088
d241fd58 1089 for(index = 0; index < ndevices; index++)
aa337ef1 1090 {
d241fd58 1091 if(dt3155_status[index].device_installed == 1)
aa337ef1 1092 {
d241fd58
JB
1093 printk("DT3155: Freeing irq %d for device %d\n",
1094 dt3155_status[index].irq, index);
1095 free_irq(dt3155_status[index].irq, (void*)&dt3155_status[index]);
aa337ef1
SS
1096 }
1097 }
aa337ef1
SS
1098}
1099