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